Make portfolio invitation specific to portfolio
- add a base domain class - extract shared model code to mixin - rename invitation classes - invitation model relationship to portfolio_role name is now more generic "role"
This commit is contained in:
@@ -5,14 +5,16 @@ Base = declarative_base()
|
||||
from .permissions import Permissions
|
||||
from .permission_set import PermissionSet
|
||||
from .user import User
|
||||
from .portfolio_role import PortfolioRole
|
||||
from .application_role import ApplicationRole
|
||||
from .portfolio_role import PortfolioRole, Status as PortfolioRoleStatus
|
||||
from .application_role import ApplicationRole, Status as ApplicationRoleStatus
|
||||
from .environment_role import EnvironmentRole
|
||||
from .portfolio import Portfolio
|
||||
from .application import Application
|
||||
from .environment import Environment
|
||||
from .attachment import Attachment
|
||||
from .audit_event import AuditEvent
|
||||
from .invitation import Invitation
|
||||
from .portfolio_invitation import PortfolioInvitation
|
||||
from .task_order import TaskOrder
|
||||
from .dd_254 import DD254
|
||||
|
||||
from .mixins.invites import Status as InvitationStatus
|
||||
|
@@ -2,3 +2,4 @@ from .timestamps import TimestampsMixin
|
||||
from .auditable import AuditableMixin
|
||||
from .permissions import PermissionsMixin
|
||||
from .deletable import DeletableMixin
|
||||
from .invites import InvitesMixin
|
||||
|
@@ -3,12 +3,11 @@ from enum import Enum
|
||||
import secrets
|
||||
|
||||
from sqlalchemy import Column, ForeignKey, Enum as SQLAEnum, TIMESTAMP, String
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from atst.models import Base, types
|
||||
from atst.models.mixins.timestamps import TimestampsMixin
|
||||
from atst.models.mixins.auditable import AuditableMixin
|
||||
from atst.models import types
|
||||
|
||||
|
||||
class Status(Enum):
|
||||
@@ -19,24 +18,24 @@ class Status(Enum):
|
||||
REJECTED_EXPIRED = "rejected_expired"
|
||||
|
||||
|
||||
class Invitation(Base, TimestampsMixin, AuditableMixin):
|
||||
__tablename__ = "invitations"
|
||||
|
||||
class InvitesMixin(object):
|
||||
id = types.Id()
|
||||
|
||||
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
|
||||
user = relationship("User", backref="invitations", foreign_keys=[user_id])
|
||||
@declared_attr
|
||||
def user_id(cls):
|
||||
return Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
|
||||
|
||||
portfolio_role_id = Column(
|
||||
UUID(as_uuid=True), ForeignKey("portfolio_roles.id"), index=True
|
||||
)
|
||||
portfolio_role = relationship(
|
||||
"PortfolioRole",
|
||||
backref=backref("invitations", order_by="Invitation.time_created"),
|
||||
)
|
||||
@declared_attr
|
||||
def user(cls):
|
||||
return relationship("User", foreign_keys=[cls.user_id])
|
||||
|
||||
inviter_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
|
||||
inviter = relationship("User", backref="sent_invites", foreign_keys=[inviter_id])
|
||||
@declared_attr
|
||||
def inviter_id(cls):
|
||||
return Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
|
||||
|
||||
@declared_attr
|
||||
def inviter(cls):
|
||||
return relationship("User", foreign_keys=[cls.inviter_id])
|
||||
|
||||
status = Column(SQLAEnum(Status, native_enum=False, default=Status.PENDING))
|
||||
|
||||
@@ -47,8 +46,9 @@ class Invitation(Base, TimestampsMixin, AuditableMixin):
|
||||
email = Column(String, nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Invitation(user='{}', portfolio_role='{}', id='{}', email='{}')>".format(
|
||||
self.user_id, self.portfolio_role_id, self.id, self.email
|
||||
role_id = self.role.id if self.role else None
|
||||
return "<{}(user='{}', role='{}', id='{}', email='{}')>".format(
|
||||
self.__class__.__name__, self.user_id, role_id, self.id, self.email
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -90,14 +90,9 @@ class Invitation(Base, TimestampsMixin, AuditableMixin):
|
||||
Status.REVOKED,
|
||||
]
|
||||
|
||||
@property
|
||||
def portfolio(self):
|
||||
if self.portfolio_role: # pragma: no branch
|
||||
return self.portfolio_role.portfolio
|
||||
|
||||
@property
|
||||
def user_name(self):
|
||||
return self.portfolio_role.user.full_name
|
||||
return self.role.user.full_name
|
||||
|
||||
@property
|
||||
def is_revokable(self):
|
||||
@@ -110,21 +105,3 @@ class Invitation(Base, TimestampsMixin, AuditableMixin):
|
||||
@property
|
||||
def user_dod_id(self):
|
||||
return self.user.dod_id if self.user is not None else None
|
||||
|
||||
@property
|
||||
def event_details(self):
|
||||
return {"email": self.email, "dod_id": self.user_dod_id}
|
||||
|
||||
@property
|
||||
def history(self):
|
||||
changes = self.get_changes()
|
||||
change_set = {}
|
||||
|
||||
if "status" in changes:
|
||||
change_set["status"] = [s.name for s in changes["status"]]
|
||||
|
||||
return change_set
|
||||
|
||||
@property
|
||||
def portfolio_id(self):
|
||||
return self.portfolio_role.portfolio_id
|
41
atst/models/portfolio_invitation.py
Normal file
41
atst/models/portfolio_invitation.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from sqlalchemy import Column, ForeignKey
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
|
||||
from atst.models import Base
|
||||
from atst.models.mixins import TimestampsMixin, AuditableMixin, InvitesMixin
|
||||
|
||||
|
||||
class PortfolioInvitation(Base, TimestampsMixin, AuditableMixin, InvitesMixin):
|
||||
__tablename__ = "invitations"
|
||||
|
||||
portfolio_role_id = Column(
|
||||
UUID(as_uuid=True), ForeignKey("portfolio_roles.id"), index=True
|
||||
)
|
||||
role = relationship(
|
||||
"PortfolioRole",
|
||||
backref=backref("invitations", order_by="PortfolioInvitation.time_created"),
|
||||
)
|
||||
|
||||
@property
|
||||
def portfolio(self):
|
||||
if self.role: # pragma: no branch
|
||||
return self.role.portfolio
|
||||
|
||||
@property
|
||||
def portfolio_id(self):
|
||||
return self.role.portfolio_id
|
||||
|
||||
@property
|
||||
def event_details(self):
|
||||
return {"email": self.email, "dod_id": self.user_dod_id}
|
||||
|
||||
@property
|
||||
def history(self):
|
||||
changes = self.get_changes()
|
||||
change_set = {}
|
||||
|
||||
if "status" in changes:
|
||||
change_set["status"] = [s.name for s in changes["status"]]
|
||||
|
||||
return change_set
|
@@ -4,6 +4,7 @@ from sqlalchemy.dialects.postgresql import UUID
|
||||
|
||||
from atst.models import Base, types, mixins
|
||||
from atst.models.permissions import Permissions
|
||||
from atst.models.portfolio_invitation import PortfolioInvitation
|
||||
|
||||
|
||||
users_permission_sets = Table(
|
||||
@@ -31,6 +32,13 @@ class 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
|
||||
)
|
||||
|
||||
email = Column(String)
|
||||
dod_id = Column(String, unique=True, nullable=False)
|
||||
first_name = Column(String)
|
||||
|
Reference in New Issue
Block a user