Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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 ['']
Ejemplo n.º 7
0
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 ['']
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
 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)
Ejemplo n.º 10
0
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))
Ejemplo n.º 11
0
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 ['']
Ejemplo n.º 12
0
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))
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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)