class UserRoleEntity(db.Model, CRUDMixin):
    """ Stores the user-role mapping """

    __tablename__ = 'UserRole'
    id = db.Column("urID", db.Integer, primary_key=True)
    user_id = db.Column("usrID",
                        db.Integer,
                        db.ForeignKey('User.usrID', ondelete='CASCADE'),
                        nullable=False)
    role_id = db.Column("rolID",
                        db.Integer,
                        db.ForeignKey('Role.rolID', ondelete='CASCADE'),
                        nullable=False)
    added_at = db.Column('urAddedAt',
                         db.DateTime(),
                         nullable=False,
                         server_default='0000-00-00 00:00:00')

    role = db.relationship('RoleEntity', uselist=False)
    user = db.relationship('UserEntity', uselist=False)

    def get_id(self):
        """ return the unicode of the primary key value """
        return unicode(self.id)

    def __repr__(self):
        return "<UserRoleEntity (\n\t" \
            "urID: {0.id}, \n\t" \
            " {0.user!r}, \n\t" \
            " {0.role!r}, \n" \
            " {0.added_at}, \n" \
            ")>".format(self)
Пример #2
0
class SubjectFileEntity(db.Model, CRUDMixin):

    """ Stores the file metadata """
    __tablename__ = 'SubjectFile'

    id = db.Column("sfID", db.Integer, primary_key=True)
    subject_id = db.Column("sbjID", db.Integer, db.ForeignKey('Subject.sbjID'),
                           nullable=False)
    event_id = db.Column("evtID", db.Integer, db.ForeignKey('Event.evtID'),
                         nullable=False)
    file_name = db.Column("sfFileName", db.String(255), nullable=False)
    file_check_sum = db.Column("sfFileCheckSum", db.String(32), nullable=False)
    file_size = db.Column("sfFileSize", db.String(255), nullable=False)
    uploaded_at = db.Column("sfUploadedAt", db.DateTime(), nullable=False,
                            server_default='0000-00-00 00:00:00')
    user_id = db.Column("usrID", db.Integer, db.ForeignKey('User.usrID'),
                        nullable=False)

    # @OneToOne
    subject = db.relationship('SubjectEntity', uselist=False, lazy='joined')
    event = db.relationship('EventEntity', uselist=False, lazy='joined')
    user = db.relationship('UserEntity', uselist=False, lazy='joined')

    def get_full_path(self, prefix):
        """
        Build the full path using the database info and the prefix
        @TODO: implement the naming convention
        """
        return os.path.join(prefix, self.file_name)

    def __repr__(self):
        return "<SubjectFileEntity (sfID: {0.id}, sbjID: {0.subject_id})>" \
            "usrID: {0.user_id}".format(self)

    def serialize(self):
        """Return object data for jsonification """

        return {
            'id': self.id,
            'file_name': self.file_name,
            'file_check_sum': self.file_check_sum,
            'file_size': self.file_size,
            'uploaded_at': dump_datetime(self.uploaded_at),
            'subject_id': self.subject_id,
            'event_id': self.event_id,
            'user_id': self.user_id,
            'user_name': self.user.get_name(),
            # 'subject': self.subject.serialize(),
            # 'event': self.event.serialize(),
            # 'user': self.user.serialize(),
        }
class WebSessionEntity(db.Model, CRUDMixin):
    """Store web session details"""
    __tablename__ = 'WebSession'

    id = db.Column('webID', db.Integer, primary_key=True)
    session_id = db.Column('webSessID',
                           db.String(255),
                           nullable=False,
                           default='')
    user_id = db.Column('usrID',
                        db.Integer,
                        db.ForeignKey('User.usrID'),
                        nullable=False,
                        default=0)
    ip = db.Column('webIP', db.String(15), nullable=False, default='')
    date_time = db.Column('webDateTime',
                          db.DateTime,
                          nullable=False,
                          default=datetime.datetime(datetime.MINYEAR, 1, 1))
    user_agent_id = db.Column('uaID',
                              db.Integer,
                              db.ForeignKey('UserAgent.uaID'),
                              nullable=False)
    # @OneToMany
    user_agent = db.relationship(UserAgentEntity, lazy='joined')
    user = db.relationship(UserEntity, lazy='joined')

    @staticmethod
    def get_by_session_id(session_id):
        """ Search helper: WHERE webSessID = ???"""
        return WebSessionEntity.query.filter_by(session_id=session_id).first()

    def __repr__(self):
        """ Return a friendly object representation """
        return "<WebSessionEntity (webID: '{0.id}', webSessID: {0.session_id},"\
               " usrID: {0.user_id}, webIP: {0.ip})>".format(self)
Пример #4
0
class SubjectFileEntity(db.Model, CRUDMixin):
    """ Stores the uploaded file metadata """
    __tablename__ = 'SubjectFile'

    id = db.Column("sfID", db.Integer, primary_key=True)
    subject_id = db.Column("sbjID",
                           db.Integer,
                           db.ForeignKey('Subject.sbjID'),
                           nullable=False)
    event_id = db.Column("evtID",
                         db.Integer,
                         db.ForeignKey('Event.evtID'),
                         nullable=False)
    file_name = db.Column("sfFileName", db.String(255), nullable=False)
    file_check_sum = db.Column("sfFileCheckSum", db.String(32), nullable=False)
    file_size = db.Column("sfFileSize", db.String(255), nullable=False)
    uploaded_at = db.Column("sfUploadedAt",
                            db.DateTime,
                            nullable=False,
                            server_default='0000-00-00 00:00:00')
    user_id = db.Column("usrID",
                        db.Integer,
                        db.ForeignKey('User.usrID'),
                        nullable=False)

    # @OneToOne
    subject = db.relationship('SubjectEntity', uselist=False, lazy='joined')
    event = db.relationship('EventEntity', uselist=False, lazy='joined')
    user = db.relationship('UserEntity', uselist=False, lazy='joined')

    def create_folder(self, directory):
        """
        Create folder if it does not exist
        """
        success = True

        if not os.path.exists(directory):
            try:
                os.makedirs(directory)
            except Exception as exc:
                print "Failed due: {}".format(exc)
                success = False
        return success

    @classmethod
    def get_convention_file_name(cls, date_and_time, subject_id, file_name):
        """
        Concatenate the pieces to obtain a fiendly file name.

        @TODO: check if we need to need the "site ID" and
            how to obtain it.

        Original convention:
            20120101_0123_SiteID_A_SubjectID_B_Sequence123_xyz.jpg

        Actual implementation (does not keep track of sequences):
            20120101_0123_site_subject_B_xyz.jpg
        """
        date_part = date_and_time.strftime("%Y%m%d")
        time_part = date_and_time.strftime("%H%M")

        file_convention = "{}_{}_site_subject_{}_{}".format(
            date_part, time_part, subject_id, file_name)
        return file_convention

    def get_full_path(self, prefix):
        """
        Build the full path using the database info and the prefix
        @TODO: implement the naming convention

        20120101_0123_SiteIDA_SubjectIDB_Sequence123_xyz.jpg
        """
        subject_dir = os.path.join(prefix,
                                   "subject_{}".format(self.subject.redcap_id))
        success = self.create_folder(subject_dir)
        assert success

        file_convention = SubjectFileEntity.get_convention_file_name(
            self.uploaded_at, self.subject.redcap_id, self.file_name)
        full_path = os.path.join(subject_dir, file_convention)
        return full_path

    def __repr__(self):
        """ Return a friendly object representation """
        return "<SubjectFileEntity (sfID: {0.id}, sbjID: {0.subject_id}, " \
            "usrID: {0.user_id}, sfFileName: {0.file_name}>)".format(self)

    def serialize(self):
        """Return object data for jsonification """
        # @TODO: add information about download counts
        return {
            'id': self.id,
            'file_name': self.file_name,
            'file_check_sum': self.file_check_sum,
            'file_size': self.file_size,
            'uploaded_at': utils.localize_est_datetime(self.uploaded_at),
            'subject_id': self.subject_id,
            'event_id': self.event_id,
            'user_id': self.user_id,
            'user_name': self.user.get_name(),
            # 'subject': self.subject.serialize(),
            # 'event': self.event.serialize(),
            # 'user': self.user.serialize(),
        }
Пример #5
0
class LogEntity(db.Model, CRUDMixin):

    """ Keep track of important user actions """
    __tablename__ = 'Log'

    id = db.Column('logID', db.Integer, primary_key=True)
    type_id = db.Column('logtID', db.Integer,
                        db.ForeignKey('LogType.logtID'),
                        nullable=False)
    web_session_id = db.Column('webID', db.Integer,
                               db.ForeignKey('WebSession.webID'),
                               nullable=False)
    date_time = db.Column('logDateTime', db.DateTime, nullable=False,
                          server_default='0000-00-00 00:00:00')
    details = db.Column('logDetails', db.Text, nullable=False)

    # @OneToOne
    log_type = db.relationship(LogTypeEntity, uselist=False, lazy='joined')
    web_session = db.relationship(WebSessionEntity, uselist=False,
                                  lazy='joined')

    @staticmethod
    def get_logs(per_page=25, page_num=1):
        """
        Helper for formating the event details
        """
        def item_from_entity(entity):
            return {
                'id': entity.id,
                'user_email': entity.web_session.user.email
                if entity.web_session.user is not None else '',
                'type': entity.log_type.type,
                'details': entity.details,
                'web_session_ip': entity.web_session.ip,
                'date_time': utils.localize_est_datetime(entity.date_time),
                }

        pagination = LogEntity.query.paginate(page_num, per_page, False)
        items = map(item_from_entity, pagination.items)
        return items, pagination.pages

    @staticmethod
    def _log(log_type, session_id, details=''):
        """ Helper for logging """
        logt = LogTypeEntity.query.filter_by(type=log_type).first()
        if logt is None:
            app.logger.error("Developer error. Invalid log type: {}"
                             .format(log_type))
            return

        web_session = WebSessionEntity.get_by_session_id(session_id)
        if web_session is None:
            app.logger.error("Developer error. Invalid session id: {}"
                             .format(session_id))
            return

        LogEntity.create(log_type=logt,
                         date_time=datetime.datetime.now(),
                         details=details,
                         web_session=web_session)

    @staticmethod
    def account_created(session_id, details=''):
        """ Log account creation """
        LogEntity._log(LOG_TYPE_ACCOUNT_CREATED, session_id, details)

    @staticmethod
    def login(session_id, details=''):
        """ Log successful login """
        LogEntity._log(LOG_TYPE_LOGIN, session_id, details)

    @staticmethod
    def logout(session_id, details=''):
        """ Log logout click """
        LogEntity._log(LOG_TYPE_LOGOUT, session_id, details)

    @staticmethod
    def login_error(session_id, details=''):
        """ Log failed login """
        LogEntity._log(LOG_TYPE_LOGIN_ERROR, session_id, details)

    @staticmethod
    def file_uploaded(session_id, details=''):
        """ Log file upload """
        LogEntity._log(LOG_TYPE_FILE_UPLOADED, session_id, details)

    @staticmethod
    def file_downloaded(session_id, details=''):
        """ Log file download """
        LogEntity._log(LOG_TYPE_FILE_DOWNLOADED, session_id, details)

    @staticmethod
    def account_modified(session_id, details=''):
        """ Log account changes """
        LogEntity._log(LOG_TYPE_ACCOUNT_MODIFIED, session_id, details)

    @staticmethod
    def redcap_subjects_imported(session_id, details=''):
        """ Log it """
        LogEntity._log(LOG_TYPE_REDCAP_SUBJECTS_IMPORTED, session_id, details)

    @staticmethod
    def redcap_events_imported(session_id, details=''):
        """ Log it """
        LogEntity._log(LOG_TYPE_REDCAP_EVENTS_IMPORTED, session_id, details)

    def __repr__(self):
        """ Return a friendly object representation """
        return "<LogEntity(logID: {0.id}, "\
            "logtID: {0.type_id}" \
            "webID: {0.web_session_id}, "\
            "date_time: {0.date_time})>".format(self)