Esempio n. 1
0
def incompletes(lti=lti):
    enrollment_term = get_enrollment_term()
    stmt = db.text(
        """
        SELECT DISTINCT u.id AS user_id, u.name, u.login_id, cnt.count
        FROM course_user_link cl
            INNER JOIN users u ON cl.user_id = u.id
            LEFT JOIN (
                SELECT g.user_id, count(*)
                FROM grades g
                    INNER JOIN courses c ON c.id = g.course_id
                WHERE g.grade = 'I'
                    AND c.enrollment_term_id = :enrollment_term_id
                GROUP BY g.user_id
            ) cnt ON cnt.user_id = cl.user_id
        ORDER BY name;
        """
    ).bindparams(enrollment_term_id=enrollment_term.id)
    results = db.session.execute(stmt)
    keys = ["user_id", "name", "email", "incomplete_count"]
    incompletes = [dict(zip(keys, res)) for res in results]

    return render_template(
        "account/incomplete_report.html",
        incompletes=incompletes,
        enrollment_term_id=enrollment_term.id,
    )
Esempio n. 2
0
def dragon_time():
    token = None
    if 'x-access-tokens' in request.headers:
        token = request.headers['x-access-tokens']

    if not token:
        return jsonify({'message': 'a valid token is missing'})
    try:
        data = jwt.decode(token, SECRET_API, algorithms='HS256')
    except Exception as e:
        return jsonify({'message': 'token is invalid'})

    if data["id"] != os.getenv('DRAGON_TIME_ID'):
        return jsonify({'message': 'Invalid id!'})

    enrollment_term = get_enrollment_term()
    stmt = db.text("""
        SELECT
            u.sis_user_id
            , g.grade
            , c.sis_course_id
        FROM grades g
            JOIN courses c on c.id = g.course_id
            JOIN users u on u.id = g.user_id
        WHERE c.enrollment_term_id = :enrollment_term_id
        ORDER BY g.id
        """).bindparams(enrollment_term_id=enrollment_term.id)

    results = db.session.execute(stmt)

    return jsonify([dict(row) for row in results])
Esempio n. 3
0
class OrganizationMembership(db.Model):
    __tablename__ = 'organization_memberships'
    __table_args__ = (UniqueConstraint("organization_uuid", "user_uuid"), )
    uuid = db.Column(UUID(as_uuid=True),
                     primary_key=True,
                     server_default=db.text('uuid_generate_v4()'))
    organization_uuid = db.Column(UUID(as_uuid=True),
                                  db.ForeignKey('organizations.uuid'),
                                  index=True,
                                  nullable=False)
    user_uuid = db.Column(UUID(as_uuid=True),
                          db.ForeignKey('users.uuid'),
                          index=True,
                          nullable=False)
    role = db.Column('user_role',
                     ENUM('admin', 'write', 'read', name='user_role'),
                     nullable=False)
    organizations = db.relationship("Organization",
                                    backref="memberships",
                                    lazy=True)
    users = db.relationship("User", backref="memberships", lazy=True)

    def __init__(self, org_uuid, user_uuid, role='read'):
        self.organization_uuid = org_uuid
        self.user_uuid = user_uuid
        self.role = role

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self
Esempio n. 4
0
class AnalysisResultField(db.Model):
    """Represent a single field of a single result in the database."""
    __abstract__ = True
    kind = 'virtual'

    uuid = db.Column(UUID(as_uuid=True),
                     primary_key=True,
                     server_default=db.text('uuid_generate_v4()'))
    created_at = db.Column(db.DateTime, nullable=False)
    field_name = db.Column(db.String(256), index=True, nullable=False)
    stored_data = db.Column(db.String(MAX_DATA_FIELD_LENGTH),
                            index=False,
                            nullable=False)

    def __init__(  # pylint: disable=too-many-arguments
        self,
        analysis_result_uuid,
        field_name,
        data=[],
        created_at=datetime.datetime.utcnow()):
        """Initialize Analysis Result model."""
        self.parent_uuid = analysis_result_uuid
        self.field_name = field_name
        self.stored_data = json.dumps(data)
        self.created_at = created_at

    @property
    def data(self):
        """Return the deserialized data for this field."""
        return json.loads(self.stored_data)

    def set_data(self, data):
        self.stored_data = json.dumps(data)
        return self.save()

    def serializable(self):
        return {
            'analysis_result_field': {
                'uuid': self.uuid,
                'parent_uuid': self.uuid,
                'field_name': self.field_name,
                'created_at': self.created_at,
            },
            'data': self.data,
        }

    def serialize(self):
        return json.dumps(self.serializable())

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self
Esempio n. 5
0
 def outcome_stats(course_id):
     stmt = db.text("""
         SELECT title, id, max(cnt) max, min(cnt) min
         FROM
             (SELECT o.id, o.title title, count(*) cnt
             FROM outcome_results ores
                 JOIN outcomes o ON o.id = ores.outcome_id
             WHERE ores.course_id = :course_id
             GROUP BY ores.user_id, o.id, o.title) temp
         GROUP BY id, title
         ORDER BY max DESC;
     """)
     results = db.session.execute(stmt, dict(course_id=course_id))
     return results
Esempio n. 6
0
 def course_grades(course_id):
     stmt = db.text("""
         SELECT grade, cast( count(*) AS FLOAT)/cnt AS percent
         FROM 
             (SELECT u.id, COALESCE(left(g.grade, 1), 'N/A') AS GRADE, count(*) OVER() AS cnt
             FROM course_user_link cl
                 LEFT JOIN users u ON u.id = cl.user_id
                 LEFT JOIN grades g ON g.course_id = cl.course_id AND g.user_id = cl.user_id
             WHERE cl.course_id = :course_id) temp
         GROUP BY grade, cnt
         ORDER BY grade;
     """)
     grades = db.session.execute(stmt, dict(course_id=course_id))
     return grades
Esempio n. 7
0
def get_user_dash_data(user_id):
    # Get student, which is linked to user-courses relationship table
    user = User.query.filter(User.id == user_id).first()

    current_term = EnrollmentTerm.query.filter(
        EnrollmentTerm.current_term).first()

    # get student grades
    grades = (user.grades.join(Course).filter(
        Course.enrollment_term_id == current_term.id).all())
    # Get outcome results
    outcomes_stmt = db.text("""
        SELECT ores.id AS ores_id,
            ores.score AS ores_score,
            ores.course_id AS ores_course_id,
            ores.user_id AS ores_user_id,
            ores.outcome_id AS ores_outcome_id,
            ores.alignment_id AS ores_alignment_id,
            ores.submitted_or_assessed_at AS ores_submitted_or_assessed_at,
            ores.last_updated AS ores_last_updated,
            ores.enrollment_term AS ores_enrollment_term,
            c.id AS c_id,
            c.name AS c_name,
            c.enrollment_term_id AS c_enrollment_term_id,
            c.sis_course_id AS c_sis_course_id,
            o.id AS o_id,
            o.title AS o_title,
            o.display_name AS o_display_name,
            o.calculation_int AS o_calculation_int,
            a.id AS a_id,
            a.name AS a_name
        FROM outcome_results ores
            JOIN courses c on c.id = ores.course_id
            JOIN outcomes o on o.id = ores.outcome_id
            JOIN alignments a on a.id = ores.alignment_id
        WHERE ores.user_id = :user_id
                AND ores.score IS NOT NULL
                AND c.enrollment_term_id = :current_term
        ORDER BY  ores.course_id, ores.outcome_id;
        """)
    outcomes = db.session.execute(
        outcomes_stmt, dict(user_id=user_id, current_term=current_term.id))

    # format outcome results into json format
    alignments = [alignment_dict(a) for a in outcomes]

    return alignments, grades, user
class Organization(db.Model):
    """MetaGenScope Organization model."""

    __tablename__ = 'organizations'

    # pylint: disable=invalid-name
    id = db.Column(UUID(as_uuid=True),
                   primary_key=True,
                   server_default=db.text('uuid_generate_v4()'))
    name = db.Column(db.String(128), unique=True, nullable=False)
    admin_email = db.Column(db.String(128), nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)

    # Use association proxy to skip association object for most cases
    users = association_proxy('organization_users', 'user')

    admin_memberships = db.relationship(
        'OrganizationMembership',
        primaryjoin=
        'and_(Organization.id==OrganizationMembership.organization_id, '
        'OrganizationMembership.role==\'admin\')',
        viewonly=True)
    admin_users = association_proxy('admin_memberships', 'user')

    sample_groups = db.relationship('SampleGroup',
                                    backref='organization',
                                    lazy='dynamic')

    def __init__(self,
                 name,
                 admin_email,
                 created_at=datetime.datetime.utcnow()):
        """Initialize MetaGenScope Organization model."""
        self.name = name
        self.admin_email = admin_email
        self.created_at = created_at

    def add_admin(self, admin_user):
        """Add admin user to organization."""
        membership = OrganizationMembership.query.filter_by(
            user=admin_user).first()
        if not membership:
            membership = OrganizationMembership(organization=self,
                                                user=admin_user)
        membership.role = 'admin'
        db.session.commit()
Esempio n. 9
0
def dashboard():

    form = DashboardYearForm()

    years = db.session.query(db.extract('year', Expense.date).label('year')) \
        .filter(Expense.user_id == current_user.id) \
        .distinct() \
        .order_by(db.text('year asc'))
    form.year.choices = [('', 'Year')] + [(y[0], str(y[0])) for y in years]

    ctx = {}
    if form.validate_on_submit():
        year = int(form.year.data)
        ctx = get_context(year)
    elif request.method == 'GET':
        current_year = datetime.utcnow().year
        ctx = get_context(current_year)

    return render_template('main/dashboard.html',
                           form=form,
                           ctx=ctx,
                           title='Dashboard')
Esempio n. 10
0
class Organization(db.Model):
    """Represent an orgnization.

    One to Many relationship to SampleGroups
    Many to Many relationship with Users
    Many to One realtionship with a User as a primary admin
    """

    __tablename__ = 'organizations'

    uuid = db.Column(UUID(as_uuid=True),
                     primary_key=True,
                     server_default=db.text('uuid_generate_v4()'))
    name = db.Column(db.String(128), nullable=False, unique=True)
    primary_admin_uuid = db.Column(db.ForeignKey('users.uuid'), nullable=False)
    users = association_proxy("memberships", "users")
    sample_groups = db.relationship('SampleGroup',
                                    backref='organization',
                                    lazy=True)
    is_deleted = db.Column(db.Boolean, default=False, nullable=False)
    is_public = db.Column(db.Boolean, default=True, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)

    def __init__(self,
                 primary_admin_uuid,
                 name,
                 is_deleted=False,
                 is_public=True,
                 created_at=datetime.datetime.utcnow()):
        """Initialize Pangea User model."""
        self.primary_admin_uuid = primary_admin_uuid
        self.name = name
        self.is_deleted = is_deleted
        self.is_public = is_public
        self.created_at = created_at

    def serializable(self):
        out = {
            'organization': {
                'uuid': self.uuid,
                'name': self.name,
                'is_public': self.is_public,
                'is_deleted': self.is_deleted,
                'created_at': self.created_at,
                'primary_admin_uuid': self.primary_admin_uuid,
                'sample_group_uuids': [sg.uuid for sg in self.sample_groups],
                'users': [user.uuid for user in self.users],
            },
        }
        return out

    def serialize(self):
        return json.dumps(self.serializable())

    def add_user(self, user, role_in_org='read'):
        OrganizationMembership(self.uuid, user.uuid, role=role_in_org).save()
        return self

    def admin_uuids(self):
        return [
            membership.user_uuid for membership in self.memberships
            if membership.role == 'admin'
        ]

    def writer_uuids(self):
        return [
            membership.user_uuid for membership in self.memberships
            if membership.role in ['admin', 'write']
        ]

    def reader_uuids(self):
        return [
            membership.user_uuid for membership in self.memberships
            if membership.role in ['admin', 'write', 'read']
        ]

    def sample_group(self,
                     name,
                     description='',
                     is_library=False,
                     is_public=True):
        """Return a SampleGroup bound to this organization.

        Create and save the SampleGroup if it does not already exist.
        """
        sample_groups = [sg for sg in self.sample_groups if sg.name == name]
        if sample_groups:
            sample_group = sample_groups[0]
        else:
            sample_group = SampleGroup(name,
                                       self.uuid,
                                       description=description,
                                       is_library=is_library,
                                       is_public=is_public).save()
        return sample_group

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self

    @classmethod
    def from_user(cls, user, name, is_public=True):
        org = cls(user.uuid, name, is_public=is_public).save()
        org.add_user(user, role_in_org='admin')
        return org.save()

    @classmethod
    def from_uuid(cls, uuid):
        return cls.query.filter_by(uuid=uuid).one()

    @classmethod
    def from_name(cls, name):
        return cls.query.filter_by(name=name).one()
Esempio n. 11
0
class User(db.Model):
    """Pangea User model.

    To make ownership of sample libraries easier, users and organizations
    are treated as the same entity.
    """

    __tablename__ = 'users'

    uuid = db.Column(UUID(as_uuid=True),
                     primary_key=True,
                     server_default=db.text('uuid_generate_v4()'))
    organizations = association_proxy("memberships", "organizations")
    username = db.Column(db.String(128), nullable=False)
    email = db.Column(db.String(128), unique=True, nullable=False)
    is_deleted = db.Column(db.Boolean, default=False, nullable=False)
    is_fake = db.Column(db.Boolean, default=False, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)

    __table_args__ = (db.Index('_user_lower_username_idx',
                               func.lower(username),
                               unique=True), )

    def __init__(self,
                 username,
                 email,
                 is_deleted=False,
                 is_fake=False,
                 created_at=datetime.datetime.utcnow()):
        """Initialize Pangea User model."""
        self.username = username
        self.email = email
        self.is_deleted = is_deleted
        self.is_fake = is_fake
        self.created_at = created_at

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self

    @classmethod
    def from_uuid(cls, uuid):
        return cls.query.filter_by(uuid=uuid).one()

    @classmethod
    def from_name(cls, name):
        return cls.query.filter_by(username=name).one()

    def serializable(self):
        out = {
            'user': {
                'uuid': self.uuid,
                'username': self.username,
                'organizations': [org.uuid for org in self.organizations],
                'email': self.email,
                'is_deleted': self.is_deleted,
                'created_at': self.created_at,
            },
        }
        return out

    def serialize(self):
        return json.dumps(self.serializable())
Esempio n. 12
0
class AnalysisResult(db.Model):
    """Represent a single field of a single result in the database.

    Example:
        KrakenUniq produces a table of read-classifications and a report.
        These are stored separately as two separate AnalysisResults.
        Both ARs have the same `module_name` (e.g. KrakenUniq)
        Both ARs have the same owner (e.g. sample-123)
        Both ARs have different a `field_name` (e.g. report or read_class).

    `owner_uuid` should reference a group or sample. Whether it is a group
    or sample is determined by `owned_by_group`. This is only enforced in
    code. The reverse (sample->AR or group->AR) is enforced in SQL.

    AR Fields carry a status marker. In principle all fields of an ARs always
    have the same status.
    """
    __abstract__ = True
    kind = 'virtual'

    uuid = db.Column(UUID(as_uuid=True),
                     primary_key=True,
                     server_default=db.text('uuid_generate_v4()'))
    created_at = db.Column(db.DateTime, nullable=False)

    module_name = db.Column(db.String(256), index=True, nullable=False)
    status = db.Column(ENUM(*ANALYSIS_RESULT_STATUSES, name='status'),
                       nullable=False)

    def __init__(  # pylint: disable=too-many-arguments
        self,
        module_name,
        parent_uuid,
        status='PENDING',
        created_at=datetime.datetime.utcnow()):
        """Initialize Analysis Result model."""
        self.module_name = module_name
        self.parent_uuid = parent_uuid
        self.status = status
        self.created_at = created_at

    def field(self, field_name):
        """Return an AR-filed for the module bound to this AR.

        Create and save the AR-field if it does not already exist.
        """
        ar_fs = [
            ar_f for ar_f in self.module_fields
            if ar_f.field_name == field_name
        ]
        if ar_fs:
            return ar_fs[0]
        return type(self)._field_type()(self.uuid, field_name).save()

    def set_status(self, status):
        """Set status and save. Return self."""
        assert status in ANALYSIS_RESULT_STATUSES
        self.status = status
        return self.save()

    def serializable(self):
        out = {
            'analysis_result': {
                'uuid': self.uuid,
                'parent_uuid': self.uuid,
                'module_name': self.module_name,
                'kind': self.kind,
                'status': self.status,
                'created_at': self.created_at,
                'fields': {}
            },
            'data': {},
        }
        for field in self.module_fields:
            myfield = field.serializable()
            out['data'][field.field_name] = myfield['data']
            out['analysis_result']['fields'][
                field.field_name] = myfield['analysis_result_field']
        return out

    def serialize(self):
        return json.dumps(self.serializable())

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self
Esempio n. 13
0
class SampleGroup(db.Model):  # pylint: disable=too-many-instance-attributes
    """MetaGenScope Sample Group model."""

    __tablename__ = 'sample_groups'

    uuid = db.Column(UUID(as_uuid=True),
                     primary_key=True,
                     server_default=db.text('uuid_generate_v4()'))
    name = db.Column(db.String(128), index=True, nullable=False)
    organization_uuid = db.Column(db.ForeignKey('organizations.uuid'),
                                  nullable=False)
    description = db.Column(db.String(300), nullable=False, default='')
    is_library = db.Column(db.Boolean, default=False, nullable=False)
    is_public = db.Column(db.Boolean, default=True, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)
    samples = db.relationship('Sample', lazy=True)
    analysis_results = db.relationship('SampleGroupAnalysisResult',
                                       backref='parent',
                                       lazy=True)

    # Duplicate owner properties/indices because we don't know how we will be looking it up
    __table_args__ = (db.Index('_sample_group_lower_name_idx',
                               func.lower(name),
                               unique=True), )

    def __init__(  # pylint: disable=too-many-arguments
        self,
        name,
        organization_uuid,
        description='',
        is_library=False,
        is_public=True,
        created_at=datetime.datetime.utcnow()):
        """Initialize MetaGenScope User model."""
        self.name = name
        self.organization_uuid = organization_uuid
        self.description = description
        self.is_library = is_library
        self.is_public = is_public
        self.created_at = created_at

    def sample(self, sample_name, metadata={}, force_new=False):
        """Return a sample bound to this library.

        Create and save the sample if it does not already exist.
        """
        samps = [samp for samp in self.samples if samp.name == sample_name]
        if samps and not force_new:
            return samps[0]
        return Sample(sample_name, self.uuid, metadata=metadata).save()

    def analysis_result(self, module_name):
        """Return an AR for the module bound to this sample.

        Create and save the AR if it does not already exist.
        """
        ars = [
            ar for ar in self.analysis_results if ar.module_name == module_name
        ]
        if ars:
            result = ars[0]
        else:
            result = SampleGroupAnalysisResult(module_name, self.uuid).save()
        return result

    @property
    def sample_uuids(self):
        return [sample.uuid for sample in self.samples]

    @property
    def tools_present(self):
        """Return list of names for Tool Results present across all Samples in this group."""
        # Cache samples
        samples = self.samples

        tools_present_in_all = set([])
        for i, sample in enumerate(samples):
            tool_results = set(sample.tool_result_names)
            if i == 0:
                tools_present_in_all |= tool_results
            else:
                tools_present_in_all &= tool_results
        return list(tools_present_in_all)

    def serializable(self):
        out = {
            'sample_group': {
                'uuid': self.uuid,
                'name': self.name,
                'organization_uuid': self.organization_uuid,
                'description': self.description,
                'is_library': self.is_library,
                'is_public': self.is_public,
                'created_at': self.created_at,
                'sample_uuids': [sample.uuid for sample in self.samples],
                'analysis_result_uuids':
                [ar.uuid for ar in self.analysis_results],
            },
        }
        return out

    def serialize(self):
        return json.dumps(self.serializable())

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self

    @classmethod
    def from_uuid(cls, uuid):
        return cls.query.filter_by(uuid=uuid).one()

    @classmethod
    def from_name(cls, name):
        return cls.query.filter_by(name=name).one()
class SampleGroup(db.Model):  # pylint: disable=too-many-instance-attributes
    """MetaGenScope Sample Group model."""

    __tablename__ = 'sample_groups'

    id = db.Column(UUID(as_uuid=True),
                   primary_key=True,
                   server_default=db.text('uuid_generate_v4()'))

    organization_id = db.Column(UUID(as_uuid=True),
                                db.ForeignKey('organizations.id'))

    name = db.Column(db.String(128), unique=True, nullable=False)
    description = db.Column(db.String(300), nullable=False, default='')
    access_scheme = db.Column(db.String(128), default='public', nullable=False)
    theme = db.Column(db.String(16), nullable=False, default='')
    created_at = db.Column(db.DateTime, nullable=False)

    sample_placeholders = db.relationship(SamplePlaceholder)
    sample_ids = association_proxy('sample_placeholders', 'sample_id')

    analysis_result_uuid = db.Column(UUID(as_uuid=True), nullable=False)

    def __init__(  # pylint: disable=too-many-arguments
        self,
        name,
        analysis_result,
        description='',
        access_scheme='public',
        theme='',
        created_at=datetime.datetime.utcnow()):
        """Initialize MetaGenScope User model."""
        self.name = name
        self.description = description
        self.access_scheme = access_scheme
        self.theme = theme
        self.created_at = created_at
        self.analysis_result_uuid = analysis_result.uuid

    @property
    def samples(self):
        """
        Get SampleGroup's associated Samples.

        This will hit Mongo every time it is called! Responsibility for caching
        the result lies on the calling method.
        """
        return Sample.objects(uuid__in=self.sample_ids)

    @samples.setter
    def samples(self, value):
        """Set SampleGroup's samples."""
        self.sample_ids = [sample.uuid for sample in value]

    @samples.deleter
    def samples(self):
        """Remove SampleGroup's samples."""
        self.sample_ids = []

    @property
    def tools_present(self):
        """Return list of names for Tool Results present across all Samples in this group."""
        # Cache samples
        samples = self.samples

        tools_present_in_all = set([])
        for i, sample in enumerate(samples):
            tool_results = set(sample.tool_result_names)
            if i == 0:
                tools_present_in_all |= tool_results
            else:
                tools_present_in_all &= tool_results
        return list(tools_present_in_all)

    @property
    def analysis_result(self):
        """Get sample group's analysis result model."""
        return AnalysisResultMeta.objects.get(uuid=self.analysis_result_uuid)

    @analysis_result.setter
    def analysis_result(self, new_analysis_result):
        """Store new analysis result UUID (caller must still commit session!)."""
        self.analysis_result_uuid = new_analysis_result.uuid
class User(db.Model):
    """MetaGenScope User model."""

    __tablename__ = 'users'

    # pylint: disable=invalid-name
    id = db.Column(UUID(as_uuid=True),
                   primary_key=True,
                   server_default=db.text('uuid_generate_v4()'))
    username = db.Column(db.String(128), unique=True, nullable=False)
    email = db.Column(db.String(128), unique=True, nullable=False)
    password = db.Column(db.String(255), nullable=False)
    active = db.Column(db.Boolean, default=True, nullable=False)
    admin = db.Column(db.Boolean, default=False, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)

    # Use association proxy to skip association object for most cases
    organizations = association_proxy('user_organizations', 'organization')

    def __init__(self,
                 username,
                 email,
                 password,
                 created_at=datetime.datetime.utcnow()):
        """Initialize MetaGenScope User model."""
        self.username = username
        self.email = email
        self.password = bcrypt.generate_password_hash(
            password, current_app.config.get('BCRYPT_LOG_ROUNDS')).decode()
        self.created_at = created_at

    @classmethod
    def encode_auth_token(cls, user_id):
        """Generate the auth token."""
        try:
            days = current_app.config.get('TOKEN_EXPIRATION_DAYS')
            seconds = current_app.config.get('TOKEN_EXPIRATION_SECONDS')
            payload = {
                'exp':
                datetime.datetime.utcnow() +
                datetime.timedelta(days=days, seconds=seconds),
                'iat':
                datetime.datetime.utcnow(),
                'sub':
                str(user_id)
            }
            return jwt.encode(payload,
                              current_app.config.get('SECRET_KEY'),
                              algorithm='HS256')
        except Exception as e:  # pylint: disable=broad-except
            return e

    @staticmethod
    def decode_auth_token(auth_token):
        """Decode the auth token - :param auth_token: - :return: UUID|string."""
        try:
            secret = current_app.config.get('SECRET_KEY')
            payload = jwt.decode(auth_token, secret)
            return uuid.UUID(payload['sub'])
        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed(
                'Signature expired. Please log in again.')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('Invalid token. Please log in again.')
Esempio n. 16
0
class Sample(db.Model):
    """Represent a sample in the database."""

    __tablename__ = 'samples'
    __table_args__ = (
        UniqueConstraint("library_uuid", "name"),
    )

    uuid = db.Column(
        UUID(as_uuid=True),
        primary_key=True,
        server_default=db.text('uuid_generate_v4()')
    )
    created_at = db.Column(db.DateTime, nullable=False)

    library_uuid = db.Column(
        db.ForeignKey('sample_groups.uuid'),
        nullable=False
    )
    name = db.Column(db.String(256), index=True, nullable=False)
    _sample_metadata = db.Column(db.String(10 * 1000), nullable=True)
    analysis_results = db.relationship(
        'SampleAnalysisResult', backref='parent', lazy=True
    )
    theme = db.Column(db.String(256), default='')

    def __init__(  # pylint: disable=too-many-arguments
            self, name, library_uuid,
            metadata={},
            created_at=datetime.utcnow()):
        self.library_uuid = library_uuid
        self.name = name
        metadata['name'] = name
        self._sample_metadata = json.dumps(metadata)
        self.created_at = created_at

    def serializable(self):
        out = {
            'sample': {
                'uuid': self.uuid,
                'name': self.name,
                'library_uuid': self.library_uuid,
                'created_at': self.created_at,
                'analysis_result_uuids': [ar.uuid for ar in self.analysis_results],
            },
            'sample_metadata': self.sample_metadata,
        }
        return out

    def serialize(self):
        return json.dumps(self.serializable())

    def analysis_result(self, module_name):
        """Return an AR for the module bound to this sample.

        Create and save the AR if it does not already exist.
        """
        ars = [ar for ar in self.analysis_results if ar.module_name == module_name]
        if ars:
            result = ars[0]
        else:
            result = SampleAnalysisResult(module_name, self.uuid).save()
        return result

    def set_sample_metadata(self, data):
        metadata = self.sample_metadata
        metadata.update(data)
        self._sample_metadata = json.dumps(metadata)
        return self.save()

    @property
    def sample_metadata(self):
        return json.loads(self._sample_metadata)

    def save(self):
        db.session.add(self)
        db.session.commit()
        return self

    @classmethod
    def from_uuid(cls, uuid):
        return cls.query.filter_by(uuid=uuid).one()

    @classmethod
    def from_name_library(cls, module_name, library_uuid):
        return cls.query.filter_by(library_uuid=library_uuid, name=module_name).one()