Entity Framework: справка по реляционной модели для разрешений, пользователей и т. Д. - PullRequest
1 голос
/ 14 августа 2011

Кто-нибудь может помочь?

Я хочу создать хорошую реляционную модель для управления разрешениями.

В настоящее время у меня есть таблица «Пользователи» и другие таблицы, например «Клиенты, поставщики».

Пользователю необходимы разрешения на просмотр, редактирование, создание в любом из клиентов, поставщиков.

Я буду использовать эти таблицы в EF, чтобы решить, какой доступ имеет пользователь и какая погода отображать форму или нет и т. Д.

Моя оригинальная модель выглядит следующим образом, хотя я думаю, что это неправильно, поскольку ничего не говорится о разрешениях.

Пользователи UsersCustomers (содержит связь между пользователями и клиентами) UsersSuppliers (содержит отношение между пользователями и поставщиками) Клиенты (таблица клиентов) Поставщики (таблица поставщиков).

Хотя это работает, то есть, например, оно связывает пользователя с клиентом ... Это просто кажется неправильным.

Я думал о том, чтобы поместить промежуточную таблицу, называемую Permissions, которая будет иметь Id и UserId, который связывал бы пользовательскую таблицу. Тогда я мог бы связать разрешения для таблицы, как

PermissionsCustomers (вместо UsersCustomers), которые будут содержать отношение между персиденцией и клиентами.

Я думаю, что это не совсем оптимальный дизайн. Как только эта схема будет правильной, будет также отсутствовать таблица для назначения типа разрешения, которое пользователь имеет для Клиента, т.е. редактирование, создание или только просмотр и т. Д.

Я хотел бы услышать некоторые отзывы или пример сильной модели, которая существует, которая функционирует следующим образом.

Что касается клиентов, поставщиков, это всего лишь 2 примера, будет намного больше таблиц, таких как deliveryLocation, accountsLedger и т. Д.

Было бы замечательно, если бы я мог сделать запрос, который гласил бы: «Показать мне все разрешения, которые есть у пользователя X», в настоящее время с моими настройками мне придется запрашивать каждую промежуточную таблицу отдельно.

Я бы использовал это через ORM-подобную структуру сущностей.

Немного потерян со структурой реляционной модели.

Заранее спасибо.

1 Ответ

2 голосов
/ 14 августа 2011

Учитывая, что у вас будет очень небольшое количество клиентов и поставщиков (всего 20), вам не понадобится очень сложная система.

В подобных ситуациях я сделал настройку таблицы разрешений со структурой, подобной этой:

  • UserId (идентификатор пользователя)
  • RoleId (идентификатор, который связывается с таблицей ролей, с такими вещами, как «Изменить клиента», «Удалить поставщика», просмотр клиента и т.д.)
  • ObjectId (это будет идентификатор, который идентифицирует все объект, который вы хотите защитить, поэтому либо идентификатор поставщика, либо идентификатор клиента.)

Таблица ролей будет иметь:

  • Id (уникальный идентификатор относится к RoleId в таблице разрешений)
  • Имя (уникальное имя роли, т. Е. «Редактировать клиента»)

Затем каждый пользовательский объект связывается с таблицей разрешений, каждый пользователь имеет несколько разрешений. Когда пользователь входит в систему, я обычно загружаю все его разрешения в список в памяти, чтобы у него был список разрешений. Список разрешений будет иметь только ObjectId, а также RoleName и / или RoleId (я склонен использовать rolename для облегчения чтения кода, как вы можете видеть ниже в примере)

protected bool HasPermission(long ObjectId, string RoleName)
{

//Users in the Administrator role have access to everything in the system.
if (this.IsAdministrator) {
    HasPermission = true;
    return;
}

foreach (Permission P in Permissions) {
    if (P.ObjectID == ObjectID & P.RoleName == Role) {
        HasPermission = true;
        return;
    }
}
return false;

}

тогда, если я хочу знать, есть ли у пользователя разрешение на что-то, я бы сделал это:

if (myUser.HasPermission(CustomerId, "Edit Customer") {
  //allow the user to edit the customer
else
  //allow the user to only view the customer (for example)

или

    if (myUser.HasPermission(SupplierId, "Print Supplier") {
  //allow the user to print the record
else
  //give user a warning

Ключ в том, что каждая «роль» должна быть уникальной, у вас не может быть общей роли «Редактировать», потому что если у вас есть клиент и поставщик с одинаковым идентификатором, и вы хотите увидеть, если Пользователь имеет разрешение на «Редактирование», вы можете получить неверный результат. Поэтому имейте роль «Редактировать клиента» и другую роль «Редактировать поставщика».

Это решение не очень хорошо масштабировалось бы imo, но для базы данных с десятками записей, которые необходимо защитить, оно работает просто отлично и просто в реализации и обслуживании. Он также не настроен по-настоящему реляционным образом, то есть ObjectId в таблице разрешений не связан ни с таблицей поставщиков, ни с клиентами.

(Кроме того, в этом сценарии мой пользовательский объект знает, является ли он администратором или нет, администраторы не нуждаются в настройке разрешений, имеют доступ ко всему, поэтому поиск разрешений не требуется - экономит несколько наносекунд времени)

...