def remove(name): rs = db().find(auth.Favorite, auth.Favorite.name == name, auth.Favorite.user == user) favorite = not_empty(rs.one()) if favorite.user == user: db().remove(favorite) else: raise TypeError("Not your favorite!")
def add_activity(study_id, activity_id): check_access(user, study_id, "admin") study_id = uuid(study_id, user) activity_id = uuid(activity_id, user) study = not_empty(db().get(structure.Study, study_id)) activity = not_empty(db().get(structure.Activity, activity_id)) activity.studies.add(study)
def create(name, description=None, location={}): project = structure.Project() project.name = name project.description = description if len(location) : loc = structure.Location.from_struct(location) project.location = db().add(loc) return db().add(project)
def create(project_id, name, description=None, location={}): activity = structure.Activity() activity.project = db().get(structure.Project, uuid(project_id)) activity.name = name activity.description = description if len(location): loc = structure.Location.from_struct(location) activity.location = db().add(loc) return db().add(activity)
def fork(from_dataset_id, to_dataset_id, fork_type="derived"): #FIXME: Check for circular graph from_dataset_id = uuid(from_dataset_id, user) to_dataset_id = uuid(to_dataset_id, user) from_dataset = not_empty(db().get(Dataset, from_dataset_id)) to_dataset = not_empty(db().get(Dataset, to_dataset_id)) check_access(user, from_dataset.study_id, "read") check_access(user, to_dataset.study_id, "write") # FIXME: pass on to private function, what happens to user? return do_fork(from_dataset, to_dataset, user)
def create(name, unit, description=None, uniname=None): rs = db().find(dataset.Type, dataset.Type.name == name) if not rs.is_empty(): raise TypeError("Type already exists") type = dataset.Type() type.name = name type.unit = unit type.description = description type.uniname = uniname return db().add(type)
def purge(dataset_id): # Fixme: only owner should be able to purge? dataset_id = uuid(dataset_id, user) ds = not_empty(db().get(dataset.Dataset, dataset_id)) check_access(user, ds.study_id, "write") if ds.closed is None: resolver.get("dataset.%s.purge" % ds.type, user)(dataset_id) db().remove(ds) else: raise Exception("Cannot delete closed datasets")
def access(study_id, user_id=None, min_role="read"): """ Checks if user has access to study study_id: the study to check user_id: the user to check None for current user min_role: the minimal role requested """ #FIXME investigate caching study_id = uuid(study_id, user) user_id = uuid(user_id, user) try: min_role = auth.StudyGroup.ROLEMAP[min_role] except KeyError: raise TypeError("Invalid role '%s'" % min_role) if user_id is None: user_id = user.id the_user = not_empty(db().get(auth.User, user_id)) if the_user.is_admin(): return "!admin" study = not_empty(db().get(structure.Study, study_id)) if the_user == study.owner: return "!owner" checker = resolver.get("group.has_member", user) max_role = 0 max_role_name = None for sg in study.access: if sg.ROLEMAP[sg.role] >= min_role: # requested role available in group if checker(sg.group_id, user_id): # check for user is member of group if max_role < sg.ROLEMAP[sg.role]: max_role_name = sg.role max_role = sg.ROLEMAP[sg.role] if max_role_name: return max_role_name return False
def memberships(user_id=None, explicit=False): """ List group memberships for user user_id: user_id of queried user None for current user explicit: List only explicit memberships """ if user_id: user_id = uuid(user_id, user) else: user_id = user.id memberships = set() rs = db().find(auth.GroupMember, auth.GroupMember.user_id == user_id) for group in rs: memberships.add(group.group) if explicit: return list(memberships) implicit = set() for ms in memberships: while ms.parent: implicit.add(ms.parent) ms = ms.parent return rs_to_list(memberships.union(implicit))
def has_member(group_id, user_id=None, explicit=False): """ Is user a member of group group_id: group_id of queried group user_id: user_id of queried user None for current user explicit: only explicit memberships """ group_id = uuid(group_id, user) group = db().get(auth.Group, group_id) if user_id: user_id = uuid(user_id, user) else: user_id = user.id for member in group.members: if member.id == user_id: return True if explicit: return False else: return _implicit_member(group, user_id)
def all(owned_by_user=False): if owned_by_user: # owned == access rs = db().find(structure.Study, structure.Study.owner == user) rs = rs.order_by(structure.Study.name) return rs_to_list(rs) else: rs = db().find(structure.Study) rs = rs.order_by(structure.Study.name) result = [] for study in rs: if check_access(user, study.id, "read", throw=False): result.append(study) return rs_to_list(result, 0)
def remove_group(study_id, group_id): """ Remove group access to study """ check_access(user, study_id, "admin") study_id = uuid(study_id, user) group_id = uuid(group_id, user) rs = db().find(auth.StudyGroup, auth.StudyGroup.study_id == study_id, auth.StudyGroup.group_id == group_id).one() if rs: db().remove(rs) else: raise TypeError("Group access not found")
def lineage(study_id): check_access(user, study_id, "read") study_id = uuid(study_id, user) study = not_empty(db().get(structure.Study, study_id)) edges = [] nodes = [] for dataset in study.datasets: if dataset.parents.count() == 0: subtree = generate_lineage_tree(study, dataset) if subtree is not None: edges.extend(subtree[0]) nodes.append(subtree[1]) nodedict = {} for idx, node in enumerate(nodes): for obj in node: if obj not in nodedict: nodedict[obj] = node[obj] elif node[obj]["level"] > nodedict[obj]["level"]: nodedict[obj]["level"] = node[obj] return {"edges": list(set(edges)), "nodes": nodedict}
def search(keyword): keyword = "%%%s%%" % keyword rs = db().find(structure.Study, Or(structure.Study.name.like(keyword), structure.Study.description.like(keyword))) result = [] for study in rs: if check_access(user, study.id, "read", throw=False): result.append(study) return rs_to_list(result)
def create(username, fullname, email, password): u = auth.User() u.username = username u.fullname = fullname u.email = email u.set_password(password) return db().add(u)
def create(name, parent_id=None): u = auth.Group() u.name = name if parent_id: u.parent_id = uuid(parent_id) return db().add(u)
def grant(user_id, identifier): """ Grant a permission """ user_id = uuid(user_id, user) p = auth.Permission() p.user_id = user_id p.identifier = identifier p.granted_by = user return db().add(p)
def purge(dataset_id): sequence = sequence_from_dataset(dataset_id, user) for i, index in enumerate(sequence.indicies): for point in index.points: db().remove(point) db().remove(index) if i % 1000 == 0 and i > 0: debug("Purged %d datapoints, committing" % i, module="dataset-sequence-purge") db().commit() for param in sequence.parameters: db().remove(param) db().remove(sequence)
def do_fork(from_dataset, to_dataset, user, fork_type="derived"): #FIXME user wierdness lineage = structure.Lineage() lineage.from_dataset = from_dataset lineage.to_dataset = to_dataset lineage.forked_by = user lineage.fork_type = fork_type return db().add(lineage)
def authenticate(username, password): """ Authenticate a user """ u = db().find(auth.User, auth.User.username == unicode(username)).one() if u is None or not u.authenticate(password): raise UnauthorizedException("Invalid user or password") return auth.Token.create_token(u).id
def tree(): """ Get a tree of all groups """ groups = db().find(auth.Group, auth.Group.parent_id == None) objs = [] for group in groups: obj = _subtree(group) objs.append(obj) return objs
def create_token(user, valid=timedelta(hours=1)): token = Token() token.id = unicode(uuid.uuid4().hex) token.timestamp = time.time() token.user = user if valid is not None: token.validity = valid.seconds return db().add(token)
def revoke(user_id, identifier=None): """ Revoke a permission user_id: the id of the user to revoke permissions for identifier: the permission as a string None to strip all permissions from user returns the number of revoked permissions """ user_id = uuid(user_id, user) if identifier: revoked = db().find(auth.Permission, auth.Permission.user_id == user_id, auth.Permission.identifier == identifier) else: revoked = db().find(auth.Permission, auth.Permission.user_id == user_id) for perm in revoked: db().remove(perm) return len(list(revoked))
def remove_member(group_id, user_id): """ Remove user from group, but it cannot be yourself (unless you are an admin) """ group_id = uuid(group_id, user) user_id = uuid(user_id, user) # FIXME: security rs = db().find(auth.GroupMember, auth.GroupMember.group_id == group_id, auth.GroupMember.user_id == user_id) gm = rs.one() if gm is None: raise TypeError("Group membership not found") if gm.user == user and not user.is_admin(): raise TypeError("You cannot remove yourself from a group") db().remove(gm)
def add_parameter(dataset_id, type_id, uncertainty_value=None, uncertainty_type="absolute", storage="float"): sequence = sequence_from_dataset(dataset_id, user) check_access(user, sequence.dataset.study_id, "write") if sequence.dataset.closed: raise Exception("Dataset is closed") type_id = uuid(type_id, user) type = not_empty(db().get(dataset.Type, type_id)) param = dataset.sequence.Parameter() param.index = len(list(sequence.parameters)) + 1 param.type = type param.sequence = sequence param.storage = storage param.uncertainty_type = uncertainty_type param.uncertainty_value = uncertainty_value return db().add(param)
def get(activity_id): activity_id = uuid(activity_id, user) activity = not_empty(db().get(structure.Activity, activity_id)).serialize() # limit access to studies studies = [] for study in activity["studies"]: if resolver.get("study.access", user)(study["id"], min_role="read"): studies.append(study) activity["studies"] = studies return activity
def access(identifier, user_id=None): """ Check if user has access to permission """ user_id = uuid(user_id, user) if not user_id: user_id = user.id result = db().find(auth.Permission, auth.Permission.user_id == user_id and auth.Permission.identifier == identifier) return result.one() is not None
def create(study_id, description, index_type_id, index_marker_type="point", index_marker_location="center", dataset_forked_from=None): study_id = uuid(study_id, user) check_access(user, study_id, "write") index_type_id = uuid(index_type_id, user) study = not_empty(db().get(structure.Study, study_id)) index_type = not_empty(db().get(dataset.Type, index_type_id)) #FIXME unclean parent = resolver.get("dataset.create", user)(u"sequence", study, description, dataset_forked_from) sequence = dataset.sequence.Sequence() sequence.index_type = index_type sequence.index_marker_type = index_marker_type sequence.index_marker_location = index_marker_location sequence.dataset = parent sequence = db().add(sequence) return sequence
def create(type, study, description, dataset_forked_from=None, fork_type="derived"): check_access(user, study.id, "write") supported = resolver.get("dataset.supported_dataset_types", user)() if type not in supported: raise Exception("Unsupported type") ds = dataset.Dataset() ds.type = type ds.creator = user ds.study = study ds.description = description ds = db().add(ds) if dataset_forked_from is not None: from_dataset_id = uuid(dataset_forked_from, user) from_dataset = not_empty(db().get(dataset.Dataset, from_dataset_id)) #FIXME do_fork(from_dataset, ds, user, fork_type) return ds
def get_user(token_id): try: Token.expire_nonvalid() token = db().get(Token, token_id) if token is None: return None now = int(time.time()) # dont update the timestamp if the last access time was less than # one minute ago. if token.timestamp < now - 60: token.timestamp = now db().commit() return token.user except: db().rollback() raise