Я пытаюсь построить структуру полномочий пользователя в Postgres 11.5.
Основная идея c состоит в том, что пользователь может принадлежать к нескольким группам, а группа может иметь разрешения для нескольких приложений. Полномочия пользователя (если таковые имеются) будут переопределять любые разрешения, установленные на уровне группы.
Разрешения на уровне пользователя и группы пользователей будут храниться как json объекты, которые я хочу объединить вместе с разрешениями пользователя, перезаписывая разрешения группы пользователей, если они есть. любое перекрытие.
Пример: Брендан, Джеймс и другие пользователи входят в те же группы пользователей, но Джеймс не должен иметь доступа к 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 Fiddle: https://www.db-fiddle.com/f/9kb1v1T82YVxWERxnWLThL/3
Другая информация: Фактический объект разрешений, установленный на уровне группы пользователей для каждого приложения, будет более сложным, чем в примере, например, функция featureA включена, featureB отключена и т. Д. c и на самом деле в будущем будет добавлено больше приложений, поэтому я не не хочу жестко кодировать любые ссылки на определенные c приложения или функции, если это возможно.
Я полагаю, что технически, если проще, желаемый вывод будет объектом прав доступа только для одного пользователя, поэтому может заменить GROUP BY uid
с WHERE uid = 'x'
Вопрос / Проблема: Как я могу изменить запрос для создания плоского / объединенного разрешения json объект?
edit : фиксированный json