Merge branch 'master' into require-personal-info

This commit is contained in:
patricksmithdds
2018-10-31 14:12:55 -04:00
committed by GitHub
27 changed files with 661 additions and 85 deletions

View File

@@ -18,3 +18,4 @@ from .request_revision import RequestRevision
from .request_review import RequestReview
from .request_internal_comment import RequestInternalComment
from .audit_event import AuditEvent
from .invitation import Invitation

71
atst/models/invitation.py Normal file
View File

@@ -0,0 +1,71 @@
import datetime
from enum import Enum
import secrets
from sqlalchemy import Column, ForeignKey, Enum as SQLAEnum, TIMESTAMP, String
from sqlalchemy.dialects.postgresql import UUID
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
class Status(Enum):
ACCEPTED = "accepted"
REVOKED = "revoked"
PENDING = "pending"
REJECTED = "rejected"
class Invitation(Base, TimestampsMixin, AuditableMixin):
__tablename__ = "invitations"
id = types.Id()
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
user = relationship("User", backref="invitations", foreign_keys=[user_id])
workspace_role_id = Column(
UUID(as_uuid=True), ForeignKey("workspace_roles.id"), index=True
)
workspace_role = relationship("WorkspaceRole", backref="invitations")
inviter_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
inviter = relationship("User", backref="sent_invites", foreign_keys=[inviter_id])
status = Column(SQLAEnum(Status, native_enum=False, default=Status.PENDING))
expiration_time = Column(TIMESTAMP(timezone=True))
token = Column(String(), index=True, default=lambda: secrets.token_urlsafe())
def __repr__(self):
return "<Invitation(user='{}', workspace_role='{}', id='{}')>".format(
self.user_id, self.workspace_role_id, self.id
)
@property
def is_accepted(self):
return self.status == Status.ACCEPTED
@property
def is_revoked(self):
return self.status == Status.REVOKED
@property
def is_pending(self):
return self.status == Status.PENDING
@property
def is_rejected(self):
return self.status == Status.REJECTED
@property
def is_expired(self):
return datetime.datetime.now(self.expiration_time.tzinfo) > self.expiration_time
@property
def workspace(self):
if self.workspace_role:
return self.workspace_role.workspace

View File

@@ -1,4 +1,4 @@
from sqlalchemy import String, ForeignKey, Column, Date
from sqlalchemy import String, ForeignKey, Column, Date, Boolean
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID
@@ -25,6 +25,8 @@ class User(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
citizenship = Column(String)
designation = Column(String)
date_latest_training = Column(Date)
provisional = Column(Boolean)
REQUIRED_FIELDS = [
"email",

View File

@@ -49,6 +49,6 @@ class Workspace(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
return self.id
def __repr__(self):
return "<Workspace(name='{}', request='{}', task_order='{}', user_count='{}', id='{}')>".format(
self.name, self.request_id, self.task_order.number, self.user_count, self.id
return "<Workspace(name='{}', request='{}', user_count='{}', id='{}')>".format(
self.name, self.request_id, self.user_count, self.id
)

View File

@@ -1,4 +1,5 @@
from sqlalchemy import Index, ForeignKey, Column
from enum import Enum
from sqlalchemy import Index, ForeignKey, Column, Enum as SQLAEnum
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
@@ -6,6 +7,12 @@ from atst.models import Base, mixins
from .types import Id
class Status(Enum):
ACTIVE = "active"
DISABLED = "disabled"
PENDING = "pending"
class WorkspaceRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
__tablename__ = "workspace_roles"
@@ -22,6 +29,8 @@ class WorkspaceRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
UUID(as_uuid=True), ForeignKey("users.id"), index=True, nullable=False
)
status = Column(SQLAEnum(Status, native_enum=False, default=Status.PENDING))
def __repr__(self):
return "<WorkspaceRole(role='{}', workspace='{}', user_id='{}', id='{}')>".format(
self.role.name, self.workspace.name, self.user_id, self.id

View File

@@ -9,13 +9,6 @@ class WorkspaceUser(object):
self.user = user
self.workspace_role = workspace_role
def permissions(self):
atat_permissions = set(self.user.atat_role.permissions)
workspace_permissions = (
[] if self.workspace_role is None else self.workspace_role.role.permissions
)
return set(workspace_permissions).union(atat_permissions)
@property
def workspace(self):
return self.workspace_role.workspace
@@ -74,8 +67,8 @@ class WorkspaceUser(object):
def __repr__(self):
return "<WorkspaceUser(user='{}', role='{}', workspace='{}', num_environment_roles='{}')>".format(
self.user_name,
self.role.name,
self.user.full_name,
self.role,
self.workspace.name,
self.num_environment_roles,
)