def remove_member(self, team_id, user_id): """Remove the given user as member of the given team. Raises error if the team is unknown or if the user is the team owner. No error is raised if the user is unknown or not a team member. Parameters ---------- team_id: string Unique team identifier user_id: string Unique user identifier Raises ------ benchengine.error.ConstraintViolationError benchengine.error.UnknownTeamError """ # Ensure that the team exists. Raises error if team does not exist. # If the user is the team owner the constraint that the owner has to be # a team member is violated. sql = 'SELECT owner_id FROM team WHERE id = ?' team = self.con.execute(sql, (team_id, )).fetchone() if team is None: raise err.UnknownTeamError(team_id) elif team['owner_id'] == user_id: raise err.ConstraintViolationError('cannot remove team owner') sql = 'DELETE FROM team_member WHERE team_id = ? AND user_id = ?' self.con.execute(sql, (team_id, user_id)) self.con.commit()
def insert_results(self, run_id, results): """Insert the results of a benchmark run into the results table. Expects a dictionary that contains result values for all mandatory results. Parameters ---------- run_id: string Unique run identifier results: dict Dictionary containing run result values Raises ------ benchengine.error.ConstraintViolationError """ columns = list(['run_id']) values = list([run_id]) for col in self.template.schema.columns: if col.identifier in results: values.append(results[col.identifier]) elif col.required: raise err.ConstraintViolationError( 'missing result for \'{}\''.format(col.identifier)) else: values.append(None) columns.append(col.identifier) sql = 'INSERT INTO {}({}) VALUES({})'.format( self.result_table_name, ','.join(columns), ','.join(['?'] * len(columns))) self.con.execute(sql, values) self.con.commit()
def register_user(self, username, password, verify=False): """Create a new user for the given username. Raises an error if a user with that name already is registered. Returns the internal unique identifier for the created user. The verify flag allows to create active or inactive users. An inactive user cannot login until they have been activated. This option is intended for scenarios where the user receives an email after they register that contains a verification/activation link to ensure that the provided email address is valid. Parameters ---------- username: string User email address that is used as the username password: string Password used to authenticate the user verify: bool, optional Determines whether the created user is active or inactive Returns ------- string Raises ------ benchengine.error.ConstraintViolationError benchengine.error.DuplicateUserError """ # Ensure that the username does not contain more than 255 characters # and that the password has at least one (non-space) character if len(username) > 255: raise err.ConstraintViolationError('username too long') self.validate_password(password) # If a user with the given username already exists raise an error sql = 'SELECT id FROM registered_user WHERE email = ?' if not self.con.execute(sql, (username, )).fetchone() is None: raise err.DuplicateUserError(username) # Insert new user into database after creating an unique user identifier # and the password hash. user_id = util.get_unique_identifier() hash = pbkdf2_sha256.hash(password.strip()) active = 0 if verify else 1 sql = 'INSERT INTO registered_user(id, email, secret, active) ' sql += 'VALUES(?, ?, ?, ?)' self.con.execute(sql, (user_id, username, hash, active)) self.con.commit() # Log user in after successful registration and return API key return user_id
def update_team_name(self, team_id, name): """Update the name of the team with the given identifier. Will raise errors if the team is unknown or the name is invalid or not unique. Parameters ---------- team_id: string Unique team identifier name: string New unique team name Returns ------- benchengine.user.team.base.TeamHandle Raises ------ benchengine.error.ConstraintViolationError benchengine.error.UnknownTeamError """ # Ensure that the team exists. Raises error if team does not exist. self.assert_team_exists(team_id) # Ensure that no other team has the same name sql = 'SELECT * FROM team WHERE id <> ? AND name = ?' if len(name.strip()) > 255: raise err.ConstraintViolationError( 'team name contains more than 255 character') elif not self.con.execute(sql, (team_id, name)).fetchone() is None: raise err.ConstraintViolationError( 'team name \'{}\' exists'.format(name.strip())) # Update the team name sql = 'UPDATE team SET name = ? WHERE id = ?' self.con.execute(sql, (name, team_id)) self.con.commit() # Return the handle for the team return self.get_team(team_id)
def validate_password(self, password): """Validate a given password. Raises constraint violation error if an invalid password is given. Currently, the only constraint for passwords is that they are not empty Parameters ---------- password: string User password for authentication Raises ------ benchengine.error.ConstraintViolationError """ # Raise error if password is invalid if password is None or len(password.strip()) == 0: raise err.ConstraintViolationError('empty password')
def add_benchmark( self, name, description=None, instructions=None, src_dir=None, src_repo_url=None, template_spec_file=None ): """Add a benchmark to the repository. The associated workflow template is created in the template repository from either the given source directory or Git repository. The template repository will raise an error if neither or both arguments are given. Raises an error if the given benchmark name is not unique. Parameters ---------- name: string Unique benchmark headline name description: string, optional Optional short description for display in benchmark listings instructions: string, optional Text containing detailed instructions for benchmark participants src_dir: string, optional Directory containing the benchmark components, i.e., the fixed files and the template specification (optional). src_repo_url: string, optional Git repository that contains the the benchmark components template_spec_file: string, optional Path to the workflow template specification file (absolute or relative to the workflow directory) Returns ------- benchengine.benchmark.base.BenchmarkHandle Raises ------ benchengine.error.ConstraintViolationError benchtmpl.error.InvalidParameterError benchtmpl.error.InvalidTemplateError ValueError """ # Ensure that the benchmark name is not empty, not longer than 255 # character and unique. if name is None: raise err.ConstraintViolationError('missing benchmark name') name = name.strip() if name == '' or len(name) > 255: raise err.ConstraintViolationError('invalid benchmark name') sql = 'SELECT id FROM benchmark WHERE name = ?' if not self.con.execute(sql, (name,)).fetchone() is None: raise err.ConstraintViolationError('benchmark \'{}\' exists'.format(name)) # Create the workflow template in the associated template repository template = self.template_store.add_template( src_dir=src_dir, src_repo_url=src_repo_url, template_spec_file=template_spec_file ) # Insert benchmark into database and return descriptor sql = 'INSERT INTO benchmark' sql += '(id, name, description, instructions) ' sql += 'VALUES(?, ?, ?, ?)' self.con.execute( sql, (template.identifier, name, description, instructions) ) self.con.commit() handle = BenchmarkHandle( con=self.con, template=template, name=name, description=description, instructions=instructions ) handle.create_result_table() return handle
def create_team(self, name, owner_id, members=None): """Create a new team with the given name. Ensures that at least the team owner is added as a member to the new team. Parameters ---------- name: string Unique team name owner_id: string Unique user identifier for team owner members: list(string), optional List of team members Returns ------- benchengine.user.team.base.TeamDescriptor Raises ------ benchengine.error.ConstraintViolationError benchengine.error.UnknownUserError """ # Ensure that the owner exists and all team members exist. Will raise # exception if user is unknown. self.assert_user_exists(owner_id) if not members is None: for user_id in set(members): if not user_id == owner_id: self.assert_user_exists(user_id) # Ensure that the given team name is uniqe and does not contain too many # characters sql = 'SELECT * FROM team WHERE name = ?' if name is None or name.strip() == '': raise err.ConstraintViolationError('missing team name') elif len(name.strip()) > 255: raise err.ConstraintViolationError( 'team name contains more than 255 character') elif not self.con.execute(sql, (name.strip(), )).fetchone() is None: raise err.ConstraintViolationError( 'team name \'{}\' exists'.format(name.strip())) # Get unique identifier for the new team. team_id = util.get_unique_identifier() # Create the new team and add team members. Ensure that at least the # team owner is added as a team member. sql = 'INSERT INTO team_member(team_id, user_id) VALUES(?, ?)' self.con.execute( 'INSERT INTO team(id, name, owner_id) VALUES(?, ?, ?)', (team_id, name.strip(), owner_id)) self.con.execute(sql, (team_id, owner_id)) member_count = 1 if not members is None: for user_id in set(members): if not user_id == owner_id: self.con.execute(sql, (team_id, user_id)) member_count += 1 self.con.commit() # Return team descriptor return TeamDescriptor(identifier=team_id, name=name, owner_id=owner_id, member_count=member_count)