class PageList(db.Model): """Represent association between page and list.""" __versioned__ = {} __tablename__ = 'pages_pagelist' id = db.Column(db.Integer, nullable=False, primary_key=True, autoincrement=True) """PageList identifier.""" list_id = db.Column(db.Integer, db.ForeignKey(Page.id), nullable=False) """Id of a list.""" page_id = db.Column(db.Integer, db.ForeignKey(Page.id), nullable=False) """Id of a page.""" order = db.Column(db.Integer, nullable=False) list = db.relationship(Page, backref=db.backref("pages", cascade="all, delete-orphan"), foreign_keys=[list_id]) """Relation to the list.""" page = db.relationship(Page, backref=db.backref("lists", cascade="all, delete-orphan"), foreign_keys=[page_id]) """Relation to the page."""
class FlowAction(db.Model, TimestampMixin): """Action list belong to Flow.""" __tablename__ = 'workflow_flow_action' id = db.Column(db.Integer(), nullable=False, primary_key=True, autoincrement=True) """FlowAction identifier.""" flow_id = db.Column(UUIDType, db.ForeignKey(FlowDefine.flow_id), nullable=False, unique=False, index=True) """the id of flow.""" action_id = db.Column(db.Integer(), db.ForeignKey(Action.id), nullable=False, unique=False) """the id of action.""" action_version = db.Column(db.String(64), nullable=True) """the version of used action.""" action_order = db.Column(db.Integer(), nullable=False, unique=False) """the order of action.""" action_condition = db.Column(db.String(255), nullable=True, unique=False) """the condition of transition.""" TATUSPOLICY = [ (AvailableStautsPolicy.USABLE, AvailableStautsPolicy.describe(AvailableStautsPolicy.USABLE)), (AvailableStautsPolicy.UNUSABLE, AvailableStautsPolicy.describe(AvailableStautsPolicy.UNUSABLE)), ] """Subscription policy choices.""" action_status = db.Column(ChoiceType(TATUSPOLICY, impl=db.String(1)), nullable=False, default=AvailableStautsPolicy.USABLE) """the status of flow action.""" action_date = db.Column(db.DateTime, nullable=False, default=datetime.now) """the use date of action.""" action = db.relationship(Action, backref=db.backref('flow_action')) """flow action relationship.""" action_roles = db.relationship('FlowActionRole', backref=db.backref('flow_action')) """flow action relationship."""
class TermSources(db.Model): __tablename__ = 'iroko_terms_sources' # TODO: Esta relacion deberia hacerse con los UUIDs y no con los IDs term_id = db.Column(db.Integer, db.ForeignKey('iroko_terms.id'), primary_key=True) sources_id = db.Column(db.Integer, db.ForeignKey('iroko_sources.id'), primary_key=True) data = db.Column(JSONType) source = db.relationship("Source", backref=db.backref("term_sources")) term = db.relationship("Term", backref=db.backref("term_sources"))
class WorkFlow(db.Model, TimestampMixin): """Define WorkFlow.""" __tablename__ = 'workflow_workflow' id = db.Column(db.Integer(), nullable=False, primary_key=True, autoincrement=True) """Flows identifier.""" flows_id = db.Column(UUIDType, nullable=False, unique=True, index=True, default=uuid.uuid4()) """the id of flows.""" flows_name = db.Column(db.String(255), nullable=True, unique=False, index=False) """the name of flows.""" itemtype_id = db.Column(db.Integer(), db.ForeignKey(ItemType.id), nullable=False, unique=False) """the id of itemtype.""" itemtype = db.relationship(ItemType, backref=db.backref( 'workflow', lazy='dynamic', order_by=desc('item_type.tag'))) index_tree_id = db.Column(db.BigInteger, nullable=True, unique=False) """Index tree id that this workflow will belong to""" flow_id = db.Column(db.Integer(), db.ForeignKey(FlowDefine.id), nullable=False, unique=False) """the id of flow.""" flow_define = db.relationship(FlowDefine, backref=db.backref('workflow', lazy='dynamic'))
class GitSnapshot(db.Model): """Snapshot information for a Git repo.""" __tablename__ = 'git_snapshot' id = db.Column(db.Integer, primary_key=True) # webhook payload / event payload = db.Column(json_type, default={}, nullable=True) # git specifics tag = db.Column(db.String(255), nullable=True) ref = db.Column(db.String(255), nullable=True) # foreign keys (connecting to repo and events) webhook_id = db.Column(db.Integer, db.ForeignKey(GitWebhook.id), nullable=False) webhook = db.relationship(GitWebhook, backref=db.backref("snapshots", cascade="all, delete-orphan")) created = db.Column(db.DateTime, server_default=db.func.now()) @staticmethod def create(webhook, data): snapshot = GitSnapshot(payload=data, webhook_id=webhook.id, tag=data['commit'].get('tag'), ref=data['commit']['id']) db.session.add(snapshot) db.session.commit()
class Term(db.Model): __tablename__ = 'iroko_terms' id = db.Column(db.Integer, primary_key=True) uuid = db.Column(UUIDType, default=uuid.uuid4) identifier = db.Column(db.String, nullable=False, unique=True) description = db.Column(db.String) vocabulary_id = db.Column(db.String(), db.ForeignKey('iroko_vocab.identifier', ondelete='CASCADE'), nullable=False, index=True) vocabulary = db.relationship("Vocabulary", backref=db.backref( "terms", cascade="all, delete-orphan", lazy='dynamic')) parent_id = db.Column(db.Integer, db.ForeignKey('iroko_terms.id')) children = db.relationship("Term", lazy="joined", join_depth=2) # any data related to the term data = db.Column(JSONType) def __str__(self): """Representation.""" return self.identifier
class RecordsBuckets(db.Model): """Relationship between Records and Buckets.""" __tablename__ = 'records_buckets' record_id = db.Column( UUIDType, db.ForeignKey(RecordMetadata.id), primary_key=True, nullable=False, # NOTE no unique constrain for better future ... ) bucket_id = db.Column( UUIDType, db.ForeignKey(Bucket.id), primary_key=True, nullable=False, ) bucket = db.relationship(Bucket) record = db.relationship( RecordMetadata, backref=db.backref('records_buckets', uselist=False), uselist=False, )
class ActionRoles(ActionNeedMixin, db.Model): """ActionRoles data model. It relates an allowed action with a role. """ __tablename__ = 'access_actionsroles' __table_args__ = (UniqueConstraint('action', 'exclude', 'argument', 'role_id', name='access_actionsroles_unique'), ) role_id = db.Column(db.Integer(), db.ForeignKey(Role.id, ondelete='CASCADE'), nullable=False, index=True) role = db.relationship("Role", backref=db.backref("actionusers", cascade="all, delete-orphan")) @property def need(self): """Return RoleNeed instance.""" return RoleNeed(self.role.name)
class UserActor(UserMixin, Actor): """An actor matching a set of users identified by ID.""" __tablename__ = 'explicit_acls_useractor' __mapper_args__ = { 'polymorphic_identity': 'user', } id = db.Column(db.String(36), db.ForeignKey('explicit_acls_actor.id'), primary_key=True) """Id maps to base class' id""" users = db.relationship(User, secondary=users_actors, lazy='subquery', backref=db.backref('actors', lazy=True)) def __str__(self): """Returns the string representation of the actor.""" return 'UserActor[%s]' % self.name def get_elasticsearch_representation(self, another=None, record=None, **kwargs): """ Returns ES representation of this Actor. :param another: A serialized representation of the previous Actor of the same type. The implementation should merge it with its own ES representation :return: The elasticsearch representation of the property on Record """ return list(set([x.id for x in self.users] + (another or []))) def user_matches(self, user: Union[User, AnonymousUser], context: Dict, record: Record = None) -> bool: """ Checks if a user is allowed to perform any operation according to the ACL. :param user: user being checked against the ACL :param context: any extra context carrying information about the user """ if user.is_anonymous: return False for x in self.users: if x == user: return True return False def get_matching_users(self, record: Record = None) -> Iterable[int]: """ Returns a list of users matching this Actor. :return: Iterable of a user ids """ return [x.id for x in self.users]
class TemplateDefinition(db.Model, object): """Representation of a template definition.""" __tablename__ = 'sequencegenerator_template' COUNTER_REGEX = re.compile(r'({counter(!.)?(:.*)?})') """Regular expression matching the counter inside the template string.""" name = db.Column(db.String(255), primary_key=True) """The identifier of the template definition.""" meta_template = db.Column(db.String(255), unique=True) """The template generator.""" parent_name = db.Column( db.ForeignKey(name, name='fk_seqgen_template_parent_name_seqgen_template')) """Indicate that the template depends on another one.""" start = db.Column(db.Integer, default=0) """The starting counter of sequences generated from ``meta_template``.""" step = db.Column(db.Integer, default=1) """The incremental step of sequences generated from ``meta_template``.""" children = db.relationship('TemplateDefinition', backref=db.backref('parent', remote_side=name)) @validates('meta_template') def validate_meta_template(self, key, value): """Validate template string of template definition.""" if not self.COUNTER_REGEX.search(value): raise InvalidTemplate('No counter placeholder') return value def counter(self, **kwargs): """Get counter of this template definition, based on given kwargs.""" meta_template = double_counter(self.meta_template, self.COUNTER_REGEX) counter = Counter.get(meta_template, kwargs) if counter is None: with db.session.begin_nested(): counter = Counter.create( meta_template=meta_template, ctx=kwargs, counter=self.start, template_definition=self, ) db.session.add(counter) return counter def __repr__(self): """Canonical representation of ``TemplateDefinition``.""" return ('TemplateDefinition(' 'name={0.name!r}, ' 'meta_template={0.meta_template!r}, ' 'start={0.start!r}, ' 'step={0.step!r})').format(self)
class FlowDefine(db.Model, TimestampMixin): """Define Flow.""" __tablename__ = 'workflow_flow_define' id = db.Column(db.Integer(), nullable=False, primary_key=True, autoincrement=True) """Flow identifier.""" flow_id = db.Column(UUIDType, nullable=False, unique=True, index=True, default=uuid.uuid4()) """the id of flow.""" flow_name = db.Column(db.String(255), nullable=True, unique=True, index=True) """the name of flow.""" flow_user = db.Column(db.Integer(), db.ForeignKey(User.id), nullable=True, unique=False) """the user who update the flow.""" user_profile = db.relationship(User) """User relationship""" FLOWSTATUSPOLICY = [ (FlowStatusPolicy.AVAILABLE, FlowStatusPolicy.describe(FlowStatusPolicy.AVAILABLE)), (FlowStatusPolicy.INUSE, FlowStatusPolicy.describe(FlowStatusPolicy.INUSE)), (FlowStatusPolicy.MAKING, FlowStatusPolicy.describe(FlowStatusPolicy.MAKING)), ] """Subscription policy choices.""" flow_status = db.Column(ChoiceType(FLOWSTATUSPOLICY, impl=db.String(1)), nullable=False, default=FlowStatusPolicy.MAKING, info=dict( label=_('Subscription Policy'), widget=RadioGroupWidget( FlowStatusPolicy.descriptions), )) """the status of flow.""" flow_actions = db.relationship('FlowAction', backref=db.backref('flow')) """flow action relationship."""
class GitWebhookSubscriber(db.Model): """Records subscribed to the git repository events.""" __tablename__ = 'git_subscriber' __table_args__ = db.UniqueConstraint( 'record_id', 'webhook_id', name='uq_git_webhook_subscriber_unique_constraint'), id = db.Column(db.Integer, primary_key=True) status = db.Column(db.Enum('active', 'deleted', name='git_webhook_status'), nullable=False, default='active') record_id = db.Column(UUIDType, db.ForeignKey(RecordMetadata.id), nullable=False) record = db.relationship(RecordMetadata, backref=db.backref("webhooks", cascade="all, delete-orphan")) webhook_id = db.Column(db.Integer, db.ForeignKey(GitWebhook.id), nullable=False) webhook = db.relationship(GitWebhook, backref=db.backref("subscribers", cascade="all, delete-orphan")) user_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False) user = db.relationship(User) snapshots = db.relationship(GitSnapshot, order_by="desc(GitSnapshot.created)", secondary='git_subscriber_snapshots') @property def repo(self): return self.webhook.repo
class User(db.Model, UserMixin): """User data model.""" __tablename__ = "accounts_user" id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) """User email.""" password = db.Column(db.String(255)) """User password.""" active = db.Column(db.Boolean(name='active')) """Flag to say if the user is active or not .""" confirmed_at = db.Column(db.DateTime) """When the user confirmed the email address.""" last_login_at = db.Column(db.DateTime) """When the user logged-in for the last time.""" current_login_at = db.Column(db.DateTime) """When user logged into the current session.""" last_login_ip = db.Column(IPAddressType, nullable=True) """Last user IP address.""" current_login_ip = db.Column(IPAddressType, nullable=True) """Current user IP address.""" login_count = db.Column(db.Integer) """Count how many times the user logged in.""" roles = db.relationship('Role', secondary=userrole, backref=db.backref('users', lazy='dynamic')) """List of the user's roles.""" @validates('last_login_ip', 'current_login_ip') def validate_ip(self, key, value): """Hack untrackable IP addresses.""" # NOTE Flask-Security stores 'untrackable' value to IPAddressType # field. This incorrect value causes ValueError on loading # user object. if value == 'untrackable': # pragma: no cover value = None return value def __str__(self): """Representation.""" return 'User <id={0.id}, email={0.email}>'.format(self)
class PropertyValue(db.Model, Timestamp): """Property and Value match to be used in Property based ACL queries.""" __tablename__ = 'explicit_acls_propertyvalue' # # Fields # id = db.Column(db.String(36), default=gen_uuid_key, primary_key=True) """Primary key.""" acl_id = db.Column( db.ForeignKey('explicit_acls_propertyvalueacl.id', name='fk_explicit_acls_propertyvalue_acl_id')) acl = db.relationship('PropertyValueACL', back_populates='property_values') name = db.Column(db.String(64)) """Name of the property in elasticsearch.""" value = db.Column(db.String(128)) """Value of the property in elasticsearch.""" match_operation = db.Column(ChoiceType(MatchOperation, impl=db.String(length=10)), default=MatchOperation.term) """Property value matching mode: can be either term or match.""" bool_operation = db.Column(ChoiceType(BoolOperation, impl=db.String(length=10)), default=BoolOperation.must) """Bool filter operation mode this property belongs to.""" originator_id = db.Column(db.ForeignKey( User.id, ondelete='CASCADE', ), nullable=False, index=True) originator = db.relationship(User, backref=db.backref("authored_properties")) """The originator (person that last time modified the Property)""" def __str__(self): """Returns string representation of the class.""" return '%s: %s(%s=%s)' % ( self.bool_operation, self.match_operation, self.name, self.value, )
class GitWebhook(db.Model): """Webook for a Git repository.""" __tablename__ = 'git_webhook' __table_args__ = db.UniqueConstraint( 'event_type', 'repo_id', name='uq_git_webhook_unique_constraint'), id = db.Column(db.Integer, primary_key=True) event_type = db.Column(db.String(255), nullable=False) external_id = db.Column(db.String(255), nullable=False) secret = db.Column(db.String(32), nullable=True) repo_id = db.Column(db.Integer, db.ForeignKey(GitRepository.id)) repo = db.relationship(GitRepository, backref=db.backref("webhooks", cascade="all, delete-orphan"))
class GitSnapshot(db.Model): """Snapshot information for a Git repo.""" __tablename__ = 'git_snapshot' id = db.Column(db.Integer, primary_key=True) # webhook payload / event payload = db.Column(json_type, default={}, nullable=True) webhook_id = db.Column(db.Integer, db.ForeignKey(GitWebhook.id), nullable=False) webhook = db.relationship(GitWebhook, backref=db.backref("snapshots", cascade="all, delete-orphan")) created = db.Column(db.DateTime, default=datetime.utcnow)
class User(db.Model, UserMixin): """User data model.""" __tablename__ = "accounts_user" id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean) confirmed_at = db.Column(db.DateTime) last_login_at = db.Column(db.DateTime) current_login_at = db.Column(db.DateTime) last_login_ip = db.Column(IPAddressType, nullable=True) current_login_ip = db.Column(IPAddressType, nullable=True) login_count = db.Column(db.Integer) roles = db.relationship('Role', secondary=userrole, backref=db.backref('users', lazy='dynamic')) @validates('last_login_ip', 'current_login_ip') def validate_ip(self, key, value): """Hack untrackable IP addresses.""" # NOTE Flask-Security stores 'untrackable' value to IPAddressType # field. This incorrect value causes ValueError on loading # user object. if value == 'untrackable': # pragma: no cover value = None return value def __str__(self): """Representation.""" return 'User <id={0.id}, email={0.email}>'.format(self)
class Notification(db.Model): """Define a Notification""" __tablename__ = 'iroko_notification' id = db.Column(db.Integer, primary_key=True) classification = db.Column(db.Enum(NotificationType)) description = db.Column(db.String) emiter = db.Column(db.String) viewed = db.Column(db.Boolean, default=False) receiver_id = db.Column( db.Integer, db.ForeignKey(User.id, name='fk_iroko_notifications_user_id')) receiver = db.relationship(User, backref=db.backref( 'notifications', cascade='all, delete-orphan')) # any data related to the notification data = db.Column(JSONType)
class ActivityHistory(db.Model, TimestampMixin): """Define ActivityHistory.""" __tablename__ = 'workflow_action_history' id = db.Column(db.Integer(), nullable=False, primary_key=True, autoincrement=True) """ActivityHistory identifier.""" activity_id = db.Column(db.String(24), nullable=False, unique=False, index=True) """activity id of Activity.""" action_id = db.Column(db.Integer(), nullable=False, unique=False) """action id.""" action_version = db.Column(db.String(24), nullable=True, unique=False) """the used version of action.""" action_status = db.Column(db.String(1), db.ForeignKey(ActionStatus.action_status_id), nullable=True) """the status description of action.""" action_user = db.Column(db.Integer(), db.ForeignKey(User.id), nullable=True) """the user of operate action.""" action_date = db.Column(db.DateTime, nullable=False, default=datetime.now) """the date of operate action.""" action_comment = db.Column(db.Text, nullable=True) """action comment.""" user = db.relationship(User, backref=db.backref('activity_history')) """User relaionship."""
class HarvestedItem(db.Model): """The items harvested from a repository""" __tablename__ = 'iroko_harvest_items' __table_args__ = (db.UniqueConstraint( 'source_uuid', 'identifier', name='identifier_in_repository' ), ) id = db.Column(db.Integer, primary_key=True) source_uuid = db.Column( UUIDType, db.ForeignKey( 'iroko_source_repositories' '.source_uuid', ondelete='CASCADE' ), nullable=False, index=True ) repository = db.relationship( "Repository", backref=db.backref( 'harvested_items' ) ) """identifier in the repo""" identifier = db.Column(db.String, nullable=False) # el uuid del iroko record asociado record = db.Column(UUIDType, nullable=True) status = db.Column(db.Enum(HarvestedItemStatus)) error_log = db.Column(db.String) data = db.Column(JSONType) """Any other relevant data to be used in the future could be here.""" def __str__(self): """Representation.""" return self.identifier
class Comment(db.Model, Timestamp): """Comment in a request.""" __tablename__ = 'requests_comment' id = db.Column( UUIDType, default=uuid.uuid4, primary_key=True, ) request_id = db.Column( UUIDType, db.ForeignKey(Request.id, ondelete="CASCADE"), nullable=False, ) created_by = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False) message = db.Column(db.Text) request = db.relationship( Request, backref=db.backref( 'comments', cascade='all, delete-orphan', passive_deletes=True, ), ) @classmethod def create(cls, request_id, created_by, message): with db.session.begin_nested(): obj = cls( request_id=request_id, created_by=created_by, message=message, ) db.session.add(obj) return obj
class UserProfile(db.Model): """User profile model. Stores a username, display name (case sensitive version of username) and a full name for a user. """ __tablename__ = 'userprofiles_userprofile' user_id = db.Column(db.Integer, db.ForeignKey(User.id), primary_key=True) """Foreign key to :class:`~invenio_accounts.models.User`.""" user = db.relationship(User, backref=db.backref('profile', uselist=False, cascade='all, delete-orphan')) """User relationship.""" _username = db.Column('username', db.String(255), unique=True) """Lower-case version of username to assert uniqueness.""" _displayname = db.Column('displayname', db.String(255)) """Case preserving version of username.""" fullname = db.Column(db.String(100), nullable=False, default='') """Full name of person.""" timezone = db.Column(db.String(255), nullable=False, default='') """Selected timezone.""" language = db.Column(db.String(255), nullable=False, default='') """Selected language.""" """University / Institution""" university = db.Column('university', db.String(100)) """Affiliation department / Department""" department = db.Column('department', db.String(100)) """Position""" position = db.Column('position', db.String(100)) """Position""" otherPosition = db.Column('otherPosition', db.String(100)) """Phone number""" phoneNumber = db.Column('phoneNumber', db.String(15)) """Affiliation institute name 1""" """Affiliation institute name (n)""" instituteName = db.Column('instituteName', db.String(100)) """Affiliation institute position (n)""" institutePosition = db.Column('institutePosition', db.String(255)) """Affiliation institute name 2""" """Affiliation institute name (n)""" instituteName2 = db.Column('instituteName2', db.String(100)) """Affiliation institute position (n)""" institutePosition2 = db.Column('institutePosition2', db.String(255)) """Affiliation institute name 3""" """Affiliation institute name (n)""" instituteName3 = db.Column('instituteName3', db.String(100)) """Affiliation institute position (n)""" institutePosition3 = db.Column('institutePosition3', db.String(255)) """Affiliation institute name 4""" """Affiliation institute name (n)""" instituteName4 = db.Column('instituteName4', db.String(100)) """Affiliation institute position (n)""" institutePosition4 = db.Column('institutePosition4', db.String(255)) """Affiliation institute name 5""" """Affiliation institute name (n)""" instituteName5 = db.Column('instituteName5', db.String(100)) """Affiliation institute position (n)""" institutePosition5 = db.Column('institutePosition5', db.String(255)) @hybrid_property def username(self): """Get username.""" return self._displayname @hybrid_property def get_username(self): """Get username.""" return self._username @username.setter def username(self, username): """Set username. .. note:: The username will be converted to lowercase. The display name will contain the original version. """ validate_username(username) self._username = username.lower() self._displayname = username @classmethod def get_by_username(cls, username): """Get profile by username. :param username: A username to query for (case insensitive). """ return cls.query.filter( UserProfile._username == username.lower()).one() @classmethod def get_by_userid(cls, user_id): """Get profile by user identifier. :param user_id: Identifier of a :class:`~invenio_accounts.models.User`. :returns: A :class:`~invenio_userprofiles.models.UserProfile` instance or ``None``. """ return cls.query.filter_by(user_id=user_id).one_or_none() @property def is_anonymous(self): """Return whether this UserProfile is anonymous.""" return False def get_institute_data(self): """Get institute data. :return: """ institute_dict = { 1: { 'subitem_affiliated_institution_name': self.instituteName, 'subitem_affiliated_institution_position': self.institutePosition }, 2: { 'subitem_affiliated_institution_name': self.instituteName2, 'subitem_affiliated_institution_position': self.institutePosition2 }, 3: { 'subitem_affiliated_institution_name': self.instituteName3, 'subitem_affiliated_institution_position': self.institutePosition3 }, 4: { 'subitem_affiliated_institution_name': self.instituteName4, 'subitem_affiliated_institution_position': self.institutePosition4 }, 5: { 'subitem_affiliated_institution_name': self.instituteName5, 'subitem_affiliated_institution_position': self.institutePosition5 } } return institute_dict
class RoleActor(RoleMixin, Actor): """An actor matching set of invenio roles.""" __tablename__ = 'explicit_acls_roleactor' __mapper_args__ = { 'polymorphic_identity': 'role', } id = db.Column(db.String(36), db.ForeignKey('explicit_acls_actor.id'), primary_key=True) """Id maps to base class' id""" roles = db.relationship(Role, secondary=roles_actors, lazy='subquery', backref=db.backref('actors', lazy=True)) def __str__(self): """Returns the string representation of the actor.""" return 'RoleActor[%s]' % self.name def get_elasticsearch_representation(self, others=None, record=None, **kwargs): """ Returns ES representation of this Actor. :param another: A serialized representation of the previous Actor of the same type. The implementation should merge it with its own ES representation :return: The elasticsearch representation of the property on Record """ return list(set([x.id for x in self.roles] + (others or []))) def user_matches(self, user: User, context: Dict, record: Record = None) -> bool: """ Checks if a user is allowed to perform any operation according to the ACL. :param user: user being checked against the ACL :param context: any extra context carrying information about the user """ role_ids = set(x.id for x in self.roles) for role in user.roles: if role.id in role_ids: return True return False def get_matching_users(self, record: Record = None) -> Iterable[int]: """ Returns a list of users matching this Actor. :return: Iterable of a user ids """ ret = set() for r in self.roles: for u in r.users: ret.add(u.id) return ret
class Activity(db.Model, TimestampMixin): """Define Activety.""" __tablename__ = 'workflow_activity' id = db.Column(db.Integer(), nullable=False, primary_key=True, autoincrement=True) """Activity identifier.""" activity_id = db.Column(db.String(24), nullable=False, unique=True, index=True) """activity id of Activity.""" activity_name = db.Column(db.String(255), nullable=True, unique=False, index=False) """activity name of Activity.""" item_id = db.Column(UUIDType, nullable=True, unique=False, index=True) """item id.""" workflow_id = db.Column(db.Integer(), db.ForeignKey(WorkFlow.id), nullable=False, unique=False) """workflow id.""" workflow = db.relationship(WorkFlow, backref=db.backref('activity', lazy='dynamic')) workflow_status = db.Column(db.Integer(), nullable=True, unique=False) """workflow status.""" flow_id = db.Column(db.Integer(), db.ForeignKey(FlowDefine.id), nullable=True, unique=False) """flow id.""" flow_define = db.relationship(FlowDefine, backref=db.backref('activity', lazy='dynamic')) action_id = db.Column(db.Integer(), db.ForeignKey(Action.id), nullable=True, unique=False) """action id.""" action = db.relationship(Action, backref=db.backref('activity', lazy='dynamic')) # action_version = db.Column( # db.String(24), nullable=True, unique=False) # """action version.""" action_status = db.Column(db.String(1), db.ForeignKey(ActionStatus.action_status_id), nullable=True, unique=False) """action status.""" activity_login_user = db.Column(db.Integer(), db.ForeignKey(User.id), nullable=True, unique=False) """the user of create activity.""" activity_update_user = db.Column(db.Integer(), db.ForeignKey(User.id), nullable=True, unique=False) """the user of update activity.""" ACTIVITYSTATUSPOLICY = [ (ActivityStatusPolicy.ACTIVITY_BEGIN, ActivityStatusPolicy.describe(ActivityStatusPolicy.ACTIVITY_BEGIN)), (ActivityStatusPolicy.ACTIVITY_FINALLY, ActivityStatusPolicy.describe(ActivityStatusPolicy.ACTIVITY_FINALLY)), (ActivityStatusPolicy.ACTIVITY_FORCE_END, ActivityStatusPolicy.describe( ActivityStatusPolicy.ACTIVITY_FORCE_END)), (ActivityStatusPolicy.ACTIVITY_CANCEL, ActivityStatusPolicy.describe(ActivityStatusPolicy.ACTIVITY_CANCEL)), (ActivityStatusPolicy.ACTIVITY_MAKING, ActivityStatusPolicy.describe(ActivityStatusPolicy.ACTIVITY_MAKING)), (ActivityStatusPolicy.ACTIVITY_ERROR, ActivityStatusPolicy.describe(ActivityStatusPolicy.ACTIVITY_ERROR)), ] """Subscription policy choices.""" activity_status = db.Column(ChoiceType(ACTIVITYSTATUSPOLICY, impl=db.String(1)), default=ActivityStatusPolicy.ACTIVITY_BEGIN, nullable=True, unique=False, index=False) """activity status.""" activity_start = db.Column(db.DateTime, nullable=False) """activity start date.""" activity_end = db.Column(db.DateTime, nullable=True) """activity end date.""" activity_community_id = db.Column(db.Text, nullable=True) """activity community id"""
class Token(db.Model): """A bearer token is the final token that can be used by the client.""" __tablename__ = 'oauth2TOKEN' id = db.Column(db.Integer, primary_key=True, autoincrement=True) """Object ID.""" client_id = db.Column( db.String(255), db.ForeignKey(Client.client_id), nullable=False, ) """Foreign key to client application.""" client = db.relationship('Client', backref=db.backref('oauth2tokens', cascade="all, delete-orphan")) """SQLAlchemy relationship to client application.""" user_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=True) """Foreign key to user.""" user = db.relationship(User, backref=db.backref( "oauth2tokens", cascade="all, delete-orphan", )) """SQLAlchemy relationship to user.""" token_type = db.Column(db.String(255), default='bearer') """Token type - only bearer is supported at the moment.""" access_token = db.Column(String255EncryptedType(type_in=db.String(255), key=secret_key), unique=True) refresh_token = db.Column(String255EncryptedType(type_in=db.String(255), key=secret_key, engine=NoneAesEngine), unique=True, nullable=True) expires = db.Column(db.DateTime, nullable=True) _scopes = db.Column(db.Text) is_personal = db.Column(db.Boolean, default=False) """Personal accesss token.""" is_internal = db.Column(db.Boolean, default=False) """Determines if token is an internally generated token.""" @property def scopes(self): """Return all scopes.""" if self._scopes: return self._scopes.split() return [] @scopes.setter def scopes(self, scopes): """Set scopes.""" validate_scopes(scopes) self._scopes = " ".join(set(scopes)) if scopes else "" def get_visible_scopes(self): """Get list of non-internal scopes for token.""" return [ k for k, s in current_oauth2server.scope_choices() if k in self.scopes ] @classmethod def create_personal(cls, name, user_id, scopes=None, is_internal=False): """Create a personal access token. A token that is bound to a specific user and which doesn't expire, i.e. similar to the concept of an API key. """ with db.session.begin_nested(): scopes = " ".join(scopes) if scopes else "" c = Client(name=name, user_id=user_id, is_internal=True, is_confidential=False, _default_scopes=scopes) c.gen_salt() t = Token( client_id=c.client_id, user_id=user_id, access_token=gen_salt( current_app.config.get('OAUTH2_TOKEN_PERSONAL_SALT_LEN')), expires=None, _scopes=scopes, is_personal=True, is_internal=is_internal, ) db.session.add(c) db.session.add(t) return t
class ItemType(db.Model, Timestamp): """Represent an item type. The ItemType object contains a ``created`` and a ``updated`` properties that are automatically updated. """ # Enables SQLAlchemy-Continuum versioning __versioned__ = {} __tablename__ = 'item_type' id = db.Column( db.Integer(), primary_key=True, autoincrement=True ) """Identifier of item type.""" name_id = db.Column( db.Integer(), db.ForeignKey( 'item_type_name.id', name='fk_item_type_name_id' ), nullable=False ) """Name identifier of item type.""" item_type_name = db.relationship( 'ItemTypeName', backref=db.backref('item_type', lazy='dynamic', order_by=desc('item_type.tag')) ) """Name information from ItemTypeName class.""" schema = db.Column( db.JSON().with_variant( postgresql.JSONB(none_as_null=True), 'postgresql', ).with_variant( JSONType(), 'sqlite', ).with_variant( JSONType(), 'mysql', ), default=lambda: dict(), nullable=True ) """Store schema in JSON format. When you create a new ``item type`` the ``schema`` field value should never be ``NULL``. Default value is an empty dict. ``NULL`` value means that the record metadata has been deleted. """ form = db.Column( db.JSON().with_variant( postgresql.JSONB(none_as_null=True), 'postgresql', ).with_variant( JSONType(), 'sqlite', ).with_variant( JSONType(), 'mysql', ), default=lambda: dict(), nullable=True ) """Store schema form in JSON format. When you create a new ``item type`` the ``form`` field value should never be ``NULL``. Default value is an empty dict. ``NULL`` value means that the record metadata has been deleted. """ render = db.Column( db.JSON().with_variant( postgresql.JSONB(none_as_null=True), 'postgresql', ).with_variant( JSONType(), 'sqlite', ).with_variant( JSONType(), 'mysql', ), default=lambda: dict(), nullable=True ) """Store page render information in JSON format. When you create a new ``item type`` the ``render`` field value should never be ``NULL``. Default value is an empty dict. ``NULL`` value means that the record metadata has been deleted. """ tag = db.Column(db.Integer, nullable=False) """Tag of item type.""" version_id = db.Column(db.Integer, nullable=False) """Used by SQLAlchemy for optimistic concurrency control.""" __mapper_args__ = { 'version_id_col': version_id }
class UserProfile(db.Model): """User profile model. Stores a username, display name (case sensitive version of username) and a full name for a user. """ __tablename__ = 'userprofiles_userprofile' user_id = db.Column(db.Integer, db.ForeignKey(User.id), primary_key=True) """Foreign key to :class:`~invenio_accounts.models.User`.""" user = db.relationship(User, backref=db.backref('profile', uselist=False, cascade='all, delete-orphan')) """User relationship.""" _username = db.Column('username', db.String(255), unique=True) """Lower-case version of username to assert uniqueness.""" _displayname = db.Column('displayname', db.String(255)) """Case preserving version of username.""" full_name = db.Column(db.String(255), nullable=False, default='') """Full name of person.""" @hybrid_property def username(self): """Get username.""" return self._displayname @username.setter def username(self, username): """Set username. .. note:: The username will be converted to lowercase. The display name will contain the original version. """ validate_username(username) self._username = username.lower() self._displayname = username @classmethod def get_by_username(cls, username): """Get profile by username. :param username: A username to query for (case insensitive). """ return cls.query.filter( UserProfile._username == username.lower()).one() @classmethod def get_by_userid(cls, user_id): """Get profile by user identifier. :param user_id: Identifier of a :class:`~invenio_accounts.models.User`. :returns: A :class:`~invenio_userprofiles.models.UserProfile` instance or ``None``. """ return cls.query.filter_by(user_id=user_id).one_or_none() @property def is_anonymous(self): """Return whether this UserProfile is anonymous.""" return False
class User(db.Model, Timestamp, UserMixin): """User data model.""" __tablename__ = "accounts_user" id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) """User email.""" password = db.Column(db.String(255)) """User password.""" active = db.Column(db.Boolean(name='active')) """Flag to say if the user is active or not .""" confirmed_at = db.Column(db.DateTime) """When the user confirmed the email address.""" roles = db.relationship('Role', secondary=userrole, backref=db.backref('users', lazy='dynamic')) """List of the user's roles.""" # Enables SQLAlchemy version counter version_id = db.Column(db.Integer, nullable=False) """Used by SQLAlchemy for optimistic concurrency control.""" __mapper_args__ = {"version_id_col": version_id} login_info = db.relationship("LoginInformation", back_populates="user", uselist=False, lazy="joined") def _get_login_info_attr(self, attr_name): if self.login_info is None: return None return getattr(self.login_info, attr_name) def _set_login_info_attr(self, attr_name, value): if self.login_info is None: self.login_info = LoginInformation() setattr(self.login_info, attr_name, value) @property def current_login_at(self): """When user logged into the current session.""" return self._get_login_info_attr("current_login_at") @property def current_login_ip(self): """Current user IP address.""" return self._get_login_info_attr("current_login_ip") @property def last_login_at(self): """When the user logged-in for the last time.""" return self._get_login_info_attr("last_login_at") @property def last_login_ip(self): """Last user IP address.""" return self._get_login_info_attr("last_login_ip") @property def login_count(self): """Count how many times the user logged in.""" return self._get_login_info_attr("login_count") @current_login_at.setter def current_login_at(self, value): return self._set_login_info_attr("current_login_at", value) @current_login_ip.setter def current_login_ip(self, value): return self._set_login_info_attr("current_login_ip", value) @last_login_at.setter def last_login_at(self, value): return self._set_login_info_attr("last_login_at", value) @last_login_ip.setter def last_login_ip(self, value): return self._set_login_info_attr("last_login_ip", value) @login_count.setter def login_count(self, value): return self._set_login_info_attr("login_count", value) def __str__(self): """Representation.""" return 'User <id={0.id}, email={0.email}>'.format(self)
class Counter(db.Model): """Stores generated identifiers.""" __tablename__ = 'sequencegenerator_counter' template_instance = db.Column(db.String(255), nullable=False, primary_key=True, index=True) """The template string to use.""" definition_name = db.Column(db.ForeignKey(TemplateDefinition.name)) """Link to the template definition.""" counter = db.Column(db.Integer, nullable=False) """Running counter.""" template_definition = db.relationship(TemplateDefinition, lazy='joined', backref=db.backref( 'counters', cascade='all, delete-orphan')) # Optimistic concurrency control __mapper_args__ = { 'version_id_col': counter, 'version_id_generator': False } @classmethod def create(cls, meta_template, ctx=None, **kwargs): """Initialize a counter.""" assert 'meta_template' not in kwargs return cls(template_instance=meta_template.format(**ctx or {}), **kwargs) @classmethod def get(cls, definition, ctx=None): """Get a ``Counter``.""" return cls.query.get(definition.format(**ctx or {})) def increment(self): """Generate next identifier.""" next_identifier = self.template_instance.format(counter=self.counter) with db.session.begin_nested(): self.counter += self.template_definition.step return next_identifier def reset(self, start=0): """Reset counter.""" with db.session.begin_nested(): # Ensure no children exist for child in self.template_definition.children: if child.counters: raise InvalidResetCall() self.counter = start def __repr__(self): """Canonical representation of ``Counter``.""" return ('Counter(' 'template_instance={0.template_instance!r}, ' 'definition_name={0.definition_name!r}, ' 'counter={0.counter!r}, ' 'template_definition={0.template_definition!r})').format(self)
class ReanaWorkflow(db.Model): """Model defining a REANA workflow.""" __tablename__ = 'reana_workflows' id = db.Column(UUIDType, primary_key=True, default=uuid.uuid4, nullable=False) rec_uuid = db.Column(UUIDType, db.ForeignKey(RecordMetadata.id), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False) workflow_id = db.Column(UUIDType, unique=True, nullable=False) name = db.Column(db.String(100), unique=False, nullable=False) workflow_name = db.Column(db.String(100), unique=False, nullable=False) workflow_name_run = db.Column(db.String(100), unique=False, nullable=False) status = db.Column(db.Enum('created', 'queued', 'running', 'stopped', 'failed', 'finished', 'deleted', name='status'), unique=False, nullable=False) # the following fields represent the creation part of a workflow workflow_json = db.Column(json_type, default=lambda: dict(), nullable=True) # logging after the workflow runs logs = db.Column(json_type, default=lambda: dict(), nullable=True) created = db.Column(db.DateTime, server_default=db.func.now()) updated = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now()) user = db.relationship('User') record = db.relationship('RecordMetadata', backref=db.backref('reana_workflows', cascade='all, delete-orphan')) @classmethod def get_user_workflows(cls, user_id): """Get user workflows.""" workflows = cls.query \ .filter_by(user_id=user_id) \ .all() return workflows @classmethod def get_deposit_workflows(cls, depid): """Get deposit workflows.""" workflows = cls.query \ .filter_by(rec_uuid=depid) \ .all() return workflows @classmethod def get_workflow_by_id(cls, workflow_id): """Get workflow by id.""" return cls.query \ .filter_by(workflow_id=workflow_id) \ .one_or_none() def serialize(self): """Serialize schema model.""" return reana_workflow_serializer.dump(self).data