Skip to content

Commit 6e36c6e

Browse files
estebanx64tiangolo
andauthored
✨ Add role, organization and UserOrganization link table (#9)
Co-authored-by: Sebastián Ramírez <[email protected]>
1 parent d4201d4 commit 6e36c6e

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Add organization table and UserOrganization join table
2+
3+
Revision ID: 56310da83983
4+
Revises: e2412789c190
5+
Create Date: 2024-03-27 21:29:02.652462
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
12+
13+
# revision identifiers, used by Alembic.
14+
revision = '56310da83983'
15+
down_revision = 'e2412789c190'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.create_table('organization',
23+
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
24+
sa.Column('description', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
25+
sa.Column('id', sa.Integer(), nullable=False),
26+
sa.PrimaryKeyConstraint('id')
27+
)
28+
op.create_table('userorganization',
29+
sa.Column('user_id', sa.Integer(), nullable=False),
30+
sa.Column('organization_id', sa.Integer(), nullable=False),
31+
sa.Column('role', sa.Enum('MEMBER', 'ADMIN', name='permissionsenum'), nullable=False),
32+
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
33+
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
34+
sa.PrimaryKeyConstraint('user_id', 'organization_id')
35+
)
36+
# ### end Alembic commands ###
37+
38+
39+
def downgrade():
40+
# ### commands auto generated by Alembic - please adjust! ###
41+
op.drop_table('userorganization')
42+
op.drop_table('organization')
43+
# ### end Alembic commands ###

backend/app/models.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1+
from enum import Enum
2+
13
from sqlmodel import Field, Relationship, SQLModel
24

35

6+
class Role(str, Enum):
7+
member = "member"
8+
admin = "admin"
9+
10+
11+
class UserOrganization(SQLModel, table=True):
12+
user_id: int | None = Field(default=None, foreign_key="user.id", primary_key=True)
13+
organization_id: int | None = Field(
14+
default=None, foreign_key="organization.id", primary_key=True
15+
)
16+
role: Role
17+
18+
user: "User" = Relationship(back_populates="organization_links")
19+
organization: "Organization" = Relationship(back_populates="user_links")
20+
21+
422
# Shared properties
523
# TODO replace email str with EmailStr when sqlmodel supports it
624
class UserBase(SQLModel):
@@ -45,6 +63,7 @@ class User(UserBase, table=True):
4563
id: int | None = Field(default=None, primary_key=True)
4664
hashed_password: str
4765
items: list["Item"] = Relationship(back_populates="owner")
66+
organization_links: list[UserOrganization] = Relationship(back_populates="user")
4867

4968

5069
# Properties to return via API, id is always required
@@ -111,3 +130,30 @@ class TokenPayload(SQLModel):
111130
class NewPassword(SQLModel):
112131
token: str
113132
new_password: str
133+
134+
135+
class OrganizationBase(SQLModel):
136+
name: str
137+
description: str | None = None
138+
139+
140+
class Organization(OrganizationBase, table=True):
141+
id: int | None = Field(default=None, primary_key=True)
142+
user_links: list[UserOrganization] = Relationship(back_populates="organization")
143+
144+
145+
class OrganizationCreate(OrganizationBase):
146+
pass
147+
148+
149+
class OrganizationUpdate(OrganizationBase):
150+
pass
151+
152+
153+
class OrganizationOut(OrganizationBase):
154+
id: int
155+
156+
157+
class organizationsOut(SQLModel):
158+
data: list[OrganizationOut]
159+
count: int

0 commit comments

Comments
 (0)