def _check_and_validate_tiddler(environ, bag, tiddler): """ If the tiddler does not exist, check we have create in the bag. If the tiddler does exist, check we have edit. In either case, check ETag to be sure that if it is set, that it maches what is currently in the store. """ store = environ['tiddlyweb.store'] try: try: revision = store.list_tiddler_revisions(tiddler)[0] except StoreMethodNotImplemented: # If list_tiddler_revisions is not implemented # we still need to check if the tiddler exists. # If it doesn't NoTiddlerError gets raised and # the except block below is run. test_tiddler = Tiddler(tiddler.title, tiddler.bag) store.get(test_tiddler) revision = 1 tiddler.revision = revision # These both next will raise exceptions if # the contraints don't match. check_bag_constraint(environ, bag, 'write') validate_tiddler_headers(environ, tiddler) except NoTiddlerError: check_bag_constraint(environ, bag, 'create') tiddler.revision = None incoming_etag = environ.get('HTTP_IF_MATCH', None) if incoming_etag and not ( incoming_etag == _new_tiddler_etag(tiddler)): raise HTTP412('ETag incorrect for new tiddler')
def _put_tiddler(environ, start_response, tiddler): """ The guts of putting a tiddler into the store. There's a fair bit of special handling done here depending on whether the tiddler already exists or not. """ store = environ['tiddlyweb.store'] try: bag = Bag(tiddler.bag) _check_and_validate_tiddler(environ, bag, tiddler) user = environ['tiddlyweb.usersign']['name'] if not user == 'GUEST': tiddler.modifier = user tiddler.modified = current_timestring() try: check_bag_constraint(environ, bag, 'accept') except (PermissionsError), exc: _validate_tiddler_content(environ, tiddler) store.put(tiddler)
def _post_tiddler_revisions(environ, start_response, tiddler): """ We have a list of revisions, put them in a new place. """ length, content_type = content_length_and_type(environ) 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') content = environ['wsgi.input'].read(int(length)) _store_tiddler_revisions(environ, content, tiddler) response = [('Location', tiddler_url(environ, tiddler))] start_response("204 No Content", response) return []
def _post_tiddler_revisions(environ, start_response, tiddler): """ We have a list of revisions, put them in a new place. """ length, content_type = content_length_and_type(environ) if content_type not in CHRONICLE_TYPES: raise HTTP415('application/vnd.tiddlyweb+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') content = environ['wsgi.input'].read(int(length)) _store_tiddler_revisions(environ, content, tiddler) response = [('Location', tiddler_url(environ, tiddler))] start_response("204 No Content", response) return []
def _send_tiddler(environ, start_response, tiddler): """ Push a single tiddler out the network in the form of the chosen serialization. """ store = environ['tiddlyweb.store'] bag = Bag(tiddler.bag) # this will raise 403 if constraint does not pass try: check_bag_constraint(environ, bag, 'read') except NoBagError as exc: raise HTTP404('%s not found, no bag %s, %s' % (tiddler.title, tiddler.bag, exc)) try: tiddler = store.get(tiddler) except NoTiddlerError as exc: raise HTTP404('%s not found, %s' % (tiddler.title, exc)) # this will raise 304 # have to do this check after we read from the store because # we need the revision, which is sad last_modified, etag = validate_tiddler_headers(environ, tiddler) # make choices between binary or serialization content, mime_type, serialized = _get_tiddler_content(environ, tiddler) vary_header = ('Vary', 'Accept') cache_header = ('Cache-Control', 'no-cache') if CACHE_CONTROL_FIELD in tiddler.fields: try: cache_header = ('Cache-Control', 'max-age=%s' % int(tiddler.fields[CACHE_CONTROL_FIELD])) except ValueError: pass # if the value is not an int use default header # Add charset to pseudo_binary tiddler if not serialized and pseudo_binary(tiddler.type): mime_type = '%s; charset=UTF-8' % mime_type content_header = ('Content-Type', str(mime_type)) response = [cache_header, content_header, vary_header] if last_modified: response.append(last_modified) if etag: response.append(etag) start_response('200 OK', response) if isinstance(content, basestring) or isinstance(content, bytes): return [content] else: return content
def _send_tiddler(environ, start_response, tiddler): """ Push a single tiddler out the network in the form of the chosen serialization. """ store = environ['tiddlyweb.store'] bag = Bag(tiddler.bag) # this will raise 403 if constraint does not pass try: check_bag_constraint(environ, bag, 'read') except NoBagError, exc: raise HTTP404('%s not found, no bag %s, %s' % (tiddler.title, tiddler.bag, exc))
def _delete_tiddler(environ, start_response, tiddler): """ The guts of deleting a tiddler from the store. """ store = environ['tiddlyweb.store'] try: tiddler = store.get(tiddler) validate_tiddler_headers(environ, tiddler) bag = Bag(tiddler.bag) # this will raise 403 if constraint does not pass check_bag_constraint(environ, bag, 'delete') store.delete(tiddler) except NoTiddlerError, exc: raise HTTP404('%s not found, %s' % (tiddler.title, exc))
def _put_tiddler(environ, start_response, tiddler): """ The guts of putting a tiddler into the store. There's a fair bit of special handling done here depending on whether the tiddler already exists or not. """ store = environ['tiddlyweb.store'] try: bag = Bag(tiddler.bag) _check_and_validate_tiddler(environ, bag, tiddler) user = environ['tiddlyweb.usersign']['name'] if not user == 'GUEST': tiddler.modifier = user tiddler.modified = current_timestring() try: check_bag_constraint(environ, bag, 'accept') except (PermissionsError) as exc: _validate_tiddler_content(environ, tiddler) store.put(tiddler) except NoBagError as exc: raise HTTP409("Unable to put tiddler, %s. There is no bag named: " "%s (%s). Create the bag." % (tiddler.title, tiddler.bag, exc)) except NoTiddlerError as exc: raise HTTP404('Unable to put tiddler, %s. %s' % (tiddler.title, exc)) except TypeError as exc: raise HTTP409('Unable to put badly formed tiddler, %s:%s. %s' % (tiddler.bag, tiddler.title, exc)) etag = ('ETag', tiddler_etag(environ, tiddler)) response = [('Location', tiddler_url(environ, tiddler))] if etag: response.append(etag) start_response("204 No Content", response) return []
def _delete_tiddler(environ, start_response, tiddler): """ The guts of deleting a tiddler from the store. """ store = environ['tiddlyweb.store'] try: tiddler = store.get(tiddler) validate_tiddler_headers(environ, tiddler) bag = Bag(tiddler.bag) # this will raise 403 if constraint does not pass check_bag_constraint(environ, bag, 'delete') store.delete(tiddler) except NoTiddlerError as exc: raise HTTP404('%s not found, %s' % (tiddler.title, exc)) start_response("204 No Content", []) return []
def _put_tiddler(environ, start_response, tiddler): """ The guts of putting a tiddler into the store. There's a fair bit of special handling done here depending on whether the tiddler already exists or not. """ store = environ['tiddlyweb.store'] try: bag = Bag(tiddler.bag) _check_and_validate_tiddler(environ, bag, tiddler) user = environ['tiddlyweb.usersign']['name'] tiddler.modifier = user tiddler.modified = current_timestring() try: check_bag_constraint(environ, bag, 'accept') except (PermissionsError): _validate_tiddler_content(environ, tiddler) store.put(tiddler) except NoBagError as exc: raise HTTP409("Unable to put tiddler, %s. There is no bag named: " "%s (%s). Create the bag." % (tiddler.title, tiddler.bag, exc)) except NoTiddlerError as exc: raise HTTP404('Unable to put tiddler, %s. %s' % (tiddler.title, exc)) except TypeError as exc: raise HTTP409('Unable to put badly formed tiddler, %s:%s. %s' % (tiddler.bag, tiddler.title, exc)) etag = ('ETag', tiddler_etag(environ, tiddler)) response = [('Location', tiddler_url(environ, tiddler))] if etag: response.append(etag) start_response("204 No Content", response) return []
def _readable(environ, bag_name): try: check_bag_constraint(environ, Bag(bag_name), 'read') return True except PermissionsError: return False