Ejemplo n.º 1
0
class RnkCITATIONLOG(db.Model):
    """Represents a RnkCITATIONLOG record."""

    __tablename__ = 'rnkCITATIONLOG'
    id = db.Column(db.Integer(11, unsigned=True),
                   primary_key=True,
                   autoincrement=True,
                   nullable=False)
    citee = db.Column(db.Integer(10, unsigned=True), nullable=False)
    citer = db.Column(db.Integer(10, unsigned=True), nullable=False)
    type = db.Column(db.Enum('added', 'removed', name='rnkcitationlog_type'),
                     nullable=True)
    action_date = db.Column(db.DateTime, nullable=False)
    __table_args__ = (db.Index('citee', citee), db.Index('citer', citer),
                      db.Model.__table_args__)
Ejemplo n.º 2
0
class PidLog(db.Model):

    """Audit log of actions happening to persistent identifiers.

    This model is primarily used through PersistentIdentifier.log and rarely
    created manually.
    """

    __tablename__ = 'pidLOG'
    __table_args__ = (
        db.Index('idx_action', 'action'),
    )

    id = db.Column(db.Integer(15, unsigned=True), primary_key=True)
    """Id of persistent identifier entry."""

    id_pid = db.Column(
        db.Integer(15, unsigned=True), db.ForeignKey(PersistentIdentifier.id),
        nullable=True,
    )
    """PID."""

    timestamp = db.Column(db.DateTime(), nullable=False, default=datetime.now)
    """Creation datetime of entry."""

    action = db.Column(db.String(10), nullable=False)
    """Action identifier."""

    message = db.Column(db.Text(), nullable=False)
    """Log message."""

    # Relationship
    pid = db.relationship("PersistentIdentifier", backref="logs")
Ejemplo n.º 3
0
class BskRECORDCOMMENT(db.Model):
    """Represents a BskRECORDCOMMENT record."""
    __tablename__ = 'bskRECORDCOMMENT'
    id = db.Column(db.Integer(15, unsigned=True), nullable=False,
                primary_key=True, autoincrement=True)
    id_bibrec_or_bskEXTREC = db.Column(db.Integer(16), nullable=False,
                server_default='0')
    id_bskBASKET = db.Column(db.Integer(15, unsigned=True),
                db.ForeignKey(BskBASKET.id), nullable=False,
                server_default='0')
    id_user = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id),
                nullable=False, server_default='0')
    title = db.Column(db.String(255), nullable=False,
                server_default='')
    body = db.Column(db.Text, nullable=False)
    date_creation = db.Column(db.DateTime, nullable=False,
                server_default='1900-01-01 00:00:00', index=True)
    priority = db.Column(db.Integer(15), nullable=False,
                server_default='0')
    in_reply_to_id_bskRECORDCOMMENT = db.Column(db.Integer(15, unsigned=True),
                db.ForeignKey(id), nullable=False, server_default='0')
    reply_order_cached_data = db.Column(db.Binary, nullable=True)
    in_reply_to = db.relationship('BskRECORDCOMMENT')
    basket = db.relationship(BskBASKET, backref='RECORDCOMMENTs')
    user = db.relationship(User)

    __table_args__ = (db.Index('bskRECORDCOMMENT_reply_order_cached_data',
                               reply_order_cached_data, mysql_length=[40]),
                      db.Model.__table_args__)
Ejemplo n.º 4
0
class RnkCITATIONDICT(db.Model):
    """Represent a RnkCITATIONDICT record."""

    __tablename__ = 'rnkCITATIONDICT'
    citee = db.Column(db.Integer(10, unsigned=True), primary_key=True)
    citer = db.Column(db.Integer(10, unsigned=True), primary_key=True)
    last_updated = db.Column(db.DateTime, nullable=False)
    __table_args__ = (db.Index('rnkCITATIONDICT_reverse', citer,
                               citee), db.Model.__table_args__)
def do_upgrade():
    """ Implement your upgrades here  """
    m = db.MetaData(bind=db.engine)
    m.reflect()

    tpid = db.Table(
        'pid',
        m,
        db.Column('id', db.Integer(15, unsigned=True), primary_key=True, nullable=False),
        db.Column('type', db.String(length=6), nullable=False),
        db.Column('pid', db.String(length=255), nullable=False),
        db.Column('status', db.Char(length=1), nullable=False),
        db.Column('created', db.DateTime(), nullable=False),
        db.Column('last_modified', db.DateTime(), nullable=False),
        db.Index('uidx_type_pid', 'type', 'pid', unique=True),
        db.Index('idx_status', 'status'),
        mysql_engine='MyISAM',
    )

    tpidlog = db.Table(
        'pidLOG',
        m,
        db.Column('id', db.Integer(15, unsigned=True), primary_key=True, nullable=False),
        db.Column('id_pid', db.Integer(15, unsigned=True), ForeignKey('pid.id')),
        db.Column('timestamp', DateTime(), nullable=False),
        db.Column('action', db.String(length=10), nullable=False),
        db.Column('message', Text(), nullable=False),
        db.Index('idx_action', 'action'),
        mysql_engine='MyISAM',
    )

    tpidregistry = db.Table(
        'pidREGISTRY',
        m,
        db.Column('object_type', db.String(length=3), primary_key=True, nullable=False),
        db.Column('object_id', db.String(length=255), nullable=False),
        db.Column('id_pid', db.Integer(15, unsigned=True), ForeignKey('pid.id'), primary_key=True, nullable=False),
        db.Index('idx_type_id', 'object_type', 'object_id'),
        mysql_engine='MyISAM',
    )

    tpid.create()
    tpidlog.create()
    tpidregistry.create()
Ejemplo n.º 6
0
class AccARGUMENT(db.Model):
    """Represent an authorization argument."""

    __tablename__ = 'accARGUMENT'
    id = db.Column(db.Integer(15), primary_key=True, autoincrement=True)
    keyword = db.Column(db.String(32), nullable=True)
    value = db.Column(db.String(255), nullable=True)
    __table_args__ = (db.Index('KEYVAL', keyword,
                               value), db.Model.__table_args__)

    def __repr__(self):
        return "{0.keyword}={0.value}".format(self)
Ejemplo n.º 7
0
class UserEXT(db.Model):
    """Represent a UserEXT record."""

    __tablename__ = 'userEXT'

    id = db.Column(db.VARBINARY(255), primary_key=True, nullable=False)
    method = db.Column(db.String(50), primary_key=True, nullable=False)
    id_user = db.Column(db.Integer(15, unsigned=True),
                        db.ForeignKey(User.id),
                        nullable=False)

    user = db.relationship(User, backref="external_identifiers")

    __table_args__ = (db.Index('id_user', id_user, method,
                               unique=True), db.Model.__table_args__)
Ejemplo n.º 8
0
class SeqSTORE(db.Model):
    """Represents a SeqSTORE record."""
    __tablename__ = 'seqSTORE'

    id = db.Column(db.Integer(15, unsigned=True),
                   primary_key=True,
                   nullable=False,
                   autoincrement=True)
    seq_name = db.Column(db.String(15))
    seq_value = db.Column(db.String(20))

    __table_args__ = (db.Index('seq_name_value',
                               seq_name,
                               seq_value,
                               unique=True), db.Model.__table_args__)
Ejemplo n.º 9
0
class Bibdocmoreinfo(db.Model):
    """Represents a Bibdocmoreinfo record."""
    __tablename__ = 'bibdocmoreinfo'

    id = db.Column(db.MediumInteger(9, unsigned=True), primary_key=True)
    id_bibdoc = db.Column(db.MediumInteger(9, unsigned=True),
                          db.ForeignKey(Bibdoc.id),
                          nullable=True)
    version = db.Column(db.TinyInteger(4, unsigned=True), nullable=True)
    format = db.Column(db.String(50), nullable=True)
    id_rel = db.Column(db.MediumInteger(9, unsigned=True), nullable=True)
    namespace = db.Column(db.Char(25), nullable=True)
    data_key = db.Column(db.Char(25))
    data_value = db.Column(db.LargeBinary)

    __table_args__ = (db.Index('bibdocmoreinfo_key', id_bibdoc, version,
                               format, id_rel, namespace,
                               data_key), db.Model.__table_args__)
Ejemplo n.º 10
0
class Usergroup(db.Model):
    """Represent a Usergroup record."""
    def __str__(self):
        """Return string representation."""
        return "%s <%s>" % (self.name, self.description)

    __tablename__ = 'usergroup'

    JOIN_POLICIES = {
        'VISIBLEOPEN': 'VO',
        'VISIBLEMAIL': 'VM',
        'INVISIBLEOPEN': 'IO',
        'INVISIBLEMAIL': 'IM',
        'VISIBLEEXTERNAL': 'VE',
    }

    LOGIN_METHODS = {
        'INTERNAL': 'INTERNAL',
        'EXTERNAL': 'EXTERNAL',
    }

    id = db.Column(db.Integer(15, unsigned=True),
                   nullable=False,
                   primary_key=True,
                   autoincrement=True)
    name = db.Column(db.String(255),
                     nullable=False,
                     server_default='',
                     unique=True,
                     index=True)
    description = db.Column(db.Text, nullable=True)
    join_policy = db.Column(ChoiceType(map(lambda (k, v): (v, k),
                                           JOIN_POLICIES.items()),
                                       impl=db.CHAR(2)),
                            nullable=False,
                            server_default='')
    login_method = db.Column(ChoiceType(
        map(lambda (k, v): (v, k), LOGIN_METHODS.items())),
                             nullable=False,
                             server_default='INTERNAL')

    # FIXME Unique(login_method(70), name)
    __table_args__ = (db.Index('login_method_name',
                               'login_method',
                               'name',
                               mysql_length={
                                   'login_method': 60,
                                   'name': 255
                               }), db.Model.__table_args__)

    @classmethod
    def filter_visible(cls):
        """Return query object with filtered out invisible groups."""
        visible = filter(lambda k: k[0] == 0, cls.JOIN_POLICIES.values())
        assert len(visible) > 1  # if implementation chage use == instead of in
        return cls.query.filter(cls.join_policy.in_(visible))

    @property
    def login_method_is_external(self):
        """Return True if the group is external."""
        return self.login_method == Usergroup.LOGIN_METHODS['EXTERNAL']

    def join(self, user, status=None):
        """Join user to group.

        :param user: User to add into the group.
        :param status: status of user
        """
        # if I want to join another user from the group
        if (user.id != current_user.get_id() and
                # I need to be an admin of the group
                not self.is_admin(current_user.get_id())):
            raise AccountSecurityError(
                'Not enough right to '
                'add user "{0}" from group "{1}"'.format(
                    user.nickname, self.name))

        # join group
        self.users.append(
            UserUsergroup(
                id_user=user.id,
                user_status=status or self.new_user_status,
            ))
        try:
            db.session.commit()
        except Exception:
            db.session.rollback()
            raise

    def leave(self, user):
        """Remove user from group.

        :param user: User to remove from the group.
        """
        # if I want to remove another user from the group
        if (user.id != current_user.get_id() and
                # I need to be an admin of the group
                not self.is_admin(current_user.get_id())):
            raise AccountSecurityError(
                'Not enough right to '
                'remove user "{0}" from group "{1}"'.format(
                    user.nickname, self.name))

        # check that I'm not the last admin before leaving the group.
        if self.is_admin(user.id) and self.admins.count() == 1:
            raise IntegrityUsergroupError('User can leave the group '
                                          'without admins, please delete the '
                                          'group if you want to leave.')

        # leave the group
        UserUsergroup.query.filter_by(
            id_usergroup=self.id,
            id_user=user.id,
        ).delete()
        try:
            db.session.commit()
        except Exception:
            db.session.rollback()
            raise

    def is_admin(self, id_user):
        """Return True if the user is an admin of the group."""
        return db.session.query(
            self.admins.filter(
                UserUsergroup.id_user == id_user).exists()).scalar()

    def get_users_not_in_this_group(self,
                                    nickname=None,
                                    email=None,
                                    limit=None):
        """Return users that not joined this group."""
        # base query
        query = User.query.outerjoin(User.usergroups).filter(
            User.id.notin_(
                db.select([UserUsergroup.id_user],
                          UserUsergroup.id_usergroup == self.id)))
        # additional optional filters
        if nickname:
            query = query.filter(User.nickname.like(nickname))
        if email:
            query = query.filter(User.email.like(email))
        if limit:
            query = query.limit(limit)
        # return results
        return query

    @property
    def new_user_status(self):
        """Return user status for new user."""
        if not self.join_policy.code.endswith('O'):
            return UserUsergroup.USER_STATUS['PENDING']
        return UserUsergroup.USER_STATUS['MEMBER']
Ejemplo n.º 11
0
class CmtRECORDCOMMENT(db.Model):
    """Represents a CmtRECORDCOMMENT record."""

    __tablename__ = 'cmtRECORDCOMMENT'

    id = db.Column(db.Integer(15, unsigned=True),
                   nullable=False,
                   primary_key=True,
                   autoincrement=True)
    id_bibrec = db.Column(db.MediumInteger(8, unsigned=True),
                          db.ForeignKey(Bibrec.id),
                          nullable=False,
                          server_default='0')
    id_user = db.Column(db.Integer(15, unsigned=True),
                        db.ForeignKey(User.id),
                        nullable=False,
                        server_default='0')
    title = db.Column(db.String(255), nullable=False, server_default='')
    body = db.Column(db.Text, nullable=False)
    date_creation = db.Column(db.DateTime,
                              nullable=False,
                              server_default='1900-01-01 00:00:00')
    star_score = db.Column(db.TinyInteger(5, unsigned=True),
                           nullable=False,
                           server_default='0')
    nb_votes_yes = db.Column(db.Integer(10),
                             nullable=False,
                             server_default='0')
    nb_votes_total = db.Column(db.Integer(10, unsigned=True),
                               nullable=False,
                               server_default='0')
    nb_abuse_reports = db.Column(db.Integer(10),
                                 nullable=False,
                                 server_default='0')
    status = db.Column(db.Char(2),
                       nullable=False,
                       index=True,
                       server_default='ok')
    round_name = db.Column(db.String(255), nullable=False, server_default='')
    restriction = db.Column(db.String(50), nullable=False, server_default='')
    in_reply_to_id_cmtRECORDCOMMENT = db.Column(db.Integer(15, unsigned=True),
                                                db.ForeignKey(id),
                                                nullable=False,
                                                server_default='0')
    reply_order_cached_data = db.Column(db.Binary, nullable=True)
    bibrec = db.relationship(Bibrec, backref='recordcomments')
    user = db.relationship(User, backref='recordcomments')
    replies = db.relationship('CmtRECORDCOMMENT',
                              backref=db.backref('parent',
                                                 remote_side=[id],
                                                 order_by=date_creation))

    @property
    def is_deleted(self):
        """Check if is deleted."""
        return self.status != 'ok'

    def is_collapsed(self, id_user):
        """Return true if the comment is collapsed by user."""
        return CmtCOLLAPSED.query.filter(
            db.and_(CmtCOLLAPSED.id_bibrec == self.id_bibrec,
                    CmtCOLLAPSED.id_cmtRECORDCOMMENT == self.id,
                    CmtCOLLAPSED.id_user == id_user)).count() > 0

    @session_manager
    def collapse(self, id_user):
        """Collapse comment beloging to user."""
        c = CmtCOLLAPSED(id_bibrec=self.id_bibrec,
                         id_cmtRECORDCOMMENT=self.id,
                         id_user=id_user)
        db.session.add(c)
        db.session.commit()

    def expand(self, id_user):
        """Expand comment beloging to user."""
        CmtCOLLAPSED.query.filter(
            db.and_(CmtCOLLAPSED.id_bibrec == self.id_bibrec,
                    CmtCOLLAPSED.id_cmtRECORDCOMMENT == self.id,
                    CmtCOLLAPSED.id_user == id_user)).delete(
                        synchronize_session=False)

    __table_args__ = (db.Index('cmtRECORDCOMMENT_reply_order_cached_data',
                               reply_order_cached_data,
                               mysql_length=40), db.Model.__table_args__)

    @classmethod
    def count(cls, *criteria, **filters):
        """Count how many comments."""
        return cls.query.filter(*criteria).filter_by(**filters).count()
Ejemplo n.º 12
0
class PersistentIdentifier(db.Model):

    """Store and register persistent identifiers.

    Assumptions:
      * Persistent identifiers can be represented as a string of max 255 chars.
      * An object has many persistent identifiers.
      * A persistent identifier has one and only one object.
    """

    __tablename__ = 'pidSTORE'
    __table_args__ = (
        db.Index('uidx_type_pid', 'pid_type', 'pid_value', unique=True),
        db.Index('idx_status', 'status'),
        db.Index('idx_object', 'object_type', 'object_value'),
    )

    id = db.Column(db.Integer(15, unsigned=True), primary_key=True)
    """Id of persistent identifier entry."""

    pid_type = db.Column(db.String(6), nullable=False)
    """Persistent Identifier Schema."""

    pid_value = db.Column(db.String(length=255), nullable=False)
    """Persistent Identifier."""

    pid_provider = db.Column(db.String(length=255), nullable=False)
    """Persistent Identifier Provider"""

    status = db.Column(db.CHAR(length=1), nullable=False)
    """Status of persistent identifier, e.g. registered, reserved, deleted."""

    object_type = db.Column(db.String(3), nullable=True)
    """Object Type - e.g. rec for record."""

    object_value = db.Column(db.String(length=255), nullable=True)
    """Object ID - e.g. a record id."""

    created = db.Column(db.DateTime(), nullable=False, default=datetime.now)
    """Creation datetime of entry."""

    last_modified = db.Column(
        db.DateTime(), nullable=False, default=datetime.now,
        onupdate=datetime.now
    )
    """Last modification datetime of entry."""

    #
    # Class methods
    #
    @classmethod
    def create(cls, pid_type, pid_value, pid_provider='', provider=None):
        """Internally reserve a new persistent identifier.

        A provider for the given persistent identifier type must exists. By
        default the system will choose a provider according to the pid
        type. If desired, the default system provider can be overridden via
        the provider keyword argument.

        Return PID object if successful otherwise None.
        """
        # Ensure provider exists
        if provider is None:
            provider = PidProvider.create(pid_type, pid_value, pid_provider)
            if not provider:
                raise Exception(
                    "No provider found for %s:%s (%s)" % (
                        pid_type, pid_value, pid_provider)
                )

        try:
            obj = cls(pid_type=provider.pid_type,
                      pid_value=provider.create_new_pid(pid_value),
                      pid_provider=pid_provider,
                      status=cfg['PIDSTORE_STATUS_NEW'])
            obj._provider = provider
            db.session.add(obj)
            db.session.commit()
            obj.log("CREATE", "Created")
            return obj
        except SQLAlchemyError:
            db.session.rollback()
            obj.log("CREATE", "Failed to created. Already exists.")
            return None

    @classmethod
    def get(cls, pid_type, pid_value, pid_provider='', provider=None):
        """Get persistent identifier.

        Return None if not found.
        """
        pid_value = to_unicode(pid_value)
        obj = cls.query.filter_by(
            pid_type=pid_type, pid_value=pid_value, pid_provider=pid_provider
        ).first()
        if obj:
            obj._provider = provider
            return obj
        else:
            return None

    #
    # Instance methods
    #
    def has_object(self, object_type, object_value):
        """Determine if this PID is assigned to a specific object."""
        if object_type not in cfg['PIDSTORE_OBJECT_TYPES']:
            raise Exception("Invalid object type %s." % object_type)

        object_value = to_unicode(object_value)

        return self.object_type == object_type and \
            self.object_value == object_value

    def get_provider(self):
        """Get the provider for this type of persistent identifier."""
        if self._provider is None:
            self._provider = PidProvider.create(
                self.pid_type, self.pid_value, self.pid_provider
            )
        return self._provider

    def assign(self, object_type, object_value, overwrite=False):
        """Assign this persistent identifier to a given object.

        Note, the persistent identifier must first have been reserved. Also,
        if an exsiting object is already assigned to the pid, it will raise an
        exception unless overwrite=True.
        """
        if object_type not in cfg['PIDSTORE_OBJECT_TYPES']:
            raise Exception("Invalid object type %s." % object_type)
        object_value = to_unicode(object_value)

        if not self.id:
            raise Exception(
                "You must first create the persistent identifier before you "
                "can assign objects to it."
            )

        if self.is_deleted():
            raise Exception(
                "You cannot assign objects to a deleted persistent identifier."
            )

        # Check for an existing object assigned to this pid
        existing_obj_id = self.get_assigned_object(object_type)

        if existing_obj_id and existing_obj_id != object_value:
            if not overwrite:
                raise Exception(
                    "Persistent identifier is already assigned to another "
                    "object"
                )
            else:
                self.log(
                    "ASSIGN",
                    "Unassigned object %s:%s (overwrite requested)" % (
                        self.object_type, self.object_value)
                )
                self.object_type = None
                self.object_value = None
        elif existing_obj_id and existing_obj_id == object_value:
            # The object is already assigned to this pid.
            return True

        self.object_type = object_type
        self.object_value = object_value
        db.session.commit()
        self.log("ASSIGN", "Assigned object %s:%s" % (self.object_type,
                                                      self.object_value))
        return True

    def update(self, with_deleted=False, *args, **kwargs):
        """Update the persistent identifier with the provider.."""
        if self.is_new() or self.is_reserved():
            raise Exception(
                "Persistent identifier has not yet been registered."
            )

        if not with_deleted and self.is_deleted():
            raise Exception("Persistent identifier has been deleted.")

        provider = self.get_provider()
        if provider is None:
            self.log("UPDATE", "No provider found.")
            raise Exception("No provider found.")

        if provider.update(self, *args, **kwargs):
            if with_deleted and self.is_deleted():
                self.status = cfg['PIDSTORE_STATUS_REGISTERED']
                db.session.commit()
            return True
        return False

    def reserve(self, *args, **kwargs):
        """Reserve the persistent identifier with the provider.

        Note, the reserve method may be called multiple times, even if it was
        already reserved.
        """
        if not (self.is_new() or self.is_reserved()):
            raise Exception(
                "Persistent identifier has already been registered."
            )

        provider = self.get_provider()
        if provider is None:
            self.log("RESERVE", "No provider found.")
            raise Exception("No provider found.")

        if provider.reserve(self, *args, **kwargs):
            self.status = cfg['PIDSTORE_STATUS_RESERVED']
            db.session.commit()
            return True
        return False

    def register(self, *args, **kwargs):
        """Register the persistent identifier with the provider."""
        if self.is_registered() or self.is_deleted():
            raise Exception(
                "Persistent identifier has already been registered."
            )

        provider = self.get_provider()
        if provider is None:
            self.log("REGISTER", "No provider found.")
            raise Exception("No provider found.")

        if provider.register(self, *args, **kwargs):
            self.status = cfg['PIDSTORE_STATUS_REGISTERED']
            db.session.commit()
            return True
        return False

    def delete(self, *args, **kwargs):
        """Delete the persistent identifier."""
        if self.is_new():
            # New persistent identifier which haven't been registered yet. Just
            #  delete it completely but keep log)
            # Remove links to log entries (but otherwise leave the log entries)
            PidLog.query.filter_by(id_pid=self.id).update({'id_pid': None})
            db.session.delete(self)
            self.log("DELETE", "Unregistered PID successfully deleted")
        else:
            provider = self.get_provider()
            if not provider.delete(self, *args, **kwargs):
                return False
            self.status = cfg['PIDSTORE_STATUS_DELETED']
            db.session.commit()
        return True

    def sync_status(self, *args, **kwargs):
        """Synchronize persistent identifier status.

        Used when the provider uses an external service, which might have been
        modified outside of our system.
        """
        provider = self.get_provider()
        result = provider.sync_status(self, *args, **kwargs)
        db.session.commit()
        return result

    def get_assigned_object(self, object_type=None):
        """Return an assigned object."""
        if object_type is not None and self.object_type == object_type:
            return self.object_value
        return None

    def is_registered(self):
        """Return true if the persistent identifier has been registered."""
        return self.status == cfg['PIDSTORE_STATUS_REGISTERED']

    def is_deleted(self):
        """Return true if the persistent identifier has been deleted."""
        return self.status == cfg['PIDSTORE_STATUS_DELETED']

    def is_new(self):
        """Return true if the PIDhas not yet been registered or reserved."""
        return self.status == cfg['PIDSTORE_STATUS_NEW']

    def is_reserved(self):
        """Return true if the PID has not yet been reserved."""
        return self.status == cfg['PIDSTORE_STATUS_RESERVED']

    def log(self, action, message):
        """Store action and message in log."""
        if self.pid_type and self.pid_value:
            message = "[%s:%s] %s" % (self.pid_type, self.pid_value, message)
        p = PidLog(id_pid=self.id, action=action, message=message)
        db.session.add(p)
        db.session.commit()