Краткий ответ - держите ваши разрешения отдельно от ваших данных.
Длинный ответ - вам следует использовать упрощенную таблицу разрешений, в которой хранятся отношения между группами, пользователями и элементами. Вам не следует использовать какой-либо ключ сортировки, связанный с разрешениями, и если у вас нет особых причин разрешать элементы с одинаковым идентификатором (например, хранить версионную историю элементов), вы, вероятно, вообще не должны использовать какой-либо ключ сортировки. для ваших вещей.
Таблица разрешений имеет два атрибута, которые я назову entity
(ключ хеша) и relationship
(ключ сортировки). (Вы можете использовать любые имена, какие захотите.) Эта таблица также имеет GSI, где relationship
- это ключ хеша, а entity
- это ключ сортировки. Поскольку строки в этой таблице маленькие, запрос очень недорогой. Вы можете прочитать> 100 строк и использовать только 1 RCU.
Атрибут entity
- это просто идентификатор пользователя или группы. Атрибут relationship
является составной частью типа отношения и другого идентификатора. (Вы можете использовать все, что вы хотите для идентификаторов, но я буду использовать числа для всех моих примеров.)
Вот некоторые примеры данных:
entity | relationship
===========================================
user-0001 | member-of:group-1000
user-0001 | member-of:group-3000
user-0002 | can-access:item-1111
user-0002 | member-of:group-2000
group-1000 | can-access:item-1111
group-2000 | can-access:item-2222
Чтобы узнать, есть ли у пользователя разрешение на доступ к данному элементу, вам нужно выполнить два запроса. Запросите таблицу разрешений для userId и запросите GSI для отношения itemId «can-access». Затем сравните результаты двух запросов, чтобы увидеть, есть ли какие-либо общие группы (или если у пользователя есть разрешение на прямой доступ к элементу).
Например, если вы хотите узнать, может ли user-0001
получить доступ к item-1111
, вы запросите user-0001
и вернетесь [member-of:group-1000, member-of:group-3000]
. Затем вы запросите GSI для can-access:item-1111
и вернетесь [user-0002, group-1000]
. Сравнивая два результата, вы увидите, что user-0001
может получить доступ к item-1111
через group-1000
.
Дополнительным преимуществом этой модели является то, что она достаточно гибкая, чтобы обрабатывать другие варианты использования разрешений. Вот пример того, как эти данные могут выглядеть:
entity | relationship
===========================================
user-0001 | admin-of:group-1000
user-0001 | member-of:group-1000
user-0002 | member-of:group-2000
user-0002 | owner-of:item-1111
group-1000 | can-write:item-1111
group-1000 | can-read:item-1111
group-2000 | can-read:item-1111
В этом примере у нас также есть пользователи, которые могут администрировать группы, мы разделили права на чтение и запись для элементов и можем определить пользователя или группу как владельца элемента (что, возможно, означает, что они могут изменить, кто имеет разрешение на чтение или запись элемента).
Одно предупреждение: предполагается, что группы не могут быть вложенными. Если группы могут быть вложенными, вам потребуется больше запросов для обхода иерархии вложенных групп, и вам может быть лучше использовать AWS Neptune или другую базу данных для хранения ваших разрешений.