Пример #1
0
def getAdminUserView():
   #auto join user and fb_account
   User.fb_account = db.relationship("UserFacebookAccount", uselist=False, lazy='joined')
   
   #auto join circles
   User.circles = db.relationship("Circle", 
      secondary="circle_user_rel", 
      primaryjoin = "circle_user_rel.c.user_id == User.id",
      secondaryjoin = "circle_user_rel.c.circle_id == Circle.id",
      lazy = 'joined')
   
   return AdminUserView(User, db.session)
Пример #2
0
class Mine(AuditMixin, Base):
    __tablename__ = 'mine'
    mine_guid = db.Column(UUID(as_uuid=True), primary_key=True)
    mine_no = db.Column(db.String(10))
    mine_name = db.Column(db.String(60), nullable=False)
    mine_note = db.Column(db.String(300), default='')
    major_mine_ind = db.Column(db.Boolean, nullable=False, default=False)
    deleted_ind = db.Column(db.Boolean,
                            nullable=False,
                            server_default=FetchedValue())
    mine_region = db.Column(db.String(2),
                            db.ForeignKey('mine_region_code.mine_region_code'))
    # Relationships

    #Almost always used and 1:1, so these are joined
    mine_location = db.relationship('MineLocation',
                                    backref='mine',
                                    uselist=False,
                                    lazy='joined')
    mine_status = db.relationship('MineStatus',
                                  backref='mine',
                                  order_by='desc(MineStatus.update_timestamp)',
                                  lazy='joined')
    mine_tailings_storage_facilities = db.relationship(
        'MineTailingsStorageFacility',
        backref='mine',
        order_by=
        'desc(MineTailingsStorageFacility.mine_tailings_storage_facility_name)',
        lazy='joined')

    #Almost always used, but faster to use selectin to load related data
    mine_permit = db.relationship('Permit',
                                  backref='mine',
                                  order_by='desc(Permit.create_timestamp)',
                                  lazy='selectin')
    mine_type = db.relationship('MineType',
                                backref='mine',
                                order_by='desc(MineType.update_timestamp)',
                                lazy='selectin')

    #Not always desired, set to lazy load using select
    mineral_tenure_xref = db.relationship('MineralTenureXref',
                                          backref='mine',
                                          lazy='select')
    mine_expected_documents = db.relationship(
        'MineExpectedDocument',
        primaryjoin=
        "and_(MineExpectedDocument.mine_guid == Mine.mine_guid, MineExpectedDocument.active_ind==True)",
        backref='mine',
        order_by='desc(MineExpectedDocument.due_date)',
        lazy='select')
    mine_party_appt = db.relationship('MinePartyAppointment',
                                      backref="mine",
                                      lazy='select')

    def __repr__(self):
        return '<Mine %r>' % self.mine_guid

    def json(self):
        return {
            'guid':
            str(self.mine_guid),
            'mine_name':
            self.mine_name,
            'mine_no':
            self.mine_no,
            'mine_note':
            self.mine_note,
            'major_mine_ind':
            self.major_mine_ind,
            'region_code':
            self.mine_region,
            'mineral_tenure_xref':
            [item.json() for item in self.mineral_tenure_xref],
            'mine_location':
            self.mine_location.json() if self.mine_location else None,
            #Exploration permits must, always, and exclusively have an X as the second character, and we would like this to be returned last:
            'mine_permit': [
                item.json() for item in self.mine_permit
                if item.permit_no.lower()[1] != 'x'
            ] + [
                item.json() for item in self.mine_permit
                if item.permit_no.lower()[1] == 'x'
            ],
            'mine_status': [item.json() for item in self.mine_status],
            'mine_tailings_storage_facility':
            [item.json() for item in self.mine_tailings_storage_facilities],
            'mine_expected_documents':
            [item.json() for item in self.mine_expected_documents],
            'mine_type': [item.json() for item in self.active(self.mine_type)],
            'verified_status':
            self.verified_status.json() if self.verified_status else None,
        }

    def json_for_list(self):
        return {
            'guid':
            str(self.mine_guid),
            'mine_name':
            self.mine_name,
            'mine_no':
            self.mine_no,
            'mine_note':
            self.mine_note,
            'major_mine_ind':
            self.major_mine_ind,
            'region_code':
            self.mine_region,
            'mine_permit': [item.json_for_list() for item in self.mine_permit],
            'mine_status': [item.json() for item in self.mine_status],
            'mine_tailings_storage_facility':
            [item.json() for item in self.mine_tailings_storage_facilities],
            'mine_type': [item.json() for item in self.active(self.mine_type)],
            'verified_status':
            self.verified_status.json() if self.verified_status else None,
        }

    def json_for_map(self):
        return {
            'guid':
            str(self.mine_guid),
            'mine_name':
            self.mine_name,
            'mine_no':
            self.mine_no,
            'mine_note':
            self.mine_note,
            'major_mine_ind':
            self.major_mine_ind,
            'region_code':
            self.mine_region,
            'mine_location':
            self.mine_location.json() if self.mine_location else None
        }

    def json_by_name(self):
        return {
            'guid': str(self.mine_guid),
            'mine_name': self.mine_name,
            'mine_no': self.mine_no
        }

    def json_by_location(self):
        #this will get cleaned up when mine_location and mine are merged
        result = {'guid': str(self.mine_guid)}
        if self.mine_location:
            result['latitude'] = str(self.mine_location.latitude
                                     ) if self.mine_location.latitude else ''
            result['longitude'] = str(self.mine_location.longitude
                                      ) if self.mine_location.longitude else ''
        else:
            result['latitude'] = ''
            result['longitude'] = ''
        return result

    def json_by_permit(self):
        return {
            'guid': str(self.mine_guid),
            'mine_permit': [item.json() for item in self.mine_permit]
        }

    @staticmethod
    def active(records):
        return list(filter(lambda x: x.active_ind, records))

    @classmethod
    def find_by_mine_guid(cls, _id):
        try:
            uuid.UUID(_id, version=4)
            return cls.query.filter_by(mine_guid=_id).filter_by(
                deleted_ind=False).first()
        except ValueError:
            return None

    @classmethod
    def find_by_mine_no(cls, _id):
        return cls.query.filter_by(mine_no=_id).filter_by(
            deleted_ind=False).first()

    @classmethod
    def find_by_mine_name(cls, term=None):
        MINE_LIST_RESULT_LIMIT = 50
        if term:
            name_filter = Mine.mine_name.ilike('%{}%'.format(term))
            mines_q = Mine.query.filter(name_filter).filter_by(
                deleted_ind=False)
            mines = mines_q.limit(MINE_LIST_RESULT_LIMIT).all()
        else:
            mines = Mine.query.limit(MINE_LIST_RESULT_LIMIT).all()
        return mines

    @classmethod
    def find_by_name_no_permit(cls, term=None):
        MINE_LIST_RESULT_LIMIT = 50
        if term:
            name_filter = Mine.mine_name.ilike('%{}%'.format(term))
            number_filter = Mine.mine_no.ilike('%{}%'.format(term))
            permit_filter = Permit.permit_no.ilike('%{}%'.format(term))
            mines_q = Mine.query.filter(name_filter | number_filter).filter_by(
                deleted_ind=False)
            permit_q = Mine.query.join(Permit).filter(permit_filter)
            mines = mines_q.union(permit_q).limit(MINE_LIST_RESULT_LIMIT).all()
        else:
            mines = Mine.query.limit(MINE_LIST_RESULT_LIMIT).all()
        return mines

    @classmethod
    def find_all_major_mines(cls):
        return cls.query.filter_by(major_mine_ind=True).filter_by(
            deleted_ind=False).all()

    @classmethod
    def find_by_mine_no_or_guid(cls, _id):
        result = cls.find_by_mine_guid(_id)
        if result is None:
            result = cls.find_by_mine_no(_id)

        return result

    @classmethod
    def create_mine(cls,
                    mine_no,
                    mine_name,
                    mine_category,
                    mine_region,
                    user_kwargs,
                    save=True):
        mine = cls(mine_guid=uuid.uuid4(),
                   mine_no=mine_no,
                   mine_name=mine_name,
                   major_mine_ind=mine_category,
                   mine_region=mine_region,
                   **user_kwargs)
        if save:
            mine.save(commit=False)
        return mine

    @validates('mine_name')
    def validate_mine_name(self, key, mine_name):
        if not mine_name:
            raise AssertionError('No mine name provided.')
        if len(mine_name) > 60:
            raise AssertionError('Mine name must not exceed 60 characters.')
        return mine_name

    @validates('mine_note')
    def validate_mine_note(self, key, mine_note):
        mine_note = mine_note if mine_note else ''
        if len(mine_note) > 300:
            raise AssertionError('Mine note must not exceed 300 characters.')
        return mine_note

    @validates('mine_no')
    def validate_mine_no(self, key, mine_no):
        mine_no = mine_no if mine_no else ''
        if mine_no and len(mine_no) > 10:
            raise AssertionError('Mine number must not exceed 10 characters.')
        return mine_no
Пример #3
0
class MineIncident(AuditMixin, Base):
    __tablename__ = 'mine_incident'

    mine_incident_id = db.Column(db.Integer,
                                 primary_key=True,
                                 server_default=FetchedValue())
    mine_incident_id_year = db.Column(db.Integer,
                                      nullable=False,
                                      default=datetime.datetime.now().year)
    mine_incident_guid = db.Column(UUID(as_uuid=True),
                                   nullable=False,
                                   server_default=FetchedValue())

    mine_guid = db.Column(UUID(as_uuid=True),
                          db.ForeignKey('mine.mine_guid'),
                          nullable=False)

    incident_timestamp = db.Column(db.DateTime, nullable=False)
    incident_description = db.Column(db.String, nullable=False)

    reported_timestamp = db.Column(db.DateTime)
    reported_by_name = db.Column(db.String)
    reported_by_email = db.Column(db.String)
    reported_by_phone_no = db.Column(db.String)
    reported_by_phone_ext = db.Column(db.String)

    number_of_fatalities = db.Column(db.Integer)
    number_of_injuries = db.Column(db.Integer)
    emergency_services_called = db.Column(db.Boolean)
    followup_inspection = db.Column(db.Boolean)
    followup_inspection_date = db.Column(db.DateTime)

    mms_insp_cd = db.Column(db.String)

    reported_to_inspector_party_guid = db.Column(
        UUID(as_uuid=True), db.ForeignKey('party.party_guid'), nullable=False)
    responsible_inspector_party_guid = db.Column(
        UUID(as_uuid=True), db.ForeignKey('party.party_guid'), nullable=False)
    determination_inspector_party_guid = db.Column(
        UUID(as_uuid=True), db.ForeignKey('party.party_guid'), nullable=False)

    proponent_incident_no = db.Column(db.String)
    mine_incident_no = db.Column(db.String)

    determination_type_code = db.Column(
        db.String,
        db.ForeignKey(
            'mine_incident_determination_type.mine_incident_determination_type_code'
        ))

    status_code = db.Column(
        db.String,
        db.ForeignKey('mine_incident_status_code.mine_incident_status_code'))

    followup_investigation_type_code = db.Column(
        db.String,
        db.ForeignKey(
            'mine_incident_followup_investigation_type.mine_incident_followup_investigation_type_code'
        ))
    mine_determination_type_code = db.Column(
        db.String,
        db.ForeignKey(
            'mine_incident_determination_type.mine_incident_determination_type_code'
        ))
    mine_determination_representative = db.Column(db.String)

    determination_type = db.relationship(
        'MineIncidentDeterminationType',
        backref='mine_incidents',
        lazy='joined',
        uselist=False,
        foreign_keys=[determination_type_code])
    dangerous_occurrence_subparagraphs = db.relationship(
        'ComplianceArticle',
        backref='mine_incidents',
        lazy='joined',
        secondary='mine_incident_do_subparagraph')
    followup_investigation_type = db.relationship(
        'MineIncidentFollowupInvestigationType',
        backref='mine_incidents',
        lazy='joined',
        uselist=False)

    recommendations = db.relationship(
        'MineIncidentRecommendation',
        primaryjoin=
        "and_(MineIncidentRecommendation.mine_incident_id == MineIncident.mine_incident_id, MineIncidentRecommendation.deleted_ind==False)",
        lazy='selectin')

    documents = db.relationship('MineIncidentDocumentXref', lazy='joined')
    mine_documents = db.relationship('MineDocument',
                                     lazy='joined',
                                     secondary='mine_incident_document_xref')

    categories = db.relationship('MineIncidentCategory',
                                 lazy='joined',
                                 secondary='mine_incident_category_xref')

    mine_table = db.relationship('Mine', lazy='joined')
    mine_name = association_proxy('mine_table', 'mine_name')
    mine_region = association_proxy('mine_table', 'mine_region')
    major_mine_ind = association_proxy('mine_table', 'major_mine_ind')

    @hybrid_property
    def mine_incident_report_no(self):
        return str(self.mine_incident_id_year) + '-' + str(
            self.mine_incident_id)

    @hybrid_property
    def dangerous_occurrence_subparagraph_ids(self):
        return [
            sub.compliance_article_id
            for sub in self.dangerous_occurrence_subparagraphs
        ]

    @classmethod
    def find_by_mine_incident_guid(cls, _id):
        try:
            uuid.UUID(_id, version=4)
            return cls.query.filter_by(mine_incident_guid=_id).first()
        except ValueError:
            return None

    @classmethod
    def create(cls,
               mine,
               incident_timestamp,
               incident_description,
               determination_type_code=None,
               mine_determination_type_code=None,
               mine_determination_representative=None,
               followup_investigation_type_code=None,
               reported_timestamp=None,
               reported_by_name=None,
               add_to_session=True):
        mine_incident = cls(
            incident_timestamp=incident_timestamp,
            incident_description=incident_description,
            reported_timestamp=reported_timestamp,
            reported_by_name=reported_by_name,
            determination_type_code=determination_type_code,
            mine_determination_type_code=mine_determination_type_code,
            mine_determination_representative=mine_determination_representative,
            followup_investigation_type_code=followup_investigation_type_code,
        )
        mine.mine_incidents.append(mine_incident)
        if add_to_session:
            mine_incident.save(commit=False)
        return mine_incident

    @validates('reported_by')
    def validate_reported_by(self, key, reported_by):
        if reported_by:
            if len(reported_by) > 100:
                raise AssertionError(
                    'reported_by must not exceed 100 characters.')
        return reported_by

    @validates('reported_by_role')
    def validate_reported_by_role(self, key, reported_by_role):
        if reported_by_role:
            if len(reported_by_role) > 100:
                raise AssertionError(
                    'reported_by_role must not exceed 100 characters.')
        return reported_by_role

    @validates('followup_inspection_number')
    def validate_followup_inspection_number(self, key,
                                            followup_inspection_number):
        if followup_inspection_number:
            if len(followup_inspection_number) > 20:
                raise AssertionError(
                    'followup_inspection_number must not exceed 100 characters.'
                )
        return followup_inspection_number

    @validates('incident_timestamp')
    def validate_incident_timestamp(self, key, incident_timestamp):
        if incident_timestamp:
            if incident_timestamp > datetime.datetime.utcnow():
                raise AssertionError(
                    'incident_timestamp must not be in the future')
        return incident_timestamp

    @validates('reported_timestamp')
    def validate_reported_timestamp(self, key, reported_timestamp):
        if reported_timestamp:
            if reported_timestamp > datetime.datetime.utcnow():
                raise AssertionError(
                    'reported_timestamp must not be in the future')
        return reported_timestamp
Пример #4
0
class User(db.Model, ModelMixin, UserMixin):
    __tablename__ = "users"
    email = db.Column(db.String(128), unique=True, nullable=False)
    salt = db.Column(db.String(128), nullable=False)
    password = db.Column(db.String(128), nullable=False)
    name = db.Column(db.String(128), nullable=False)
    is_admin = db.Column(db.Boolean, nullable=False, default=False)
    alias_generator = db.Column(
        db.Integer,
        nullable=False,
        default=AliasGeneratorEnum.word.value,
        server_default=str(AliasGeneratorEnum.word.value),
    )
    notification = db.Column(db.Boolean,
                             default=True,
                             nullable=False,
                             server_default="1")

    activated = db.Column(db.Boolean, default=False, nullable=False)

    profile_picture_id = db.Column(db.ForeignKey(File.id), nullable=True)

    otp_secret = db.Column(db.String(16), nullable=True)
    enable_otp = db.Column(db.Boolean,
                           nullable=False,
                           default=False,
                           server_default="0")

    # some users could have lifetime premium
    lifetime = db.Column(db.Boolean,
                         default=False,
                         nullable=False,
                         server_default="0")

    profile_picture = db.relationship(File)

    @classmethod
    def create(cls, email, name, password=None, **kwargs):
        user: User = super(User, cls).create(email=email, name=name, **kwargs)

        if not password:
            # set a random password
            password = random_string(20)

        user.set_password(password)
        db.session.flush()

        # create a first alias mail to show user how to use when they login
        GenEmail.create_new(user.id, prefix="my-first-alias")
        db.session.flush()

        return user

    def should_upgrade(self):
        return not self.is_premium()

    def is_premium(self):
        """user is premium if they have a active subscription"""
        if self.lifetime:
            return True

        sub: Subscription = self.get_subscription()
        if sub:
            return True

        return False

    def can_create_new_alias(self):
        if self.is_premium():
            return True

        return GenEmail.filter_by(
            user_id=self.id).count() < MAX_NB_EMAIL_FREE_PLAN

    def set_password(self, password):
        salt = bcrypt.gensalt()
        password_hash = bcrypt.hashpw(password.encode(), salt).decode()
        self.salt = salt.decode()
        self.password = password_hash

    def check_password(self, password) -> bool:
        password_hash = bcrypt.hashpw(password.encode(), self.salt.encode())
        return self.password.encode() == password_hash

    def profile_picture_url(self):
        if self.profile_picture_id:
            return self.profile_picture.get_url()
        else:
            return url_for("static", filename="default-avatar.png")

    def suggested_emails(self, website_name) -> (str, [str]):
        """return suggested email and other email choices """
        website_name = convert_to_id(website_name)

        all_gen_emails = [
            ge.email for ge in GenEmail.filter_by(user_id=self.id)
        ]
        if self.can_create_new_alias():
            suggested_gen_email = GenEmail.create_new(
                self.id, prefix=website_name).email
        else:
            # pick an email from the list of gen emails
            suggested_gen_email = random.choice(all_gen_emails)

        return (
            suggested_gen_email,
            list(set(all_gen_emails).difference({suggested_gen_email})),
        )

    def suggested_names(self) -> (str, [str]):
        """return suggested name and other name choices """

        other_name = convert_to_id(self.name)

        return self.name, [other_name, "Anonymous", "whoami"]

    def get_name_initial(self) -> str:
        names = self.name.split(" ")
        return "".join([n[0].upper() for n in names if n])

    def plan_name(self) -> str:
        if self.is_premium():
            sub = self.get_subscription()

            if sub.plan == PlanEnum.monthly:
                return "Monthly ($2.99/month)"
            else:
                return "Yearly ($29.99/year)"
        else:
            return "Free Plan"

    def get_subscription(self):
        """return *active* subscription
        TODO: support user unsubscribe and re-subscribe
        """
        sub = Subscription.get_by(user_id=self.id)
        if sub and sub.cancelled:
            # sub is active until the next billing_date + 1
            if sub.next_bill_date >= arrow.now().shift(days=-1).date():
                return sub
            else:  # past subscription, user is considered not having a subscription
                return None
        else:
            return sub

    def verified_custom_domains(self):
        return CustomDomain.query.filter_by(user_id=self.id,
                                            verified=True).all()

    def __repr__(self):
        return f"<User {self.id} {self.name} {self.email}>"
Пример #5
0
class Driver(db.Model):
    __tablename__ = "drivers"

    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(254), nullable=False, unique=True)
    first_name = db.Column(db.String(40), nullable=False)
    last_name = db.Column(db.String(40), nullable=True)
    password = db.Column(db.LargeBinary(60), nullable=False)
    phone_number = db.Column(db.Integer, nullable=True)
    car_description = db.Column(db.Text, nullable=True)
    reward_points = db.Column(db.Integer, nullable=False, default=0)
    food_requests = db.relationship('FoodRequest', backref="driver", lazy=True)

    def __init__(self, **kwargs):
        super(Driver, self).__init__(**kwargs)

        self.email = self.email.strip()
        self.first_name = self.first_name.strip()
        self.password = bcrypt.hashpw(
            self.password.encode(), bcrypt.gensalt()
        )

    def __repr__(self):
        return f"<Driver id: {self.id} {self.email}>"

    def verify_password(self, password):
        """Returns True if this password matches for this User."""

        if isinstance(password, str):
            password = password.encode()

        if bcrypt.checkpw(password, self.password):
            return True

        return False

    def gen_access_token(self, exp=None):
        """Returns JWT token for this User"""

        if not exp:
            exp = settings.TOKEN_TYPES["session"]["expires_in"]

        payload = {
            "driver_id": self.id,
            "is_driver": True
        }
        token = generate_token(payload, "session", expires_in=exp)

        return {
            "access_token": token,
            "expires_in": exp
        }

    @staticmethod
    def verify_access_token(access_token):
        """Returns the User for this access_token if it passes verification"""

        try:
            payload = validate_token(access_token)
        except itsdangerous.BadSignature:
            abort(401, "Invalid token")

        return payload

    @staticmethod
    def identify(user_identity):
        """Returns a User object corresponding with this username or email or id"""

        if isinstance(user_identity, int):
            return Driver.query.get(user_identity)

        return Driver.query.filter(
            Driver.email.ilike(user_identity)
        ).first()
Пример #6
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()
Пример #7
0
class Item(db.Model, BaseModel):
    body = db.Column(db.Text)
    done = db.Column(db.Boolean)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    author = db.relationship('User', back_populates='items')
    order = db.Column(db.Integer, autoincrement=True)
Пример #8
0
class User(db.Model, FeatherModel, UserEDMMixin):
    """
    User database model.

    TODO:
    * Upgrade to HoustonModel after full transition for Users out of EDM is
      complete
    """
    def __init__(self, *args, **kwargs):
        if 'password' not in kwargs:
            raise ValueError('User must have a password')
        super().__init__(*args, **kwargs)

    guid = db.Column(db.GUID, default=uuid.uuid4, primary_key=True)  # pylint: disable=invalid-name
    version = db.Column(db.Integer, default=None, nullable=True)

    email = db.Column(db.String(length=120),
                      index=True,
                      unique=True,
                      nullable=False)

    password = db.Column(
        column_types.PasswordType(max_length=128, schemes=('bcrypt', )),
        nullable=False)  # can me migrated from EDM field "password"

    full_name = db.Column(
        db.String(length=120), default='',
        nullable=False)  # can be migrated from EDM field "fullName"
    website = db.Column(
        db.String(length=120),
        nullable=True)  # can be migrated from EDM field "userURL"
    location = db.Column(db.String(length=120), nullable=True)
    affiliation = db.Column(
        db.String(length=120),
        nullable=True)  # can be migrated from BE field "affiliation"
    forum_id = db.Column(db.String(length=120), nullable=True)
    locale = db.Column(db.String(length=20), default='EN', nullable=True)

    accepted_user_agreement = db.Column(
        db.Boolean, default=False, nullable=False
    )  # can be migrated from EDM field "acceptedUserAgreement"
    use_usa_date_format = db.Column(db.Boolean, default=True, nullable=False)
    show_email_in_profile = db.Column(db.Boolean,
                                      default=False,
                                      nullable=False)
    receive_notification_emails = db.Column(
        db.Boolean, default=True,
        nullable=False)  # can be migrated from BE field "receiveEmails"
    receive_newsletter_emails = db.Column(db.Boolean,
                                          default=False,
                                          nullable=False)
    shares_data = db.Column(
        db.Boolean, default=True,
        nullable=False)  # can be migrated from BE field "sharing"

    default_identification_catalogue = db.Column(
        db.GUID, nullable=True
    )  # this may just be a string, however EDM wants to do ID catalogues

    profile_asset_guid = db.Column(
        db.GUID,
        nullable=True)  # should be reconciled with Jon's MediaAsset class
    footer_logo_asset_guid = db.Column(
        db.GUID,
        nullable=True)  # should be reconciled with Jon's MediaAsset class

    organization_membership_enrollments = db.relationship(
        'OrganizationUserMembershipEnrollment', back_populates='user')

    project_membership_enrollments = db.relationship(
        'ProjectUserMembershipEnrollment', back_populates='user')

    class StaticRoles(enum.Enum):
        # pylint: disable=missing-docstring,unsubscriptable-object
        INTERNAL = (0x8000, 'Internal')
        ADMIN = (0x4000, 'Site Administrator')
        STAFF = (0x2000, 'Staff Member')
        ACTIVE = (0x1000, 'Active Account')

        SETUP = (0x0800, 'Account in Setup')
        RESET = (0x0400, 'Account in Password Reset')
        ALPHA = (0x0200, 'Enrolled in Alpha')
        BETA = (0x0100, 'Enrolled in Beta')

        @property
        def mask(self):
            return self.value[0]

        @property
        def title(self):
            return self.value[1]

    static_roles = db.Column(db.Integer, default=0, nullable=False)

    is_internal = _get_is_static_role_property('is_internal',
                                               StaticRoles.INTERNAL)
    is_admin = _get_is_static_role_property('is_admin', StaticRoles.ADMIN)
    is_staff = _get_is_static_role_property('is_staff', StaticRoles.STAFF)
    is_active = _get_is_static_role_property('is_active', StaticRoles.ACTIVE)

    in_beta = _get_is_static_role_property('in_beta', StaticRoles.BETA)
    in_alpha = _get_is_static_role_property('in_alpha', StaticRoles.ALPHA)

    in_reset = _get_is_static_role_property('in_reset', StaticRoles.RESET)
    in_setup = _get_is_static_role_property('in_setup', StaticRoles.SETUP)

    def __repr__(self):
        return ('<{class_name}('
                'guid={self.guid}, '
                'email="{self.email}", '
                'name="{self.full_name}", '
                'is_internal={self.is_internal}, '
                'is_admin={self.is_admin}, '
                'is_staff={self.is_staff}, '
                'is_active={self.is_active}, '
                ')>'.format(class_name=self.__class__.__name__, self=self))

    @classmethod
    def get_admins(cls):
        # used for first run admin creation
        users = cls.query.all()  # NOQA

        admin_users = []
        for user in users:
            # TODO: Remove the check below at a later point after default admin create is removed
            if user.email.endswith('@localhost'):
                continue
            if user.is_admin:
                admin_users.append(user)

        return admin_users

    @classmethod
    def admin_user_initialized(cls):
        # used for first run admin creation
        return len(cls.get_admins()) > 0

    @classmethod
    def ensure_user(cls,
                    email,
                    password,
                    is_internal=False,
                    is_admin=False,
                    is_staff=False,
                    is_active=True,
                    in_beta=False,
                    in_alpha=False,
                    update=False,
                    **kwargs):
        """
        Create a new user.
        """
        from app.extensions import db

        user = User.find(email=email)

        if user is None:
            user = User(password=password,
                        email=email,
                        is_internal=is_internal,
                        is_admin=is_admin,
                        is_staff=is_staff,
                        is_active=is_active,
                        in_beta=in_beta,
                        in_alpha=in_alpha,
                        **kwargs)

            with db.session.begin():
                db.session.add(user)

            log.info('New user created: %r' % (user, ))
        elif update:
            user.password = password
            user.is_internal = is_internal
            user.is_admin = is_admin
            user.is_staff = is_staff
            user.is_active = is_active
            user.in_beta = in_beta
            user.in_alpha = in_alpha

            with db.session.begin():
                db.session.merge(user)

            log.info('Updated user: %r' % (user, ))

        db.session.refresh(user)

        return user

    @classmethod
    def find(cls, email=None, password=None, edm_login_fallback=True):
        # Look-up via email

        if email is None:
            return None

        email_candidates = [
            email,
            '%s@localhost' % (email, ),
        ]
        for email_candidate in email_candidates:

            user = cls.query.filter(User.email == email_candidate).first()

            if password is None:
                # If no password was provided to check, return any user account we find
                if user is not None:
                    return user
            else:
                # Check local Houston password first
                if user is not None:
                    # We found the user, check their provided password
                    if user.password == password:
                        return user

                # As a fallback, check all EDMs if the user can login
                if edm_login_fallback:
                    # We want to check the EDM even if we don't have a local user record
                    if current_app.edm.check_user_login(
                            email_candidate, password):
                        log.info('User authenticated via EDM: %r' %
                                 (email_candidate, ))

                        if user is not None:
                            # We authenticated a local user against an EDM (but the local password failed)
                            if user.password != password:
                                # The user passed the login with an EDM, update local password
                                log.warning(
                                    "Updating user's local password: %r" %
                                    (user, ))
                                user = user.set_password(password)
                            return user
                        else:
                            log.critical(
                                'The user authenticated via EDM but has no local user record'
                            )
                            # Try syncing all users from EDM
                            cls.edm_sync_all()
                            # If the user was just synced, go grab it (recursively) and return
                            user = cls.find(email=email,
                                            edm_login_fallback=False)
                            return user

        # If we have gotten here, one of these things happened:
        #    1) the user wasn't found
        #    2) the user's password was provided and was incorrect
        #    3) the user authenticated against the EDM but has no local user record

        return None

    @classmethod
    def query_search(cls, search=None):
        from sqlalchemy import or_, and_
        from app.modules.auth.models import Code, CodeTypes

        if search is not None:
            search = search.strip().split(' ')
            search = [term.strip() for term in search]
            search = [term for term in search if len(term) > 0]

            or_terms = []
            for term in search:
                codes = (Code.query.filter_by(
                    code_type=CodeTypes.checkin).filter(
                        Code.accept_code.contains(term), ).all())
                code_users = set([])
                for code in codes:
                    if not code.is_expired:
                        code_users.add(code.user.guid)

                or_term = or_(
                    cls.guid.in_(code_users),
                    cls.email.contains(term),
                    cls.affiliation.contains(term),
                    cls.forum_id.contains(term),
                    cls.full_name.contains(term),
                )
                or_terms.append(or_term)
            users = cls.query.filter(and_(*or_terms))
        else:
            users = cls.query

        return users

    @property
    def is_authenticated(self):
        return True

    @property
    def is_anonymous(self):
        return False

    @property
    def is_email_confirmed(self):
        from app.modules.auth.models import Code, CodeTypes

        # Get any codes that fit this request
        code = (Code.query.filter_by(user=self,
                                     code_type=CodeTypes.email).order_by(
                                         Code.created.desc()).first())
        if code is None:
            return False
        return code.is_resolved

    @property
    def picture(self):
        from app.modules.assets.models import Asset

        asset = Asset.query.filter_by(id=self.profile_asset_guid).first()
        if asset is None:
            placeholder_guid = (self.guid % 7) + 1
            filename = 'images/placeholder_profile_%d.png' % (
                placeholder_guid, )
            return url_for('static', filename=filename)
        return url_for('backend.asset', code=asset.code)

    @property
    def memberships(self):
        return [
            enrollment.organization
            for enrollment in self.organization_membership_enrollments
        ]

    @property
    def projects(self):
        return [
            enrollment.project
            for enrollment in self.project_membership_enrollments
        ]

    def get_id(self):
        return self.guid

    def has_static_role(self, role):
        return (self.static_roles & role.mask) != 0

    def set_static_role(self, role):
        if self.has_static_role(role):
            return
        self.static_roles |= role.mask

    def unset_static_role(self, role):
        if not self.has_static_role(role):
            return
        self.static_roles ^= role.mask

    def check_owner(self, user):
        return self == user

    def check_supervisor(self, user):
        return self.check_owner(user)

    def get_codes(self, code_type, **kwargs):
        # This import for Code needs to be local
        from app.modules.auth.models import Code

        code = Code.get(self, code_type, **kwargs)
        return code

    def get_invite_code(self):
        # This import for Code needs to be local
        from app.modules.auth.models import CodeTypes

        return self.get_codes(CodeTypes.invite, replace=True)

    def get_email_confirmation_code(self):
        # This import for Code needs to be local
        from app.modules.auth.models import CodeTypes

        return self.get_codes(CodeTypes.email, replace=True)

    def get_account_recovery_code(self):
        # This import for Code needs to be local
        from app.modules.auth.models import CodeTypes

        return self.get_codes(CodeTypes.recover,
                              replace=True,
                              replace_ttl=None)

    def set_password(self, password):
        if password is None:
            # This function "sets" the password, it's the responsibility of the caller to ensure it's valid
            raise ValueError('Empty password not allowed')

        self.password = password
        with db.session.begin():
            db.session.merge(self)
        db.session.refresh(self)

        return self

    def lockout(self):
        from app.modules.auth.models import OAuth2Client, OAuth2Grant, OAuth2Token, Code

        # Disable permissions
        self.is_staff = False
        self.is_admin = False
        self.is_active = False
        self.in_reset = False
        self.in_setup = False

        with db.session.begin():
            db.session.merge(self)
        db.session.refresh(self)

        # Logout of sessions and API keys
        auth_list = []
        auth_list += OAuth2Token.query.filter_by(user_guid=self.guid).all()
        auth_list += OAuth2Grant.query.filter_by(user_guid=self.guid).all()
        auth_list += OAuth2Client.query.filter_by(user_guid=self.guid).all()
        auth_list += Code.query.filter_by(user_guid=self.guid).all()
        for auth_ in auth_list:
            auth_.delete()

        return self

    def owns_object(self, obj):
        from app.modules.assets.models import Asset
        from app.modules.submissions.models import Submission
        from app.modules.encounters.models import Encounter
        from app.modules.sightings.models import Sighting
        from app.modules.projects.models import Project

        ret_val = False

        # Submission, Encounters and Projects all have an owner field, check that
        if (isinstance(obj, Submission) or isinstance(obj, Encounter)
                or isinstance(obj, Project)):
            ret_val = obj.owner is self
        elif isinstance(obj, Asset):
            # assets are not owned directly by the user but the submission they're in is.
            # todo, need to understand once assets become part of an encounter, do they still have a submission
            if obj.submission is not None:
                ret_val = obj.submission.owner is self
        elif isinstance(obj, Sighting):
            # up for consideration. old world allows control of a sighting if you own at least one encounter on it.
            for encounter in obj.get_encounters():
                if encounter.get_owner() is self:
                    ret_val = True
                    break

        return ret_val
Пример #9
0
class Permit(AuditMixin, Base):
    __tablename__ = 'permit'
    _edit_groups = [PERMIT_EDIT_GROUP]
    _edit_key = PERMIT_EDIT_GROUP

    permit_id = db.Column(db.Integer, primary_key=True)
    permit_guid = db.Column(UUID(as_uuid=True), server_default=FetchedValue())
    mine_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('mine.mine_guid'))
    permit_no = db.Column(db.String(16), nullable=False)
    permit_status_code = db.Column(
        db.String(2), db.ForeignKey('permit_status_code.permit_status_code'))
    permit_amendments = db.relationship(
        'PermitAmendment',
        backref='permit',
        primaryjoin=
        "and_(PermitAmendment.permit_id == Permit.permit_id, PermitAmendment.deleted_ind==False)",
        order_by=
        'desc(PermitAmendment.issue_date), desc(PermitAmendment.permit_amendment_id)',
        lazy='select')

    permittee_appointments = db.relationship(
        'MinePartyAppointment',
        lazy='select',
        order_by=
        'desc(MinePartyAppointment.start_date), desc(MinePartyAppointment.mine_party_appt_id)'
    )
    permit_status_code_relationship = db.relationship('PermitStatusCode',
                                                      lazy='select')
    permit_status_code_description = association_proxy(
        'permit_status_code_relationship', 'description')
    mine_name = association_proxy('mine', 'mine_name')

    @hybrid_property
    def current_permittee(self):
        if len(self.permittee_appointments) > 0:
            return self.permittee_appointments[0].party.name
        else:
            return ""

    def __repr__(self):
        return '<Permit %r>' % self.permit_guid

    @classmethod
    def find_by_permit_guid(cls, _id):
        return cls.query.filter_by(permit_guid=_id).first()

    @classmethod
    def find_by_mine_guid(cls, _id):
        return cls.query.filter_by(mine_guid=_id).all()

    @classmethod
    def find_by_permit_no(cls, _permit_no):
        return cls.query.filter_by(permit_no=_permit_no).first()

    @classmethod
    def find_by_permit_guid_or_no(cls, _permit_guid_or_no):
        result = cls.find_by_permit_guid(_permit_guid_or_no)
        if not result:
            result = cls.find_by_permit_no(_permit_guid_or_no)
        return result

    @classmethod
    def create(cls,
               mine_guid,
               permit_no,
               permit_status_code,
               add_to_session=True):
        mine_permit = cls(mine_guid=mine_guid,
                          permit_no=permit_no,
                          permit_status_code=permit_status_code)
        if add_to_session:
            mine_permit.save(commit=False)
        return mine_permit

    @validates('permit_status_code')
    def validate_status_code(self, key, permit_status_code):
        if not permit_status_code:
            raise AssertionError('Permit status code is not provided.')
        if len(permit_status_code) > 2:
            raise AssertionError('Permit status code is invalid.')
        return permit_status_code

    @validates('permit_no')
    def validate_permit_no(self, key, permit_no):
        if not permit_no:
            raise AssertionError('Permit number is not provided.')
        if len(permit_no) > 16:
            raise AssertionError(
                'Permit number must not exceed 16 characters.')
        return permit_no
Пример #10
0
class User(PaginatedAPIMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    name = db.Column(db.String(64))
    location = db.Column(db.String(64))
    about_me = db.Column(db.Text())
    member_since = db.Column(db.DateTime(), default=datetime.utcnow)
    last_seen = db.Column(db.DateTime(), default=datetime.utcnow)
    # 一对多 字段名,作者,
    # 反向引用,直接查询出当前用户的所有博客文章; 同时,Post实例中会有 author 属性
    # cascade 用于级联删除,当删除user时,该user下面的所有posts都会被级联删除
    posts = db.relationship('Post',
                            backref='author',
                            lazy='dynamic',
                            cascade='all, delete-orphan')

    def __repr__(self):
        return '<User {}>'.format(self.username)  # 添加打印对象

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def avatar(self, size):
        '''头像'''
        digest = md5(self.email.lower().encode('utf-8')).hexdigest()
        return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format(
            digest, size)

    def to_dict(self, include_email=False):  # 默认参数为False
        data = {
            'id': self.id,
            'username': self.username,
            'name': self.name,
            'location': self.location,
            'about_me': self.about_me,
            'member_since': self.member_since.isoformat() + 'Z',
            'last_seen': self.last_seen.isoformat() + 'Z',
            '_links': {
                'self': url_for('api.get_user', id=self.id),
                'avatar': self.avatar(128)
            }
        }
        if include_email:
            data['email'] = self.email
        return data

    # 将表单里填写的信息变成实例的属性
    def from_dict(self, data, new_user=True):  # 默认新用户为真
        for field in ['username', 'email', 'name', 'location',
                      'about_me']:  # 遍历表单中的username 和 email
            # 如果 data中 有存在得字段
            if field in data:
                # 将值设置成实例对应的field属性
                setattr(self, field, data[field])
        # 如果还是新用户 且 有设置密码
        if new_user and 'password' in data:
            # 将密码字段也设置成属性
            self.set_password(data['password'])

    def ping(self):
        self.last_seen = datetime.utcnow()
        db.session.add(self)

    def get_jwt(self, expires_in=3600):  # 将get_token方法修改为get_jwt()方法
        now = datetime.utcnow()  # 当前时间
        payload = {
            'user_id': self.id,
            'name': self.name
            if self.name else self.username,  # 如果用户的名字存在则放name,否则username
            'exp': now + timedelta(seconds=expires_in),
            'iat': now
        }
        return jwt.encode(payload,
                          current_app.config['SECRET_KEY'],
                          algorithm='HS256').decode(
                              'utf-8')  # 返回一个字段payload,先进行编码再解码成utf-8格式

    # 静态方法
    @staticmethod
    def verify_jwt(token):  # 使用jwt的decode解码
        try:
            payload = jwt.decode(token,
                                 current_app.config['SECRET_KEY'],
                                 algorithm=['HS256'])
        except (jwt.exceptions.ExpiredSignatureError,
                jwt.exceptions.InvalidSignatureError) as e:
            # Token过期,或者被人修改,name签名验证也会失败
            return None
        return User.query.get(payload.get('user_id'))  # 返回user_id
Пример #11
0
class Permit(AuditMixin, Base):
    __tablename__ = 'permit'
    permit_id = db.Column(db.Integer, primary_key=True)
    permit_guid = db.Column(UUID(as_uuid=True), server_default=FetchedValue())
    mine_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('mine.mine_guid'))
    permit_no = db.Column(db.String(16), nullable=False)
    permit_status_code = db.Column(
        db.String(2), db.ForeignKey('permit_status_code.permit_status_code'))
    permit_amendments = db.relationship(
        'PermitAmendment',
        backref='permit',
        primaryjoin=
        "and_(PermitAmendment.permit_id == Permit.permit_id, PermitAmendment.deleted_ind==False)",
        order_by=
        'desc(PermitAmendment.issue_date), desc(PermitAmendment.permit_amendment_id)',
        lazy='select')

    def __repr__(self):
        return '<Permit %r>' % self.permit_guid

    def json(self):
        return {
            'permit_id': str(self.permit_id),
            'permit_guid': str(self.permit_guid),
            'mine_guid': str(self.mine_guid),
            'permit_no': self.permit_no,
            'permit_status_code': self.permit_status_code,
            'amendments': [x.json() for x in self.permit_amendments]
        }

    def json_for_list(self):
        return {
            'permit_id': str(self.permit_id),
            'permit_guid': str(self.permit_guid),
            'mine_guid': str(self.mine_guid),
            'permit_no': self.permit_no,
            'permit_status_code': self.permit_status_code
        }

    @classmethod
    def find_by_permit_guid(cls, _id):
        return cls.query.filter_by(permit_guid=_id).first()

    @classmethod
    def find_by_mine_guid(cls, _id):
        return cls.query.filter_by(mine_guid=_id)

    @classmethod
    def find_by_permit_no(cls, _permit_no):
        return cls.query.filter_by(permit_no=_permit_no).first()

    @classmethod
    def create(cls, mine_guid, permit_no, permit_status_code, save=True):
        mine_permit = cls(mine_guid=mine_guid,
                          permit_no=permit_no,
                          permit_status_code=permit_status_code)
        if save:
            mine_permit.save(commit=False)
        return mine_permit

    @validates('permit_status_code')
    def validate_status_code(self, key, permit_status_code):
        if not permit_status_code:
            raise AssertionError('Permit status code is not provided.')
        if len(permit_status_code) > 2:
            raise AssertionError('Permit status code is invalid.')
        return permit_status_code

    @validates('permit_no')
    def validate_permit_no(self, key, permit_no):
        if not permit_no:
            raise AssertionError('Permit number is not provided.')
        if len(permit_no) > 16:
            raise AssertionError(
                'Permit number must not exceed 16 characters.')
        return permit_no
Пример #12
0
class MinePartyAppointment(AuditMixin, Base):
    __tablename__ = "mine_party_appt"
    # Columns
    mine_party_appt_id = db.Column(db.Integer, primary_key=True, server_default=FetchedValue())
    mine_party_appt_guid = db.Column(UUID(as_uuid=True), server_default=FetchedValue())
    mine_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('mine.mine_guid'))
    party_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('party.party_guid'))
    mine_party_appt_type_code = db.Column(
        db.String(3), db.ForeignKey('mine_party_appt_type_code.mine_party_appt_type_code'))
    start_date = db.Column(db.DateTime)
    end_date = db.Column(db.DateTime)
    processed_by = db.Column(db.String(60), server_default=FetchedValue())
    processed_on = db.Column(db.DateTime, nullable=False, server_default=FetchedValue())

    #type specific foreign keys
    mine_tailings_storage_facility_guid = db.Column(
        UUID(as_uuid=True),
        db.ForeignKey('mine_tailings_storage_facility.mine_tailings_storage_facility_guid'))
    permit_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('permit.permit_guid'))

    deleted_ind = db.Column(db.Boolean, server_default=FetchedValue())

    # Relationships
    party = db.relationship('Party', lazy='joined')

    mine_party_appt_type = db.relationship(
        'MinePartyAppointmentType',
        backref='mine_party_appt',
        order_by='desc(MinePartyAppointmentType.display_order)',
        lazy='joined')

    def assign_related_guid(self, related_guid):
        if self.mine_party_appt_type_code == "EOR":
            self.mine_tailings_storage_facility_guid = related_guid

        if self.mine_party_appt_type_code == "PMT":
            self.permit_guid = related_guid
        return

    # json
    def json(self, relationships=[]):
        result = {
            'mine_party_appt_guid': str(self.mine_party_appt_guid),
            'mine_guid': str(self.mine_guid),
            'party_guid': str(self.party_guid),
            'mine_party_appt_type_code': str(self.mine_party_appt_type_code),
            'start_date': str(self.start_date) if self.start_date else None,
            'end_date': str(self.end_date) if self.end_date else None,
        }
        if 'party' in relationships:
            result.update({'party': self.party.json(show_mgr=False) if self.party else str({})})
        related_guid = ""
        if self.mine_party_appt_type_code == "EOR":
            related_guid = str(self.mine_tailings_storage_facility_guid)
        elif self.mine_party_appt_type_code == "PMT":
            related_guid = str(self.permit_guid)
        result["related_guid"] = related_guid
        return result

    # search methods
    @classmethod
    def find_by_mine_party_appt_guid(cls, _id):
        try:
            return cls.query.filter_by(mine_party_appt_guid=_id).filter_by(
                deleted_ind=False).first()
        except ValueError:
            return None

    @classmethod
    def find_all_by_mine_party_appt_guid(cls, _id):
        try:
            return cls.query.filter_by(mine_party_appt_guid=_id).filter_by(
                deleted_ind=False)
        except ValueError:
            return None

    @classmethod
    def find_by_mine_guid(cls, _id):
        try:
            return cls.find_by(mine_guid=_id)
        except ValueError:
            return None

    @classmethod
    def find_by_party_guid(cls, _id):
        try:
            return cls.find_by(party_guid=_id)
        except ValueError:
            return None

    @classmethod
    def find_parties_by_mine_party_appt_type_code(cls, code):
        try:
            return cls.find_by(mine_party_appt_type_codes=[code])
        except ValueError:
            return None

    @classmethod
    def find_manager_history_by_mine_no(cls, mine_no):
        # send internal API call to fetch matching mine record
        mines_url = current_app.config['MINES_URL'] + '/mines/' + str(mine_no)
        auth_headers = request.headers.get('Authorization')
        if not auth_headers:
            return None, 401, 'Unauthorized'

        headers = {'Authorization': auth_headers}
        response = requests.get(url=mines_url, headers=headers)
        if not response:
            return None, 500, 'Server error'
        if response.status_code != 200:
            return None, response.status_code, response.reason

        # fetch mine history by mine_guid
        try:
            json_response = response.json()
        except:
            return None, 500, 'Server error'

        related_mine_guid = json_response.get('guid')
        if not related_mine_guid:
            return None, 404, 'Mine not found'

        records = cls.query.filter_by(mine_guid=related_mine_guid).all()
        if len(records) == 0:
            return None, 404, 'No Mine Manager history found'
        return records, 200, 'OK'

    @classmethod
    def find_by(cls, mine_guid=None, party_guid=None, mine_party_appt_type_codes=None):
        try:
            built_query = cls.query.filter_by(deleted_ind=False)
            if mine_guid:
                built_query = built_query.filter_by(mine_guid=mine_guid)
            if party_guid:
                built_query = built_query.filter_by(party_guid=party_guid)
            if mine_party_appt_type_codes:
                built_query = built_query.filter(
                    cls.mine_party_appt_type_code.in_(mine_party_appt_type_codes))
            return built_query.all()
        except ValueError:
            return None

    @classmethod
    def to_csv(cls, records, columns):
        rows = [','.join(columns)]
        for record in records:
            row = []
            for column in columns:
                row.append(str(getattr(record, column)))
            rows.append(','.join(row))
        return '\n'.join(rows)

    @classmethod
    def create(cls,
               mine_guid,
               party_guid,
               mine_party_appt_type_code,
               start_date=None,
               end_date=None,
               processed_by=processed_by,
               permit_guid=None,
               save=True):
        mpa = cls(
            mine_guid=mine_guid,
            party_guid=party_guid,
            permit_guid=permit_guid,
            mine_party_appt_type_code="PMT",
            start_date=start_date,
            end_date=end_date,
            processed_by=processed_by)
        if save:
            mpa.save(commit=False)
        return mpa

    # validators
    @validates('mine_guid')
    def validate_mine_guid(self, key, val):
        if not val:
            raise AssertionError('No mine guid provided.')
        return val

    @validates('party_guid')
    def validate_party_guid(self, key, val):
        if not val:
            raise AssertionError('No party guid provided.')
        return val

    @validates('mine_party_appt_type_code')
    def validate_mine_party_appt_type_code(self, key, val):
        if not val:
            raise AssertionError('No mine party appointment type code')
        if len(val) is not 3:
            raise AssertionError('invalid mine party appointment type code')
        return val

    @validates('mine_tailings_storage_facility_guid')
    def validate_mine_tailings_storage_facility_guid(self, key, val):
        if self.mine_party_appt_type_code == 'EOR':
            if not val:
                raise AssertionError(
                    'No mine_tailings_storage_facility_guid, but mine_party_appt_type_code is EOR.')
        return val

    @validates('permit_guid')
    def validate_permit_guid(self, key, val):
        if self.mine_party_appt_type_code == 'PMT':
            if not val:
                raise AssertionError('No permit_guid, but mine_party_appt_type_code is PMT.')
        return val
Пример #13
0
class User(UserMixin,db.Model):
    __tablename__ = 'user'
    id = db.Column('id',db.Integer,primary_key=True)
    username = db.Column(db.String(12),index=True)
    password_hash = db.Column(db.String(128))
    sex = db.Column(db.Boolean,default=True)
    age = db.Column(db.Integer)
    email = db.Column(db.String(40))
    icon = db.Column(db.String(70),default='default.jpg')
    #当期账户激活状态
    confirm = db.Column(db.Boolean,default=False)
    #参数1模型名称   参数2反向引用的字段名   参数3 加载方式 提供对象
    posts = db.relationship('Posts',backref='user',lazy='dynamic')
    #secondary在多对多关系中指定关联表的名称
    favorite = db.relationship('Posts',secondary='collections',backref=db.backref('users',lazy='dynamic'),lazy='dynamic')
    #添加使用append   删除使用remove

    @property
    def password(self):
        raise ValueError

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    #生成token的方法
    def generate_token(self):
        s = Seralize(current_app.config['SECRET_KEY'])
        return s.dumps({'id':self.id})

    #检测token的方法
    @staticmethod
    def check_token(token):
        s = Seralize(current_app.config['SECRET_KEY'])
        #从当前的token中拿出字典
        try:
            id = s.loads(token)['id']
        except:
            return False
        #根据用户id取出对应用户的对象
        u = User.query.get(id)
        #判断 当期u对象是否存在
        if not u:
            return False
        #判断当期用户的激活状态 如果没有激活 则激活
        if not u.confirm:
            u.confirm = True
            db.session.add(u)
        return True
    #验证密码
    def check_password_hash(self,password):
        return check_password_hash(self.password_hash,password)


    def is_favorite(self,postsId):
        all = self.favorite.all()
        for p in all:
            if p.id==postsId:
                return True
            #lambda表达式
            if list(filter(lambda p:p.id==int(postsId),all)):
                return True
            return False

    #定义一个收藏与取消收藏方法
    def add_favorite(self,pid):
        self.favorite.append(Posts.query.get(pid))

    #定义一个取消收藏方法
    def remove_favorite(self,pid):
        self.favorite.remove(Posts.query.get(pid))
Пример #14
0
class Item(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.Text)
    done = db.Column(db.Boolean, default=False)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    author = db.relationship('User', back_populates='items')
Пример #15
0
class TowerDB(db.Model):
    tower_id = db.Column(db.Integer, primary_key=True)
    tower_name = db.Column(db.String(32), index=True)
    created_on = db.Column(db.Date, default=date.today)
    last_access = db.Column(db.Date,
                            nullable=False,
                            default=date.today,
                            onupdate=date.today)
    users = db.relationship("UserTowerRelation", back_populates="tower")
    host_mode_enabled = db.Column(db.Boolean, default=False)
    additional_sizes_enabled = db.Column(db.Boolean, default=False)
    half_muffled = db.Column(db.Boolean, default=False)
    fully_muffled = db.Column(db.Boolean, default=False)
    wheatley_enabled = db.Column(db.Boolean, default=False)
    wheatley_settings_json = db.Column(db.String(), default="{}")
    anticlockwise = db.Column(db.Boolean, default=False)
    cowbell_enabled = db.Column(db.Boolean, default=False)

    def __repr__(self):
        return '<TowerDB {}: {}>'.format(self.tower_id, self.tower_name)

    def to_dict(self):
        data = {
            'tower_id': self.tower_id,
            'tower_name': self.tower_name,
            'host_mode_enabled': self.host_mode_enabled,
            'hosts': [u.to_dict() for u in self.hosts],
        }
        return data

    def to_Tower(self):
        has_changed_db = False

        # Parse Wheatley's settings from JSON (and initialise with '{}' if invalid or non-existent)
        wheatley_settings = None
        while wheatley_settings is None:
            try:
                wheatley_settings = json.loads(self.wheatley_settings_json)
            except TypeError:
                self.wheatley_settings_json = "{}"
                has_changed_db = True
            except Exception as e:
                self.log(
                    f"Invalid Wheatley settings JSON {self.wheatley_settings_json}: {e}"
                )
                self.wheatley_settings_json = "{}"
                has_changed_db = True

        # Read Wheatley's enabledness from the database, and initialise it if it's null
        if self.wheatley_enabled is None:
            self.wheatley_enabled = False
            has_changed_db = True

        # Commit the changes to the database if they've been made
        if has_changed_db:
            db.session.commit()

        return Tower(
            self.tower_name,
            tower_id=self.tower_id,
            host_mode_enabled=self.host_mode_enabled,
            # Force wheatley_enabled to be False if the Wheatley feature flag is not set
            wheatley_enabled=self.wheatley_enabled
            and app.wheatley.feature_flag(),
            wheatley_db_settings=wheatley_settings)

    def created_by(self, user):
        # Expects a User object
        # This should go through the user object, to avoid duplicating the
        # relation
        rel = user._get_relation_to_tower(self)
        rel.creator = True
        rel.host = True
        db.session.commit()

    @property
    def creator(self):
        rel = UserTowerRelation.query.filter(
            UserTowerRelation.tower == self,
            UserTowerRelation.creator == True).first()
        return rel.user if rel else None

    # We need to be able to get this from the TowerDB object for the User Menu
    @property
    def url_safe_name(self):
        out = re.sub(r'\s', '_', self.tower_name)
        out = re.sub(r'\W', '', out)
        return out.lower()

    @property
    def hosts(self):
        return [
            rel.user for rel in UserTowerRelation.query.filter(
                UserTowerRelation.tower == self, UserTowerRelation.host ==
                True).all()
        ]

    @property
    def host_ids(self):
        return [
            rel.user.id for rel in UserTowerRelation.query.filter(
                UserTowerRelation.tower == self, UserTowerRelation.host ==
                True).all()
        ]
Пример #16
0
class GroupSchedule(Schedule):
    user_group_id = reference_col('user_group')
    user_group = db.relationship("UserGroup", back_populates='schedules')

    __mapper_args__ = {'polymorphic_identity': 'group_schedule'}
Пример #17
0
class Lecture(db.Model):
    __tablename__ = 'lecture'

    id = db.Column(db.Integer, primary_key=True)
    dept = db.Column(db.String(10), nullable=False)
    course_num = db.Column(db.Integer, nullable=False)
    title = db.Column(db.String(50), nullable=False)
    section = db.Column(db.Integer, nullable=False)
    days = db.Column(db.String(10), nullable=False)
    start = db.Column(db.Integer, nullable=False)
    end = db.Column(db.Integer, nullable=False)
    professor = db.Column(db.String(50), nullable=True)

    hall_id = db.Column(db.Integer, db.ForeignKey('hall.id'))
    hall = db.relationship("Hall")
    discussion = db.relationship("Discussion",
                                 uselist=False,
                                 back_populates="lecture")
    user = db.relationship("User",
                           secondary=UserLectureAssociation,
                           back_populates="lecture")

    def __init__(self, dept, course_num, title, section, days, start, end,
                 professor):
        self.dept = dept
        self.course_num = course_num
        self.title = title
        self.section = section
        self.days = days
        self.start = start
        self.end = end
        self.professor = professor

    def __repr__(self):
        return "<Lecture: {} {} {}>".format(self.dept, self.course_num,
                                            self.section)

    def get(id):
        return Lecture.query.get(id)

    def json_to_database():
        classes = schedule.get_classes()['classes']
        print('Writing {} lectures to database...'.format(len(classes)))
        for c in classes:
            try:
                lect = Lecture(c['dept'], c['course_num'], c['title'],
                               c['section'], c['days'], c['start'], c['end'],
                               c['professor'])

                lect.hall = Hall.query.filter(
                    Hall.abbr == c['hall'].split(' ')[0]).first()

                print('Adding Lecture {} {} {}, starts at {}, taught by {}'.
                      format(lect.dept, lect.course_num, lect.title,
                             lect.start, lect.professor))
                db.session.add(lect)
            except Exception as e:
                print('Error in writing lectures to table -- {}'.format(e))
                print('Skipping...')
                continue
        db.session.commit()
Пример #18
0
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True)
    password_hash = db.Column(db.String(20))
    email = db.Column(db.String(64), unique=True)
    confirmed = db.Column(db.Boolean, default=False)
    # 添加保存头像文件名的字段
    icon = db.Column(db.String(64), default='default.jpg')
    # 添加博客的反向引用
    posts = db.relationship('Posts', lazy='dynamic', backref='user')
    # 添加收藏的反向引用
    favorites = db.relationship('Posts',
                                lazy='dynamic',
                                secondary='collections',
                                backref=db.backref('users', lazy='dynamic'))

    # 判断是否收藏
    def is_favorite(self, pid):
        favorite = self.favorites.filter(Posts.id == pid).first()
        if favorite:
            return True
        return False

    # 添加收藏
    def add_favorite(self, pid):
        p = Posts.query.get(pid)
        self.favorites.append(p)

    # 取消收藏
    def del_favorite(self, pid):
        p = Posts.query.get(pid)
        self.favorites.remove(p)

    # 属性函数
    @property
    def password(self):
        raise AttributeError('密码属性不可读')

    # 设置密码
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    # 密码校验
    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    # 生成账户激活的token
    def generate_activate_token(self, expires_in=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in=expires_in)
        return s.dumps({'id': self.id})

    # 账户激活token的检验
    @staticmethod
    def check_activate_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
            # 根据用户名查找数据库
            u = User.query.get(data['id'])
            # 查看用户是否激活
            if not u.confirmed:
                # 若没有激活,激活用户
                u.confirmed = True
                db.session.add(u)
            return True
        except:
            return False
Пример #19
0
class User(UserMixin, db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'), nullable=False)
    role = db.relationship('Role', back_populates='users')
    posts = db.relationship('Post', back_populates='author', lazy='dynamic')
    last_visit = db.Column(db.DateTime)
    is_confirmed = db.Column(db.Boolean, default=False)
    member_since = db.Column(db.DateTime, default=datetime.utcnow)
    image_hash = db.Column(db.String(128))

    followings = db.relationship('Follow',
                                 foreign_keys=[Follow.follower_id],
                                 backref=db.backref('follower', lazy='joined'),
                                 lazy='dynamic')
    followers = db.relationship('Follow',
                                foreign_keys=[Follow.followed_id],
                                backref=db.backref('followed', lazy='joined'),
                                lazy='dynamic')

    messages_sent = db.relationship('Message',
                                    foreign_keys=[Message.sender_id],
                                    backref='author',
                                    lazy='dynamic')
    messages_received = db.relationship('Message',
                                        foreign_keys=[Message.receiver_id],
                                        backref='receiver',
                                        lazy='dynamic')

    notifications = db.relationship('Notification',
                                    back_populates='receiver',
                                    lazy='dynamic')

    @property
    def password(self):
        raise AttributeError('password is not readable attribute')

    @password.setter
    def password(self, value):
        self.password_hash = generate_password_hash(value)

    def verify_password(self, value):
        return check_password_hash(self.password_hash, value)

    def ping(self):
        self.last_visit = datetime.utcnow()
        db.session.add(self)
        db.session.commit()

    def generate_confirmation_token(self):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in=3600)
        return s.dumps({'id': self.id}).decode('utf-8')

    def confirm(self, token):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in=3600)
        try:
            o = s.loads(token)
            return o['id'] == self.id
        except Exception:
            return False

    def gravatar(self, size=100, default='identicon', rating='g'):
        url = 'https://secure.gravatar.com/avatar'
        # hash = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
        return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(
            url=url,
            hash=self.image_hash,
            size=size,
            default=default,
            rating=rating)

    def follow(self, user):
        if user is not None:
            model = Follow(follower_id=self.id, followed_id=user.id)
            db.session.add(model)

    def unfollow(self, user):
        if user is not None:
            model = self.followings.filter_by(followed_id=user.id).first()
            # model = Follow.query.filter(Follow.follower_id == self.id, Follow.followed_id == user.id).first()
            db.session.delete(model)
            db.session.commit()

    def is_following(self, user):
        if user is None:
            return False
        return self.followings.filter_by(
            followed_id=user.id).first() is not None

    def is_followed_by(self, user):
        pass

    def can(self, permission_name):
        role = Role.query.filter_by(name=permission_name).first()
        if role and self.role.permissions & role.permissions:
            return True
        return False

    @property
    def is_admin(self):
        return self.role.name == 'Administrator'

    @staticmethod
    def on_email_change(target, value, oldvalue, initiator):

        if value != oldvalue:
            target.image_hash = hashlib.md5(
                value.lower().encode('utf-8')).hexdigest()

    def __repr__(self):
        return '<User %r>' % self.username
Пример #20
0
class EmailAddress(db.Model):
    __tablename__ = 'email_address'
    __versioned__ = {}
    __mapper_args__ = {'extension': BaseExtension()}

    id = db.Column(db.Integer, primary_key=True, index=True)
    email = db.Column("email", db.Text, index=True)
    primary = db.Column("primary", db.Boolean, default=False)
    active = db.Column("active", db.Boolean, default=False)
    patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), index=True)
    patient = db.relationship("Patient", back_populates="email_addresses")
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True)
    user = db.relationship("User", back_populates="email_addresses")
    avatar_hash = db.Column(db.Text)
    created_at = db.Column(db.DateTime, default=datetime.utcnow())
    updated_at = db.Column(db.DateTime)
    row_hash = db.Column(db.Text, index=True)

    def __init__(self, email=None, primary=False, active=True):
        self.email = email
        self.primary = primary
        self.active = active
        self._fhir = None

    def generate_avatar_hash(self):
        __doc__ = """
        Generate an MD5 hash of the user's email.  Stores the result in the user
        'avatar_hash' attribute.  This value is used when constructing the gravatar URL."""
        if self.email and not re.search(r'(@EXAMPLE)+', self.email):
            email_lower = self.email.lower()
            self.avatar_hash = hashlib.md5(
                email_lower.encode('utf-8')).hexdigest()

    def gravatar_url(self, size=100, default='identicon', rating='g'):
        __doc__ = """
        Generate a Gravatar url based on an MD5 hash of the user's email. URL output
        conforms to standards for Globally Recognized Avatar service.
        Defaults established as:
         Size: 100px
         Default: identicon (if gravatar not found, pattern unique to MD5 hash is displayed\
         Rating: g
         """
        url = 'https://secure.gravatar.com/avatar'
        if not self.avatar_hash:
            self.generate_avatar_hash()
            db.session.add(self)
        return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(
            url=url,
            hash=self.avatar_hash,
            size=size,
            default=default,
            rating=rating)

    def dump(self):
        schema = EmailAddressSchema()
        return schema.dump(self).data

    @property
    def fhir(self):
        """
        Returns fhir-client ContactPoint model object associated with SQLAlchemy Instance
        If no fhir-client object is initialized, one is created and stored in protected attrib _fhir
        :return:
            fhir-client ContactPoint object matching SQLAlchemy ORM object instance
        """
        if not getattr(self, '_fhir', None):
            self.create_fhir_object()
            return self._fhir
        else:
            return self._fhir

    @fhir.setter
    def fhir(self, fhir_obj):
        """
        Allows setting of the protected attribute _fhir
        Validates object is fhir-client model ContactPoint object
        :param fhir_obj:
            A fhir-client ContactPOint model object instance
        :return:
            None
        """
        if not isinstance(fhir_obj, contactpoint.ContactPoint):
            raise TypeError('Object is not a fhirclient ContactPoint object')
        else:
            self._fhir = fhir_obj

    def create_fhir_object(self):
        fhir_contact = contactpoint.ContactPoint()
        fhir_contact.system = 'email'
        if self.active:
            fhir_contact.use = 'home'
            if self.primary:
                fhir_contact.rank = 1
            else:
                fhir_contact.rank = 2
        else:
            fhir_contact.use = 'old'
            fhir_contact.rank = 3

        if self.email:
            fhir_contact.value = self.email

        self._fhir = fhir_contact

    def dump_fhir_json(self):
        self.create_fhir_object()
        return self.fhir.as_json()

    def generate_row_hash(self):
        data = {
            "email": self.email,
            "patient_id": self.patient_id,
            "user_id": self.user_id
        }
        data_str = json.dumps(data, sort_keys=True, default=json_serial)
        data_hash = hashlib.sha1(data_str.encode('utf-8')).hexdigest()
        return data_hash

    def before_insert(self):
        self.row_hash = self.generate_row_hash()
        if not self.avatar_hash:
            self.generate_avatar_hash()

    def before_update(self):
        self.row_hash = self.generate_row_hash()
        if not self.avatar_hash:
            self.generate_avatar_hash()
Пример #21
0
class Party(AuditMixin, Base):
    __tablename__ = 'party'
    party_guid = db.Column(UUID(as_uuid=True),
                           primary_key=True,
                           server_default=FetchedValue())
    first_name = db.Column(db.String, nullable=True)
    middle_name = db.Column(db.String, nullable=True)
    party_name = db.Column(db.String, nullable=False)
    phone_no = db.Column(db.String, nullable=False)
    phone_ext = db.Column(db.String, nullable=True)
    email = db.Column(db.String, nullable=True)
    effective_date = db.Column(db.DateTime,
                               nullable=False,
                               server_default=FetchedValue())
    expiry_date = db.Column(db.DateTime)
    party_type_code = db.Column(
        db.String, db.ForeignKey('party_type_code.party_type_code'))
    deleted_ind = db.Column(db.Boolean,
                            nullable=False,
                            server_default=FetchedValue())

    mine_party_appt = db.relationship('MinePartyAppointment', lazy='joined')
    address = db.relationship('Address', lazy='joined')
    job_title = db.Column(db.String, nullable=True)
    postnominal_letters = db.Column(db.String, nullable=True)
    idir_username = db.Column(db.String, nullable=True)

    business_role_appts = db.relationship('PartyBusinessRoleAppointment',
                                          lazy='joined')

    @hybrid_property
    def name(self):
        return self.first_name + ' ' + self.party_name if self.first_name else self.party_name

    @hybrid_property
    def business_roles_codes(self):
        return [
            x.party_business_role_code for x in self.business_role_appts
            if (not x.end_date or x.end_date > datetime.utcnow())
        ]

    @name.expression
    def name(cls):
        return func.concat(cls.first_name, ' ', cls.party_name)

    def __repr__(self):
        return '<Party %r>' % self.party_guid

    # TODO: Remove this once mine_party_appt has been refactored
    def json(self, show_mgr=True, relationships=[]):
        context = {
            'party_guid':
            str(self.party_guid),
            'party_type_code':
            self.party_type_code,
            'phone_no':
            self.phone_no,
            'phone_ext':
            self.phone_ext,
            'email':
            self.email,
            'effective_date':
            self.effective_date.isoformat(),
            'expiry_date':
            self.expiry_date.isoformat()
            if self.expiry_date is not None else None,
            'party_name':
            self.party_name,
            'name':
            self.name,
            'address':
            self.address[0].json() if len(self.address) > 0 else [{}],
            'job_title':
            self.job_title,
            'postnominal_letters':
            self.postnominal_letters,
            'idir_username':
            self.idir_username
        }
        if self.party_type_code == 'PER':
            context.update({
                'first_name': self.first_name,
            })

        if 'mine_party_appt' in relationships:
            context.update({
                'mine_party_appt':
                [item.json() for item in self.mine_party_appt],
            })

        return context

    @classmethod
    def find_by_party_guid(cls, _id):
        try:
            uuid.UUID(_id)
        except ValueError:
            raise BadRequest('Invalid Party guid')
        return cls.query.filter_by(party_guid=_id, deleted_ind=False).first()

    @classmethod
    def find_by_name(cls, party_name, first_name=None):
        party_type_code = 'PER' if first_name else 'ORG'
        filters = [
            func.lower(cls.party_name) == func.lower(party_name),
            cls.party_type_code == party_type_code, cls.deleted_ind == False
        ]
        if first_name:
            filters.append(
                func.lower(cls.first_name) == func.lower(first_name))
        return cls.query.filter(*filters).first()

    @classmethod
    def search_by_name(cls, search_term, party_type=None, query_limit=50):
        _filter_by_name = func.upper(cls.name).contains(
            func.upper(search_term))
        if party_type:
            return cls.query.filter(cls.party_type_code == party_type).filter(
                _filter_by_name).filter(
                    cls.deleted_ind == False).limit(query_limit)
        else:
            return cls.query.filter(_filter_by_name).filter(
                cls.deleted_ind == False).limit(query_limit)

    @classmethod
    def create(
            cls,
            # Required fields
            party_name,
            phone_no,
            party_type_code,
            # Optional fields
            address_type_code=None,
            # Nullable fields
            email=None,
            first_name=None,
            phone_ext=None,
            suite_no=None,
            address_line_1=None,
            address_line_2=None,
            city=None,
            sub_division_code=None,
            post_code=None,
            add_to_session=True):
        party = cls(
            # Required fields
            party_name=party_name,
            phone_no=phone_no,
            party_type_code=party_type_code,
            # Optional fields
            email=email,
            first_name=first_name,
            phone_ext=phone_ext)
        if add_to_session:
            party.save(commit=False)
        return party

    @validates('party_type_code')
    def validate_party_type_code(self, key, party_type_code):
        if not party_type_code:
            raise AssertionError('Party type is not provided.')
        if party_type_code not in ['PER', 'ORG']:
            raise AssertionError('Invalid party type.')
        return party_type_code

    @validates('first_name')
    def validate_first_name(self, key, first_name):
        if self.party_type_code == 'PER' and not first_name:
            raise AssertionError('Person first name is not provided.')
        if first_name and len(first_name) > 100:
            raise AssertionError(
                'Person first name must not exceed 100 characters.')
        return first_name

    @validates('party_name')
    def validate_party_name(self, key, party_name):
        if not party_name:
            raise AssertionError('Party name is not provided.')
        if len(party_name) > 100:
            raise AssertionError('Party name must not exceed 100 characters.')
        return party_name

    @validates('phone_no')
    def validate_phone_no(self, key, phone_no):
        if not phone_no:
            raise AssertionError('Party phone number is not provided.')
        if not re.match(r'[0-9]{3}-[0-9]{3}-[0-9]{4}', phone_no):
            raise AssertionError(
                'Invalid phone number format, must be of XXX-XXX-XXXX.')
        return phone_no

    @validates('email')
    def validate_email(self, key, email):
        if email and not re.match(r'[^@]+@[^@]+\.[^@]+', email):
            raise AssertionError(f'Invalid email format. {email}')
        return email
Пример #22
0
class Application(Base):
    __tablename__ = "application"
    __table_args__ = {"schema": "now_submissions"}
    messageid = db.Column(db.Integer, primary_key=True)
    application_guid = db.Column(UUID(as_uuid=True), nullable=False)
    mine_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('mine.mine_guid'))
    trackingnumber = db.Column(db.Integer)
    applicationtype = db.Column(db.String)
    status = db.Column(db.String)
    submitteddate = db.Column(db.DateTime)
    receiveddate = db.Column(db.DateTime)
    applicantclientid = db.Column(
        db.Integer, db.ForeignKey('now_submissions.client.clientid'))
    submitterclientid = db.Column(
        db.Integer, db.ForeignKey('now_submissions.client.clientid'))
    noticeofworktype = db.Column(db.String)
    typeofpermit = db.Column(db.String)
    typeofapplication = db.Column(db.String)
    minenumber = db.Column(db.String)
    latitude = db.Column(db.Numeric(9, 7))
    longitude = db.Column(db.Numeric(11, 7))
    nameofproperty = db.Column(db.String)
    tenurenumbers = db.Column(db.String)
    crowngrantlotnumbers = db.Column(db.String)
    sitedirections = db.Column(db.String)
    firstaidequipmentonsite = db.Column(db.String)
    firstaidcertlevel = db.Column(db.String)
    descexplorationprogram = db.Column(db.String)
    proposedstartdate = db.Column(db.DateTime)
    proposedenddate = db.Column(db.DateTime)
    yearroundseasonal = db.Column(db.String)
    landcommunitywatershed = db.Column(db.String)
    landprivate = db.Column(db.String)
    landlegaldesc = db.Column(db.String)
    archsitesaffected = db.Column(db.String)
    sandgravelquarryoperations = db.Column(db.String)
    storeexplosivesonsite = db.Column(db.String)
    bcexplosivespermitissued = db.Column(db.String)
    bcexplosivespermitnumber = db.Column(db.String)
    bcexplosivespermitexpiry = db.Column(db.DateTime)
    campdisturbedarea = db.Column(db.Numeric(14, 2))
    camptimbervolume = db.Column(db.Numeric(14, 2))
    bldgdisturbedarea = db.Column(db.Numeric(14, 2))
    bldgtimbervolume = db.Column(db.Numeric(14, 2))
    stgedisturbedarea = db.Column(db.Numeric(14, 2))
    stgetimbervolume = db.Column(db.Numeric(14, 2))
    fuellubstoreonsite = db.Column(db.String)
    fuellubstored = db.Column(db.Integer)
    fuellubstoremethodbulk = db.Column(db.String)
    fuellubstoremethodbarrel = db.Column(db.String)
    cbsfreclamation = db.Column(db.String)
    cbsfreclamationcost = db.Column(db.Numeric(14, 2))
    mechtrenchingreclamation = db.Column(db.String)
    mechtrenchingreclamationcost = db.Column(db.Numeric(14, 2))
    expsurfacedrillreclamation = db.Column(db.String)
    expsurfacedrillreclcorestorage = db.Column(db.String)
    expsurfacedrillreclamationcost = db.Column(db.Numeric(14, 2))
    expaccessreclamation = db.Column(db.String)
    expaccessreclamationcost = db.Column(db.Numeric(14, 2))
    surfacebulksampleprocmethods = db.Column(db.String)
    surfacebulksamplereclamation = db.Column(db.String)
    surfacebulksamplereclsephandl = db.Column(db.String)
    surfacebulksamplerecldrainmiti = db.Column(db.String)
    surfacebulksamplereclcost = db.Column(db.Numeric(14, 2))
    underexptotalore = db.Column(db.Integer)
    underexptotaloreunits = db.Column(db.String)
    underexptotalwaste = db.Column(db.Integer)
    underexptotalwasteunits = db.Column(db.String)
    underexpreclamation = db.Column(db.String)
    underexpreclamationcost = db.Column(db.Numeric(14, 2))
    placerundergroundoperations = db.Column(db.String)
    placerhandoperations = db.Column(db.String)
    placerreclamationarea = db.Column(db.Numeric(14, 2))
    placerreclamation = db.Column(db.String)
    placerreclamationcost = db.Column(db.Numeric(14, 2))
    sandgrvqrydepthoverburden = db.Column(db.Numeric(14, 2))
    sandgrvqrydepthtopsoil = db.Column(db.Numeric(14, 2))
    sandgrvqrystabilizemeasures = db.Column(db.String)
    sandgrvqrywithinaglandres = db.Column(db.String)
    sandgrvqryalrpermitnumber = db.Column(db.String)
    sandgrvqrylocalgovsoilrembylaw = db.Column(db.String)
    sandgrvqryofficialcommplan = db.Column(db.String)
    sandgrvqrylandusezoning = db.Column(db.String)
    sandgrvqryendlanduse = db.Column(db.String)
    sandgrvqrytotalmineres = db.Column(db.Integer)
    sandgrvqrytotalmineresunits = db.Column(db.String)
    sandgrvqryannualextrest = db.Column(db.Integer)
    sandgrvqryannualextrestunits = db.Column(db.String)
    sandgrvqryreclamation = db.Column(db.String)
    sandgrvqryreclamationbackfill = db.Column(db.String)
    sandgrvqryreclamationcost = db.Column(db.Numeric(14, 2))
    sandgrvqrygrdwtravgdepth = db.Column(db.Numeric(14, 1))
    sandgrvqrygrdwtrexistingareas = db.Column(db.String)
    sandgrvqrygrdwtrtestpits = db.Column(db.String)
    sandgrvqrygrdwtrtestwells = db.Column(db.String)
    sandgrvqrygrdwtrother = db.Column(db.String)
    sandgrvqrygrdwtrmeasprotect = db.Column(db.String)
    sandgrvqryimpactdistres = db.Column(db.Integer)
    sandgrvqryimpactdistwater = db.Column(db.Integer)
    sandgrvqryimpactnoise = db.Column(db.String)
    sandgrvqryimpactprvtaccess = db.Column(db.String)
    sandgrvqryimpactprevtdust = db.Column(db.String)
    sandgrvqryimpactminvisual = db.Column(db.String)
    cutlinesexplgridtotallinekms = db.Column(db.Integer)
    cutlinesexplgridtimbervolume = db.Column(db.Numeric(14, 2))
    cutlinesreclamation = db.Column(db.String)
    cutlinesreclamationcost = db.Column(db.Numeric(14, 2))
    pondswastewatertreatfacility = db.Column(db.String)
    freeusepermit = db.Column(db.String)
    licencetocut = db.Column(db.String)
    timbertotalvolume = db.Column(db.Numeric(14, 2))
    campbuildstgetotaldistarea = db.Column(db.Numeric(14, 2))
    mechtrenchingtotaldistarea = db.Column(db.Numeric(14, 2))
    expsurfacedrilltotaldistarea = db.Column(db.Numeric(14, 2))
    expaccesstotaldistarea = db.Column(db.Numeric(14, 2))
    surfacebulksampletotaldistarea = db.Column(db.Numeric(14, 2))
    placertotaldistarea = db.Column(db.Numeric(14, 2))
    underexptotaldistarea = db.Column(db.Numeric(14, 2))
    sandgrvqrytotaldistarea = db.Column(db.Numeric(14, 2))
    pondstotaldistarea = db.Column(db.Numeric(14, 2))
    reclcostsubtotal = db.Column(db.Numeric(14, 2))
    reclcostexist = db.Column(db.Numeric(14, 2))
    reclcostrecl = db.Column(db.Numeric(14, 2))
    reclcosttotal = db.Column(db.Numeric(14, 2))
    reclareasubtotal = db.Column(db.Numeric(14, 2))
    reclareaexist = db.Column(db.Numeric(14, 2))
    reclarearecl = db.Column(db.Numeric(14, 2))
    reclareatotal = db.Column(db.Numeric(14, 2))
    anyotherinformation = db.Column(db.String)
    vfcbcapplicationurl = db.Column(db.String)
    messagecreateddate = db.Column(db.DateTime)
    processed = db.Column(db.String)
    processeddate = db.Column(db.DateTime)
    cutlinesexplgriddisturbedarea = db.Column(db.Numeric(14, 2))
    pondsrecycled = db.Column(db.String)
    pondsexfiltratedtoground = db.Column(db.String)
    pondsdischargedtoenv = db.Column(db.String)
    pondsreclamation = db.Column(db.String)
    pondsreclamationcost = db.Column(db.Numeric(14, 2))
    sandgrvqrytotalexistdistarea = db.Column(db.Numeric(14, 2))
    nrsosapplicationid = db.Column(db.String)
    isblastselect = db.Column(db.String)
    istimberselect = db.Column(db.String)

    mine = db.relationship('Mine', lazy='joined')

    applicant = db.relationship('Client',
                                lazy='joined',
                                foreign_keys=[applicantclientid])
    submitter = db.relationship('Client',
                                lazy='joined',
                                foreign_keys=[submitterclientid])
    contacts = db.relationship('Contact', lazy='joined')
    documents = db.relationship('Document', lazy='joined')
    sand_grv_qry_activity = db.relationship('SandGrvQryActivity',
                                            lazy='joined')
    surface_bulk_sample_activity = db.relationship('SurfaceBulkSampleActivity',
                                                   lazy='joined')
    under_exp_new_activity = db.relationship('UnderExpNewActivity',
                                             lazy='joined')
    under_exp_rehab_activity = db.relationship('UnderExpRehabActivity',
                                               lazy='joined')
    under_exp_surface_activity = db.relationship('UnderExpSurfaceActivity',
                                                 lazy='joined')
    water_source_activity = db.relationship('WaterSourceActivity',
                                            lazy='joined')
    exp_access_activity = db.relationship('ExpAccessActivity', lazy='joined')
    mech_trenching_activity = db.relationship('MechTrenchingActivity',
                                              lazy='joined')

    existing_placer_activity = db.relationship(
        'PlacerActivity',
        lazy='joined',
        secondary='now_submissions.existing_placer_activity_xref')
    existing_settling_pond = db.relationship(
        'SettlingPond',
        lazy='joined',
        secondary='now_submissions.existing_settling_pond_xref')
    proposed_placer_activity = db.relationship(
        'PlacerActivity',
        lazy='joined',
        secondary='now_submissions.proposed_placer_activity_xref')
    proposed_settling_pond = db.relationship(
        'SettlingPond',
        lazy='joined',
        secondary='now_submissions.proposed_settling_pond_xref')

    mine_name = association_proxy('mine', 'mine_name')
    mine_region = association_proxy('mine', 'mine_region')

    def __repr__(self):
        return '<Application %r>' % self.messageid

    @classmethod
    def find_by_application_guid(cls, guid):
        cls.validate_guid(guid)
        return cls.query.filter_by(application_guid=guid).first()

    @classmethod
    def validate_guid(cls, guid, msg='Invalid guid.'):
        try:
            uuid.UUID(str(guid), version=4)
        except ValueError:
            raise AssertionError(msg)
Пример #23
0
class MineStatusXref(AuditMixin, Base):
    __tablename__ = 'mine_status_xref'
    mine_status_xref_guid = db.Column(UUID(as_uuid=True), primary_key=True)

    mine_operation_status_code = db.Column(
        db.String(3),
        db.ForeignKey('mine_operation_status_code.mine_operation_status_code'))
    mine_operation_status = db.relationship('MineOperationStatusCode',
                                            lazy='joined')

    mine_operation_status_reason_code = db.Column(
        db.String(3),
        db.ForeignKey(
            'mine_operation_status_reason_code.mine_operation_status_reason_code'
        ))
    mine_operation_status_reason = db.relationship(
        'MineOperationStatusReasonCode', lazy='joined')

    mine_operation_status_sub_reason_code = db.Column(
        db.String(3),
        db.ForeignKey(
            'mine_operation_status_sub_reason_code.mine_operation_status_sub_reason_code'
        ))
    mine_operation_status_sub_reason = db.relationship(
        'MineOperationStatusSubReasonCode', lazy='joined')
    description = db.Column(db.String(1024))

    active_ind = db.Column(db.Boolean,
                           nullable=False,
                           server_default=FetchedValue())

    def __repr__(self):
        return '<MineStatusXref %r>' % self.mine_status_xref_guid

    def json(self):
        return {
            'mine_status_xref_guid': str(self.mine_status_xref_guid),
            'mine_operation_status_code':
            self.mine_operation_status_code.json()
            if self.mine_operation_status_code else {},
            'mine_operation_status_reason_code':
            self.mine_operation_status_reason_code.json()
            if self.mine_operation_status_reason_code else {},
            'mine_operation_status_sub_reason_code':
            self.mine_operation_status_sub_reason_code.json()
            if self.mine_operation_status_sub_reason_code else {},
        }

    @classmethod
    def active(cls):
        return cls.query.filter_by(active_ind=True).all()

    @classmethod
    def find_by_mine_status_xref_guid(cls, _id):
        return cls.query.filter_by(mine_status_xref_guid=_id).first()

    @classmethod
    def find_by_codes(cls,
                      _mine_operation_status_code,
                      _mine_operation_status_reason_code=None,
                      _mine_operation_status_sub_reason_code=None):
        xref_query = cls.query \
            .filter_by(mine_operation_status_code=_mine_operation_status_code) \
            .order_by(
                cls.mine_operation_status_reason_code.desc(),
                cls.mine_operation_status_sub_reason_code.desc())
        if _mine_operation_status_reason_code:
            xref_query = xref_query.filter_by(
                mine_operation_status_reason_code=
                _mine_operation_status_reason_code)
        if _mine_operation_status_sub_reason_code:
            xref_query = xref_query.filter_by(
                mine_operation_status_sub_reason_code=
                _mine_operation_status_sub_reason_code)
        return xref_query.first()
Пример #24
0
class ClientUser(db.Model, ModelMixin):
    __table_args__ = (db.UniqueConstraint("user_id",
                                          "client_id",
                                          name="uq_client_user"), )

    user_id = db.Column(db.ForeignKey(User.id, ondelete="cascade"),
                        nullable=False)
    client_id = db.Column(db.ForeignKey(Client.id, ondelete="cascade"),
                          nullable=False)

    # Null means client has access to user original email
    gen_email_id = db.Column(db.ForeignKey(GenEmail.id, ondelete="cascade"),
                             nullable=True)

    # user can decide to send to client another name
    name = db.Column(db.String(128),
                     nullable=True,
                     default=None,
                     server_default=text("NULL"))

    # user can decide to send to client a default avatar
    default_avatar = db.Column(db.Boolean,
                               nullable=False,
                               default=False,
                               server_default="0")

    gen_email = db.relationship(GenEmail, backref="client_users")

    user = db.relationship(User)
    client = db.relationship(Client)

    def get_email(self):
        return self.gen_email.email if self.gen_email_id else self.user.email

    def get_user_name(self):
        if self.name:
            return self.name
        else:
            return self.user.name

    def get_user_info(self) -> dict:
        """return user info according to client scope
        Return dict with key being scope name. For now all the fields are the same for all clients:

        {
          "client": "Demo",
          "email": "*****@*****.**",
          "email_verified": true,
          "id": 1,
          "name": "Son GM",
          "avatar_url": "http://s3..."
        }

        """
        res = {
            "id": self.id,
            "client": self.client.name,
            "email_verified": True,
            "sub": str(self.id),
        }

        for scope in self.client.get_scopes():
            if scope == Scope.NAME:
                if self.name:
                    res[Scope.NAME.value] = self.name
                else:
                    res[Scope.NAME.value] = self.user.name
            elif scope == Scope.AVATAR_URL:
                if self.user.profile_picture_id:
                    if self.default_avatar:
                        res[Scope.AVATAR_URL.
                            value] = URL + "/static/default-avatar.png"
                    else:
                        res[Scope.AVATAR_URL.
                            value] = self.user.profile_picture.get_url(
                                AVATAR_URL_EXPIRATION)
                else:
                    res[Scope.AVATAR_URL.value] = None
            elif scope == Scope.EMAIL:
                # Use generated email
                if self.gen_email_id:
                    LOG.debug("Use gen email for user %s, client %s",
                              self.user, self.client)
                    res[Scope.EMAIL.value] = self.gen_email.email
                # Use user original email
                else:
                    res[Scope.EMAIL.value] = self.user.email

        return res
Пример #25
0
class User(UserMixin, db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64),
                         index=True,
                         unique=True,
                         nullable=False)
    email = db.Column(db.String(120), index=True, unique=True, nullable=False)
    password = db.Column(db.Binary(128), nullable=True)
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)
    last_message_read_time = db.Column(db.DateTime)

    posts = db.relationship('Post', backref='author', lazy='dynamic')

    followed = db.relationship('User',
                               secondary=followers,
                               primaryjoin=(followers.c.follower_id == id),
                               secondaryjoin=(followers.c.followed_id == id),
                               backref=db.backref('followers', lazy='dynamic'),
                               lazy='dynamic')

    messages_sent = db.relationship('Message',
                                    foreign_keys='Message.sender_id',
                                    backref='author',
                                    lazy='dynamic')

    messages_received = db.relationship('Message',
                                        foreign_keys='Message.recipient_id',
                                        backref='recipient',
                                        lazy='dynamic')

    notifications = db.relationship('Notification',
                                    backref='user',
                                    lazy='dynamic')

    def __init__(self, username, email, password=None, **kwargs):
        db.Model.__init__(self, username=username, email=email, **kwargs)
        if password:
            self.set_password(password)
        else:
            self.password = None

    def set_password(self, password):
        self.password = bcrypt.generate_password_hash(password)

    def check_password(self, value):
        return bcrypt.check_password_hash(self.password, value)

    def follow(self, user):
        if not self.is_following(user):
            self.followed.append(user)

    def unfollow(self, user):
        if self.is_following(user):
            self.followed.remove(user)

    def is_following(self, user):
        return self.followed.filter(
            followers.c.followed_id == user.id).count() > 0

    def followed_posts(self):
        followed = Post.query.join(
            followers, (followers.c.followed_id == Post.user_id)).filter(
                followers.c.follower_id == self.id)
        own = Post.query.filter_by(user_id=self.id)
        return followed.union(own).order_by(Post.timestamp.desc())

    def get_reset_password_token(self, expires_in=600):
        return jwt.encode(
            {
                'reset_password': self.id,
                'exp': time() + expires_in
            },
            current_app.config['SECRET_KEY'],
            algorithm='HS256').decode('utf-8')

    def avatar(self, size):
        digest = md5(self.email.lower().encode('utf-8')).hexdigest()
        return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format(
            digest, size)

    def new_messages(self):
        last_read_time = self.last_message_read_time or datetime(1900, 1, 1)
        return Message.query.filter_by(recipient=self).filter(
            Message.timestamp > last_read_time).count()

    def add_notification(self, name, data):
        self.notifications.filter_by(name=name).delete()
        n = Notification(name=name, payload_json=json.dumps(data), user=self)
        db.session.add(n)
        return n

    @staticmethod
    def verify_reset_password_token(token):
        try:
            id = jwt.decode(token,
                            current_app.config['SECRET_KEY'],
                            algorithms=['HS256'])['reset_password']
        except:
            return
        return User.query.get(id)
Пример #26
0
class Project(db.Model, HoustonModel, Timestamp):
    """
    Projects database model.
    """

    guid = db.Column(db.GUID, default=uuid.uuid4, primary_key=True)  # pylint: disable=invalid-name
    title = db.Column(db.String(length=50), nullable=False)

    user_membership_enrollments = db.relationship(
        'ProjectUserMembershipEnrollment', back_populates='project')

    encounter_members = db.relationship('ProjectEncounter',
                                        back_populates='project')

    owner_guid = db.Column(db.GUID,
                           db.ForeignKey('user.guid'),
                           index=True,
                           nullable=False)
    owner = db.relationship('User', backref=db.backref('owned_projects'))

    def __repr__(self):
        return ('<{class_name}('
                'guid={self.guid}, '
                "title='{self.title}', "
                'members={self.members} '
                ')>'.format(class_name=self.__class__.__name__, self=self))

    @property
    def members(self):
        return [
            enrollment.user for enrollment in self.user_membership_enrollments
        ]

    @property
    def encounters(self):
        return [member.encounter for member in self.encounter_members]

    @db.validates('title')
    def validate_title(self, key, title):  # pylint: disable=unused-argument,no-self-use
        if len(title) < 3:
            raise ValueError('Title has to be at least 3 characters long.')
        return title

    def add_user(self, user):
        with db.session.begin():
            self.add_user_in_context(user)

    def add_encounter(self, encounter):
        with db.session.begin():
            self.add_encounter_in_context(encounter)

    def add_user_in_context(self, user):
        enrollment = ProjectUserMembershipEnrollment(
            project=self,
            user=user,
        )

        db.session.add(enrollment)
        self.user_membership_enrollments.append(enrollment)

    def add_encounter_in_context(self, encounter):
        enrollment = ProjectEncounter(
            project=self,
            encounter=encounter,
        )

        db.session.add(enrollment)
        self.encounter_members.append(enrollment)

    def remove_user_in_context(self, user):
        for member in self.user_membership_enrollments:
            if member.user == user:
                db.session.delete(member)
                break

    def remove_encounter_in_context(self, encounter):
        for member in self.encounter_members:
            if member.encounter == encounter:
                db.session.delete(member)
                break

    def delete(self):
        with db.session.begin():
            while self.user_membership_enrollments:
                db.session.delete(self.user_membership_enrollments.pop())
            while self.encounter_members:
                db.session.delete(self.encounter_members.pop())
            db.session.delete(self)
Пример #27
0
class NOWApplicationIdentity(Base, AuditMixin):
    __tablename__ = "now_application_identity"
    _edit_groups = [NOW_APPLICATION_EDIT_GROUP]
    _edit_key = NOW_APPLICATION_EDIT_GROUP

    now_application_guid = db.Column(UUID(as_uuid=True),
                                     primary_key=True,
                                     server_default=FetchedValue())
    now_number = db.Column(db.String)
    now_application_id = db.Column(
        db.Integer, db.ForeignKey('now_application.now_application_id'))
    messageid = db.Column(db.Integer)
    mms_cid = db.Column(db.Integer)

    mine_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('mine.mine_guid'))
    mine = db.relationship('Mine', lazy='joined')

    permit_id = db.Column(db.Integer, db.ForeignKey('permit.permit_id'))
    permit = db.relationship('Permit', lazy='select')

    now_application = db.relationship('NOWApplication')

    def __repr__(self):
        return '<NOWApplicationIdentity %r>' % self.now_application_guid

    @property
    def now_submission(self):
        return Application.query.get(self.messageid)

    @now_submission.setter
    def now_submission(self, now_submission):
        self.messageid = now_submission.messageid

    @hybrid_property
    def mms_now_submission(self):
        return MMSApplication.query.filter_by(mms_cid=self.mms_cid).first()

    @classmethod
    def find_by_guid(cls, _id):
        try:
            uuid.UUID(_id, version=4)
            return cls.query.filter_by(now_application_guid=_id).first()
        except ValueError:
            return None

    @classmethod
    def find_by_messageid(cls, messageid):
        return cls.query.filter_by(messageid=messageid).first()

    @classmethod
    def find_by_now_number(cls, now_number):
        return cls.query.filter_by(now_number=now_number).first()

    @classmethod
    def submission_count_ytd(cls, _mine_guid, _sub_year):
        try:
            return cls.query.filter_by(mine_guid=_mine_guid).filter(
                cls.now_number.ilike(f'%-{_sub_year}-%')).count()
        except ValueError:
            return None

    @classmethod
    def create_now_number(cls, mine):
        current_year = datetime.now().strftime("%Y")
        number_of_now = cls.submission_count_ytd(mine.mine_guid, current_year)
        return f'{mine.mine_no}-{current_year}-{str(number_of_now + 1).zfill(2)}'
Пример #28
0
class Mine(AuditMixin, Base):
    __tablename__ = 'mine'
    mine_guid = db.Column(UUID(as_uuid=True),
                          primary_key=True,
                          server_default=FetchedValue())
    mine_no = db.Column(db.String(10))
    mine_name = db.Column(db.String(60), nullable=False)
    mine_note = db.Column(db.String(300), default='')
    legacy_mms_mine_status = db.Column(db.String(50))
    major_mine_ind = db.Column(db.Boolean, nullable=False, default=False)
    deleted_ind = db.Column(db.Boolean,
                            nullable=False,
                            server_default=FetchedValue())
    mine_region = db.Column(db.String(2),
                            db.ForeignKey('mine_region_code.mine_region_code'))
    ohsc_ind = db.Column(db.Boolean,
                         nullable=False,
                         server_default=FetchedValue())
    union_ind = db.Column(db.Boolean,
                          nullable=False,
                          server_default=FetchedValue())
    latitude = db.Column(db.Numeric(9, 7))
    longitude = db.Column(db.Numeric(11, 7))
    geom = db.Column(Geometry('POINT', 3005))
    mine_location_description = db.Column(db.String)
    # Relationships

    #Almost always used and 1:1, so these are joined
    mine_status = db.relationship('MineStatus',
                                  backref='mine',
                                  order_by='desc(MineStatus.update_timestamp)',
                                  lazy='joined')
    mine_tailings_storage_facilities = db.relationship(
        'MineTailingsStorageFacility',
        backref='mine',
        order_by=
        'desc(MineTailingsStorageFacility.mine_tailings_storage_facility_name)',
        lazy='joined')

    #Almost always used, but faster to use selectin to load related data
    mine_permit = db.relationship('Permit',
                                  backref='mine',
                                  order_by='desc(Permit.create_timestamp)',
                                  lazy='selectin')
    mine_type = db.relationship(
        'MineType',
        backref='mine',
        order_by='desc(MineType.update_timestamp)',
        primaryjoin=
        "and_(MineType.mine_guid == Mine.mine_guid, MineType.active_ind==True)",
        lazy='selectin')

    mine_documents = db.relationship(
        'MineDocument',
        backref='mine',
        primaryjoin=
        "and_(MineDocument.mine_guid == Mine.mine_guid, MineDocument.active_ind==True)",
        lazy='select')

    mine_party_appt = db.relationship('MinePartyAppointment',
                                      backref="mine",
                                      lazy='select')
    mine_incidents = db.relationship('MineIncident',
                                     backref="mine",
                                     lazy='select')
    mine_reports = db.relationship('MineReport', backref="mine", lazy='select')

    def __repr__(self):
        return '<Mine %r>' % self.mine_guid

    @reconstructor
    def init_on_load(self):
        if self.latitude and self.longitude:
            try:
                self.utm_values = utm.from_latlon(self.latitude,
                                                  self.longitude)
            except utm.error.OutOfRangeError:
                self.utm_values = ()

    @hybrid_property
    def utm_easting(self):
        return self.utm_values[0] if self.utm_values else None

    @hybrid_property
    def utm_northing(self):
        return self.utm_values[1] if self.utm_values else None

    @hybrid_property
    def utm_zone_number(self):
        return self.utm_values[2] if self.utm_values else None

    @hybrid_property
    def utm_zone_letter(self):
        return self.utm_values[3] if self.utm_values else None

    @hybrid_property
    def mine_location(self):
        return {
            'latitude': self.latitude,
            'longitude': self.longitude,
            'utm_easting': self.utm_easting,
            'utm_northing': self.utm_northing,
            'utm_zone_number': self.utm_zone_number,
            'utm_zone_letter': self.utm_zone_letter,
            'mine_location_description': self.mine_location_description
        }

    @staticmethod
    def active(records):
        return list(filter(lambda x: x.active_ind, records))

    @classmethod
    def find_by_mine_guid(cls, _id):
        try:
            uuid.UUID(_id, version=4)
            return cls.query.filter_by(mine_guid=_id).filter_by(
                deleted_ind=False).first()
        except ValueError:
            return None

    @classmethod
    def find_by_mine_no(cls, _id):
        return cls.query.filter_by(mine_no=_id).filter_by(
            deleted_ind=False).first()

    @classmethod
    def find_by_mine_name(cls, term=None):
        MINE_LIST_RESULT_LIMIT = 50
        if term:
            name_filter = Mine.mine_name.ilike('%{}%'.format(term))
            mines_q = Mine.query.filter(name_filter).filter_by(
                deleted_ind=False)
            mines = mines_q.limit(MINE_LIST_RESULT_LIMIT).all()
        else:
            mines = Mine.query.limit(MINE_LIST_RESULT_LIMIT).all()
        return mines

    @classmethod
    def find_by_name_no_permit(cls, term=None):
        MINE_LIST_RESULT_LIMIT = 50
        if term:
            name_filter = Mine.mine_name.ilike('%{}%'.format(term))
            number_filter = Mine.mine_no.ilike('%{}%'.format(term))
            permit_filter = Permit.permit_no.ilike('%{}%'.format(term))
            mines_q = Mine.query.filter(name_filter | number_filter).filter_by(
                deleted_ind=False)
            permit_q = Mine.query.join(Permit).filter(permit_filter)
            mines = mines_q.union(permit_q).limit(MINE_LIST_RESULT_LIMIT).all()
        else:
            mines = Mine.query.limit(MINE_LIST_RESULT_LIMIT).all()
        return mines

    @classmethod
    def find_all_major_mines(cls):
        return cls.query.filter_by(major_mine_ind=True).filter_by(
            deleted_ind=False).all()

    @classmethod
    def find_by_mine_no_or_guid(cls, _id):
        result = cls.find_by_mine_guid(_id)
        if result is None:
            result = cls.find_by_mine_no(_id)

        return result

    @classmethod
    def create_mine(cls,
                    mine_no,
                    mine_name,
                    mine_category,
                    mine_region,
                    add_to_session=True,
                    ohsc_ind=None,
                    union_ind=None):
        mine = cls(mine_guid=uuid.uuid4(),
                   mine_no=mine_no,
                   mine_name=mine_name,
                   major_mine_ind=mine_category,
                   mine_region=mine_region,
                   ohsc_ind=ohsc_ind,
                   union_ind=union_ind)
        if add_to_session:
            mine.save(commit=False)
        return mine

    @validates('mine_name')
    def validate_mine_name(self, key, mine_name):
        if not mine_name:
            raise AssertionError('No mine name provided.')
        if len(mine_name) > 60:
            raise AssertionError('Mine name must not exceed 60 characters.')
        return mine_name

    @validates('mine_note')
    def validate_mine_note(self, key, mine_note):
        mine_note = mine_note if mine_note else ''
        if len(mine_note) > 300:
            raise AssertionError('Mine note must not exceed 300 characters.')
        return mine_note

    @validates('mine_no')
    def validate_mine_no(self, key, mine_no):
        mine_no = mine_no if mine_no else ''
        if mine_no and len(mine_no) > 10:
            raise AssertionError('Mine number must not exceed 10 characters.')
        return mine_no

    @validates('mine_region')
    def validate_mine_region(self, key, mine_region):
        if not mine_region:
            raise AssertionError('No mine region code provided.')
        if len(mine_region) > 2:
            raise AssertionError('Invalid region code')
        return mine_region
Пример #29
0
class User(AppModel):
    __tablename__ = 'auth_users'

    description = None
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    email = db.Column(db.String(64), unique=True, index=True)
    active = db.Column(db.Boolean, default=True)
    confirmed = db.Column(db.Boolean, default=False)
    confirmed_at = db.Column(db.DateTime())
    last_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(INET)
    login_count = db.Column(db.Integer, default=0)

    roles = db.relationship('Role',
                            secondary='auth_users_roles',
                            backref=db.backref('users', lazy='dynamic'))

    @classmethod
    def create_with_role(cls, username, password, email, role, **kwargs):
        new_user = cls(username=username,
                       password=password,
                       email=email,
                       **kwargs)
        role = Role.get_by(name=role)
        new_user.roles.append(role)
        db.session.add(new_user)
        db.session.commit()
        return new_user

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = pwd_ctx.encrypt(password)

    def verify_password(self, password):
        return pwd_ctx.verify(password, self.password_hash)

    def generate_auth_token(self, expiration):
        s = Serializer(current_app.config.get('SECRET_KEY'),
                       expires_in=int(expiration))
        return s.dumps({'id': self.id})

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(current_app.config.get('SECRET_KEY'))
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None  # valid token, but expired
        except BadSignature:
            return None  # invalid token
        user_id = data.get('id')
        if not user_id:
            return None
        return User.query.get(user_id)

    def generate_email_token(self, expiration):
        s = Serializer(current_app.config.get('SECRET_KEY'),
                       expires_in=int(expiration))
        return s.dumps({'email': self.email})

    @staticmethod
    def confirm(token):
        s = Serializer(current_app.config.get('SECRET_KEY'))
        try:
            data = s.loads(token)
        except (BadSignature, SignatureExpired):
            return False
        user = db.session.query(User).filter_by(
            email=data.get('email')).first()
        if not user or user.confirmed:
            return False
        user.confirmed = True
        user.confirmed_at = datetime.now()
        db.session.add(user)
        db.session.commit()
        return True

    def generate_reset_token(self, expiration=3600):
        s = Serializer(current_app.config.get('SECRET_KEY'), int(expiration))
        return s.dumps({'reset': self.id})

    @staticmethod
    def verify_reset_password_token(token):
        s = Serializer(current_app.config.get('SECRET_KEY'))
        try:
            data = s.loads(token)
        except (BadSignature, SignatureExpired):
            return False
        return db.session.query(User).filter_by(id=data.get('reset')).first()

    def generate_email_change_token(self, new_email, expiration=3600):
        s = Serializer(current_app.config.get('SECRET_KEY'), int(expiration))
        return s.dumps({'change_email': self.id, 'new_email': new_email})

    @staticmethod
    def change_email(token):
        s = Serializer(current_app.config.get('SECRET_KEY'))
        try:
            data = s.loads(token)
        except (BadSignature, SignatureExpired):
            return False
        user = db.session.query(User).filter_by(
            email=data.get('new_email')).first()
        if not user or user.confirmed:
            return False
        user.confirmed = True
        user.confirmed_at = datetime.now()
        db.session.add(user)
        db.session.commit()
        return True

    def can(self, permissions):
        return self.role is not None and \
               (self.role.permissions & permissions) == permissions

    def is_administrator(self):
        return self.can(Permission.ADMINISTER)

    def logged_in(self, commit=True):
        self.last_login_at = datetime.now()
        self.last_login_ip = request.remote_addr
        self.login_count += 1
        if commit:
            db.session.commit()

    def list_roles_names(self):
        return [role.name for role in self.roles]

    def add_role(self, role_name, commit=True):
        new_role = Role.get_by(name=role_name)
        if new_role:
            self.roles.append(new_role)
            if commit:
                db.session.commit()
            return True
        return False

    def remove_role(self, role_name, commit=True):
        if role_name not in self.list_roles_names():
            return False
        if len(self.roles) == 1:
            return False
        for i, role in enumerate(self.roles):
            if role.name == role_name:
                self.roles.pop(i)
                break
        if commit:
            db.session.commit()
        return True

    def export_data(self, exclude=None):
        response = super().export_data(exclude=exclude)
        roles = list()
        for role in self.roles:
            roles.append(role.export_data(exclude=exclude))
        response.update({'roles': roles})
        return response

    def set_active(self, commit=True):
        self.active = True
        if commit:
            db.session.commit()

    def set_inactive(self, commit=True):
        self.active = False
        if commit:
            db.session.commit()

    def set_confirmed(self, commit=True):
        self.confirmed = True
        if commit:
            db.session.commit()

    def set_not_confirmed(self, commit=True):
        self.confirmed = False
        if commit:
            db.session.commit()

    @classmethod
    def is_valid_username(cls, username):
        return User.get_by(username=username) is None

    @classmethod
    def is_valid_email(cls, email):
        return User.get_by(email=email) is None

    @classmethod
    def remove_fake(cls, item):
        max_user_role_id = UserRole.get_max_id()
        count = len(item.roles)
        super().remove_fake(item)
        UserRole.set_sequence_value(value=max_user_role_id - count)
Пример #30
0
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(64), index=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    towers = db.relationship("UserTowerRelation", back_populates="user")
    joined = db.Column(db.Date, default=date.today)
    token = db.Column(db.String(32), index=True, unique=True)
    token_expiration = db.Column(db.DateTime)
    donation_thank_you = db.Column(db.String(64), index=True)
    donation_badge = db.Column(db.Integer)
    user_settings_json = db.Column(db.String(), default="{}")

    def to_dict(self):
        data = {
            'username': self.username,
            'email': self.email,
        }
        return data

    def get_token(self, expires_in=86400):
        now = datetime.utcnow()
        if self.token and self.token_expiration > now + timedelta(seconds=60):
            return self.token
        self.token = base64.b64encode(os.urandom(24)).decode('utf-8')
        self.token_expiration = now + timedelta(seconds=expires_in)
        db.session.commit()
        return self.token

    def revoke_token(self):
        self.token_expiration = datetime.utcnow() - timedelta(seconds=1)

    @staticmethod
    def check_token(token):
        user = User.query.filter_by(token=token).first()
        if user is None or user.token_expiration < datetime.utcnow():
            return None
        return user

    @property
    def badge(self):
        try:
            return {
                0: 'badge-tower.png',
                1: 'badge-hand.png'
            }[self.donation_badge]
        except KeyError:
            return None

    def __repr__(self):
        return '<User {}>'.format(self.username)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def _clean_recent_towers(self, cutoff=10):
        # delete all but the cuttoff most recent towers
        old_rels = sorted([tower for tower in self.towers if tower.recent],
                          key=lambda x: x.visited,
                          reverse=True)[cutoff:]
        for rel in old_rels:
            db.session.delete(rel)

    def get_reset_password_token(self, expires_in=86400):
        return jwt.encode(
            {
                'reset_password': self.id,
                'exp': time() + expires_in
            },
            Config.SECRET_KEY,
            algorithm='HS256').decode('utf-8')

    @staticmethod
    def verify_reset_password_token(token):
        try:
            id = jwt.decode(token, Config.SECRET_KEY,
                            algorithms=['HS256'])['reset_password']
        except BaseException:
            return
        return User.query.get(id)

    def _get_relation_to_tower(self, tower):
        # Helper function: returns a relation between the user and the tower.
        # Creates the relation if none existed before.
        if isinstance(tower, Tower):
            # cast to TowerDB
            tower = tower.to_TowerDB()
        # See if a relation already exists
        rel = UserTowerRelation.query.filter(
            UserTowerRelation.user == self,
            UserTowerRelation.tower == tower).first()
        if not rel:
            # Just creating this is enough to add it to the database with
            # relevant relations
            rel = UserTowerRelation(user=self, tower=tower)

        return rel

    def clear_all_towers(self):
        for rel in self.towers:
            db.session.delete(rel)

    def add_recent_tower(self, tower):
        rel = self._get_relation_to_tower(tower)
        # Update the timestamp (and recent, if necessary)
        rel.recent = True
        rel.visited = datetime.now()
        # self._clean_recent_towers() # no reason to do this now that the
        # my_towers page exists
        db.session.commit()

    def remove_recent_tower(self, tower):
        rel = self._get_relation_to_tower(tower)
        rel.recent = False
        db.session.commit()

    def toggle_bookmark(self, tower):
        rel = self._get_relation_to_tower(tower)
        rel.bookmark = not rel.bookmark
        db.session.commit()

    def recent_towers(self, n=0):
        # Allows you to limit to n items; returns all by default
        # This returns a list of TowerDB objects — if we want to convert them
        # to memory, that should
        # happen by looking them up in the TowerDict instance
        n = n or len(self.towers)
        return [
            rel.tower for rel in sorted(
                self.towers, key=lambda r: r.visited, reverse=True)
            if rel.recent
        ][:n]

    def bookmarked_towers(self, n=0):
        # Allows you to limit to n items; returns all by default
        # This returns a list of TowerDB objects — if we want to convert them
        # to memory, that should
        # happen by looking them up in the TowerDict instance
        n = n or len(self.towers)
        return [rel.tower for rel in self.towers if rel.bookmark][:n]

    def bookmarked(self, tower_id):
        # checks if a tower_id is bookmarked
        return tower_id in [
            rel.tower.tower_id for rel in self.towers if rel.bookmark
        ]

    @property
    def tower_properties(self):
        # For the my_towers page, we need the tower relations as a list of
        # dictionaries, which each include the tower info + the relation info
        tower_properties = []
        for rel in sorted(self.towers, key=lambda x: x.visited, reverse=True):
            tower_properties.append(
                dict(
                    {
                        'tower_id': rel.tower.tower_id,
                        'tower_url': rel.tower.url_safe_name,
                        'tower_name': rel.tower.tower_name
                    }, **rel.relation_dict))
        return tower_properties

    def check_permissions(self, tower_id, permission):
        # Given a tower_id: check if the user has relevant permissions
        # 'creator': can edit settings
        # 'host': can manage practices in host mode
        if permission not in ['creator', 'host']:
            raise KeyError('The requested permission type does not exist.')
        return tower_id in [
            int(t.tower_id) for t in self.towers if getattr(t, permission)
        ]

    def make_host(self, tower):
        rel = self._get_relation_to_tower(tower)
        rel.host = True
        if not isinstance(tower, Tower):
            tower = tower.to_Tower()
        tower.add_host_id(self.id)
        db.session.commit()

    def remove_host(self, tower):
        rel = self._get_relation_to_tower(tower)
        rel.host = False
        if not isinstance(tower, Tower):
            tower = tower.to_Tower()
        try:
            tower.remove_host_id(self.id)
        except ValueError:
            pass
        db.session.commit()

    @property
    def user_settings(self):
        # Parse user settings from json to dict
        user_settings = defaultdict(dict)
        try:
            user_settings.update(json.loads(self.user_settings_json))
        except TypeError:
            pass
        return user_settings

    def get_settings_with_defaults(self):
        try:
            user_settings = json.loads(self.user_settings_json)
        except TypeError:
            user_settings = {}
        merged_dict = {}
        for key, val in Config.DEFAULT_SETTINGS.items():
            merged_dict[key] = val.copy()
            if key in user_settings:
                merged_dict[key].update(user_settings[key])

        return merged_dict

    @user_settings.setter
    def user_settings(self, update):
        self.user_settings_json = json.dumps(update)
        db.session.commit()

    def reset_category(self, category):
        user_settings = json.loads(self.user_settings_json)
        user_settings[category] = {}
        self.user_settings_json = json.dumps(user_settings)
        db.session.commit()

    def reset_keybinding(self, setting):
        user_settings = json.loads(self.user_settings_json)
        if setting in user_settings['keybindings']:
            del user_settings['keybindings'][setting]
            for keybinding in Config.DEFAULT_SETTINGS['keybindings'][setting]:
                for val in user_settings['keybindings'].values():
                    if keybinding in val:
                        val.remove(keybinding)
        self.user_settings_json = json.dumps(user_settings)
        db.session.commit()
Пример #31
0
class ApplicationNDA(Base):
    __tablename__ = "application_nda"
    __table_args__ = {"schema": "now_submissions"}

    class _ModelSchema(Base._ModelSchema):
        application_nda_guid = fields.String(dump_only=True)
        mine_guid = fields.String(dump_only=True)
        status = FieldTemplate(field=fields.String,
                               one_of='NOWApplicationStatus_description')

    messageid = db.Column(db.Integer, primary_key=True)
    application_nda_guid = db.Column(UUID(as_uuid=True),
                                     nullable=False,
                                     server_default=FetchedValue())
    mine_guid = db.Column(UUID(as_uuid=True), db.ForeignKey('mine.mine_guid'))
    trackingnumber = db.Column(db.Integer)
    applicationtype = db.Column(db.String)
    status = db.Column(db.String)
    submitteddate = db.Column(db.DateTime)
    receiveddate = db.Column(db.DateTime)
    applicantclientid = db.Column(
        db.Integer, db.ForeignKey('now_submissions.client.clientid'))
    submitterclientid = db.Column(
        db.Integer, db.ForeignKey('now_submissions.client.clientid'))
    typedeemedauthorization = db.Column(db.String)
    permitnumber = db.Column(db.String)
    minenumber = db.Column(db.String)
    nownumber = db.Column(db.String)
    planactivitiesdrillprogram = db.Column(db.String)
    planactivitiesipsurvey = db.Column(db.String)
    proposedstartdate = db.Column(db.DateTime)
    proposedenddate = db.Column(db.DateTime)
    totallinekilometers = db.Column(db.Integer)
    descplannedactivities = db.Column(db.String)
    proposednewenddate = db.Column(db.DateTime)
    reasonforextension = db.Column(db.String)
    anyotherinformation = db.Column(db.String)
    vfcbcapplicationurl = db.Column(db.String)
    messagecreateddate = db.Column(db.DateTime)
    processed = db.Column(db.String)
    processeddate = db.Column(db.DateTime)
    nrsosapplicationid = db.Column(db.String)
    originating_system = db.Column(db.String)

    mine = db.relationship(
        'Mine',
        lazy='joined',
        uselist=False,
        primaryjoin='Mine.mine_guid==ApplicationNDA.mine_guid',
        foreign_keys=mine_guid)

    applicant = db.relationship('Client',
                                uselist=False,
                                lazy='select',
                                foreign_keys=[applicantclientid])
    submitter = db.relationship('Client',
                                uselist=False,
                                lazy='select',
                                foreign_keys=[submitterclientid])
    documents = db.relationship('DocumentNDA', lazy='select')

    def __repr__(self):
        return '<ApplicationNDA %r>' % self.messageid

    @classmethod
    def find_by_messageid(cls, messageid):
        return cls.query.filter_by(messageid=messageid).first()
Пример #32
0
def getAdminBugPostView():
   #auto join user
   BugPost.user = db.relationship("User", uselist=False, lazy='joined')

   return AdminBugPostView(BugPost, db.session)
Пример #33
0
def getAdminEmailView():
    # auto join user
    Email.user = db.relationship("User", uselist=False, lazy="joined")

    return AdminEmailView(Email, db.session)