371 lines
13 KiB
Python
371 lines
13 KiB
Python
from routers.scim import helpers
|
|
|
|
from chalicelib.utils import pg_client
|
|
from scim2_models import Resource
|
|
|
|
|
|
def convert_provider_resource_to_client_resource(
|
|
provider_resource: dict,
|
|
) -> dict:
|
|
groups = []
|
|
if provider_resource["role_id"]:
|
|
groups.append(
|
|
{
|
|
"value": str(provider_resource["role_id"]),
|
|
"$ref": f"Groups/{provider_resource['role_id']}",
|
|
}
|
|
)
|
|
return {
|
|
"id": str(provider_resource["user_id"]),
|
|
"schemas": [
|
|
"urn:ietf:params:scim:schemas:core:2.0:User",
|
|
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
|
|
"urn:ietf:params:scim:schemas:extension:openreplay:2.0:User",
|
|
],
|
|
"meta": {
|
|
"resourceType": "User",
|
|
"created": provider_resource["created_at"].strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
"lastModified": provider_resource["updated_at"].strftime(
|
|
"%Y-%m-%dT%H:%M:%SZ"
|
|
),
|
|
},
|
|
"userName": provider_resource["email"],
|
|
"externalId": provider_resource["internal_id"],
|
|
"name": {
|
|
"formatted": provider_resource["name"],
|
|
},
|
|
"displayName": provider_resource["name"] or provider_resource["email"],
|
|
"active": provider_resource["deleted_at"] is None,
|
|
"groups": groups,
|
|
"urn:ietf:params:scim:schemas:extension:openreplay:2.0:User": {
|
|
"permissions": provider_resource.get("permissions") or [],
|
|
"projectKeys": provider_resource.get("project_keys") or [],
|
|
},
|
|
}
|
|
|
|
|
|
def query_resources(tenant_id: int) -> list[dict]:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
f"""
|
|
SELECT
|
|
users.*,
|
|
roles.permissions AS permissions,
|
|
COALESCE(
|
|
(
|
|
SELECT json_agg(projects.project_key)
|
|
FROM public.projects
|
|
LEFT JOIN public.roles_projects USING (project_id)
|
|
WHERE roles_projects.role_id = roles.role_id
|
|
),
|
|
'[]'
|
|
) AS project_keys
|
|
FROM public.users
|
|
LEFT JOIN public.roles ON roles.role_id = users.role_id
|
|
WHERE users.tenant_id = {tenant_id} AND users.deleted_at IS NULL
|
|
"""
|
|
)
|
|
items = cur.fetchall()
|
|
return [convert_provider_resource_to_client_resource(item) for item in items]
|
|
|
|
|
|
def get_resource(resource_id: str, tenant_id: int) -> dict | None:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
f"""
|
|
SELECT
|
|
users.*,
|
|
roles.permissions AS permissions,
|
|
COALESCE(
|
|
(
|
|
SELECT json_agg(projects.project_key)
|
|
FROM public.projects
|
|
LEFT JOIN public.roles_projects USING (project_id)
|
|
WHERE roles_projects.role_id = roles.role_id
|
|
),
|
|
'[]'
|
|
) AS project_keys
|
|
FROM public.users
|
|
LEFT JOIN public.roles ON roles.role_id = users.role_id
|
|
WHERE users.tenant_id = {tenant_id} AND users.deleted_at IS NULL AND users.user_id = {resource_id}
|
|
"""
|
|
)
|
|
item = cur.fetchone()
|
|
if item:
|
|
return convert_provider_resource_to_client_resource(item)
|
|
return None
|
|
|
|
|
|
def delete_resource(resource_id: str, tenatn_id: int) -> None:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
UPDATE public.users
|
|
SET
|
|
deleted_at = NULL,
|
|
updated_at = now()
|
|
WHERE users.user_id = %(user_id)s
|
|
""",
|
|
{"user_id": resource_id},
|
|
)
|
|
)
|
|
|
|
|
|
def search_existing(tenant_id: int, resource: Resource) -> dict | None:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
SELECT *
|
|
FROM public.users
|
|
WHERE email = %(email)s
|
|
""",
|
|
{"email": resource.user_name},
|
|
)
|
|
)
|
|
item = cur.fetchone()
|
|
if item:
|
|
return convert_provider_resource_to_client_resource(item)
|
|
return None
|
|
|
|
|
|
def restore_resource(tenant_id: int, resource: Resource) -> dict | None:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
SELECT role_id
|
|
FROM public.users
|
|
WHERE user_id = %(user_id)s
|
|
""",
|
|
{"user_id": resource.id},
|
|
)
|
|
)
|
|
item = cur.fetchone()
|
|
if item and item["role_id"] is not None:
|
|
_update_role_projects_and_permissions(
|
|
item["role_id"],
|
|
resource.OpenreplayUser.project_keys,
|
|
resource.OpenreplayUser.permissions,
|
|
cur,
|
|
)
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
WITH u AS (
|
|
UPDATE public.users
|
|
SET
|
|
tenant_id = %(tenant_id)s,
|
|
email = %(email)s,
|
|
name = %(name)s,
|
|
internal_id = %(internal_id)s,
|
|
deleted_at = NULL,
|
|
created_at = now(),
|
|
updated_at = now(),
|
|
api_key = default,
|
|
jwt_iat = NULL,
|
|
weekly_report = default
|
|
WHERE users.email = %(email)s
|
|
RETURNING *
|
|
)
|
|
SELECT
|
|
u.*,
|
|
roles.permissions AS permissions,
|
|
COALESCE(
|
|
(
|
|
SELECT json_agg(projects.project_key)
|
|
FROM public.projects
|
|
LEFT JOIN public.roles_projects USING (project_id)
|
|
WHERE roles_projects.role_id = roles.role_id
|
|
),
|
|
'[]'
|
|
) AS project_keys
|
|
FROM u
|
|
LEFT JOIN public.roles ON roles.role_id = u.role_id
|
|
""",
|
|
{
|
|
"tenant_id": tenant_id,
|
|
"email": resource.user_name,
|
|
"name": " ".join(
|
|
[
|
|
x
|
|
for x in [
|
|
resource.name.honorific_prefix,
|
|
resource.name.given_name,
|
|
resource.name.middle_name,
|
|
resource.name.family_name,
|
|
resource.name.honorific_suffix,
|
|
]
|
|
if x
|
|
]
|
|
)
|
|
if resource.name
|
|
else "",
|
|
"internal_id": resource.external_id,
|
|
},
|
|
)
|
|
)
|
|
item = cur.fetchone()
|
|
return convert_provider_resource_to_client_resource(item)
|
|
|
|
|
|
def create_resource(tenant_id: int, resource: Resource) -> dict:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
WITH u AS (
|
|
INSERT INTO public.users (
|
|
tenant_id,
|
|
email,
|
|
name,
|
|
internal_id
|
|
)
|
|
VALUES (
|
|
%(tenant_id)s,
|
|
%(email)s,
|
|
%(name)s,
|
|
%(internal_id)s
|
|
)
|
|
RETURNING *
|
|
)
|
|
SELECT *
|
|
FROM u
|
|
""",
|
|
{
|
|
"tenant_id": tenant_id,
|
|
"email": resource.user_name,
|
|
"name": " ".join(
|
|
[
|
|
x
|
|
for x in [
|
|
resource.name.honorific_prefix,
|
|
resource.name.given_name,
|
|
resource.name.middle_name,
|
|
resource.name.family_name,
|
|
resource.name.honorific_suffix,
|
|
]
|
|
if x
|
|
]
|
|
)
|
|
if resource.name
|
|
else "",
|
|
"internal_id": resource.external_id,
|
|
},
|
|
)
|
|
)
|
|
item = cur.fetchone()
|
|
return convert_provider_resource_to_client_resource(item)
|
|
|
|
|
|
def update_resource(tenant_id: int, resource: Resource) -> dict | None:
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
SELECT role_id
|
|
FROM public.users
|
|
WHERE user_id = %(user_id)s
|
|
""",
|
|
{"user_id": resource.id},
|
|
)
|
|
)
|
|
item = cur.fetchone()
|
|
if item and item["role_id"] is not None:
|
|
_update_role_projects_and_permissions(
|
|
item["role_id"],
|
|
resource.OpenreplayUser.project_keys,
|
|
resource.OpenreplayUser.permissions,
|
|
cur,
|
|
)
|
|
cur.execute(
|
|
cur.mogrify(
|
|
"""
|
|
WITH u AS (
|
|
UPDATE public.users
|
|
SET
|
|
tenant_id = %(tenant_id)s,
|
|
email = %(email)s,
|
|
name = %(name)s,
|
|
internal_id = %(internal_id)s,
|
|
updated_at = now()
|
|
WHERE user_id = %(user_id)s
|
|
RETURNING *
|
|
)
|
|
SELECT
|
|
u.*,
|
|
roles.permissions AS permissions,
|
|
COALESCE(
|
|
(
|
|
SELECT json_agg(projects.project_key)
|
|
FROM public.projects
|
|
LEFT JOIN public.roles_projects USING (project_id)
|
|
WHERE roles_projects.role_id = roles.role_id
|
|
),
|
|
'[]'
|
|
) AS project_keys
|
|
FROM u
|
|
LEFT JOIN public.roles ON roles.role_id = u.role_id
|
|
""",
|
|
{
|
|
"user_id": resource.id,
|
|
"tenant_id": tenant_id,
|
|
"email": resource.user_name,
|
|
"name": " ".join(
|
|
[
|
|
x
|
|
for x in [
|
|
resource.name.honorific_prefix,
|
|
resource.name.given_name,
|
|
resource.name.middle_name,
|
|
resource.name.family_name,
|
|
resource.name.honorific_suffix,
|
|
]
|
|
if x
|
|
]
|
|
)
|
|
if resource.name
|
|
else "",
|
|
"internal_id": resource.external_id,
|
|
},
|
|
)
|
|
)
|
|
item = cur.fetchone()
|
|
return convert_provider_resource_to_client_resource(item)
|
|
|
|
|
|
def _update_role_projects_and_permissions(
|
|
role_id: int,
|
|
project_keys: list[str] | None,
|
|
permissions: list[str] | None,
|
|
cur: pg_client.PostgresClient,
|
|
) -> None:
|
|
all_projects = "true" if not project_keys else "false"
|
|
project_key_clause = helpers.safe_mogrify_array(project_keys, "varchar", cur)
|
|
permission_clause = helpers.safe_mogrify_array(permissions, "varchar", cur)
|
|
cur.execute(
|
|
f"""
|
|
UPDATE public.roles
|
|
SET
|
|
updated_at = now(),
|
|
all_projects = {all_projects},
|
|
permissions = {permission_clause}
|
|
WHERE role_id = {role_id}
|
|
RETURNING *
|
|
"""
|
|
)
|
|
cur.execute(
|
|
f"""
|
|
DELETE FROM public.roles_projects
|
|
WHERE roles_projects.role_id = {role_id}
|
|
"""
|
|
)
|
|
cur.execute(
|
|
f"""
|
|
INSERT INTO public.roles_projects (role_id, project_id)
|
|
SELECT {role_id}, projects.project_id
|
|
FROM public.projects
|
|
WHERE projects.project_key = ANY({project_key_clause})
|
|
"""
|
|
)
|