feat(workspace): restore core routes on sqlalchemy adapters
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from sqlalchemy import Boolean, Column, DateTime, Float, String, Text, create_engine
|
||||
from sqlalchemy import Boolean, Column, DateTime, Float, String, Text, UniqueConstraint, create_engine
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
@@ -23,6 +23,48 @@ class UserModel(Base):
|
||||
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
|
||||
|
||||
class WorkspaceModel(Base):
|
||||
__tablename__ = "workspaces"
|
||||
|
||||
id = Column(String(36), primary_key=True)
|
||||
name = Column(String(100), nullable=False)
|
||||
owner_user_id = Column(String(36), nullable=False, index=True)
|
||||
subscription_plan = Column(String(20), nullable=False, default="free")
|
||||
subscription_status = Column(String(20), nullable=False, default="active")
|
||||
subscription_expires_at = Column(DateTime, nullable=True)
|
||||
max_projects = Column(Float, nullable=False, default=3)
|
||||
max_storage_gb = Column(Float, nullable=False, default=10)
|
||||
used_storage_gb = Column(Float, nullable=False, default=0.0)
|
||||
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
|
||||
|
||||
class WorkspaceMemberModel(Base):
|
||||
__tablename__ = "workspace_members"
|
||||
__table_args__ = (UniqueConstraint("workspace_id", "user_id", name="uq_workspace_members_workspace_user"),)
|
||||
|
||||
id = Column(String(36), primary_key=True)
|
||||
workspace_id = Column(String(36), nullable=False, index=True)
|
||||
user_id = Column(String(36), nullable=False, index=True)
|
||||
role = Column(String(20), nullable=False)
|
||||
invited_by = Column(String(36), nullable=True)
|
||||
joined_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
|
||||
|
||||
class WorkspaceInvitationModel(Base):
|
||||
__tablename__ = "workspace_invitations"
|
||||
|
||||
id = Column(String(36), primary_key=True)
|
||||
workspace_id = Column(String(36), nullable=False, index=True)
|
||||
inviter_user_id = Column(String(36), nullable=False)
|
||||
invitee_email = Column(String(255), nullable=False, index=True)
|
||||
role = Column(String(20), nullable=False)
|
||||
invitation_token = Column(String(255), nullable=False, unique=True, index=True)
|
||||
status = Column(String(20), nullable=False, default="pending", index=True)
|
||||
expires_at = Column(DateTime, nullable=True)
|
||||
accepted_at = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
|
||||
|
||||
class ProjectModel(Base):
|
||||
__tablename__ = "projects"
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from packages.adapters.sqlalchemy_impl.models import WorkspaceMemberModel
|
||||
from packages.domain.entities import WorkspaceMember
|
||||
from packages.ports.workspace_member_repository import WorkspaceMemberRepository
|
||||
|
||||
|
||||
class SQLAlchemyWorkspaceMemberRepository(WorkspaceMemberRepository):
|
||||
def __init__(self, session: Session):
|
||||
self.session = session
|
||||
|
||||
def save(self, member: WorkspaceMember) -> None:
|
||||
model = self.session.get(WorkspaceMemberModel, member.id)
|
||||
if model is None:
|
||||
model = (
|
||||
self.session.query(WorkspaceMemberModel)
|
||||
.filter(
|
||||
WorkspaceMemberModel.workspace_id == member.workspace_id,
|
||||
WorkspaceMemberModel.user_id == member.user_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if model is None:
|
||||
model = WorkspaceMemberModel(id=member.id)
|
||||
self.session.add(model)
|
||||
|
||||
model.workspace_id = member.workspace_id
|
||||
model.user_id = member.user_id
|
||||
model.role = str(member.role)
|
||||
model.invited_by = member.invited_by
|
||||
model.joined_at = member.joined_at
|
||||
|
||||
self.session.commit()
|
||||
self.session.refresh(model)
|
||||
|
||||
def find_by_id(self, member_id: str) -> WorkspaceMember | None:
|
||||
return self._to_entity(self.session.get(WorkspaceMemberModel, member_id))
|
||||
|
||||
def find_by_workspace_and_user(self, workspace_id: str, user_id: str) -> WorkspaceMember | None:
|
||||
model = (
|
||||
self.session.query(WorkspaceMemberModel)
|
||||
.filter(WorkspaceMemberModel.workspace_id == workspace_id, WorkspaceMemberModel.user_id == user_id)
|
||||
.first()
|
||||
)
|
||||
return self._to_entity(model)
|
||||
|
||||
def find_by_user(self, user_id: str) -> list[WorkspaceMember]:
|
||||
models = (
|
||||
self.session.query(WorkspaceMemberModel)
|
||||
.filter(WorkspaceMemberModel.user_id == user_id)
|
||||
.order_by(WorkspaceMemberModel.joined_at.desc())
|
||||
.all()
|
||||
)
|
||||
return [self._to_entity(model) for model in models if model is not None]
|
||||
|
||||
def find_by_workspace(self, workspace_id: str) -> list[WorkspaceMember]:
|
||||
models = (
|
||||
self.session.query(WorkspaceMemberModel)
|
||||
.filter(WorkspaceMemberModel.workspace_id == workspace_id)
|
||||
.order_by(WorkspaceMemberModel.joined_at.asc())
|
||||
.all()
|
||||
)
|
||||
return [self._to_entity(model) for model in models if model is not None]
|
||||
|
||||
def count_by_workspace(self, workspace_id: str) -> int:
|
||||
return (
|
||||
self.session.query(WorkspaceMemberModel).filter(WorkspaceMemberModel.workspace_id == workspace_id).count()
|
||||
)
|
||||
|
||||
def delete(self, member_id: str) -> bool:
|
||||
model = self.session.get(WorkspaceMemberModel, member_id)
|
||||
if model is None:
|
||||
return False
|
||||
self.session.delete(model)
|
||||
self.session.commit()
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _to_entity(model: WorkspaceMemberModel | None) -> WorkspaceMember | None:
|
||||
if model is None:
|
||||
return None
|
||||
return WorkspaceMember(
|
||||
id=model.id,
|
||||
workspace_id=model.workspace_id,
|
||||
user_id=model.user_id,
|
||||
role=model.role,
|
||||
invited_by=model.invited_by,
|
||||
joined_at=model.joined_at,
|
||||
)
|
||||
@@ -0,0 +1,59 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from packages.adapters.sqlalchemy_impl.models import WorkspaceModel
|
||||
from packages.domain.entities import Workspace
|
||||
from packages.ports.workspace_repository import WorkspaceRepository
|
||||
|
||||
|
||||
class SQLAlchemyWorkspaceRepository(WorkspaceRepository):
|
||||
def __init__(self, session: Session):
|
||||
self.session = session
|
||||
|
||||
def save(self, workspace: Workspace) -> None:
|
||||
model = self.session.get(WorkspaceModel, workspace.id)
|
||||
if model is None:
|
||||
model = WorkspaceModel(id=workspace.id)
|
||||
self.session.add(model)
|
||||
|
||||
model.name = workspace.name
|
||||
model.owner_user_id = workspace.owner_user_id
|
||||
model.subscription_plan = workspace.subscription_plan
|
||||
model.subscription_status = workspace.subscription_status
|
||||
model.subscription_expires_at = workspace.subscription_expires_at
|
||||
model.max_projects = workspace.max_projects
|
||||
model.max_storage_gb = workspace.max_storage_gb
|
||||
model.used_storage_gb = workspace.used_storage_gb
|
||||
model.created_at = workspace.created_at
|
||||
|
||||
self.session.commit()
|
||||
self.session.refresh(model)
|
||||
|
||||
def find_by_id(self, workspace_id: str) -> Workspace | None:
|
||||
return self._to_entity(self.session.get(WorkspaceModel, workspace_id))
|
||||
|
||||
def delete(self, workspace_id: str) -> bool:
|
||||
model = self.session.get(WorkspaceModel, workspace_id)
|
||||
if model is None:
|
||||
return False
|
||||
self.session.delete(model)
|
||||
self.session.commit()
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _to_entity(model: WorkspaceModel | None) -> Workspace | None:
|
||||
if model is None:
|
||||
return None
|
||||
return Workspace(
|
||||
id=model.id,
|
||||
name=model.name,
|
||||
owner_user_id=model.owner_user_id,
|
||||
subscription_plan=model.subscription_plan,
|
||||
subscription_status=model.subscription_status,
|
||||
subscription_expires_at=model.subscription_expires_at,
|
||||
max_projects=int(model.max_projects),
|
||||
max_storage_gb=int(model.max_storage_gb),
|
||||
used_storage_gb=float(model.used_storage_gb),
|
||||
created_at=model.created_at,
|
||||
)
|
||||
Reference in New Issue
Block a user