예제 #1
0
def _post_tiddler_revisions(environ, start_response, tiddler):
    """
    We have a list of revisions, put them in a new place.
    """
    content_type = environ['tiddlyweb.type']

    if content_type != 'application/json':
        raise HTTP415('application/json required')

    # we need a matching etag in order to be able to do
    # this operation. This will raise exception if there
    # isn't a valid etag.
    _require_valid_etag_for_write(environ, tiddler)

    bag = Bag(tiddler.bag)
    #  both create and write required for this action
    _check_bag_constraint(environ, bag, 'create')
    _check_bag_constraint(environ, bag, 'write')

    length = environ['CONTENT_LENGTH']
    content = environ['wsgi.input'].read(int(length))

    _store_tiddler_revisions(environ, content, tiddler)

    response = [('Location', web.tiddler_url(environ, tiddler))]
    start_response("204 No Content", response)

    return []
예제 #2
0
def _get_tiddler_content(environ, tiddler):
    """
    Extract the content of the tiddler, either straight up if
    the content is not considered text, or serialized if it is
    """
    config = environ['tiddlyweb.config']
    default_serializer = config['default_serializer']
    default_serialize_type = config['serializers'][default_serializer][0]
    serialize_type, mime_type = web.get_serialize_type(environ)
    extension = environ.get('tiddlyweb.extension')

    if not renderable(tiddler, environ):
        if (serialize_type == default_serialize_type
                or mime_type.startswith(tiddler.type) or extension == 'html'):
            mime_type = tiddler.type
            content = tiddler.text
            return content, mime_type

    serializer = Serializer(serialize_type, environ)
    serializer.object = tiddler

    try:
        content = serializer.to_string()
    except (TiddlerFormatError, NoSerializationError), exc:
        raise HTTP415(exc)
예제 #3
0
def put_user(environ, start_response):
    """
    Allow a user or an admin to set the password for a user
    at /users/{usersign}. A non-admin can only set their
    own password.

    The sent data is a JSON dict with at least the key
    'password' with a value of whatever the password
    should be.

    Users of this method should take not that that password
    is being sent in the clear over what is likely an
    unencrypted network.
    """
    store = environ['tiddlyweb.store']
    current_user = environ['tiddlyweb.usersign']
    target_user = environ['wsgiorg.routing_args'][1]['usersign']
    target_user = urllib.unquote(target_user)
    target_user = unicode(target_user, 'utf-8')

    if not ('ADMIN' in current_user['roles']
            or current_user['name'] == target_user):
        raise HTTP403('Incorrect User')

    content_type = environ['tiddlyweb.type']
    length = environ['CONTENT_LENGTH']
    if content_type != 'application/json':
        raise HTTP415('application/json required')
    content = environ['wsgi.input'].read(int(length))

    try:
        user_info = simplejson.loads(content)
    except ValueError, exc:
        raise HTTP400('Invalid JSON, %s' % exc)
예제 #4
0
파일: util.py 프로젝트: funkyeah/tiddlyweb
def get_serialize_type(environ):
    """
    Look in the environ to determine which serializer
    we should use for this request.
    """
    config = environ['tiddlyweb.config']
    accept = environ.get('tiddlyweb.type')[:]
    ext = environ.get('tiddlyweb.extension')
    serializers = config['serializers']
    serialize_type, mime_type = None, None

    if type(accept) == str:
        accept = [accept]

    while len(accept) and serialize_type == None:
        candidate_type = accept.pop(0)
        try:
            serialize_type, mime_type = serializers[candidate_type]
        except KeyError:
            pass
    if not serialize_type:
        if ext:
            raise HTTP415('%s type unsupported' % ext)
        # If we are a PUT and we haven't found a serializer, don't
        # state a default as that makes no sense.
        if environ['REQUEST_METHOD'] == 'GET':
            default_serializer = config['default_serializer']
            serialize_type, mime_type = serializers[default_serializer]
    return serialize_type, mime_type
예제 #5
0
def send_entity(environ, start_response, entity):
    """
    Send a bag or recipe out HTTP, first serializing to
    the correct type.
    """
    username = environ['tiddlyweb.usersign']['name']
    try:
        serialize_type, mime_type = get_serialize_type(environ)
        serializer = Serializer(serialize_type, environ)
        serializer.object = entity
        content = serializer.to_string()
    except NoSerializationError:
        raise HTTP415('Content type %s not supported' % mime_type)

    etag_string = '"%s"' % (sha(
        _entity_etag(entity) + encode_name(username) +
        encode_name(mime_type)).hexdigest())

    start_response("200 OK", [('Content-Type', mime_type),
                              ('ETag', etag_string), ('Vary', 'Accept')])

    if isinstance(content, basestring):
        return [content]
    else:
        return content
예제 #6
0
def send_entity(environ, start_response, entity):
    """
    Send a bag or recipe out HTTP, first serializing to
    the correct type. If the incoming etag matches, raise
    304.
    """
    etag_string = entity_etag(environ, entity)
    incoming_etag = environ.get('HTTP_IF_NONE_MATCH', None)
    if incoming_etag:
        if incoming_etag == etag_string:
            raise HTTP304(incoming_etag)

    try:
        serialize_type, mime_type = get_serialize_type(environ)
        serializer = Serializer(serialize_type, environ)
        serializer.object = entity
        content = serializer.to_string()
    except NoSerializationError:
        raise HTTP415('Content type %s not supported' % mime_type)

    start_response("200 OK", [('Content-Type', mime_type),
                              ('Cache-Control', 'no-cache'),
                              ('ETag', etag_string), ('Vary', 'Accept')])

    if isinstance(content, basestring):
        return [content]
    else:
        return content
예제 #7
0
def profile(environ, start_response):
    """
    Choose between an atom or html profile.
    """
    http_host, host_url = determine_host(environ)
    if http_host != host_url:
        # Or should it be a 302?
        raise HTTP404('No profiles at this host: %s' % http_host)

    _, mime_type = get_serialize_type(environ)
    if 'atom' in mime_type:
        return atom_profile(environ, start_response)
    elif 'html' in mime_type:
        return html_profile(environ, start_response)
    else:
        raise HTTP415('Atom and HTML only')
예제 #8
0
def post_user(environ, start_response):
    """
    Create a new user through a JSON POST to /users.
    If the not JSON, return 415. If users exists, return 409.

    The JSON should be a dict with two keys: 'username'
    and 'password'. Future iterations of this code
    will take additional keys and save them as fields
    to be used with the tiddlywebplugins.magicuser
    extractor.
    """
    content_type = environ['tiddlyweb.type']
    if content_type != 'application/json':
        raise HTTP415('application/json required')
    length = environ['CONTENT_LENGTH']
    content = environ['wsgi.input'].read(int(length))
    store = environ['tiddlyweb.store']

    try:
        user_info = simplejson.loads(content)
    except ValueError, exc:
        raise HTTP400('Invalid JSON, %s' % exc)
예제 #9
0
    try:
        serializer = Serializer(serialize_type, environ)
        serializer.object = recipe
        content = environ['wsgi.input'].read(int(length))
        serializer.from_string(content.decode('utf-8'))

        recipe.policy.owner = usersign['name']

        _validate_recipe(environ, recipe)
        store.put(recipe)
    except RecipeFormatError, exc:
        raise HTTP400('unable to put recipe: %s' % exc)
    except TypeError, exc:
        raise HTTP400('malformed input: %s' % exc)
    except NoSerializationError:
        raise HTTP415('Content type %s not supported' % serialize_type)

    start_response("204 No Content",
                   [('Location', web.recipe_url(environ, recipe))])

    return []


def _validate_recipe(environ, recipe):
    """
    Unless recipe is valid raise a 409 with the reason why.
    """
    try:
        validate_recipe(recipe, environ)
    except InvalidBagError, exc:
        raise HTTP409('Recipe content is invalid: %s' % exc)
예제 #10
0
파일: bag.py 프로젝트: funkyeah/tiddlyweb
        serialize_type = web.get_serialize_type(environ)[0]
        serializer = Serializer(serialize_type, environ)
        serializer.object = bag
        content = environ['wsgi.input'].read(int(length))
        serializer.from_string(content.decode('utf-8'))

        bag.policy.owner = usersign['name']

        _validate_bag(environ, bag)
        store.put(bag)
    except BagFormatError, exc:
        raise HTTP400('unable to put bag: %s' % exc)
    except TypeError:
        raise HTTP400('Content-type header required')
    except NoSerializationError:
        raise HTTP415('Content type not supported: %s' % serialize_type)

    start_response("204 No Content",
            [('Location', web.bag_url(environ, bag))])

    return []


def _validate_bag(environ, bag):
    """
    Unless bag is valid raise a 409 with the reason why.
    """
    try:
        validate_bag(bag, environ)
    except InvalidBagError, exc:
        raise HTTP409('Bag content is invalid: %s' % exc)
예제 #11
0
    username = environ['tiddlyweb.usersign']['name']
    try:
        kept_entities = _filter_readable(environ, store_list(), filters)
    except FilterError, exc:
        raise HTTP400(exc)

    etag_string = '"%s:%s"' % (kept_entities.hexdigest(),
                               sha('%s:%s' %
                                   (username, mime_type)).hexdigest())
    start_response("200 OK", [('Content-Type', mime_type), ('Vary', 'Accept'),
                              ('Etag', etag_string)])

    try:
        output = serializer_list(kept_entities)
    except NoSerializationError:
        raise HTTP415('Content type not supported: %s' % mime_type)

    if isinstance(output, basestring):
        return [output]
    else:
        return output


def _filter_readable(environ, entities, filters):
    """
    Traverse entities to get those that are readable
    and those that pass the filter.

    XXX: There is a bug here, depending on how
    filters are to be interpreted: If limit is used
    it is being calculated before the readability
예제 #12
0
    if download:
        response.append(
            ('Content-Disposition',
             'attachment; filename="%s"' % download.encode('utf-8')))

    if last_modified:
        response.append(last_modified)

    if etag:
        response.append(etag)

    try:
        serializer = Serializer(serialize_type, environ)
        output = serializer.list_tiddlers(candidate_tiddlers)
    except NoSerializationError, exc:
        raise HTTP415('Content type not supported: %s:%s, %s' %
                      (serialize_type, mime_type, exc))
    except FilterError, exc:  # serializations may filter tildders
        raise HTTP400('malformed filter or tiddler during filtering: %s' % exc)

    start_response("200 OK", response)

    if isinstance(output, basestring):
        return [output]
    else:
        return output


def _validate_tiddler_list(environ, tiddlers):
    """
    Do Etag and Last modified checks on the
    collection of tiddlers.