def _validate_subscription(environ, name, recipe): """ Determine if this space can be subscribed to. We know that the space exists, what we want to determine here is if it has been blacklisted or already been subscribed. """ space = Space(name) if name in environ['tiddlyweb.config'].get('blacklisted_spaces', []): raise HTTP409('Subscription not allowed to space: %s' % name) elif [space.public_bag(), ''] in recipe: raise HTTP409('Space already subscribed: %s' % name) return space
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 _do_unsubscriptions(space_name, unsubscriptions, public_recipe_list, private_recipe_list): """ Remove unsubscriptions from the space represented by public_recipe_list and private_recipe_list. """ for space in unsubscriptions: if space == space_name: raise HTTP409('Attempt to unsubscribe self') try: unsubscribed_space = Space(space) bag = unsubscribed_space.public_bag() public_recipe_list.remove([bag, ""]) private_recipe_list.remove([bag, ""]) except ValueError, exc: raise HTTP409('Invalid content for unsubscription: %s' % exc)
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 _validate_bag(environ, bag): """ Unless bag is valid raise a `409` with the reason why. """ try: validate_bag(bag, environ) except InvalidBagError as exc: raise HTTP409('Bag content is invalid: %s' % exc)
def _validate_recipe(environ, recipe): """ Unless recipe is valid raise a ``409`` with the reason why. """ try: validate_recipe(recipe, environ) except InvalidBagError as exc: raise HTTP409('Recipe content is invalid: %s' % exc)
def _validate_tiddler_content(environ, tiddler): """ Unless tiddler is valid raise a 409 with the reason why things to check are presumably tags and title, but we don't want to worry about that here, we want to dispatch elsewhere. """ try: validate_tiddler(tiddler, environ) except InvalidTiddlerError as exc: raise HTTP409('Tiddler content is invalid: %s' % exc)
def _validate_space_name(environ, name): """ Determine if space name can be used. We've already checked if the space exists. """ store = environ['tiddlyweb.store'] try: space = Space(name) except ValueError, exc: raise HTTP409(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'] 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 _get_subscription_info(environ): """ Extract subscription info from the JSON posted to a space. """ try: length = environ['CONTENT_LENGTH'] content = environ['wsgi.input'].read(int(length)) info = simplejson.loads(content) subscriptions = info.get('subscriptions', []) unsubscriptions = info.get('unsubscriptions', []) except (JSONDecodeError, KeyError), exc: raise HTTP409('Invalid content for subscription: %s' % exc)
def _do_subscriptions(environ, subscriptions, public_recipe_list, private_recipe_list, store): """ Add subscriptions to the space represented by public_recipe_list and private_recipe_list. """ for space in subscriptions: try: subscribed_space = _validate_subscription(environ, space, private_recipe_list) except ValueError, exc: raise HTTP409('Invalid space name: %s' % exc) try: subscribed_recipe = store.get( Recipe(subscribed_space.public_recipe())) for bag, filter_string in subscribed_recipe.get_recipe()[2:]: if [bag, filter_string] not in public_recipe_list: public_recipe_list.insert(-1, (bag, filter_string)) if [bag, filter_string] not in private_recipe_list: private_recipe_list.insert(-2, (bag, filter_string)) except NoRecipeError, exc: raise HTTP409('Invalid content for subscription: %s' % exc)
def subscribe_space(environ, start_response): """ Subscribe and/or unsubscribe the spaces named in the JSON content of the request to the space named in the URI. The current user must be a member of the space. Raise 409 if the JSON is no good. Raise 404 if the space does not exist. Raise 409 if a space in the JSON does not exist. """ store = environ['tiddlyweb.store'] space_name = get_route_value(environ, 'space_name') current_user = environ['tiddlyweb.usersign'] try: current_space = Space(space_name) except ValueError, exc: raise HTTP409('Invalid space name: %s' % exc)
def _update_policy(policy, add=None, subtract=None): """ Update the policy adding or subtracting the user named in add or subtract. """ for constraint in ('read', 'write', 'create', 'delete', 'manage'): constraint_values = getattr(policy, constraint) if add and add not in constraint_values: if constraint == 'read' and constraint_values == []: pass else: if 'ANY' in constraint_values or 'NONE' in constraint_values: raise HTTP409('Policy contains ANY or NONE.') constraint_values.append(add) if subtract and subtract in constraint_values: constraint_values.remove(subtract) return policy
def _store_tiddler_revisions(environ, content, tiddler): """ Given JSON revisions in content, store them as a revision history to tiddler. """ try: json_tiddlers = simplejson.loads(content) except ValueError as exc: raise HTTP409('unable to handle json: %s' % exc) store = environ['tiddlyweb.store'] serializer = Serializer('json', environ) serializer.object = tiddler try: for json_tiddler in reversed(json_tiddlers): json_string = simplejson.dumps(json_tiddler) serializer.from_string(json_string) store.put(tiddler) except NoTiddlerError as exc: raise HTTP400('Unable to store tiddler revisions: %s' % exc)
def destroy_key(environ, start_response): """ Remove a key. """ config = environ['tiddlyweb.config'] store = environ['tiddlyweb.store'] username = environ['tiddlyweb.usersign']['name'] bag_name = config.get('oauth.tokens_bag', 'oauth_tokens') key_name = get_route_value(environ, 'key_name') tiddler = Tiddler(key_name, bag_name) try: tiddler = store.get(tiddler) except NoTiddlerError: raise HTTP404('key does not exist') if tiddler.modifier != username: raise HTTP409('owner mismatch') store.delete(tiddler) start_response('204 No Content', [('Content-Type', 'text/plain')]) return []
def _validate_space_name(environ, name): """ Determine if space name can be used. We've already checked if the space exists. """ store = environ['tiddlyweb.store'] try: space = Space(name) except ValueError, exc: raise HTTP409(exc) # This reserved list should/could be built up from multiple # sources. reserved_space_names = environ['tiddlyweb.config'].get( 'socialusers.reserved_names', []) if name in reserved_space_names: raise HTTP409('Invalid space name: %s' % name) try: store.get(Recipe(space.private_recipe())) raise HTTP409('%s already exists as space' % name) except NoRecipeError: pass import tiddlywebplugins.socialusers original_validate_user = tiddlywebplugins.socialusers._validate_user def _validate_user_name(environ, user_info): """ Override socialusers _validate_user. """