There was a leftover method listing all the portfolios a user has access to inside the string-serialization for the User. This is too verbose. The leftover method was not being used anywhere else, so it was removed.
131 lines
3.7 KiB
Python
131 lines
3.7 KiB
Python
from sqlalchemy import and_, String, ForeignKey, Column, Date, Boolean, Table, TIMESTAMP
|
|
from sqlalchemy.orm import relationship
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.event import listen
|
|
|
|
from atst.models import Base, ApplicationRole, types, 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 == 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)
|
|
last_name = Column(String)
|
|
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)
|
|
|
|
provisional = Column(Boolean)
|
|
|
|
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)
|