@ -1,6 +1,6 @@
import enum
import enum
import json
import json
from typing import cast
from typing import Optional, cast
from flask_login import UserMixin # type: ignore
from flask_login import UserMixin # type: ignore
from sqlalchemy import func
from sqlalchemy import func
@ -12,6 +12,66 @@ from .engine import db
from . types import StringUUID
from . types import StringUUID
class TenantAccountRole ( enum . StrEnum ) :
OWNER = " owner "
ADMIN = " admin "
EDITOR = " editor "
NORMAL = " normal "
DATASET_OPERATOR = " dataset_operator "
@staticmethod
def is_valid_role ( role : str ) - > bool :
if not role :
return False
return role in {
TenantAccountRole . OWNER ,
TenantAccountRole . ADMIN ,
TenantAccountRole . EDITOR ,
TenantAccountRole . NORMAL ,
TenantAccountRole . DATASET_OPERATOR ,
}
@staticmethod
def is_privileged_role ( role : Optional [ " TenantAccountRole " ] ) - > bool :
if not role :
return False
return role in { TenantAccountRole . OWNER , TenantAccountRole . ADMIN }
@staticmethod
def is_admin_role ( role : Optional [ " TenantAccountRole " ] ) - > bool :
if not role :
return False
return role == TenantAccountRole . ADMIN
@staticmethod
def is_non_owner_role ( role : Optional [ " TenantAccountRole " ] ) - > bool :
if not role :
return False
return role in {
TenantAccountRole . ADMIN ,
TenantAccountRole . EDITOR ,
TenantAccountRole . NORMAL ,
TenantAccountRole . DATASET_OPERATOR ,
}
@staticmethod
def is_editing_role ( role : Optional [ " TenantAccountRole " ] ) - > bool :
if not role :
return False
return role in { TenantAccountRole . OWNER , TenantAccountRole . ADMIN , TenantAccountRole . EDITOR }
@staticmethod
def is_dataset_edit_role ( role : Optional [ " TenantAccountRole " ] ) - > bool :
if not role :
return False
return role in {
TenantAccountRole . OWNER ,
TenantAccountRole . ADMIN ,
TenantAccountRole . EDITOR ,
TenantAccountRole . DATASET_OPERATOR ,
}
class AccountStatus ( enum . StrEnum ) :
class AccountStatus ( enum . StrEnum ) :
PENDING = " pending "
PENDING = " pending "
UNINITIALIZED = " uninitialized "
UNINITIALIZED = " uninitialized "
@ -21,6 +81,8 @@ class AccountStatus(enum.StrEnum):
class Account ( UserMixin , Base ) :
class Account ( UserMixin , Base ) :
role : Optional [ " TenantAccountRole " ] = None
_current_tenant : Optional [ " Tenant " ] = None
__tablename__ = " accounts "
__tablename__ = " accounts "
__table_args__ = ( db . PrimaryKeyConstraint ( " id " , name = " account_pkey " ) , db . Index ( " account_email_idx " , " email " ) )
__table_args__ = ( db . PrimaryKeyConstraint ( " id " , name = " account_pkey " ) , db . Index ( " account_email_idx " , " email " ) )
@ -47,18 +109,16 @@ class Account(UserMixin, Base):
@property
@property
def current_tenant ( self ) :
def current_tenant ( self ) :
return self . _current_tenant # type: ignore
return self . _current_tenant
@current_tenant.setter
@current_tenant.setter
def current_tenant ( self , value : " Tenant " ) :
def current_tenant ( self , tenant : " Tenant " ) :
tenant = value
ta = db . session . query ( TenantAccountJoin ) . filter_by ( tenant_id = tenant . id , account_id = self . id ) . first ( )
ta = db . session . query ( TenantAccountJoin ) . filter_by ( tenant_id = tenant . id , account_id = self . id ) . first ( )
if ta :
if ta :
tenant . current_role = ta . role
self . role = TenantAccountRole ( ta . role )
else :
self . _current_tenant = tenant
tenant = None # type: ignore
return
self . _current_tenant = None
self . _current_tenant = tenant
@property
@property
def current_tenant_id ( self ) - > str | None :
def current_tenant_id ( self ) - > str | None :
@ -80,12 +140,12 @@ class Account(UserMixin, Base):
return
return
tenant , join = tenant_account_join
tenant , join = tenant_account_join
tenant . current_ role = join . role
self . role = join . role
self . _current_tenant = tenant
self . _current_tenant = tenant
@property
@property
def current_role ( self ) :
def current_role ( self ) :
return self . _current_tenant. current_ role
return self . role
def get_status ( self ) - > AccountStatus :
def get_status ( self ) - > AccountStatus :
status_str = self . status
status_str = self . status
@ -105,23 +165,23 @@ class Account(UserMixin, Base):
# check current_user.current_tenant.current_role in ['admin', 'owner']
# check current_user.current_tenant.current_role in ['admin', 'owner']
@property
@property
def is_admin_or_owner ( self ) :
def is_admin_or_owner ( self ) :
return TenantAccountRole . is_privileged_role ( self . _current_tenant. current_ role)
return TenantAccountRole . is_privileged_role ( self . role)
@property
@property
def is_admin ( self ) :
def is_admin ( self ) :
return TenantAccountRole . is_admin_role ( self . _current_tenant. current_ role)
return TenantAccountRole . is_admin_role ( self . role)
@property
@property
def is_editor ( self ) :
def is_editor ( self ) :
return TenantAccountRole . is_editing_role ( self . _current_tenant. current_ role)
return TenantAccountRole . is_editing_role ( self . role)
@property
@property
def is_dataset_editor ( self ) :
def is_dataset_editor ( self ) :
return TenantAccountRole . is_dataset_edit_role ( self . _current_tenant. current_ role)
return TenantAccountRole . is_dataset_edit_role ( self . role)
@property
@property
def is_dataset_operator ( self ) :
def is_dataset_operator ( self ) :
return self . _current_tenant. current_ role == TenantAccountRole . DATASET_OPERATOR
return self . role == TenantAccountRole . DATASET_OPERATOR
class TenantStatus ( enum . StrEnum ) :
class TenantStatus ( enum . StrEnum ) :
@ -129,66 +189,6 @@ class TenantStatus(enum.StrEnum):
ARCHIVE = " archive "
ARCHIVE = " archive "
class TenantAccountRole ( enum . StrEnum ) :
OWNER = " owner "
ADMIN = " admin "
EDITOR = " editor "
NORMAL = " normal "
DATASET_OPERATOR = " dataset_operator "
@staticmethod
def is_valid_role ( role : str ) - > bool :
if not role :
return False
return role in {
TenantAccountRole . OWNER ,
TenantAccountRole . ADMIN ,
TenantAccountRole . EDITOR ,
TenantAccountRole . NORMAL ,
TenantAccountRole . DATASET_OPERATOR ,
}
@staticmethod
def is_privileged_role ( role : str ) - > bool :
if not role :
return False
return role in { TenantAccountRole . OWNER , TenantAccountRole . ADMIN }
@staticmethod
def is_admin_role ( role : str ) - > bool :
if not role :
return False
return role == TenantAccountRole . ADMIN
@staticmethod
def is_non_owner_role ( role : str ) - > bool :
if not role :
return False
return role in {
TenantAccountRole . ADMIN ,
TenantAccountRole . EDITOR ,
TenantAccountRole . NORMAL ,
TenantAccountRole . DATASET_OPERATOR ,
}
@staticmethod
def is_editing_role ( role : str ) - > bool :
if not role :
return False
return role in { TenantAccountRole . OWNER , TenantAccountRole . ADMIN , TenantAccountRole . EDITOR }
@staticmethod
def is_dataset_edit_role ( role : str ) - > bool :
if not role :
return False
return role in {
TenantAccountRole . OWNER ,
TenantAccountRole . ADMIN ,
TenantAccountRole . EDITOR ,
TenantAccountRole . DATASET_OPERATOR ,
}
class Tenant ( Base ) :
class Tenant ( Base ) :
__tablename__ = " tenants "
__tablename__ = " tenants "
__table_args__ = ( db . PrimaryKeyConstraint ( " id " , name = " tenant_pkey " ) , )
__table_args__ = ( db . PrimaryKeyConstraint ( " id " , name = " tenant_pkey " ) , )