You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am implementing schema-based multi-tenancy loosely based upon this excellent blog post from MergeBoard (however, I am using MySQL instead of PostgreSQL, so "database" and "schema" are interchangeable terms in this case).
That is to say:
Tenant 1: {database_schema_1}.{table}.{column}, available at mysql://user:password@host:port/database_schema_1
Tenant 2: {database_schema_2}.{table}.{column}, available at mysql://user:password@host:port/database_schema_2
. . .
Tenant N: {database_schema_n}.{table}.{column}, available at mysql://user:password@host:port/database_schema_n
Problem: I have successfully implemented AuthenticationBackend and am able to allow/deny users access to the admin. However, because the Admin takes Engine in its constructor (which in my case doesn't point to a specific database schema), attempting to view models throws this error:
sqlalchemy.exc.OperationalError: (MySQLdb.OperationalError) (1046, 'No database selected')
[SQL: SELECT count(table.id) AS count_1
FROM table]
Question: Is there a way to set up sqladmin with multiple database schemas, such that it can dynamically set the bind connectable using information from an authorized user?
Multi-tenancy Implementation Details
Not all of these functions are in the same file, and some details are elided. The excerpts below are only to provide an overview.
# Nota bene: no database schema is specified! The engine is updated with the correct database schema in the `tenancy` context manager.ENGINE: Engine=make_engine("mysql://user:password@host:port")
classTenantConfiguration(pydantic.BaseModel):
database_schema: strdefget_tenant(authorization: str) ->TenantConfiguration:
""" Returns the correct TenantConfiguration using a passed authentication token """
...
@contextmanagerdeftenancy(database_schema: Optional[str]) ->Session:
""" """ifdatabase_schema:
schema_translate_map= {None: database_schema}
else:
schema_translate_map=Noneconnectable=ENGINE.execution_options(schema_translate_map=schema_translate_map)
session=Session(autocommit=False, autoflush=False, bind=connectable)
try:
yieldsessionfinally:
session.close()
defget_database_session(
authorization: str=Header(alias="Authorization"),
) ->Generator[Session, None, None]:
tenant_configuration: TenantConfiguration=get_tenant(authorization)
withtenancy(tenant_configuration.database_schema) assession:
yieldsession@fastapi_app.get("/item")defexample(session: Session=Depends(get_database_session)):
""" Returns items from the authorized tenant's database schema """
response: Response=requests.get(url="https://example.com/example/endpoint", headers={"Authorization": "token"})
# response.json() will only return the items from the database corresponding to the passed token
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I am implementing schema-based multi-tenancy loosely based upon this excellent blog post from MergeBoard (however, I am using MySQL instead of PostgreSQL, so "database" and "schema" are interchangeable terms in this case).
That is to say:
{database_schema_1}.{table}.{column}
, available atmysql://user:password@host:port/database_schema_1
{database_schema_2}.{table}.{column}
, available atmysql://user:password@host:port/database_schema_2
{database_schema_n}.{table}.{column}
, available atmysql://user:password@host:port/database_schema_n
Problem: I have successfully implemented
AuthenticationBackend
and am able to allow/deny users access to the admin. However, because theAdmin
takesEngine
in its constructor (which in my case doesn't point to a specific database schema), attempting to view models throws this error:Question: Is there a way to set up
sqladmin
with multiple database schemas, such that it can dynamically set thebind
connectable using information from an authorized user?Multi-tenancy Implementation Details
Not all of these functions are in the same file, and some details are elided. The excerpts below are only to provide an overview.
Beta Was this translation helpful? Give feedback.
All reactions