def get_tiddlers(environ, start_response): """ Handle ``GET`` on a tiddlers-within-a-recipe URI. Get a list representation of the :py:class:`tiddlers <tiddlyweb.model.tiddler.Tiddler>` generated from a :py:class:`recipe <tiddlyweb.model.recipe.Recipe>`. The information sent is dependent on the serialization chosen via :py:mod:`tiddlyweb.web.negotiate`. """ usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] filters = environ['tiddlyweb.filters'] recipe = _determine_recipe(environ) title = 'Tiddlers From Recipe %s' % recipe.name title = environ['tiddlyweb.query'].get('title', [title])[0] # check the recipe can be read recipe.policy.allows(usersign, 'read') # check the bags in the recipe can be read try: template = control.recipe_template(environ) for bag_name, _ in recipe.get_recipe(template): bag = Bag(bag_name) bag = store.get(bag) bag.policy.allows(usersign, 'read') except NoBagError as exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) # from this point forward we know the tiddlers are # readable # get the tiddlers from the recipe and uniquify them try: candidate_tiddlers = control.get_tiddlers_from_recipe(recipe, environ) except NoBagError as exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) except FilterError as exc: raise HTTP400('malformed filter: %s' % exc) tiddlers = Tiddlers(title=title) if not filters: tiddlers.store = store tiddlers.recipe = recipe.name for tiddler in candidate_tiddlers: tiddler.recipe = recipe.name tiddlers.add(tiddler) tiddlers.link = '%s/tiddlers' % web.recipe_url(environ, recipe, full=False) return send_tiddlers(environ, start_response, tiddlers=tiddlers)
def uploader(environ, start_response): usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] bag_name = environ['tiddlyweb.query'].get('bag', [''])[0] if not 'MEMBER' in usersign['roles']: raise HTTP404('bad edit') try: bag = Bag(bag_name) bag = store.get(bag) bag.policy.allows(usersign, 'write') except NoBagError: raise HTTP404('bad edit') data = {} data['bag'] = bag_name return send_template(environ, 'uploader.html', data)
def get_tiddler_edit(environ, start_response): usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] title = environ['tiddlyweb.query'].get('title', [''])[0] bag_name = environ['tiddlyweb.query'].get('bag', [''])[0] username = usersign['name'] if not 'MEMBER' in usersign['roles']: raise HTTP404('bad edit') if not title and not bag_name: tiddler = get_profile(store, usersign, username) page_title = 'Edit Profile' return_url = '%s/home' % server_base_url(environ) elif not title: tiddler = Tiddler('', bag_name) page_title = 'Edit New Tiddler' return_url = '' else: tiddler = Tiddler(title, bag_name) page_title = 'Edit %s' % title return_url = tiddler_url(environ, tiddler) try: tiddler = store.get(tiddler) except StoreError: pass bag = Bag(tiddler.bag) bag = store.get(bag) bag.policy.allows(usersign, 'write') data = {} data['tiddler'] = tiddler data['return_url'] = return_url data['title'] = page_title return send_template(environ, 'profile_edit.html', data)
def user_page(environ, start_response): userpage = environ['wsgiorg.routing_args'][1]['userpage'] user = environ['tiddlyweb.usersign'] userpage = _decode_name(userpage) first_time_check(environ, user) store = environ['tiddlyweb.store'] # If we try to go to a user page that doesn't exist, # just go to the home page. XXX maybe should 404 instead. try: userpage_user = User(userpage) userpage_user = store.get(userpage_user) except NoUserError: pass # roles will be empty if 'MEMBER' not in userpage_user.list_roles(): raise HTTP404('%s has no page' % userpage) user_friend_names = get_friends(store, user['name']) friend_names = sorted(get_friends(store, userpage)) friends = [] for name in friend_names: email = get_email_tiddler(store, name) email_md5 = md5(email.lower()).hexdigest() friends.append((name, email_md5)) profile_tiddler = get_profile(store, user, userpage) profile_html = render_wikitext(profile_tiddler, environ) notice_tiddler = get_notice(environ) notice_html = render_wikitext(notice_tiddler, environ) kept_recipes = get_stuff(store, store.list_recipes(), user, userpage) kept_bags = get_stuff(store, store.list_bags(), user, userpage) kept_favorites = get_stuff(store, get_favorited_bags(store, userpage), user) kept_bookmarks = get_stuff(store, get_bookmarked_recipes(store, userpage), user) email = get_email_tiddler(store, userpage) email_md5 = md5(email.lower()).hexdigest() data = { 'bags': kept_bags, 'user_friends': user_friend_names, 'friends': friends, 'recipes': kept_recipes, 'favorites': kept_favorites, 'bookmarks': kept_bookmarks, 'home': userpage, 'profile': profile_html, 'notice': { 'html': notice_html, 'modified': notice_tiddler.modified }, 'title': userpage, 'email': email, 'email_md5': email_md5, 'user': get_user_object(environ) } return send_template(environ, 'profile.html', data)
def app_info(environ, start_response): """ At the provider display the stored information about a app, given its id in the query parameter `app`. Only the client/app owner can see the secret. """ query = environ['tiddlyweb.query'] current_user = environ['tiddlyweb.usersign']['name'] app_id = query.get('app', [None])[0] if not app_id: raise HTTP400('app parameter required') try: app = get_app(environ, app_id) except StoreError: raise HTTP404('no matching app found') start_response('200 OK', [( 'Content-Type', 'text/plain; charset=UTF-8')]) output = ['client id: %s' % app.title] if current_user == app.modifier: output.append('client secret: %s' % app.fields['client_secret']) return output
def add_space_member(environ, start_response): """ Add a member to a space if they are not already a member. If they are already a member, nothing happens. If the username given does not exist, raise 409. If the space does not exist raise 404. """ store = environ['tiddlyweb.store'] space_name = get_route_value(environ, 'space_name') user_name = get_route_value(environ, 'user_name') current_user = environ['tiddlyweb.usersign'] _same_space_required(environ, space_name) try: change_space_member(store, space_name, add=user_name, current_user=current_user) except (NoBagError, NoRecipeError): raise HTTP404('space %s does not exist' % space_name) except NoUserError: raise HTTP409('attempt to add non-existent user: %s' % user_name) start_response('204 No Content', []) return ['']
def delete_space_member(environ, start_response): """ Remove a member from a space. If the space does not exist raise 404. If the named member is not in the space, do nothing. """ store = environ['tiddlyweb.store'] space_name = get_route_value(environ, 'space_name') user_name = get_route_value(environ, 'user_name') current_user = environ['tiddlyweb.usersign'] _same_space_required(environ, space_name) try: change_space_member(store, space_name, remove=user_name, current_user=current_user) except (NoBagError, NoRecipeError): raise HTTP404('space %s does not exist' % space_name) except NoUserError: raise HTTP409('attempt to remove non-member user: %s' % user_name) start_response('204 No Content', []) return ['']
def _get_bag(environ, bag_name): """ Get the named bag out of the store. """ store = environ['tiddlyweb.store'] bag = Bag(bag_name) try: bag = store.get(bag) except NoBagError as exc: raise HTTP404('%s not found, %s' % (bag.name, exc)) return bag
def _handle_core_request(self, environ, req_uri, space_name, start_response): """ Override a core request, adding filters or sending 404s where necessary to limit the visibility of entities. """ recipe_name = determine_space_recipe(environ, space_name) store = environ['tiddlyweb.store'] try: recipe = store.get(Recipe(recipe_name)) except NoRecipeError, exc: raise HTTP404('No recipe for space: %s', exc)
def change_space_member(store, space_name, add=None, remove=None, current_user=None): """ The guts of adding a member to space. """ try: space = Space(space_name) except ValueError, exc: raise HTTP404('Space %s invalid: %s' % (space_name, exc))
def confirm_space(environ, start_response): """ Confirm a spaces exists. If it does, raise 204. If not, raise 404. """ store = environ['tiddlyweb.store'] space_name = get_route_value(environ, 'space_name') try: space = Space(space_name) store.get(Recipe(space.public_recipe())) store.get(Recipe(space.private_recipe())) except (NoRecipeError, ValueError): raise HTTP404('%s does not exist' % space_name) start_response('204 No Content', []) return ['']
def post_tiddler_edit(environ, start_response): usersign = environ['tiddlyweb.usersign'] text = environ['tiddlyweb.query'].get('text', [''])[0] title = environ['tiddlyweb.query'].get('title', [''])[0] bag = environ['tiddlyweb.query'].get('bag', [''])[0] return_url = environ['tiddlyweb.query'].get('return_url', [''])[0] store = environ['tiddlyweb.store'] tiddler = Tiddler(title, bag) tiddler.text = text tiddler.modifier = usersign['name'] bag = Bag(bag) try: bag = store.get(bag) except NoBagError, exc: raise HTTP404('tiddler %s not found: %s' % (tiddler.title, exc))
def _determine_recipe(environ): """ Interpret URL information to determine the target recipe and then get it from the store. """ recipe_name = web.get_route_value(environ, 'recipe_name') recipe_name = web.handle_extension(environ, recipe_name) recipe = Recipe(recipe_name) store = environ['tiddlyweb.store'] try: recipe = store.get(recipe) except NoRecipeError as exc: raise HTTP404('%s not found, %s' % (recipe.name, exc)) return recipe
def list_space_members(environ, start_response): """ List the members of the named space. You must be a member to list the members. """ store = environ['tiddlyweb.store'] space_name = get_route_value(environ, 'space_name') current_user = environ['tiddlyweb.usersign'] try: space = Space(space_name) private_space_bag = store.get(Bag(space.private_bag())) private_space_bag.policy.allows(current_user, 'manage') members = [ member for member in private_space_bag.policy.manage if not member.startswith('R:') ] except (ValueError, NoBagError): raise HTTP404('No space for %s' % space_name) start_response('200 OK', [('Cache-Control', 'no-cache'), ('Content-Type', 'application/json; charset=UTF-8')]) return simplejson.dumps(members)