Files
atst/atst/models/user.py
dandds a0b96402f2 Remove user.provisional column.
This is leftover from a previous iteration of ATAT where inviting a user
to a portfolio would create a pending entry in the users table. This is
no longer used.
2020-01-10 10:20:35 -05:00

129 lines
3.7 KiB
Python

from sqlalchemy import String, ForeignKey, Column, Date, Table, TIMESTAMP
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.event import listen
from atst.models.base import Base
import atst.models.types as types
import atst.models.mixins as mixins
from atst.models.portfolio_invitation import PortfolioInvitation
from atst.models.application_invitation import ApplicationInvitation
from atst.models.mixins.auditable import (
AuditableMixin,
ACTION_UPDATE,
record_permission_sets_updates,
)
users_permission_sets = Table(
"users_permission_sets",
Base.metadata,
Column("user_id", UUID(as_uuid=True), ForeignKey("users.id")),
Column("permission_set_id", UUID(as_uuid=True), ForeignKey("permission_sets.id")),
)
class User(
Base, mixins.TimestampsMixin, mixins.AuditableMixin, mixins.PermissionsMixin
):
__tablename__ = "users"
id = types.Id()
username = Column(String)
permission_sets = relationship("PermissionSet", secondary=users_permission_sets)
portfolio_roles = relationship("PortfolioRole", backref="user")
application_roles = relationship(
"ApplicationRole",
backref="user",
primaryjoin="and_(ApplicationRole.user_id == User.id, ApplicationRole.deleted == False)",
)
portfolio_invitations = relationship(
"PortfolioInvitation", foreign_keys=PortfolioInvitation.user_id
)
sent_portfolio_invitations = relationship(
"PortfolioInvitation", foreign_keys=PortfolioInvitation.inviter_id
)
application_invitations = relationship(
"ApplicationInvitation", foreign_keys=ApplicationInvitation.user_id
)
sent_application_invitations = relationship(
"ApplicationInvitation", foreign_keys=ApplicationInvitation.inviter_id
)
email = Column(String)
dod_id = Column(String, unique=True, nullable=False)
first_name = Column(String, nullable=False)
last_name = Column(String, nullable=False)
phone_number = Column(String)
phone_ext = Column(String)
service_branch = Column(String)
citizenship = Column(String)
designation = Column(String)
date_latest_training = Column(Date)
last_login = Column(TIMESTAMP(timezone=True), nullable=True)
last_session_id = Column(UUID(as_uuid=True), nullable=True)
cloud_id = Column(String)
REQUIRED_FIELDS = [
"email",
"dod_id",
"first_name",
"last_name",
"phone_number",
"service_branch",
"citizenship",
"designation",
"date_latest_training",
]
@property
def profile_complete(self):
return all(
[
getattr(self, field_name) is not None
for field_name in self.REQUIRED_FIELDS
]
)
@property
def full_name(self):
return "{} {}".format(self.first_name, self.last_name)
@property
def displayname(self):
return self.full_name
@property
def portfolio_id(self):
return None
@property
def application_id(self):
return None
def __repr__(self):
return "<User(name='{}', dod_id='{}', email='{}', id='{}')>".format(
self.full_name, self.dod_id, self.email, self.id
)
def to_dictionary(self):
return {
c.name: getattr(self, c.name)
for c in self.__table__.columns
if c.name not in ["id"]
}
@staticmethod
def audit_update(mapper, connection, target):
changes = AuditableMixin.get_changes(target)
if changes and not "last_login" in changes:
target.create_audit_event(connection, target, ACTION_UPDATE)
listen(User.permission_sets, "bulk_replace", record_permission_sets_updates, raw=True)