Updates to workspace role permissions, invitations
This commit is contained in:
@@ -3,6 +3,7 @@ from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from atst.database import db
|
||||
from atst.models.invitation import Invitation, Status as InvitationStatus
|
||||
from atst.domain.workspace_users import WorkspaceUsers
|
||||
|
||||
from .exceptions import NotFoundError
|
||||
|
||||
@@ -30,9 +31,9 @@ class Invitations(object):
|
||||
return invite
|
||||
|
||||
@classmethod
|
||||
def create(cls, workspace, inviter, user):
|
||||
def create(cls, workspace_role, inviter, user):
|
||||
invite = Invitation(
|
||||
workspace=workspace,
|
||||
workspace_role=workspace_role,
|
||||
inviter=inviter,
|
||||
user=user,
|
||||
status=InvitationStatus.PENDING,
|
||||
@@ -43,20 +44,6 @@ class Invitations(object):
|
||||
|
||||
return invite
|
||||
|
||||
@classmethod
|
||||
def create_for_owner(cls, workspace, user):
|
||||
invite = Invitation(
|
||||
workspace=workspace,
|
||||
inviter=user,
|
||||
user=user,
|
||||
status=InvitationStatus.ACCEPTED,
|
||||
expiration_time=Invitations.current_expiration_time(),
|
||||
)
|
||||
db.session.add(invite)
|
||||
db.session.commit()
|
||||
|
||||
return invite
|
||||
|
||||
@classmethod
|
||||
def accept(cls, token):
|
||||
invite = Invitations._get(token)
|
||||
@@ -72,6 +59,8 @@ class Invitations(object):
|
||||
if invite.is_revoked or invite.is_rejected:
|
||||
raise InvitationError(invite)
|
||||
|
||||
WorkspaceUsers.enable(invite.workspace_role)
|
||||
|
||||
return invite
|
||||
|
||||
@classmethod
|
||||
|
@@ -1,10 +1,9 @@
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from atst.database import db
|
||||
from atst.models.workspace_role import WorkspaceRole
|
||||
from atst.models.workspace_role import WorkspaceRole, Status as WorkspaceRoleStatus
|
||||
from atst.models.workspace_user import WorkspaceUser
|
||||
from atst.models.user import User
|
||||
from atst.models.invitation import Invitation, Status as InvitationStatus
|
||||
|
||||
from .roles import Roles
|
||||
from .users import Users
|
||||
@@ -38,9 +37,7 @@ class WorkspaceUsers(object):
|
||||
db.session.query(WorkspaceRole)
|
||||
.join(User)
|
||||
.filter(User.id == user_id, WorkspaceRole.workspace_id == workspace_id)
|
||||
.join(Invitation, WorkspaceRole.workspace_id == Invitation.workspace_id)
|
||||
.filter(Invitation.user_id == WorkspaceRole.user_id)
|
||||
.filter(Invitation.status == InvitationStatus.ACCEPTED)
|
||||
.filter(WorkspaceRole.status == WorkspaceRoleStatus.ACTIVE)
|
||||
.one()
|
||||
)
|
||||
except NoResultFound:
|
||||
@@ -150,3 +147,10 @@ class WorkspaceUsers(object):
|
||||
db.session.commit()
|
||||
|
||||
return workspace_users
|
||||
|
||||
@classmethod
|
||||
def enable(cls, workspace_role):
|
||||
workspace_role.status = WorkspaceRoleStatus.ACTIVE
|
||||
|
||||
db.session.add(workspace_role)
|
||||
db.session.commit()
|
||||
|
@@ -4,8 +4,7 @@ from atst.database import db
|
||||
from atst.domain.common import Query
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
from atst.models.workspace import Workspace
|
||||
from atst.models.workspace_role import WorkspaceRole
|
||||
from atst.models.invitation import Invitation, Status as InvitationStatus
|
||||
from atst.models.workspace_role import WorkspaceRole, Status as WorkspaceRoleStatus
|
||||
|
||||
|
||||
class WorkspacesQuery(Query):
|
||||
@@ -25,10 +24,8 @@ class WorkspacesQuery(Query):
|
||||
return (
|
||||
db.session.query(Workspace)
|
||||
.join(WorkspaceRole)
|
||||
.join(Invitation)
|
||||
.filter(WorkspaceRole.user == user)
|
||||
.filter(Invitation.user == user)
|
||||
.filter(Invitation.status == InvitationStatus.ACCEPTED)
|
||||
.filter(WorkspaceRole.status == WorkspaceRoleStatus.ACTIVE)
|
||||
.all()
|
||||
)
|
||||
|
||||
|
@@ -3,7 +3,7 @@ from atst.domain.authz import Authorization
|
||||
from atst.models.permissions import Permissions
|
||||
from atst.domain.users import Users
|
||||
from atst.domain.workspace_users import WorkspaceUsers
|
||||
from atst.domain.invitations import Invitations
|
||||
from atst.models.workspace_role import Status as WorkspaceRoleStatus
|
||||
|
||||
from .query import WorkspacesQuery
|
||||
from .scopes import ScopedWorkspace
|
||||
@@ -14,8 +14,9 @@ class Workspaces(object):
|
||||
def create(cls, request, name=None):
|
||||
name = name or request.displayname
|
||||
workspace = WorkspacesQuery.create(request=request, name=name)
|
||||
Workspaces._create_workspace_role(request.creator, workspace, "owner")
|
||||
Invitations.create_for_owner(workspace, request.creator)
|
||||
Workspaces._create_workspace_role(
|
||||
request.creator, workspace, "owner", status=WorkspaceRoleStatus.ACTIVE
|
||||
)
|
||||
WorkspacesQuery.add_and_commit(workspace)
|
||||
return workspace
|
||||
|
||||
@@ -109,9 +110,13 @@ class Workspaces(object):
|
||||
return WorkspaceUsers.update_role(member, workspace.id, role_name)
|
||||
|
||||
@classmethod
|
||||
def _create_workspace_role(cls, user, workspace, role_name):
|
||||
def _create_workspace_role(
|
||||
cls, user, workspace, role_name, status=WorkspaceRoleStatus.PENDING
|
||||
):
|
||||
role = Roles.get(role_name)
|
||||
workspace_role = WorkspacesQuery.create_workspace_role(user, role, workspace)
|
||||
workspace_role = WorkspacesQuery.create_workspace_role(
|
||||
user, role, workspace, status=status
|
||||
)
|
||||
WorkspacesQuery.add_and_commit(workspace_role)
|
||||
return workspace_role
|
||||
|
||||
|
@@ -25,8 +25,10 @@ class Invitation(Base, TimestampsMixin):
|
||||
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True)
|
||||
user = relationship("User", backref="invitations", foreign_keys=[user_id])
|
||||
|
||||
workspace_id = Column(UUID(as_uuid=True), ForeignKey("workspaces.id"), index=True)
|
||||
workspace = relationship("Workspace", backref="invitations")
|
||||
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])
|
||||
@@ -61,3 +63,8 @@ class Invitation(Base, TimestampsMixin):
|
||||
@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
|
||||
|
@@ -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
|
||||
|
@@ -237,7 +237,9 @@ def create_member(workspace_id):
|
||||
if form.validate():
|
||||
try:
|
||||
new_member = Workspaces.create_member(g.current_user, workspace, form.data)
|
||||
invite = Invitations.create(workspace, g.current_user, new_member.user)
|
||||
invite = Invitations.create(
|
||||
new_member.workspace_role, g.current_user, new_member.user
|
||||
)
|
||||
send_invite_email(
|
||||
g.current_user.full_name, invite.token, new_member.user.email
|
||||
)
|
||||
|
Reference in New Issue
Block a user