feat: add tenant-scoped rule and permission management
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
"""`sso_users` 表结构兼容工具。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import text
|
||||
|
||||
|
||||
class SsoUserCompat:
|
||||
"""兼容旧环境 `sso_users` 尚未完成租户字段迁移的场景。"""
|
||||
|
||||
_columns_cache: set[str] | None = None
|
||||
|
||||
@classmethod
|
||||
async def get_columns(cls, session) -> set[str]:
|
||||
if cls._columns_cache is not None:
|
||||
return cls._columns_cache
|
||||
|
||||
rows = await session.execute(
|
||||
text(
|
||||
"""
|
||||
SELECT column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = current_schema()
|
||||
AND table_name = 'sso_users'
|
||||
"""
|
||||
)
|
||||
)
|
||||
cls._columns_cache = {str(row[0]) for row in rows.fetchall()}
|
||||
return cls._columns_cache
|
||||
|
||||
@staticmethod
|
||||
def raw_optional_column(
|
||||
columns: set[str],
|
||||
*,
|
||||
alias: str,
|
||||
column: str,
|
||||
pg_type: str = "varchar",
|
||||
) -> str:
|
||||
if column in columns:
|
||||
return f"{alias}.{column}"
|
||||
return f"NULL::{pg_type}"
|
||||
|
||||
@classmethod
|
||||
def optional_column_as(
|
||||
cls,
|
||||
columns: set[str],
|
||||
*,
|
||||
alias: str,
|
||||
column: str,
|
||||
pg_type: str = "varchar",
|
||||
output_alias: str | None = None,
|
||||
) -> str:
|
||||
expression = cls.raw_optional_column(columns, alias=alias, column=column, pg_type=pg_type)
|
||||
return f"{expression} AS {output_alias or column}"
|
||||
|
||||
@classmethod
|
||||
def optional_coalesce_as(
|
||||
cls,
|
||||
columns: set[str],
|
||||
*,
|
||||
alias: str,
|
||||
column: str,
|
||||
fallback_sql: str,
|
||||
pg_type: str = "varchar",
|
||||
output_alias: str | None = None,
|
||||
) -> str:
|
||||
expression = cls.raw_optional_column(columns, alias=alias, column=column, pg_type=pg_type)
|
||||
return f"COALESCE({expression}, {fallback_sql}) AS {output_alias or column}"
|
||||
Reference in New Issue
Block a user