Skip to content

Commit

Permalink
✨ Add role, organization and UserOrganization link table (#9)
Browse files Browse the repository at this point in the history
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
  • Loading branch information
estebanx64 and tiangolo authored Mar 27, 2024
1 parent d4201d4 commit 6e36c6e
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Add organization table and UserOrganization join table
Revision ID: 56310da83983
Revises: e2412789c190
Create Date: 2024-03-27 21:29:02.652462
"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes


# revision identifiers, used by Alembic.
revision = '56310da83983'
down_revision = 'e2412789c190'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('organization',
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('description', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('userorganization',
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('organization_id', sa.Integer(), nullable=False),
sa.Column('role', sa.Enum('MEMBER', 'ADMIN', name='permissionsenum'), nullable=False),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'organization_id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('userorganization')
op.drop_table('organization')
# ### end Alembic commands ###
46 changes: 46 additions & 0 deletions backend/app/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
from enum import Enum

from sqlmodel import Field, Relationship, SQLModel


class Role(str, Enum):
member = "member"
admin = "admin"


class UserOrganization(SQLModel, table=True):
user_id: int | None = Field(default=None, foreign_key="user.id", primary_key=True)
organization_id: int | None = Field(
default=None, foreign_key="organization.id", primary_key=True
)
role: Role

user: "User" = Relationship(back_populates="organization_links")
organization: "Organization" = Relationship(back_populates="user_links")


# Shared properties
# TODO replace email str with EmailStr when sqlmodel supports it
class UserBase(SQLModel):
Expand Down Expand Up @@ -45,6 +63,7 @@ class User(UserBase, table=True):
id: int | None = Field(default=None, primary_key=True)
hashed_password: str
items: list["Item"] = Relationship(back_populates="owner")
organization_links: list[UserOrganization] = Relationship(back_populates="user")


# Properties to return via API, id is always required
Expand Down Expand Up @@ -111,3 +130,30 @@ class TokenPayload(SQLModel):
class NewPassword(SQLModel):
token: str
new_password: str


class OrganizationBase(SQLModel):
name: str
description: str | None = None


class Organization(OrganizationBase, table=True):
id: int | None = Field(default=None, primary_key=True)
user_links: list[UserOrganization] = Relationship(back_populates="organization")


class OrganizationCreate(OrganizationBase):
pass


class OrganizationUpdate(OrganizationBase):
pass


class OrganizationOut(OrganizationBase):
id: int


class organizationsOut(SQLModel):
data: list[OrganizationOut]
count: int

0 comments on commit 6e36c6e

Please sign in to comment.