def send_template(environ, template_name, template_data=None): """ Set some defualt data to send to template and then send it. """ if template_data is None: template_data = {} config = environ.get('tiddlyweb.config', {}) try: usersign = environ['tiddlyweb.usersign'] except KeyError: usersign = {'name': 'GUEST', 'roles': []} environ['tiddlyweb.usersign'] = usersign template = get_template(environ, template_name) template_defaults = { 'socket_link': config.get('socket.link'), 'csrf_token': get_nonce(environ), 'gravatar': gravatar(environ), 'user': usersign['name'], } template_defaults.update(template_data) return template.generate(template_defaults)
def _editor_display(environ, tiddler, message=''): """ Serve up the editing interface via the editor.html template. """ template = get_template(environ, 'editor.html') environ['tiddlyweb.title'] = 'Edit ' + tiddler.title return template.generate(tiddler=tiddler, message=message)
def send_template(environ, template_name, template_data=None): if template_data is None: template_data = {} template = get_template(environ, template_name) server_prefix = environ['tiddlyweb.config']['server_prefix'] user = get_user_object(environ) template_defaults = { #'message': 'test me you are a message', 'version': VERSION, 'user': user, 'member_role': 'MEMBER', 'title': '', 'userpage': { 'link': '%s/home' % server_prefix, 'title': 'homepage', }, 'login': { 'link': '%s/login' % server_prefix, 'title': 'Login', }, 'help': { 'link': '%s/help' % server_prefix, 'title': 'Help', }, 'register': { 'link': '%s/register' % server_prefix, 'title': 'Register', }, 'server_prefix': server_prefix, 'main_css': environ['tiddlyweb.config'].get('hoster.main_css', 'main.css'), } template_defaults.update(template_data) return template.generate(template_defaults)
def provider_auth(environ, start_response): """ Authorize endpoint on the provider. If the right information is provided and validates against stored info, and the user says it is okay, return a code back to the redirect_uri, which must begin with the stored callback_url. That code is stored to be compared later, when the consumer sends it requesting an access_token. XXX: Missing scope handling. """ query = environ['tiddlyweb.query'] data = {} input_errors = False for key in [ 'redirect_uri', 'scope', 'response_type', 'client_id', 'access_type', 'state' ]: if key in query: data[key] = query[key][0] elif key in ['client_id', 'response_type', 'scope']: input_errors = True try: app = get_app(environ, data['client_id']) except (StoreError, KeyError): return provider_auth_error(data, error='unauthorized_client') if 'redirect_uri' not in data: data['redirect_uri'] = app.fields['callback_url'] # This comes after loading the app, as we might not have a # redirect uri if input_errors: provider_auth_error(data, error='invalid_request') if not data['redirect_uri'].startswith(app.fields['callback_url']): return provider_auth_error(data, error='invalid_request') # XXX check scope data['name'] = app.fields['name'] if already_authorized(environ, app): return provider_auth_success(environ, data) if environ['REQUEST_METHOD'] == 'GET': template = get_template(environ, 'provider_auth.html') start_response('200 OK', [('Content-Type', 'text/html; charset=UTF-8')]) return template.generate(data=data) else: if 'accept' in query: save_provider_auth(environ, data) return provider_auth_success(environ, data) else: return provider_auth_error(data, error='access_denied')
def recent_changes(environ, start_response): """ List recent changes for the named tank. """ tank_name = get_route_value(environ, 'bag_name') store = environ['tiddlyweb.store'] usersign = environ['tiddlyweb.usersign'] config = environ['tiddlyweb.config'] days = environ['tiddlyweb.query'].get('d', [7])[0] try: bag = store.get(Bag(tank_name)) bag.policy.allows(usersign, 'read') except NoBagError: raise HTTP404('no tank found for %s' % tank_name) tiddlers = filter_tiddlers(store.list_bag_tiddlers(bag), 'select=modified:>%sd;sort=-modified' % days, environ) changes_template = get_template(environ, CHANGES_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-cache')]) return changes_template.generate({ 'socket_link': config.get('socket.link'), 'csrf_token': get_nonce(environ), 'days': days, 'tiddlers': tiddlers, 'bag': bag, 'gravatar': gravatar(environ), 'user': usersign['name'], })
def _editor_display(environ, tiddler, message=""): """ Serve up the editing interface via the editor.html template. """ template = get_template(environ, "editor.html") environ["tiddlyweb.title"] = "Edit " + tiddler.title return template.generate(tiddler=tiddler, message=message)
def _render_template(environ, start_response, name, status='200 OK', headers={}, **data): template = get_template(environ, name) if not 'Content-Type' in headers: # XXX: case-sensitivity conflicts? headers['Content-Type'] = 'text/html; charset=UTF-8' start_response(status, headers.items()) return template.generate(**data)
def send_template(environ, template_name, template_data=None): if template_data == None: template_data = {} template = get_template(environ, template_name) server_prefix = environ['tiddlyweb.config']['server_prefix'] user = get_user_object(environ) template_defaults = { #'message': 'test me you are a message', 'version': VERSION, 'user': user, 'member_role': 'MEMBER', 'title': 'TiddlyHoster', 'userpage': { 'link': '%s/home' % server_prefix, 'title': 'homepage', }, 'login': { 'link': '%s/challenge' % server_prefix, 'title': 'Login', }, 'help': { 'link': '%s/help' % server_prefix, 'title': 'Help', }, 'register': { 'link': '%s/register' % server_prefix, 'title': 'Register', }, 'server_prefix': server_prefix, 'main_css': environ['tiddlyweb.config'].get( 'hoster.main_css', 'main.css'), } template_defaults.update(template_data) return template.generate(template_defaults)
def view_auth(environ, start_response): """ Get a list of extant keys with an interface to revoke and to create more. """ config = environ['tiddlyweb.config'] store = environ['tiddlyweb.store'] usersign = environ['tiddlyweb.usersign'] username = usersign['name'] bag_name = config.get('oauth.tokens_bag', 'oauth_tokens') our_tokens = [store.get(tiddler) for tiddler in filter_tiddlers(store.list_bag_tiddlers(Bag(bag_name)), 'select=modifier:%s' % username, environ)] template = get_template(environ, AUTH_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-cache')]) return template.generate({ 'socket_link': config.get('socket.link'), 'csrf_token': get_nonce(environ), 'gravatar': gravatar(environ), 'user': username, 'tokens': our_tokens, })
def _send_start(environ, start_response, message=''): target_role = environ['tiddlyweb.config'].get('register.role', 'MEMBER') template = get_template(environ, 'register.html') username = environ['tiddlyweb.usersign']['name'] roles = environ['tiddlyweb.usersign'].get('roles', []) return template.generate(message=message, target_role=target_role, username=username, roles=roles, challenge_url=_challenge_url(environ))
def _send_finish(environ, start_response): template = get_template(environ, "registered.html") username = environ["tiddlyweb.usersign"]["name"] start = { "href": environ["tiddlyweb.config"].get("register.start_href", "/"), "title": environ["tiddlyweb.config"].get("register.start_title", "Get Started"), } return template.generate(start=start, username=username, home=server_base_url(environ) + "/")
def _send_start(environ, start_response, message=""): target_role = environ["tiddlyweb.config"].get("register.role", "MEMBER") template = get_template(environ, "register.html") username = environ["tiddlyweb.usersign"]["name"] roles = environ["tiddlyweb.usersign"].get("roles", []) return template.generate( message=message, target_role=target_role, username=username, roles=roles, challenge_url=_challenge_url(environ) )
def provider_auth(environ, start_response): """ Authorize endpoint on the provider. If the right information is provided and validates against stored info, and the user says it is okay, return a code back to the redirect_uri, which must begin with the stored callback_url. That code is stored to be compared later, when the consumer sends it requesting an access_token. XXX: Missing scope handling. """ query = environ['tiddlyweb.query'] data = {} input_errors = False for key in ['redirect_uri', 'scope', 'response_type', 'client_id', 'access_type', 'state']: if key in query: data[key] = query[key][0] elif key in ['client_id', 'response_type', 'scope']: input_errors = True try: app = get_app(environ, data['client_id']) except (StoreError, KeyError): return provider_auth_error(data, error='unauthorized_client') if 'redirect_uri' not in data: data['redirect_uri'] = app.fields['callback_url'] # This comes after loading the app, as we might not have a # redirect uri if input_errors: provider_auth_error(data, error='invalid_request') if not data['redirect_uri'].startswith(app.fields['callback_url']): return provider_auth_error(data, error='invalid_request') # XXX check scope data['name'] = app.fields['name'] if already_authorized(environ, app): return provider_auth_success(environ, data) if environ['REQUEST_METHOD'] == 'GET': template = get_template(environ, 'provider_auth.html') start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8')]) return template.generate(data=data) else: if 'accept' in query: save_provider_auth(environ, data) return provider_auth_success(environ, data) else: return provider_auth_error(data, error='access_denied')
def _do_login_or_register(environ, start_response, server_name, response_map, content): """ We had a valid response from the oauth provider, let's see if that is a user or somebody we can register. """ store = environ['tiddlyweb.store'] config = environ['tiddlyweb.config'] userinfo = simplejson.loads(content) userdata = {} for key, value in response_map.iteritems(): userdata[key] = userinfo.get(value, '') server_login = None username = userdata['login'] if not username: raise HTTP400('extractable username data required') userdata['server_name'] = server_name if config.get('oauth.use_mapuser', False): server_login = '******' % (server_name, username) map_bag_name = config.get('magicuser.map', 'MAPUSER') tiddler = Tiddler(server_login, map_bag_name) try: tiddler = store.get(tiddler) mapped_user = tiddler.fields.get('mapped_user') store.get(User(mapped_user)) user = User(server_login) return _send_cookie(environ, start_response, user) except StoreError: try: local_user = store.get(User(username)) except StoreError: local_user = None pass # fall through to register else: try: user = store.get(User(username)) return _send_cookie(environ, start_response, user) except StoreError: local_user = None pass # fall through to register registration_template = get_template(environ, 'registration.html') start_response('200 OK', [('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-store')]) if local_user: userdata['local_user'] = local_user.usersign userdata['server_name_sig'] = _sign(config, server_name) if server_login: userdata['server_login'] = server_login userdata['server_login_sig'] = _sign(config, server_login) return registration_template.generate(userdata)
def send_template(environ, template_name, template_data=None): if template_data == None: template_data = {} template = get_template(environ, template_name) template_defaults = { 'title': '', } template_defaults.update(template_data) return template.generate(template_defaults)
def _send_finish(environ, start_response): template = get_template(environ, 'registered.html') username = environ['tiddlyweb.usersign']['name'] start = { 'href': environ['tiddlyweb.config'].get('register.start_href', '/'), 'title': environ['tiddlyweb.config'].get('register.start_title', 'Get Started'), } return template.generate(start=start, username=username, home=server_base_url(environ) + '/')
def _send_template(environ, template_name, template_data=None): if template_data == None: template_data = {} template = get_template(environ, template_name) server_prefix = environ['tiddlyweb.config']['server_prefix'] template_defaults = { 'user': environ['tiddlyweb.usersign'], 'server_prefix': server_prefix, } template_defaults.update(template_data) return template.generate(template_defaults)
def policymgr(environ, start_response): config = environ['tiddlyweb.config'] usersign = environ['tiddlyweb.usersign'] template = get_template(environ, POLICYMGR_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8')]) return template.generate({ 'socket_link': config.get('socket.link'), 'gravatar': gravatar(environ), 'user': usersign['name'], })
def _show_chooser(environ, tmp_bag, fixed_bag): # refresh the bag object store = environ['tiddlyweb.store'] tmp_bag.skinny = True tmp_bag = store.get(tmp_bag) tiddlers = filter_tiddlers(store.list_bag_tiddlers(tmp_bag), 'sort=title') template = get_template(environ, 'chooser.html') return template.generate(tiddlers=tiddlers, tmp_bag=tmp_bag.name, fixed_bag=fixed_bag, bags=_get_bags(environ))
def render(b, content=None, template=None, **kwargs): """ Return iterated content or template, or both. """ if content is None: content = [] if template is not None: template_object = get_template(b.env, template) template_generator = template_object.generate(kwargs) else: template_generator = [] return chain(content, template_generator)
def challenge_get(self, environ, start_response): """ Respond to a ``GET`` with a link. """ try: redirect = environ['tiddlyweb.query']['tiddlyweb_redirect'][0] except KeyError: redirect = None template = get_template(environ, 'challenger.html') start_response('200 OK', [('Content-Type', 'text/html; charset=UTF-8')]) return template.generate({'redirect': redirect})
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ if template_data == None: template_data = {} template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': ['/bags/common/tiddlers/profile.css'], 'HtmlJavascript': [] } # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe( recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: urls = tiddler.text.strip().rstrip().split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def hello(environ, start_response): store = environ['tiddlyweb.store'] username = environ['tiddlyweb.usersign']['name'] template = get_template(environ, 'hello.html') tiddlers = store.list_bag_tiddlers(Bag('system')) bags = [store.get(bag) for bag in store.list_bags()] start_response('200 OK', [ ('Content-Type', 'text/html')]) return template.render({'username': username, 'tiddlers': tiddlers, 'bags': bags, })
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ if template_data == None: template_data = {} template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': ['/bags/common/tiddlers/profile.css'], 'HtmlJavascript': []} # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: urls = tiddler.text.strip().rstrip().split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def hello(environ, start_response): store = environ['tiddlyweb.store'] username = environ['tiddlyweb.usersign']['name'] template = get_template(environ, 'hello.html') tiddlers = store.list_bag_tiddlers(Bag('system')) bags = [store.get(bag) for bag in store.list_bags()] start_response('200 OK', [('Content-Type', 'text/html')]) return template.render({ 'username': username, 'tiddlers': tiddlers, 'bags': bags, })
def editor(environ, start_response, extant_tiddler=None, message=''): store = environ['tiddlyweb.store'] usersign = environ['tiddlyweb.usersign'] query = environ['tiddlyweb.query'] config = environ['tiddlyweb.config'] if extant_tiddler: tiddler = extant_tiddler else: bag_name = query['bag'][0] tiddler_title = query['tiddler'][0] if not (bag_name and tiddler_title): raise HTTP400('bad query: bag and tiddler required') bag = Bag(bag_name) try: bag = store.get(bag) except NoBagError: raise HTTP404('that tank does not exist') tiddler = Tiddler(tiddler_title, bag_name) tiddler_new = False try: tiddler = store.get(tiddler) except NoTiddlerError: tiddler.text = '' tiddler.type = 'text/x-markdown' tiddler_new = True if tiddler_new: bag.policy.allows(usersign, 'create') else: bag.policy.allows(usersign, 'write') edit_template = get_template(environ, EDIT_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-cache')]) return edit_template.generate({ 'socket_link': config.get('socket.link'), 'csrf_token': get_nonce(environ), 'gravatar': gravatar(environ), 'message': message, 'user': usersign['name'], 'tiddler': tiddler, 'etag': tiddler_etag(environ, tiddler).replace('"', '').split(':', 1)[0] })
def page(environ, start_response): """ Display a page created from the tiddler named in the URL. If the tiddler title is in SPECIAL_PAGES, run the special page handling code. Otherwise, render the tiddler to html and provide it to the page.html template. """ tiddler = _determine_tiddler(environ) if tiddler.title in SPECIAL_PAGES: return SPECIAL_PAGES[tiddler.title](tiddler, environ) template = get_template(environ, "page.html") environ["tiddlyweb.title"] = tiddler.title return template.generate(html=render_wikitext(tiddler, environ), tiddler=tiddler)
def home(environ, start_response): """ Display a starting page. """ username = environ['tiddlyweb.usersign']['name'] config = environ['tiddlyweb.config'] frontpage_template = get_template(environ, FRONTPAGE_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-cache')]) return frontpage_template.generate({ 'user': username, 'socket_link': config.get('socket.link'), })
def _all_info(self, out_method, in_method=None): method_info = self._method_info() out_serialization_info = self._serialization_info(out_method) if in_method and 'PUT' in method_info['method']: in_serialization_info = self._serialization_info(in_method) else: in_serialization_info = {} # Disable HTMLPresenter if it is in the stack. if 'tiddlyweb.title' in self.environ: del self.environ['tiddlyweb.title'] template = get_template(self.environ, 'tiddlywebdocs.html') return template.generate({'outserialization': out_serialization_info, 'inserialization': in_serialization_info, 'method': method_info})
def dash(environ, start_response, message=None): """ Display info for the current user. """ usersign = environ['tiddlyweb.usersign'] username = usersign['name'] store = environ['tiddlyweb.store'] config = environ['tiddlyweb.config'] def load_and_test_entity(entity): try: entity = store.get(entity) except StoreError: return False return entity.policy.owner == username and not entity.name.startswith('_') def augment_bag(bag): bag = store.get(bag) policy_type = determine_tank_type(bag, username) bag.icon = POLICY_ICONS[policy_type] bag.type = policy_type return bag kept_bags = (augment_bag(bag) for bag in store.list_bags() if load_and_test_entity(bag)) comp_bags = get_comp_bags(store, config, usersign) comps = (recipe for recipe in store.list_recipes() if load_and_test_entity(recipe)) dash_template = get_template(environ, DASH_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-cache')]) return dash_template.generate({ 'socket_link': config.get('socket.link'), 'gravatar': gravatar(environ), 'user': username, 'bags': kept_bags, 'message': message, 'comp_bags': comp_bags, 'comps': comps, 'csrf_token': get_nonce(environ) })
def recent_changes(tiddler, environ): """ Display recent changes for the wiki. RecentChanges is handled as a SPECIAL_PAGES, described below. Recent changes are simply the 30 most recently modified tiddlers from the recipe. We make a list of those tiddlers and provide them to the changes.html template. """ # XXX to be strict we should do permissions checking # on the bags of all the tiddlers returned. store = environ["tiddlyweb.store"] recipe = _get_recipe(environ) recipe = store.get(Recipe(recipe)) tiddlers = Tiddlers() for tiddler in control.get_tiddlers_from_recipe(recipe, environ): tiddlers.add(tiddler) tiddlers = control.filter_tiddlers(tiddlers, "sort=-modified;limit=30") template = get_template(environ, "changes.html") environ["tiddlyweb.title"] = "Recent Changes" return template.generate(tiddlers=(store.get(tiddler) for tiddler in tiddlers))
def list_tiddlers(self, tiddlers): if not tiddlers.is_search: return HTMLSerialization.list_tiddlers(self, tiddlers) config = self.environ['tiddlyweb.config'] search_query = self.environ['tiddlyweb.query'].get('q', [''])[0] tiddlers.link = '/search?%s' % self.environ.get('QUERY_STRING', '') if 'bag:' in search_query and ( 'OR' not in search_query and 'AND' not in search_query): global_query = globalize_query(search_query) else: global_query = '' search_template = get_template(self.environ, SEARCH_TEMPLATE) return search_template.generate({ 'socket_link': config.get('socket.link'), 'gravatar': gravatar(self.environ), 'user': self.environ['tiddlyweb.usersign']['name'], 'tiddlers': tiddlers, 'global_query': global_query, 'csrf_token': get_nonce(self.environ), })
def _init(self): self.template = get_template(self.environ, 's5.html')
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ default_css_tiddler = '/bags/common/tiddlers/profile.css' if template_data is None: template_data = {} html_template_prefix = environ['tiddlyweb.space_settings']['htmltemplate'] if html_template_prefix: default_css_tiddler = ('/bags/common/tiddlers/%s.css' % html_template_prefix) html_template_prefix += '/' try: name = html_template_prefix + template_name template = get_template(environ, name) except TemplateNotFound: template = get_template(environ, template_name) else: template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = {'HtmlCss': [], 'HtmlJavascript': []} if not html_template_prefix or template_name in CUSTOMIZABLES: linked_resources['HtmlCss'] = [default_css_tiddler] # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe( recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: url_content = tiddler.text.strip() if url_content: urls = url_content.split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def _send_wimport(environ, start_response, message=''): query = environ["tiddlyweb.query"] bag = query.get("bag", [None])[0] template = get_template(environ, 'wimport.html') return template.generate(bag=bag, message=message)
def manifestos(environ, start_response): store = environ['tiddlyweb.store'] recipes = store.list_recipes() template = get_template(environ, 'list.html') return template.generate(recipes=recipes)
def wiki_page(environ, start_response): """ Present a single tiddler from a given tank. """ tank_name = get_route_value(environ, 'bag_name') store = environ['tiddlyweb.store'] usersign = environ['tiddlyweb.usersign'] config = environ['tiddlyweb.config'] try: bag = store.get(Bag(tank_name)) except NoBagError: raise HTTP404('no tank found for %s' % tank_name) try: tiddler_name = get_route_value(environ, 'tiddler_name') except (KeyError, AttributeError): raise HTTP302(tank_page_uri(environ, tank_name, 'index')) if tiddler_name in SPECIAL_PAGES: return SPECIAL_PAGES[tiddler_name](environ, start_response) # let permissions problems raise bag.policy.allows(usersign, 'read') editable = True creatable = True deletable = True try: bag.policy.allows(usersign, 'write') except PermissionsError: editable = False try: bag.policy.allows(usersign, 'create') except PermissionsError: creatable = False try: bag.policy.allows(usersign, 'delete') except PermissionsError: deletable = False try: tiddler = Tiddler(tiddler_name, tank_name) tiddler = store.get(tiddler) except NoTiddlerError: tiddler.type = 'text/x-markdown' tiddler.text = '### This tiddler does not yet exist\n' if creatable: editable = True deletable = False if renderable(tiddler, environ): backlinks = get_backlinks(environ, tiddler) compable = full_search(config, 'id:"%s:app"' % tank_name) html = render_wikitext(tiddler, environ) wiki_template = get_template(environ, WIKI_TEMPLATE) start_response('200 OK', [ ('Content-Type', 'text/html; charset=UTF-8'), ('Cache-Control', 'no-cache')]) return wiki_template.generate({ 'socket_link': config.get('socket.link'), 'csrf_token': get_nonce(environ), 'gravatar': gravatar(environ), 'user': usersign['name'], 'tiddler': tiddler, 'html': html, 'bag': bag, 'backlinks': backlinks, 'edit': editable, 'delete': deletable, 'compable': compable, }) else: return tiddler_get(environ, start_response)