fix: finalize unified schema and correct permission snapshot mapping
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
from sqlalchemy import and_, delete, or_, select
|
from sqlalchemy import and_, delete, literal, or_, select
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.models.company import Company
|
from app.models.company import Company
|
||||||
@@ -16,6 +16,7 @@ class PermissionsRepository:
|
|||||||
def list_by_user(self, user_id: str, authentik_sub: str) -> list[tuple[str, str, str | None, str, str]]:
|
def list_by_user(self, user_id: str, authentik_sub: str) -> list[tuple[str, str, str | None, str, str]]:
|
||||||
direct_stmt = (
|
direct_stmt = (
|
||||||
select(
|
select(
|
||||||
|
literal("direct"),
|
||||||
UserScopePermission.scope_type,
|
UserScopePermission.scope_type,
|
||||||
Company.company_key,
|
Company.company_key,
|
||||||
Site.site_key,
|
Site.site_key,
|
||||||
@@ -30,6 +31,7 @@ class PermissionsRepository:
|
|||||||
)
|
)
|
||||||
group_stmt = (
|
group_stmt = (
|
||||||
select(
|
select(
|
||||||
|
literal("group"),
|
||||||
PermissionGroupPermission.scope_type,
|
PermissionGroupPermission.scope_type,
|
||||||
PermissionGroupPermission.scope_id,
|
PermissionGroupPermission.scope_id,
|
||||||
PermissionGroupPermission.system,
|
PermissionGroupPermission.system,
|
||||||
@@ -44,10 +46,11 @@ class PermissionsRepository:
|
|||||||
result: list[tuple[str, str, str | None, str, str]] = []
|
result: list[tuple[str, str, str | None, str, str]] = []
|
||||||
dedup = set()
|
dedup = set()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
if len(row) == 5:
|
source = row[0]
|
||||||
scope_type, scope_id, system_key, module_key, action = row
|
if source == "group":
|
||||||
|
_, scope_type, scope_id, system_key, module_key, action = row
|
||||||
else:
|
else:
|
||||||
scope_type, company_key, site_key, module_key, action = row
|
_, scope_type, company_key, site_key, module_key, action = row
|
||||||
scope_id = company_key if scope_type == "company" else site_key
|
scope_id = company_key if scope_type == "company" else site_key
|
||||||
system_key = module_key.split(".", 1)[0] if isinstance(module_key, str) and "." in module_key else None
|
system_key = module_key.split(".", 1)[0] if isinstance(module_key, str) and "." in module_key else None
|
||||||
key = (scope_type, scope_id or "", system_key, module_key, action)
|
key = (scope_type, scope_id or "", system_key, module_key, action)
|
||||||
|
|||||||
@@ -2,30 +2,13 @@ BEGIN;
|
|||||||
|
|
||||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'record_status') THEN
|
|
||||||
CREATE TYPE record_status AS ENUM ('active','inactive');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'client_status') THEN
|
|
||||||
CREATE TYPE client_status AS ENUM ('active','inactive');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'scope_type') THEN
|
|
||||||
CREATE TYPE scope_type AS ENUM ('company','site');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'permission_action') THEN
|
|
||||||
CREATE TYPE permission_action AS ENUM ('view','create','update','delete','manage');
|
|
||||||
END IF;
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
authentik_sub TEXT NOT NULL UNIQUE,
|
authentik_sub TEXT NOT NULL UNIQUE,
|
||||||
authentik_user_id INTEGER,
|
authentik_user_id INTEGER,
|
||||||
email TEXT UNIQUE,
|
email TEXT UNIQUE,
|
||||||
display_name TEXT,
|
display_name TEXT,
|
||||||
status record_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
@@ -43,7 +26,7 @@ CREATE TABLE IF NOT EXISTS companies (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
company_key TEXT NOT NULL UNIQUE,
|
company_key TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
status record_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
@@ -53,7 +36,7 @@ CREATE TABLE IF NOT EXISTS sites (
|
|||||||
site_key TEXT NOT NULL UNIQUE,
|
site_key TEXT NOT NULL UNIQUE,
|
||||||
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
status record_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
@@ -62,7 +45,7 @@ CREATE TABLE IF NOT EXISTS systems (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
system_key TEXT NOT NULL UNIQUE,
|
system_key TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
status record_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
@@ -71,7 +54,7 @@ CREATE TABLE IF NOT EXISTS modules (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
module_key TEXT NOT NULL UNIQUE,
|
module_key TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
status record_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
@@ -93,8 +76,8 @@ CREATE TABLE IF NOT EXISTS user_scope_permissions (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
module_id UUID NOT NULL REFERENCES modules(id) ON DELETE CASCADE,
|
module_id UUID NOT NULL REFERENCES modules(id) ON DELETE CASCADE,
|
||||||
action permission_action NOT NULL,
|
action VARCHAR(32) NOT NULL,
|
||||||
scope_type scope_type NOT NULL,
|
scope_type VARCHAR(16) NOT NULL,
|
||||||
company_id UUID REFERENCES companies(id) ON DELETE CASCADE,
|
company_id UUID REFERENCES companies(id) ON DELETE CASCADE,
|
||||||
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
|
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
@@ -113,7 +96,7 @@ CREATE TABLE IF NOT EXISTS permission_groups (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
group_key TEXT NOT NULL UNIQUE,
|
group_key TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
status record_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
@@ -142,7 +125,7 @@ CREATE TABLE IF NOT EXISTS api_clients (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
client_key TEXT NOT NULL UNIQUE,
|
client_key TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
status client_status NOT NULL DEFAULT 'active',
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||||
api_key_hash TEXT NOT NULL,
|
api_key_hash TEXT NOT NULL,
|
||||||
allowed_origins JSONB NOT NULL DEFAULT '[]'::jsonb,
|
allowed_origins JSONB NOT NULL DEFAULT '[]'::jsonb,
|
||||||
allowed_ips JSONB NOT NULL DEFAULT '[]'::jsonb,
|
allowed_ips JSONB NOT NULL DEFAULT '[]'::jsonb,
|
||||||
|
|||||||
27
scripts/migrate_enum_to_text.sql
Normal file
27
scripts/migrate_enum_to_text.sql
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- users / master tables
|
||||||
|
ALTER TABLE users ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
ALTER TABLE companies ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
ALTER TABLE sites ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
ALTER TABLE systems ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
ALTER TABLE modules ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
ALTER TABLE permission_groups ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
|
||||||
|
-- api_clients
|
||||||
|
ALTER TABLE api_clients ALTER COLUMN status TYPE VARCHAR(16) USING status::text;
|
||||||
|
|
||||||
|
-- user scoped permissions
|
||||||
|
ALTER TABLE user_scope_permissions ALTER COLUMN action TYPE VARCHAR(32) USING action::text;
|
||||||
|
ALTER TABLE user_scope_permissions ALTER COLUMN scope_type TYPE VARCHAR(16) USING scope_type::text;
|
||||||
|
|
||||||
|
-- keep check constraint compatible with varchar
|
||||||
|
ALTER TABLE user_scope_permissions DROP CONSTRAINT IF EXISTS user_scope_permissions_check;
|
||||||
|
ALTER TABLE user_scope_permissions
|
||||||
|
ADD CONSTRAINT user_scope_permissions_check
|
||||||
|
CHECK (
|
||||||
|
((scope_type = 'company' AND company_id IS NOT NULL AND site_id IS NULL)
|
||||||
|
OR (scope_type = 'site' AND site_id IS NOT NULL AND company_id IS NULL))
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Reference in New Issue
Block a user