67 lines
1.8 KiB
Python
67 lines
1.8 KiB
Python
"""Organization member ORM model."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from enum import StrEnum
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
from sqlalchemy import DateTime, Enum as SqlEnum, ForeignKey, Integer, UniqueConstraint, func
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.models.base import Base, enum_values
|
|
|
|
|
|
class OrganizationRole(StrEnum):
|
|
OWNER = "owner"
|
|
ADMIN = "admin"
|
|
MANAGER = "manager"
|
|
MEMBER = "member"
|
|
|
|
|
|
class OrganizationMember(Base):
|
|
"""Links users to organizations with role-based access."""
|
|
|
|
__tablename__ = "organization_members"
|
|
__table_args__ = (
|
|
UniqueConstraint("organization_id", "user_id", name="uq_organization_member"),
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
organization_id: Mapped[int] = mapped_column(ForeignKey("organizations.id", ondelete="CASCADE"))
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"))
|
|
role: Mapped[OrganizationRole] = mapped_column(
|
|
SqlEnum(
|
|
OrganizationRole,
|
|
name="organization_role",
|
|
values_callable=enum_values,
|
|
),
|
|
nullable=False,
|
|
default=OrganizationRole.MEMBER,
|
|
)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
nullable=False,
|
|
)
|
|
|
|
organization = relationship("Organization", back_populates="members")
|
|
user = relationship("User", back_populates="memberships")
|
|
|
|
|
|
class OrganizationMemberBase(BaseModel):
|
|
organization_id: int
|
|
user_id: int
|
|
role: OrganizationRole
|
|
|
|
|
|
class OrganizationMemberCreate(OrganizationMemberBase):
|
|
pass
|
|
|
|
|
|
class OrganizationMemberRead(OrganizationMemberBase):
|
|
id: int
|
|
created_at: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|