def query_accessible_rows(self, cls, user_or_token, columns=None): """Construct a Query object that, when executed, returns the rows of a specified table that are accessible to a specified user or token. Parameters ---------- cls: `baselayer.app.models.DeclarativeMeta` The mapped class of the target table. user_or_token: `baselayer.app.models.User` or `baselayer.app.models.Token` The User or Token to check. columns: list of sqlalchemy.Column, optional, default None The columns to retrieve from the target table. If None, queries the mapped class directly and returns mapped instances. Returns ------- query: sqlalchemy.Query Query for the accessible rows. """ # system admins automatically get full access if user_or_token.is_admin: return public.query_accessible_rows(cls, user_or_token, columns=columns) # return only selected columns if requested if columns is not None: query = DBSession().query(*columns).select_from(cls) else: query = DBSession().query(cls) # traverse the relationship chain via sequential JOINs for relationship_name in self.relationship_names: self.check_cls_for_attributes(cls, [relationship_name]) relationship = sa.inspect( cls).mapper.relationships[relationship_name] # not a private attribute, just has an underscore to avoid name # collision with python keyword cls = relationship.entity.class_ if str(relationship) == "Group.users": # For the last relationship between Group and User, just join # in the join table and not the join table and the full User table # since we only need the GroupUser.user_id field to match on query = query.join(GroupUser) else: query = query.join(relationship.class_attribute) # filter for records with at least one matching user user_id = self.user_id_from_user_or_token(user_or_token) query = query.filter(GroupUser.user_id == user_id) return query
def source_create_access_logic(cls, user_or_token): user_id = UserAccessControl.user_id_from_user_or_token(user_or_token) query = DBSession().query(cls) if not user_or_token.is_system_admin: query = query.join(Group).join(GroupUser) query = query.filter(GroupUser.user_id == user_id, GroupUser.can_save.is_(True)) return query
def manage_shift_access_logic(cls, user_or_token): # admins of the shift and admins of the group associated with the shift can delete and update a shift user_id = UserAccessControl.user_id_from_user_or_token(user_or_token) query = DBSession().query(cls).join(GroupUser, cls.group_id == GroupUser.group_id) if not user_or_token.is_system_admin: admin_query = query.filter( GroupUser.user_id == user_id, GroupUser.admin.is_(True) ) if admin_query.count() == 0: query = query.join(ShiftUser) query = query.filter( ShiftUser.user_id == user_id, ShiftUser.admin.is_(True) ) else: query = admin_query return query