*vmr писал(а): права назначаются обьекту, а не обьект выбирает права (что обычно захардкожено)Права — это свойства обьекта, а не наоборот (когда для каждой роли есть жестко прописанные обьекты)
Вы не поняли описанной идеи. Грубо говоря, в моем примере, роль - является объектом права. И чтобы дать/забрать право используются методы grant/revoke. "Хадкодом" определяется только список ролей (объектов права) и что, что они позволяют. А то, кому дается право, определяется в рантайме.
Пример. Допустим мы делаем какой-то крупный информационный сайт. Допустим нужно сделать модуль новостей. Нужно предоставить возможность открывать доступ оператором на модерирование новостей (добавление, правка, удаление). Вводиться роль (или специальная группа, если хотите) news_editor, которая дает право модерирования новостей (ведь бессмыслено развать права на каждую отдельно взятую новость). Если пользователь состоит в этой группе, то ему разрешается доступ. В коде, мы можем проверить с помощью check_access, обладает ли пользовать требуемой ролью (состоит ли в этой спец. группе).
Для админа отображается список ролей/групп (название, описание роли, кто обладает ролью). Он выбирает роль и смотрит список пользователей, которые обладают этой ролью. Он может добавлять в этот список пользователей (и они получат право) и удалять (тогда они теряют право). С другой стороны мы можем посмотреть, какими ролями обладает конкретный пользователь: посмотреть/изменить список ролей.
Например, Васе Пупкину, нужно дать право модерировать новости. Админ, находит пользователя, открывает его список ролей и добавляет туда news_editor.
*vmr писал(а):Если проверять на права только форму будет достаточно, то необходимость в дальнейших проверках отпадает (поставил permissions на папку, и все лежащие в ней файлы вдруг, словно сговорились, стали требовать аутентификацию)
Если все данные храняться в файлах, если используются системные аккаунты, то можно и так.
А если наши данные храняться в базе? Если у нас виртуальные пользователи, никак не связанные с системными аккаунтами? Тогда расстановка прав на папки просто не применима.
*vmr писал(а):ACL же позволяет кодировать в стиле: "а есть ли у текущего пользователя право на открытие этой формы".
Ну и в нашем случае тоже стоит точно такой же вопрос:
if check_access(Form1{.RequireRole}, CurrentUser) then ... else ShowMessage('Фиг.');
*vmr писал(а):Например твоя функция check_acces требует указания роли для проверки. А это означает что роль ты пишеш прямо в коде: вот эта вот фомочка будет требовать такую роль, а вот та сякую. Это хардкод.
Для особо ленивых можно например, вместо имени роли использовать имя класса формы:
if check_access(Form1.ClassName, CurrentUser) then ... else ShowMessage('Фиг');
Можно вообще использовать наследование форм, определить класс TSecuredForm, потомком от TForm, определить там пару методов
- Код: Выделить всё
procedure TSecuredForm.CheckAccess(User);
begin
Result := check_access(Self.ClassName, User);
end;
procedure TSecuredForm.RequireAccess(User);
begin
if not check_access(Self.ClassName, User) then
raise EAccessDeny.Create('У вас нет права на работу с формой ' + Self.Caption);
end;
function TSecuredForm.Execute: Integer;
begin
RequireAccess( GetCurrentUser );
Result := ShowModal;
end;
Но это уже вопросы реализации, которые могут отличаться для разных задач. А приницип один - определить связи между объектами права и субъектами. В случае описываемого вашего подхода, когда данные храняться в файлах и вы разраничиваете доступ настройками ACL, вы просто делегируете эту функцию операционной системе.
Что есть ACL - Access Control List? Фактически список доступа. Для каждого объекта права заводиться список "записей", каждая из которых говорит: "вот такому-то пользователю нужно дать право на такое-то действие над этим объектом". В случае использования ролей, такой список строиться простым запросом:
SELECT * FROM grants, roles, users WHERE grants.role_id = roles.role_id AND grants.user_id = users.user_id
AND roles.name = $roleName;
Этот запрос выдает список записей, который ровно тоже самое: "вот такому-то пользователю нужно дать право на такое-то действие над этим объектом"
Если нужно различать действия (например, read / write), то в таблицу grants можно добавить поле mask, которое будет задавать битовую маску - установлен в 1 - действие разрешается, сброшен в 0 - запрещается.
PS:
1. Если слово "роль" вас смущает, поменяйте его на слово "объект", "группа" и т.п.
2. Хм.. если есть "хардкод", то наверное должен быть и "софткод"...
Осюда вопросы: чем отличается хардкод, от софткода? чем мерять твердость кода? Эта мера непрерываная или дискретная?