def init_db(fname: str, path: str = None): if path: db_path = pathlib.Path(path) / fname else: db_path = pathlib.Path(fname) if db_path.exists(): db_path.unlink() db_url = f"sqlite:///{db_path}" session_factory = new_session_factory(url=db_url) db = session_factory() users = [ User(name="Alice", admin=True), User(name="Bob", admin=False), User(name="Charlie", admin=False), ] groups = [ Group(name="group1", users=[users[0], users[1]]), Group(name="group2", users=[users[0], users[2]]), Group(name="group3", users=[users[1], users[2]]), ] projects = [ Project(name="project1", groups=[groups[0], groups[1]]), Project(name="project2", groups=[groups[1], groups[2]]), ] items = users + groups + projects for item in items: db.add(item) db.commit() return db
def __init__(self, cdsconfig, db): self.spawn_allow_group = cdsconfig.spawn_allow_group self.spawn_block_group = cdsconfig.spawn_block_group self.spawn_allow_group_orm = None self.spawn_block_group_orm = None created_group = False if self.spawn_allow_group != '': group = Group.find(db, self.spawn_allow_group) if group is None: group = Group(name=self.spawn_allow_group) db.add(group) created_group = True self.spawn_allow_group_orm = group if self.spawn_block_group != '': group = Group.find(db, self.spawn_block_group) if group is None: group = Group(name=self.spawn_block_group) db.add(group) created_group = True self.spawn_block_group_orm = group if created_group: self.db.commit()
async def post(self, groupname): current_user = await self.get_current_user() if not current_user.admin: return self.send_error(403) group = Group.find(self.db, groupname) if group is None: return self.send_error(404) errors = DefaultObjDict() existing_group_users = group.users selected_users = self.get_arguments('selected_users[]') selected_users_orm = self.db.query(User).filter( User.name.in_(selected_users)).all() if self.sync_group(group, selected_users_orm): self.db.add(group) self.db.commit() self.redirect('{}hub/groupslist'.format(self.settings['base_url']))
async def get(self, groupname): current_user = await self.get_current_user() if not current_user.admin: return self.send_error(403) group = Group.find(self.db, groupname) if group is None: return self.send_error(404) errors = DefaultObjDict() existing_group_users = group.users all_users_tuples = self.get_visitor_tuples(None, existing_group_users) html = await self.render_template( "editgroup.html", base_url=self.settings['base_url'], group=group, errors=errors, all_users_tuples=all_users_tuples ) self.write(html)
async def post(self, dashboard_urlname=None): current_user = await self.get_current_user() if not self.can_user_spawn(current_user): return self.send_error(403) dashboard = None group = None if dashboard_urlname is not None: # Edit (not new) dashboard = Dashboard.find(db=self.db, urlname=dashboard_urlname, user=current_user) if dashboard is None: return self.send_error(404) if current_user.name != dashboard.user.name: return self.send_error(403) group = dashboard.group dashboard_name = self.get_argument('name').strip() dashboard_description = self.get_argument('description').strip() dashboard_presentation_type = self.get_argument( 'presentation_type').strip() dashboard_start_path = self.get_argument('start_path').strip() errors = DefaultObjDict() # Presentation basics if dashboard_name == '': errors.name = 'Please enter a name' elif not self.name_regex.match(dashboard_name): errors.name = 'Please use letters and digits (start with one of these), and then spaces or these characters _-!@$()*+?<>\'". Max 100 chars.' if '..' in dashboard_start_path: errors.start_path = 'Path must not contain ..' elif len(dashboard_start_path) and dashboard_start_path[0] == '/': errors.start_path = 'Path must be relative to Jupyter tree home or Git repo root (not starting with /)' elif not self.start_path_regex.match(dashboard_start_path): errors.start_path = 'Please enter valid URL path characters' cdsconfig = CDSConfigStore.get_instance(self.settings['config']) merged_presentation_types = cdsconfig.merged_presentation_types all_conda_envs = cdsconfig.conda_envs allow_custom_conda_env = cdsconfig.allow_custom_conda_env if not dashboard_presentation_type in merged_presentation_types: errors.presentation_type = 'Framework {} invalid - it must be one of the allowed types: {}'.format( dashboard_presentation_type, ', '.join(merged_presentation_types)) # Visitors allowed selected_users = self.get_arguments('selected_users[]') selected_users_orm = self.db.query(User).filter( User.name.in_(selected_users)).all() user_permissions = self.get_argument( 'user_permissions', cdsconfig.default_allow_all and 'anyusers' or 'selectedusers').strip() if user_permissions not in ('anyusers', 'selectedusers'): user_permissions = cdsconfig.default_allow_all and 'anyusers' or 'selectedusers' errors.user_permissions = 'You must choose either anyusers or selectedusers' # Dashboard options dashboard_options = {} git_repo = '' git_repo_branch = '' source_type = self.get_argument('source_type', '').strip() if cdsconfig.show_source_git and source_type == 'gitrepo': git_repo = self.get_argument('git_repo', '').strip() git_repo_branch = self.get_argument('git_repo_branch', '').strip() if git_repo != '': if not re.match( '^((git|ssh|http(s)?)|(git@[\w\.]+))(:(//)?)([\w\.@\:/\-~]+)(/)?$', git_repo): errors.git_repo = 'Please enter a valid git repo URL' else: source_type = 'jupytertree' conda_env = self.get_argument('conda_env', '').strip() if conda_env != '': if allow_custom_conda_env: if not self.conda_env_regex.match(conda_env): errors.conda_env = 'Please use letters and digits, spaces or these characters _-!@$()*+?<>/\\\'".' conda_env = '' elif conda_env not in all_conda_envs: errors.conda_env = 'Please select a valid Conda env (\'{}\' is not in the allowed list)'.format( conda_env) conda_env = '' dashboard_options['source_type'] = source_type dashboard_options['git_repo'] = git_repo dashboard_options['git_repo_branch'] = git_repo_branch dashboard_options['conda_env'] = conda_env spawners = [] spawner = None spawner_id = '' if cdsconfig.show_source_servers: spawners = self.get_source_spawners(current_user) spawner, spawner_id = self.read_spawner( dashboard, spawners, dashboard_options, errors, cdsconfig.require_source_server) if len(errors) == 0: db = self.db try: orm_spawner = None if spawner: orm_spawner = spawner.orm_spawner if dashboard is None: urlname = self.calc_urlname(dashboard_name) self.log.debug('Final urlname is ' + urlname) dashboard = Dashboard( name=dashboard_name, urlname=urlname, user=current_user.orm_user, description=dashboard_description, start_path=dashboard_start_path, presentation_type=dashboard_presentation_type, source_spawner=orm_spawner, options=dashboard_options, allow_all=user_permissions == 'anyusers') self.log.debug('dashboard urlname ' + dashboard.urlname + ', main name ' + dashboard.name) else: dashboard.name = dashboard_name dashboard.description = dashboard_description dashboard.start_path = dashboard_start_path dashboard.presentation_type = dashboard_presentation_type dashboard.source_spawner = orm_spawner dashboard.options = dashboard_options allow_all = user_permissions == 'anyusers' dashboard.allow_all = allow_all if group is None: group = Group.find(db, dashboard.groupname) if group is None: group = Group(name=dashboard.groupname) self.db.add(group) dashboard.group = group db.add(dashboard) if self.sync_group(group, selected_users_orm): db.add(group) db.commit() # Now cancel any existing build and force a rebuild builders_store = BuildersStore.get_instance( self.settings['config']) builder = builders_store[dashboard] dashboard_user = self._user_from_orm(dashboard.user.name) next_page = await self.maybe_start_build( dashboard, dashboard_user, True) # next_page can be progress/options/dashboard, but actually can't be anything because with force_start==True # it will have set things off async! except Exception as e: errors.all = str(e) if len(errors): git_repo = dashboard_options['git_repo'] = dashboard_options.get( 'git_repo', '') git_repo_branch = dashboard_options[ 'git_repo_branch'] = dashboard_options.get( 'git_repo_branch', '') conda_env = dashboard_options['conda_env'] = dashboard_options.get( 'conda_env', '') all_users_tuples = self.get_visitor_tuples(current_user.id, selected_users_orm) html = await self.render_template( "editdashboard.html", **self.template_vars( dict( dashboard=dashboard, dashboard_name=dashboard_name, dashboard_description=dashboard_description, dashboard_start_path=dashboard_start_path, dashboard_presentation_type=dashboard_presentation_type, dashboard_options=dashboard_options, user_permissions=user_permissions, git_repo=git_repo, git_repo_branch=git_repo_branch, source_type=source_type, conda_env=conda_env, presentation_types=merged_presentation_types, all_conda_envs=all_conda_envs, allow_custom_conda_env=allow_custom_conda_env, spawner_id=spawner_id, spawners=spawners, show_source_servers=cdsconfig.show_source_servers, show_source_git=cdsconfig.show_source_git, require_source_server=cdsconfig.require_source_server, all_users_tuples=all_users_tuples, errors=errors, current_user=current_user))) return self.write(html) self.redirect( url_path_join(self.settings['base_url'], "hub", "dashboards", dashboard.urlname))
async def post(self, dashboard_urlname=None): current_user = await self.get_current_user() dashboard = None group = None if dashboard_urlname is not None: # Edit (not new) dashboard = Dashboard.find(db=self.db, urlname=dashboard_urlname, user=current_user) if dashboard is None: return self.send_error(404) if current_user.name != dashboard.user.name: return self.send_error(403) group = dashboard.group dashboard_name = self.get_argument('name').strip() dashboard_description = self.get_argument('description').strip() dashboard_presentation_type = self.get_argument('presentation_type').strip() dashboard_start_path = self.get_argument('start_path').strip() errors = DefaultObjDict() if dashboard_name == '': errors.name = 'Please enter a name' elif not self.name_regex.match(dashboard_name): errors.name = 'Please use letters and digits (start with one of these), and then spaces or these characters _-!@$()*+?<>. Max 100 chars.' if '..' in dashboard_start_path: errors.start_path = 'Path must not contain ..' elif not self.start_path_regex.match(dashboard_start_path): errors.start_path = 'Please enter valid URL path characters' merged_presentation_types = CDSConfigStore.get_instance(self.settings['config']).merged_presentation_types if not dashboard_presentation_type in merged_presentation_types: errors.presentation_type = 'Framework {} invalid - it must be one of the allowed types: {}'.format( dashboard_presentation_type, ', '.join(merged_presentation_types) ) dashboard_options = self.read_options(dashboard, errors) spawners = self.get_source_spawners(current_user) spawner, spawner_name = self.read_spawner(dashboard, spawners, dashboard_options, errors) if len(errors) == 0: db = self.db try: orm_spawner = None if spawner: orm_spawner = spawner.orm_spawner if dashboard is None: urlname = self.calc_urlname(dashboard_name) self.log.debug('Final urlname is '+urlname) dashboard = Dashboard( name=dashboard_name, urlname=urlname, user=current_user.orm_user, description=dashboard_description, start_path=dashboard_start_path, presentation_type=dashboard_presentation_type, source_spawner=orm_spawner, options=dashboard_options ) self.log.debug('dashboard urlname '+dashboard.urlname+', main name '+dashboard.name) else: dashboard.name = dashboard_name dashboard.description = dashboard_description dashboard.start_path = dashboard_start_path dashboard.presentation_type = dashboard_presentation_type dashboard.source_spawner = orm_spawner dashboard.options = dashboard_options if group is None: group = Group.find(db, dashboard.groupname) if group is None: group = Group(name=dashboard.groupname) self.db.add(group) dashboard.group = group db.add(dashboard) db.commit() # Now cancel any existing build and force a rebuild # TODO delete existing final_spawner builders_store = BuildersStore.get_instance(self.settings['config']) builder = builders_store[dashboard] async def do_restart_build(_): await self.maybe_start_build(dashboard, current_user, True) self.log.debug('Force build start') if builder.pending and builder._build_future and not builder._build_future.done(): self.log.debug('Cancelling build') builder._build_future.add_done_callback(do_restart_build) builder._build_future.cancel() else: await do_restart_build(None) except Exception as e: errors.all = str(e) if len(errors): html = self.render_template( "editdashboard.html", **self.template_vars(dict( base_url=self.settings['base_url'], dashboard=dashboard, dashboard_name=dashboard_name, dashboard_description=dashboard_description, dashboard_start_path=dashboard_start_path, dashboard_presentation_type=dashboard_presentation_type, dashboard_options=dashboard_options, presentation_types=merged_presentation_types, spawner_name=spawner_name, spawners=spawners, errors=errors, current_user=current_user)) ) return self.write(html) self.redirect("{}hub/dashboards/{}".format(self.settings['base_url'], dashboard.urlname))