我正在尝试在 Postgres 11.5 中构建用户权限结构。
基本思想是一个用户可以属于多个组,一个组可以拥有多个应用程序的权限。用户的权限(如果有)将覆盖在组级别设置的任何权限。
用户和用户组级别的权限将存储为 json 对象,我想将这些对象与用户权限合并在一起,如果有任何重叠,则覆盖用户组权限。
示例: Brendan、James 和其他 n 个用户在完全相同的用户组中,但 James 应该无法访问 app2。
设置:
CREATE TABLE public.users
(
uid character varying COLLATE pg_catalog."default" NOT NULL,
ugid character varying[],
permissions json,
CONSTRAINT users_pkey PRIMARY KEY (uid)
);
INSERT INTO public.users VALUES
('brendan','{default,gisteam}','{}'),
('james','{default,gisteam}','{"app2":{"enabled":false}}');
CREATE TABLE public.usergroups
(
ugid character varying COLLATE pg_catalog."default" NOT NULL,
permissions json,
CONSTRAINT usergroups_pkey PRIMARY KEY (ugid)
);
INSERT INTO public.usergroups VALUES
('default','{"app1":{"enabled":true}}'),
('gisteam','{"app2":{"enabled":true},"app3":{"enabled":true}}');
询问:
SELECT uid, json_agg(permissions)
FROM (
SELECT
u.uid,
ug.permissions,
'group' AS type
FROM public.users u
JOIN public.usergroups ug
ON ug.ugid = ANY(u.ugid)
UNION ALL
SELECT
uid,
permissions,
'user' AS type
FROM public.users u2
) a
GROUP BY uid;
实际查询结果:
+---------+----------------------------------------------------------------------------------------------------------+
| uid | final_permissions |
+---------+----------------------------------------------------------------------------------------------------------+
| brendan | [{"app1":{"enabled":true}},{"app2":{"enabled":true},"app3":{"enabled":true}},{}] |
| james | [{"app1":{"enabled":true}},{"app2":{"enabled":true},"app3":{"enabled":true}},{"app2":{"enabled":false}}] |
+---------+----------------------------------------------------------------------------------------------------------+
这种工作,但我希望对象被展平和键合并。
期望的结果:
+---------+---------------------------------------------------------------------------+
| uid | final_permissions |
+---------+---------------------------------------------------------------------------+
| brendan | {"app1":{"enabled":true},"app2":{"enabled":true},"app3":{"enabled":true}} |
| james | {"app1":{"enabled":true},"app2":{"enabled":false},"app3":{"enabled":true}}|
+---------+---------------------------------------------------------------------------+
DB小提琴:https ://www.db-fiddle.com/f/9kb1v1T82YVxWERxnWLThL/3
其他信息: 为每个应用程序在用户组级别设置的实际权限对象将比示例中更复杂,例如启用功能 A,禁用功能 B 等,实际上将来会添加更多应用程序,所以我不想如果可能,硬编码对特定应用程序或功能的任何引用。
我想从技术上讲,如果更容易的话,所需的输出将是单个用户的权限对象,因此可以GROUP BY uid将WHERE uid = 'x'
问题/问题: 如何修改查询以生成扁平/合并权限 json 对象?
编辑:固定的json