def safe_mode(environ, start_response): """ Serve up a space in safe mode. Safe mode means that non-required plugins are turned off and plugins that duplicate those in the core bags (system and tiddlyspace) are deleted from the store of the space in question. """ http_host, _ = determine_host(environ) space_name = determine_space(environ, http_host) recipe_name = determine_space_recipe(environ, space_name) if recipe_name != '%s_private' % space_name: raise HTTP403('membership required for safe mode') if environ['REQUEST_METHOD'] == 'GET': return _send_safe_mode(environ, start_response) store = environ['tiddlyweb.store'] # Get the list of core plugins core_plugin_tiddler_titles = _get_core_plugins(store) # Delete those plugins in the space's recipes which # duplicate the core plugins recipe = _delete_duplicates(environ, core_plugin_tiddler_titles, recipe_name, space_name) # Process the recipe. For those tiddlers which do not have a bag # in CORE_RECIPE, remove the systemConfig tag. try: candidate_tiddlers = control.get_tiddlers_from_recipe(recipe, environ) except NoBagError, exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc))
def get_identities(environ, start_response): """ Get a list of the identities associated with the named user. That named user must match the current user or the current user must be an admin. """ store = environ['tiddlyweb.store'] username = get_route_value(environ, 'username') usersign = environ['tiddlyweb.usersign']['name'] roles = environ['tiddlyweb.usersign']['roles'] if username != usersign and 'ADMIN' not in roles: raise HTTP403('Bad user for action') identities = [] try: mapped_bag = store.get(Bag('MAPUSER')) tiddlers = store.list_bag_tiddlers(mapped_bag) matched_tiddlers = control.filter_tiddlers( tiddlers, 'select=mapped_user:%s' % username, environ) identities = [tiddler.title for tiddler in matched_tiddlers] except NoBagError: pass start_response('200 OK', [('Content-Type', 'application/json; charset=UTF-8')]) return [simplejson.dumps(identities)]
def __call__(self, environ, start_response): try: output = self.application(environ, start_response) return output except ForbiddenError as exc: raise HTTP403(exc) except UserRequiredError as exc: # We only send to the challenger on a GET # request. Otherwise we're in for major confusion # on dealing with redirects and the like in # scripts and javascript, where follow # behavior is inconsistent. if environ['REQUEST_METHOD'] == 'GET': url = _challenge_url(environ) raise HTTP302(url) raise HTTP403(exc)
def _same_space_required(environ, space_name): """ Raise 403 unless the current space (http_host) is the same as the target space. """ current_space = determine_space(environ, determine_host(environ)[0]) if current_space != space_name: raise HTTP403('space membership changes only allowed from space')
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)) private_bag = store.get(Bag(space.private_bag())) if current_user: private_bag.policy.allows(current_user, 'manage') if remove and len(private_bag.policy.manage) == 1: raise HTTP403('must not remove the last member from a space') # This will throw NoUserError (to be handled by the caller) # if the user does not exist. if add: store.get(User(add)) bags = [store.get(Bag(bag)) for bag in space.list_bags()] recipes = [store.get(Recipe(bag)) for bag in space.list_recipes()] for entity in bags + recipes: new_policy = _update_policy(entity.policy, add=add, subtract=remove) entity.policy = new_policy store.put(entity) def confirm_space(environ, start_response):