Шаблоны проектирования для включения элементов пользовательского интерфейса на основе прав пользователя?

У нас есть веб-приложение, а его интерфейс реализован с помощью GWT/GXT. Пользователи могут принадлежать к различным группам, и эти группы могут иметь различные разрешения. Разрешения довольно мелкие, например comment_create, comment_edit, comment_delete и comment_read.

Каким будет лучший способ включить или отключить элементы управления пользовательским интерфейсом на основе прав пользователя? У нас есть метод утилиты, который возвращает логическое значение с заданным пользователем и именем разрешения. Но в данный момент каждый элемент управления обернут внутри аргумента if, и это делает бит кода грязным.

Ответ 1

У меня была та же проблема, вот мое решение.

Каждый компонент пользовательского интерфейса имеет состояние включения/выключения (видимое/скрытое, включенное/отключенное, редактируемое /readonly ), и состояние может быть связано с одним или несколькими разрешениями. Например, кнопка редактирования может быть включена, если у пользователя есть разрешение EDIT или в противном случае отключено.

Я создал класс связующего, который связывает компонент пользовательского интерфейса с разрешением. Связующее знает текущие разрешения пользователя (все разрешения) через шину событий, где набор разрешений отправляется с использованием события. Каждый раз, когда событие принимается, связующее проверяет наличие или отсутствие разрешения (альтернатива использует логическое значение для каждого разрешения) и применяет изменения к компоненту (например, включение или отключение его).

Шина событий - это единственное соединение между всеми компонентами пользовательского интерфейса.

Используя Gin и некоторый вспомогательный класс, у меня получилось что-то вроде этого для кода привязки:

FeatureBinder.bind(editButton, EDIT_PERMISSION);

Ответ 2

Я не уверен, как вы реализуете это в GWT/GXT, но старый способ MFC для включения меню может быть местом для начала.

У этого было отдельное сообщение ON_UPDATE_COMMAND_UI, в котором вы указали имя меню и имя метода. Этот метод будет вызываться, и вы можете включить или отключить этот параметр меню в зависимости от вашей логики. В вашем случае это будет основано на идентификаторе пользователя. Это зависит от каждого элемента меню и, следовательно, является настолько мелким, насколько вам нужно.

Ответ 4

Безопасность Acris

Посмотрите Обеспечение безопасности клиентов GWT с помощью Acris: использование аннотаций для определения разрешений на элементы управления декларативным способом. Из статьи

public class CustomerPanel extends SecuredComposite {
...
    @Secured(Grants.SECURITY_MANAGEMENT)
    protected TextBox securityID;
...
}

Несмотря на то, что этот подход выглядит очень многообещающим, проект не кажется активным. Страница downloads имеет последнюю версию в мае 2012 года, всего несколько сотен загрузок каждой версии (хотя это не учитывается как использование зависимость от Maven). Последним из acris forum является сообщение с июня 2013 года при переходе на Git.

Кроме того, последняя опубликованная версия совместима с GWT 2.3, а текущая разработка сосредоточена на GWT 2.5.

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

Даже если вы не используете acris, подход - это поиск работы. (Это тот же подход, что упоминается в Авторизация на основе атрибутов, связанная в комментарии к OP.) Глядя на источник, он выглядит как метапрограммирование с помощью generator и SourceWriter.

Ответ 5

Вы можете использовать setEnabled(boolean) в ограниченных виджетах и ​​сохранить 2 строки кода по сравнению с версией if:

Button editButton = new Button();
editButton.setText("Edit");
editButton.setEnabled(SecurityManager.userHasPermission(currentUser, Permissions.DOCUMENT_EDIT));
toolbar.add(editButton);

Button deleteButton = new Button();
deleteButton.setText("Delete");
deleteButton.setEnabled(SecurityManager.userHasPermission(currentUser, Permissions.DOCUMENT_DELETE));
toolbar.add(deleteButton);