1
1
import os
2
2
import logging
3
+ from enum import Enum
3
4
from typing import Optional , List
4
5
from datetime import datetime , UTC
5
6
from dotenv import load_dotenv
6
7
from sqlalchemy .engine import URL
7
- from sqlmodel import create_engine , Session , SQLModel , Field , Relationship
8
-
8
+ from sqlmodel import create_engine , Session , SQLModel , Field , Relationship , select
9
+ from sqlalchemy import Column , Enum as SQLAlchemyEnum
9
10
10
11
load_dotenv ()
11
12
@@ -41,13 +42,71 @@ def get_session():
41
42
yield session
42
43
43
44
45
+ def set_up_db (drop : bool = False ):
46
+ engine = create_engine (get_connection_url ())
47
+ if drop :
48
+ SQLModel .metadata .drop_all (engine )
49
+ SQLModel .metadata .create_all (engine )
50
+ with Session (engine ) as session :
51
+ roles_in_db = []
52
+ # Create default roles
53
+ for role_name in default_roles :
54
+ db_role = session .exec (select (Role ).where (
55
+ Role .name == role_name )).first ()
56
+ if not db_role :
57
+ db_role = Role (name = role_name )
58
+ session .add (db_role )
59
+ roles_in_db .append (db_role )
60
+ else :
61
+ roles_in_db .append (db_role )
62
+
63
+ session .commit () # Commit after adding roles
64
+
65
+ # Create default permissions
66
+ for permission in [permission for permission in ValidPermissions ]:
67
+ db_permission = session .exec (select (Permission ).where (
68
+ Permission .name == permission )).first ()
69
+ if not db_permission :
70
+ db_permission = Permission (name = permission )
71
+ session .add (db_permission )
72
+
73
+ # Create RolePermissionLink for Owner and Administrator
74
+ # Assuming first two roles are Owner and Administrator
75
+ for role in roles_in_db [:2 ]:
76
+ db_role_permission_link = session .exec (select (RolePermissionLink ).where (
77
+ RolePermissionLink .role_id == role .id ,
78
+ RolePermissionLink .permission_id == db_permission .id )).first ()
79
+ if not db_role_permission_link :
80
+ if not (permission == ValidPermissions .DELETE_ORGANIZATION and role .name == "Administrator" ):
81
+ role_permission_link = RolePermissionLink (
82
+ role_id = role .id , permission_id = db_permission .id )
83
+ session .add (role_permission_link )
84
+
85
+ session .commit () # Commit after adding permissions and links
86
+ engine .dispose ()
87
+
88
+
44
89
# --- Models ---
45
90
46
91
47
92
def utc_time ():
48
93
return datetime .now (UTC )
49
94
50
95
96
+ default_roles = ["Owner" , "Administrator" , "Member" ]
97
+
98
+
99
+ class ValidPermissions (Enum ):
100
+ DELETE_ORGANIZATION = "Delete Organization"
101
+ EDIT_ORGANIZATION = "Edit Organization"
102
+ INVITE_USER = "Invite User"
103
+ REMOVE_USER = "Remove User"
104
+ EDIT_USER_ROLE = "Edit User Role"
105
+ CREATE_ROLE = "Create Role"
106
+ DELETE_ROLE = "Delete Role"
107
+ EDIT_ROLE = "Edit Role"
108
+
109
+
51
110
class Organization (SQLModel , table = True ):
52
111
id : Optional [int ] = Field (default = None , primary_key = True )
53
112
name : str
@@ -58,6 +117,45 @@ class Organization(SQLModel, table=True):
58
117
users : List ["User" ] = Relationship (back_populates = "organization" )
59
118
60
119
120
+ class Role (SQLModel , table = True ):
121
+ id : Optional [int ] = Field (default = None , primary_key = True )
122
+ name : str
123
+ organization_id : Optional [int ] = Field (
124
+ default = None , foreign_key = "organization.id" )
125
+ created_at : datetime = Field (default_factory = utc_time )
126
+ updated_at : datetime = Field (default_factory = utc_time )
127
+ deleted : bool = Field (default = False )
128
+
129
+ users : List ["User" ] = Relationship (back_populates = "role" )
130
+ role_permission_links : List ["RolePermissionLink" ] = Relationship (
131
+ back_populates = "role" )
132
+
133
+
134
+ class Permission (SQLModel , table = True ):
135
+ id : Optional [int ] = Field (default = None , primary_key = True )
136
+ name : ValidPermissions = Field (
137
+ sa_column = Column (SQLAlchemyEnum (ValidPermissions )))
138
+ created_at : datetime = Field (default_factory = utc_time )
139
+ updated_at : datetime = Field (default_factory = utc_time )
140
+ deleted : bool = Field (default = False )
141
+
142
+ role_permission_links : List ["RolePermissionLink" ] = Relationship (
143
+ back_populates = "permission" )
144
+
145
+
146
+ class RolePermissionLink (SQLModel , table = True ):
147
+ id : Optional [int ] = Field (default = None , primary_key = True )
148
+ role_id : Optional [int ] = Field (
149
+ default = None , foreign_key = "role.id" )
150
+ permission_id : Optional [int ] = Field (
151
+ default = None , foreign_key = "permission.id" )
152
+
153
+ role : Optional ["Role" ] = Relationship (
154
+ back_populates = "role_permission_links" )
155
+ permission : Optional ["Permission" ] = Relationship (
156
+ back_populates = "role_permission_links" )
157
+
158
+
61
159
class User (SQLModel , table = True ):
62
160
id : Optional [int ] = Field (default = None , primary_key = True )
63
161
name : str
@@ -66,9 +164,19 @@ class User(SQLModel, table=True):
66
164
avatar_url : Optional [str ] = None
67
165
organization_id : Optional [int ] = Field (
68
166
default = None , foreign_key = "organization.id" )
167
+ role_id : Optional [int ] = Field (default = None , foreign_key = "role.id" )
69
168
created_at : datetime = Field (default_factory = utc_time )
70
169
updated_at : datetime = Field (default_factory = utc_time )
71
170
deleted : bool = Field (default = False )
72
171
73
172
organization : Optional ["Organization" ] = Relationship (
74
173
back_populates = "users" )
174
+ role : Optional ["Role" ] = Relationship (back_populates = "users" )
175
+
176
+
177
+ class UserOrganizationLink (SQLModel , table = True ):
178
+ id : Optional [int ] = Field (default = None , primary_key = True )
179
+ user_id : Optional [int ] = Field (
180
+ default = None , foreign_key = "user.id" )
181
+ organization_id : Optional [int ] = Field (
182
+ default = None , foreign_key = "organization.id" )
0 commit comments