from flask_hashids import HashidMixin from enum import IntEnum from typing import Union from app import db class CorpusFollowerPermission(IntEnum): VIEW = 1 MANAGE_FILES = 2 MANAGE_FOLLOWERS = 4 MANAGE_CORPUS = 8 @staticmethod def get(corpus_follower_permission: Union['CorpusFollowerPermission', int, str]) -> 'CorpusFollowerPermission': if isinstance(corpus_follower_permission, CorpusFollowerPermission): return corpus_follower_permission if isinstance(corpus_follower_permission, int): return CorpusFollowerPermission(corpus_follower_permission) if isinstance(corpus_follower_permission, str): return CorpusFollowerPermission[corpus_follower_permission] raise TypeError('corpus_follower_permission must be CorpusFollowerPermission, int, or str') class CorpusFollowerRole(HashidMixin, db.Model): __tablename__ = 'corpus_follower_roles' # Primary key id = db.Column(db.Integer, primary_key=True) # Fields name = db.Column(db.String(64), unique=True) default = db.Column(db.Boolean, default=False, index=True) permissions = db.Column(db.Integer, default=0) # Relationships corpus_follower_associations = db.relationship( 'CorpusFollowerAssociation', back_populates='role' ) def __repr__(self): return f'' def has_permission(self, permission: Union[CorpusFollowerPermission, int, str]): perm = CorpusFollowerPermission.get(permission) return self.permissions & perm.value == perm.value def add_permission(self, permission: Union[CorpusFollowerPermission, int, str]): perm = CorpusFollowerPermission.get(permission) if not self.has_permission(perm): self.permissions += perm.value def remove_permission(self, permission: Union[CorpusFollowerPermission, int, str]): perm = CorpusFollowerPermission.get(permission) if self.has_permission(perm): self.permissions -= perm.value def reset_permissions(self): self.permissions = 0 def to_json_serializeable(self, backrefs=False, relationships=False): json_serializeable = { 'id': self.hashid, 'default': self.default, 'name': self.name, 'permissions': [ x.name for x in CorpusFollowerPermission if self.has_permission(x) ] } if backrefs: pass if relationships: json_serializeable['corpus_follower_association'] = { x.hashid: x.to_json_serializeable(relationships=True) for x in self.corpus_follower_association } return json_serializeable @staticmethod def insert_defaults(): roles = { 'Anonymous': [], 'Viewer': [ CorpusFollowerPermission.VIEW ], 'Contributor': [ CorpusFollowerPermission.VIEW, CorpusFollowerPermission.MANAGE_FILES ], 'Administrator': [ CorpusFollowerPermission.VIEW, CorpusFollowerPermission.MANAGE_FILES, CorpusFollowerPermission.MANAGE_FOLLOWERS, CorpusFollowerPermission.MANAGE_CORPUS ] } default_role_name = 'Viewer' for role_name, permissions in roles.items(): role = CorpusFollowerRole.query.filter_by(name=role_name).first() if role is None: role = CorpusFollowerRole(name=role_name) role.reset_permissions() for permission in permissions: role.add_permission(permission) role.default = role.name == default_role_name db.session.add(role) db.session.commit()