def db_view_from_dirname(dirname): instance = 'instance' upstream = 'master' root = create_tmpdir('root') repo_git = {} repo_local = {'local': dirname} hi = HostInstance(instance, upstream, root, repo_git, repo_local) db_view = hi.db_view db_view.set_root() return db_view
def __init__(self, options, settings): self.options = options self.settings = settings # display options for k in sorted(self.options._values): v = self.options._values[k] logger.debug('option %20s = %r ' % (k, v)) # display settings for k in sorted(self.settings): v = self.settings[k] logger.debug('setting %20s = %r ' % (k, v)) WebApp.singleton = self dirname = options.libraries if dirname is None: package = dir_from_package_name('mcdp_data') default_libraries = os.path.join(package, 'libraries') msg = ( 'Option "-d" not passed, so I will open the default libraries ' 'shipped with PyMCDP. These might not be writable depending on your setup.' ) logger.info(msg) dirname = default_libraries self.dirname = dirname AppVisualization.__init__(self) AppQR.__init__(self) AppSolver.__init__(self) AppInteractive.__init__(self) AppSolver2.__init__(self) AppEditorFancyGeneric.__init__(self) WebAppImages.__init__(self) # name -> dict(desc: ) self.views = {} self.exceptions = [] self.add_model_view('syntax', 'Source code display') self.add_model_view('edit_fancy', 'Editor') # self.add_model_view('edit', 'Simple editor for IE') self.add_model_view('solver2', desc='Solver interface') self.add_model_view('ndp_graph', 'NDP Graph representation') self.add_model_view('ndp_repr', 'NDP Text representation') self.add_model_view('dp_graph', 'DP graph representation') self.add_model_view('dp_tree', 'DP tree representation') self.add_model_view('images', 'Other image representations') self.add_model_view('solver', 'Graphical solver [experimental]') # csfr_token -> Session self.sessions = OrderedDict() config_repos = yaml_load(self.options.repos_yaml) logger.info('Config:\n' + indent(self.options.repos_yaml, '>')) logger.info(config_repos) instance = self.options.instance #root= 'out/root' root = create_tmpdir('HostInstance_root') logger.debug('Tmp dir: %s' % root) if not 'local' in config_repos: config_repos['local'] = {} if not 'remote' in config_repos: config_repos['remote'] = {} # add the bundled repository bundled_repo_dir = os.path.join(dir_from_package_name('mcdp_data'), 'bundled.mcdp_repo') config_repos['local']['bundled'] = bundled_repo_dir self.hi = HostInstance(instance=instance, upstream='master', root=root, repo_git=config_repos['remote'], repo_local=config_repos['local']) if self.options.allow_anonymous_write: logger.warning( 'Note: because allow_anonymous_write anonymous users can admin the repos.' ) self.hi.set_local_permission_mode() from pyramid.security import Allow, Everyone, ALL_PERMISSIONS MCDPResourceRoot.__acl__.append((Allow, Everyone, ALL_PERMISSIONS))
class WebApp(AppVisualization, AppStatus, AppQR, AppSolver, AppInteractive, AppSolver2, AppEditorFancyGeneric, WebAppImages, AppLogin, AppSearch): singleton = None def __init__(self, options, settings): self.options = options self.settings = settings # display options for k in sorted(self.options._values): v = self.options._values[k] logger.debug('option %20s = %r ' % (k, v)) # display settings for k in sorted(self.settings): v = self.settings[k] logger.debug('setting %20s = %r ' % (k, v)) WebApp.singleton = self dirname = options.libraries if dirname is None: package = dir_from_package_name('mcdp_data') default_libraries = os.path.join(package, 'libraries') msg = ( 'Option "-d" not passed, so I will open the default libraries ' 'shipped with PyMCDP. These might not be writable depending on your setup.' ) logger.info(msg) dirname = default_libraries self.dirname = dirname AppVisualization.__init__(self) AppQR.__init__(self) AppSolver.__init__(self) AppInteractive.__init__(self) AppSolver2.__init__(self) AppEditorFancyGeneric.__init__(self) WebAppImages.__init__(self) # name -> dict(desc: ) self.views = {} self.exceptions = [] self.add_model_view('syntax', 'Source code display') self.add_model_view('edit_fancy', 'Editor') # self.add_model_view('edit', 'Simple editor for IE') self.add_model_view('solver2', desc='Solver interface') self.add_model_view('ndp_graph', 'NDP Graph representation') self.add_model_view('ndp_repr', 'NDP Text representation') self.add_model_view('dp_graph', 'DP graph representation') self.add_model_view('dp_tree', 'DP tree representation') self.add_model_view('images', 'Other image representations') self.add_model_view('solver', 'Graphical solver [experimental]') # csfr_token -> Session self.sessions = OrderedDict() config_repos = yaml_load(self.options.repos_yaml) logger.info('Config:\n' + indent(self.options.repos_yaml, '>')) logger.info(config_repos) instance = self.options.instance #root= 'out/root' root = create_tmpdir('HostInstance_root') logger.debug('Tmp dir: %s' % root) if not 'local' in config_repos: config_repos['local'] = {} if not 'remote' in config_repos: config_repos['remote'] = {} # add the bundled repository bundled_repo_dir = os.path.join(dir_from_package_name('mcdp_data'), 'bundled.mcdp_repo') config_repos['local']['bundled'] = bundled_repo_dir self.hi = HostInstance(instance=instance, upstream='master', root=root, repo_git=config_repos['remote'], repo_local=config_repos['local']) if self.options.allow_anonymous_write: logger.warning( 'Note: because allow_anonymous_write anonymous users can admin the repos.' ) self.hi.set_local_permission_mode() from pyramid.security import Allow, Everyone, ALL_PERMISSIONS MCDPResourceRoot.__acl__.append((Allow, Everyone, ALL_PERMISSIONS)) def add_model_view(self, name, desc): self.views[name] = dict(desc=desc, order=len(self.views)) def get_session(self, request): token = request.session.get_csrf_token() if not token in self.sessions: # print('creating new session for token %r' % token) self.sessions[token] = Session(app=self, request=request) session = self.sessions[token] session.set_last_request(request) return session def _get_views(self): return sorted(self.views, key=lambda _: self.views[_]['order']) @add_std_vars_context @cr2e def view_dummy(self, e): # @UnusedVariable return {} @add_std_vars_context_no_redir @cr2e def view_resource_not_found(self, e): e.request.response.status = 404 return {} @add_std_vars_context_no_redir @cr2e def view_resource_forbidden(self, e): e.request.response.status = 403 return {} @add_std_vars_context @cr2e def view_index(self, e): return { 'changes': self._get_changes(e), } @add_std_vars_context @cr2e def view_tree(self, e): root = MCDPResourceRoot(e.request) def get_pages(node, prefix): logger.info('get_pages(%s, %s)' % (node, prefix)) for child in node: yield "/".join(prefix + (child, )) c = node[child] if c is None: msg = 'Found invalid child %r of %r' % (child, prefix) raise ValueError(msg) for _ in get_pages(c, prefix + (child, )): yield _ pages = list(get_pages(node=root, prefix=())) pages = [(_, len(_.split('/'))) for _ in pages] return {'pages': pages} @add_std_vars_context @cr2e def view_shelf(self, e): desc_long_md = e.shelf.get_desc_long() if desc_long_md is None: desc_long = '' else: library = MCDPLibrary() desc_long = render_complete(library, desc_long_md, raise_errors=True, realpath=e.shelf_name, do_math=False) res = { 'shelf': e.shelf, 'sname': e.shelf_name, 'desc_long': unicode(desc_long, 'utf8'), } return res @add_std_vars_context @cr2e def view_shelves_subscribe(self, e): ui = e.user_struct.info if not e.shelf_name in ui.subscriptions: ui.subscriptions.append(e.shelf_name) e.session.recompute_available() raise HTTPFound(e.request.referrer) @cr2e def view_shelf_library_new(self, e): new_library_name = e.context.name # TODO: check good name url_edit = get_url_library(e, e.shelf_name, new_library_name) if new_library_name in e.shelf.libraries: error = 'The library "%s" already exists.' % new_library_name res = { 'error': error, 'library_name': new_library_name, 'url_edit': url_edit, } add_other_fields(self, res, e.request, context=e.context) template = 'error_library_exists.jinja2' e.request.response.status = 409 # Conflict return render_to_response(template, res, request=e.request, response=e.request.response) else: # The library does not exist: we create it empty = DB.library.generate_empty() e.shelf.libraries[new_library_name] = empty raise HTTPFound(url_edit) @cr2e def view_shelves_unsubscribe(self, e): ui = e.user_struct.info sname = e.context.name if sname in ui.subscriptions: ui.subscriptions.remove(sname) e.session.recompute_available() raise HTTPFound(e.request.referrer) def refresh_library(self, e): # nuclear option e.session.refresh_libraries() @cr2e def view_refresh_library(self, e): # @UnusedVariable """ Refreshes the current library (if external files have changed) then reloads the current url. """ # self._refresh_library(request) # Note this currently is equivalent to global refresh return self.view_refresh(e.context, e.request) @cr2e def view_refresh(self, e): """ Refreshes all """ self.refresh_library(e) if e.request.referrer is None: redirect = self.get_root_relative_to_here(e.request) logger.info('REFRESH') logger.info('context.url = %s' % e.request.url) logger.info('redirect = %s' % redirect) else: redirect = e.request.referrer raise HTTPFound(redirect) @cr2e def view_not_found(self, e): e.request.response.status = 404 url = e.request.url referrer = e.request.referrer #print('context: %s' % e.context) self.exceptions.append('Path not found.\n url: %s\n referrer: %s' % (url, referrer)) res = { 'url': url, 'referrer': referrer, 'root': e.root, 'static': e.root + '/static', } return res @add_std_vars_context @cr2e def view_exceptions_occurred(self, e): # @UnusedVariable exceptions = [] for e in self.exceptions: u = unicode(e, 'utf-8') exceptions.append(u) return {'exceptions': exceptions} @cr2e def view_exceptions_occurred_json(self, e): # @UnusedVariable exceptions = [] for e in self.exceptions: u = unicode(e, 'utf-8') exceptions.append(u) return {'exceptions': exceptions} def view_exception(self, exc, request): request.response.status = 500 # Internal Server Error if hasattr(request, 'context'): if isinstance(request.context, Resource): logger.debug(context_display_in_detail(request.context)) compact = (DPSemanticError, DPSyntaxError) if isinstance(exc, compact): s = exc.__str__() else: s = traceback.format_exc(exc) self.note_exception(exc, request=request) u = unicode(s, 'utf-8') logger.error(u.encode('utf8')) root = self.get_root_relative_to_here(request) res = { 'exception': u, # 'url_refresh': url_refresh, 'root': root, 'static': root + '/static' } return res def note_exception(self, exc, request=None, context=None): check_isinstance(exc, BaseException) n = '' if request is not None: url = request.url referrer = request.referrer n += 'Error during serving this URL:' n += '\n url: %s' % url n += '\n referrer: %s' % referrer if context is not None: n += '\n\n' + context_display_in_detail(context) + '\n' ss = traceback.format_exc(exc) n += '\n' + indent(ss, '| ') self.exceptions.append(n) def png_error_catch2(self, request, func): """ func is supposed to return an image response. If it raises an exception, we create an image with the error and then we add the exception to the list of exceptions. """ try: return func() except Exception as e: s = traceback.format_exc(e) try: logger.error(s) except UnicodeEncodeError: pass self.note_exception(e, request=request) return response_image(request, s) # This is where we keep all the URLS def make_relative(self, request, url): if not url.startswith('/'): msg = 'Expected url to start with /: %r' % url raise ValueError(msg) root = self.get_root_relative_to_here(request) comb = root + url return comb def get_root_relative_to_here(self, request): if request is None: raise ValueError() parsed = urlparse.urlparse(request.url) path = parsed.path if not path.endswith('/'): last = path.rfind('/') path = path[:last] if path == '': return '/' r = os.path.relpath('/', path) return r @add_std_vars_context_no_redir @cr2e def view_library_asset_not_found(self, e): e.request.response.status = 404 return {} @add_std_vars_context_no_redir @cr2e def view_library_doc_not_found(self, e): e.request.response.status = 404 return {} @add_std_vars_context_no_redir @cr2e def view_library_doc(self, e): """ '/libraries/{library}/{document}.html' """ # f['data'] not utf-8 # reopen as utf-8 document = e.context.name # filename = '%s.%s' % (document, MCDPConstants.ext_doc_md) # if not e.library.file_exists(filename): # res = {} # add_other_fields(self, res, e.request, context=e.context) # response = e.request.response # response.status = 404 # not found # template = 'library_doc_not_found.jinja2' # return render_to_response(template, res, request=e.request, # response=response) try: html = self._render_library_doc(e, document) except DPSyntaxError as exc: res = {} res['error'] = exc res['title'] = document return res # we work with utf-8 strings assert isinstance(html, str) # but we need to convert to unicode later html = unicode(html, 'utf-8') res = {} res['contents'] = html res['title'] = document res['print'] = bool(e.request.params.get('print', False)) return res @contract(e=Environment, document=str) def _render_library_doc(self, e, document): strict = int(e.request.params.get('strict', '0')) # filename = '%s.%s' % (document, MCDPConstants.ext_doc_md) # data_str = e.library.documents[document] realpath = 'Document "%s"' % document # f = e.library._get_file_data(filename) # realpath = f['realpath'] # read unicode # import codecs # data_unicode = codecs.open(realpath, encoding='utf-8').read() # data_str = data_unicode.encode('utf-8') raise_errors = bool(strict) library = library_from_env(e) html = render_complete(library=library, s=data_str, realpath=realpath, raise_errors=raise_errors) return html @cr2e def view_library_asset(self, e): name = e.context.name asset = os.path.splitext(name)[0] ext = os.path.splitext(name)[1][1:] filename = '%s.%s' % (asset, ext) try: f = e.library._get_file_data(filename) except DPSemanticError as exc: res = { 'error': exc, } add_other_fields(self, res, e.request, context=e.context) response = e.request.response response.status = 404 # not found template = 'asset_not_found.jinja2' return render_to_response(template, res, request=e.request, response=response) data = f['data'] content_type = get_mime_for_format(ext) return response_data(e.request, data, content_type) @cr2e def exit(self, e): # @UnusedVariable sys.exit(0) setattr(self.server, '_BaseServer__shutdown_request', True) howlong = duration_compact(self.get_uptime_s()) return "Bye. Uptime: %s." % howlong def get_uptime_s(self): return time.time() - self.time_start def serve(self, port): app = self.get_app() self.server = make_server('0.0.0.0', port, app) self.server.serve_forever() def get_app(self): self.time_start = time.time() secret = 'itsasecreet' # XXX self.my_session_factory = SignedCookieSessionFactory(secret + 'sign') self.root_factory = MCDPResourceRoot config = Configurator(root_factory=self.root_factory, settings=self.settings) config.set_session_factory(self.my_session_factory) # config.include('pyramid_debugtoolbar') authn_policy = AuthTktAuthenticationPolicy(secret + 'authn', hashalg='sha512', callback=groupfinder) authz_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) config.set_default_permission(Privileges.ACCESS) config.add_renderer('jsonp', JSONP(param_name='callback')) config.add_static_view(name='static', path='static', cache_max_age=3600) config.include('pyramid_jinja2') AppStatus.config(self, config) AppVisualization.config(self, config) AppQR.config(self, config) AppSolver.config(self, config) AppInteractive.config(self, config) AppEditorFancyGeneric.config(self, config) WebAppImages.config(self, config) AppLogin.config(self, config) AppSolver2.config(self, config) config.add_view(self.view_dummy, context=ResourceAbout, renderer='about.jinja2') config.add_view(self.view_index, context=MCDPResourceRoot, renderer='index.jinja2') config.add_view(self.view_dummy, context=ResourceLibraries, renderer='list_libraries.jinja2') config.add_view(self.view_dummy, context=ResourceRepos, renderer='repos.jinja2') config.add_view(self.view_dummy, context=ResourceLibraryInteractive, renderer='empty.jinja2') config.add_view(self.view_dummy, context=ResourceLibrary, renderer='library_index.jinja2', permission=Privileges.READ) config.add_view(self.view_dummy, context=ResourceThings, renderer='library_index.jinja2', permission=Privileges.READ) # same as above config.add_view(self.view_dummy, context=ResourceRepo, renderer='shelves_index.jinja2') config.add_view(self.view_dummy, context=ResourceShelves, renderer='shelves_index.jinja2') # same as above config.add_view(self.view_dummy, context=ResourceAllShelves, renderer='shelves_index.jinja2') # same as above config.add_view(self.view_changes, context=ResourceChanges, renderer='changes.jinja2') config.add_view(self.view_tree, context=ResourceTree, renderer='tree.jinja2') config.add_view(self.view_not_found_generic, context=ResourceNotFoundGeneric, renderer='not_found_generic.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_shelf_library_new, context=ResourceLibrariesNewLibname, permission=Privileges.WRITE) config.add_view(self.view_shelf, context=ResourceShelf, renderer='shelf.jinja2', permission=Privileges.DISCOVER) config.add_view(self.view_shelves_subscribe, context=ResourceShelvesShelfSubscribe, permission=Privileges.SUBSCRIBE) config.add_view(self.view_shelves_unsubscribe, context=ResourceShelvesShelfUnsubscribe, permission=Privileges.SUBSCRIBE) config.add_view(self.view_library_doc, context=ResourceLibraryDocRender, renderer='library_doc.jinja2', permission=Privileges.READ) config.add_view(self.view_library_doc_not_found, context=ResourceLibraryDocNotFound, renderer='library_doc_not_found.jinja2', permission=Privileges.READ) config.add_view(self.view_library_asset_not_found, context=ResourceLibraryAssetNotFound, renderer='asset_not_found.jinja2', permission=Privileges.READ) config.add_view(self.view_library_asset, context=ResourceLibraryAsset, permission=Privileges.READ) config.add_view(self.view_refresh_library, context=ResourceLibraryRefresh, permission=Privileges.READ) config.add_view(self.view_refresh, context=ResourceRefresh) config.add_view(self.view_users, context=ResourceListUsers, renderer='users.jinja2', permission=Privileges.VIEW_USER_LIST) config.add_view(self.view_users_user, context=ResourceListUsersUser, renderer='user_page.jinja2', permission=Privileges.VIEW_USER_PROFILE_PUBLIC) config.add_view(self.view_impersonate, context=ResourceUserImpersonate, permission=Privileges.IMPERSONATE_USER) config.add_view(self.view_exception, context=Exception, renderer='exception.jinja2') config.add_view(self.exit, context=ResourceExit, renderer='json', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_exceptions_occurred_json, context=ResourceExceptionsJSON, renderer='json', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_exceptions_occurred, context=ResourceExceptionsFormatted, renderer='exceptions_formatted.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_dummy, context=ResourceShelfNotFound, renderer='shelf_not_found.jinja2') config.add_view(self.view_dummy, context=ResourceShelfForbidden, renderer='shelf_forbidden.jinja2') config.add_view(self.view_dummy, context=ResourceShelfInactive, renderer='shelf_inactive.jinja2') config.add_view(self.view_resource_not_found, context=ResourceRepoNotFound, renderer='repo_not_found.jinja2') config.add_view(self.view_thing_delete, context=ResourceThingDelete) config.add_view(self.view_thing_rename, context=ResourceThingRename) config.add_view(self.view_thing, context=ResourceThing) config.add_view(self.view_picture, context=ResourceUserPicture) config.add_view(self.view_search, http_cache=0, context=ResourceSearchPage, renderer='search.jinja2') config.add_view(self.view_search_query, http_cache=0, context=ResourceSearchPageQuery, renderer='json') config.add_view(self.view_confirm_bind, http_cache=0, context=ResourceConfirmBind, renderer='confirm_bind.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_confirm_bind_bind, http_cache=0, context=ResourceConfirmBindBind, renderer='confirm_bind_bind.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_confirm_creation_similar, http_cache=0, context=ResourceConfirmCreationSimilar, renderer='confirm_creation_similar.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_confirm_creation, http_cache=0, context=ResourceConfirmCreation, renderer='confirm_creation.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_confirm_creation_create, http_cache=0, context=ResourceConfirmCreationCreate, renderer='confirm_creation_create.jinja2', permission=NO_PERMISSION_REQUIRED) config.add_view(self.view_db_view, http_cache=0, context=ResourceDBView, renderer='db_view.jinja2') config.add_view(serve_robots, context=ResourceRobots, permission=NO_PERMISSION_REQUIRED) config.add_notfound_view(self.view_not_found, renderer='404.jinja2') config.scan() config.add_view(self.view_authomatic, context=ResourceAuthomaticProvider, permission=NO_PERMISSION_REQUIRED) self.get_authomatic_config() app = config.make_wsgi_app() return app def show_error(self, e, msg, status=500): ''' Redirects the user to an error page with the message specified. return self.show_error(e, 'invalid session') ''' res = { 'error': msg, } e.request.response.status = status add_other_fields(self, res, e.request, context=e.context) return render_to_response('generic_error.jinja2', res, request=e.request, response=e.request.response) def get_authomatic_config(self): return get_authomatic_config_(self) @cr2e def view_authomatic(self, e): config = self.get_authomatic_config() return view_authomatic_(self, config, e) @cr2e def view_impersonate(self, e): from mcdp_web.auhtomatic_auth import success_auth username = e.context.name next_location = '..' return success_auth(self, e.request, username, next_location) @add_std_vars_context @cr2e def view_confirm_bind(self, e): return view_confirm_bind_(self, e) @add_std_vars_context @cr2e def view_confirm_bind_bind(self, e): return view_confirm_bind_bind_(self, e) @add_std_vars_context @cr2e def view_confirm_creation_similar(self, e): return view_confirm_creation_similar_(self, e) @add_std_vars_context @cr2e def view_confirm_creation(self, e): return view_confirm_creation_(self, e) @add_std_vars_context @cr2e def view_confirm_creation_create(self, e): return view_confirm_creation_create_(self, e) @cr2e def view_picture(self, e): username = e.context.name _size = e.context.size # Not used so far data_format = e.context.data_format assert data_format == 'jpg' app = self user_db = app.hi.db_view.user_db u = user_db.users[username] picture_data = u.get_picture_jpg() if picture_data is None: mime = 'image/jpeg' data = get_nopicture_jpg() # url = e.root + '/static/nopicture.jpg' # raise HTTPFound(url) else: mime = get_mime_for_format(data_format) data = picture_data return response_data(request=e.request, data=data, content_type=mime) @add_std_vars_context @cr2e def view_db_view(self, e): root = self.get_root_relative_to_here(e.request) name_string = e.request.params.get('name', '').encode('utf8') if not name_string: # special case: empty string name_seq = () else: name_seq = tuple(name_string.split(',')) db_view = e.session.app.hi.db_view view = db_view.get_descendant(name_seq) schema = view._schema if isinstance(schema, SchemaContext): links = [] for k in schema.children: n2 = name_seq + (k, ) url = root + '/db_view/?name=%s' % ",".join(n2) links.append((k, url)) content = "" content += '<ul>' for k, url in links: content += '\n <li><a href="%s">%s</a></li>' % (url, k) content += '\n</ul>' error = None elif isinstance(schema, SchemaHash): data = view._data if not data: content = '(empty)' else: links = [] for k in sorted(data): n2 = name_seq + (k, ) url = root + '/db_view/?name=%s' % ",".join(n2) links.append((k, url)) content = "" content += '<ul>' for k, url in links: content += '\n <li><a href="%s">%s</a></li>' % (url, k) content += '\n</ul>' error = None else: error = 'Unimplemented for %s' % type(view) content = None res = {} res['name'] = name_seq res['content'] = content res['error'] = error return res @cr2e def view_thing(self, e): url = e.request.url if not url.endswith('/'): url += '/' url2 = url + 'views/syntax/' logger.debug('Redirect to ' + url2) raise HTTPFound(url2) def _get_changes(self, e): user_db = e.session.app.hi.db_view.user_db repos = e.session.app.hi.db_view.repos def shelf_privilege(repo_name, sname, privilege): repo = repos[repo_name] if not sname in repo.shelves: msg = 'Cannot find shelf "%s" in repo "%s".' % (sname, repo_name) msg += '\n available: ' + format_list(repo.shelves) raise ValueError(msg) acl = repo.shelves[sname].get_acl() return acl.allowed2(privilege, e.user) def shelf_subscribed(repo_name, shelf_name): # @UnusedVariable return shelf_name in e.user.subscriptions # XXX changes = [] for id_repo, repo in repos.items(): pass if False: # XXX need to implement changes for change in repo.get_changes(): if not shelf_privilege(id_repo, change['shelf_name'], Privileges.READ): continue change['repo_name'] = id_repo a = change['author'] if a in user_db: u = user_db[a] else: #logger.debug('Cannot find user %r' % a ) u = user_db.get_unknown_user_struct(a).info change['user'] = u p = '{root}/repos/{repo_name}/shelves/{shelf_name}/libraries/{library_name}/{spec_name}/{thing_name}/views/syntax/' subscribed = shelf_subscribed(id_repo, change['shelf_name']) if change['exists'] and subscribed: change['url'] = p.format(root=e.root, **change) else: change['url'] = None #print('change: %s url = %s' % (change, change['url'])) change['date_human'] = datetime.datetime.fromtimestamp( change['date']).strftime('%b %d, %H:%M') changes.append(change) return changes @add_std_vars_context @cr2e def view_changes(self, e): return { 'changes': self._get_changes(e), } @add_std_vars_context @cr2e def view_not_found_generic(self, e): e.request.response.status = 404 res = {'context_detail': context_display_in_detail(e.context)} return res @add_std_vars_context @cr2e def view_users(self, e): # @UnusedVariable return {} @add_std_vars_context @cr2e def view_users_user(self, e): # @UnusedVariable return {} @add_std_vars_context @cr2e def view_thing_delete(self, e): name = e.thing_name # basename = "%s.%s" % (name, e.spec.extension) logger.error('Deleting %s' % name) del e.things[name] # filename = e.library.delete_file(basename) # e.session.notify_deleted_file(e.shelf_name, e.library_name, filename) raise HTTPFound(e.request.referrer) @add_std_vars_context @cr2e def view_thing_rename(self, e): name = e.thing_name new_name = e.request.params.get('new_name', False).encode('utf8') logger.error('Renaming %r to %r' % (name, new_name)) e.things.rename(name, new_name) raise HTTPFound(e.request.referrer) def redirect_to_page(self, e, page): if self.options.url_base_public: url = self.options.url_base_public + page else: url = e.root + page logger.info('redirecting to page %s\nurl: %s' % (page, url)) raise HTTPFound(location=url)
def __init__(self, instance, upstream, root, repo_git, repo_local): self.hi = HostInstance(instance=instance, upstream=upstream, root=root, repo_git=repo_git, repo_local=repo_local)