# Утилита прав доступа

Утилита util-permitions предназначена для определения прав доступа пользователей к информации системы при использовании бандлов (модулей *.jar). Т.е. пользователь стартует интерфейсный бандл, который предоставляет ему определенную информацию. Согласно прав доступа пользователя, бандл может либо только показать информацию для просмотра (guest), либо предоставить все права (granted) для внесение любых изменений (добавление, редактирование, удаление). Утилита знает, кто авторизовался в системе. Поэтому, при старте пользователем какого-либо бандла, чтобы предоставить ему соответствующие права и информацию, утилита должна получить информацию о самом бандле. Таким образом, бандл должен взаимодействовать с утилитой в разрезе пользователя.

Примечание. Определение разрешений пользователя на определенную информацию системы представлено на странице Права доступа. Здесь описывается реализация получения пользователем/бандлом предоставленных ему прав доступа.

И так, утилита знает пользователя и ей необходимо получить информацию о стартующем бандле. Но бандлы ничего не знают о сервисах других модулей. Поэтому для межмодульного взаимодействия используется механизм Публикация/Подписка (publish/subscribe). Применение сервиса Публикация/Подписка в динамической модульной системе на основе OSGi подробно описано на странице Механизм publish/subscribe в OSGi. Здесь приводится реализация сервиса publish/subscribe для получения прав доступа бандлов. В основном эта информация будет интересна и полезна разработчикам ПО, которые будут использовать утилиту при разработке своих бандлов.

Поскольку util-permitions использует сервис publish/subscribe, то она подписывается на предопределенное сообщение 'jabricks/Permition/Request' (запрос прав доступа). После того, как утилита получит от бандла такой запрос, включающий SymbolicName (GroupId, ArtifactId) бандла, она отправляет ответ 'jabricks/Permition/Response' (права доступа), в который включает параметры получателя (GroupId, ArtifactId) и права доступа [forbidden, guest, granted].

Чтобы получить права доступа бандл должен отправить (publish) сообщение 'jabricks/Permition/Request', в который необходимо включить SymbolicName (GroupId, ArtifactId). Для получения ответа бандл подписывается (subscribe) на сообщение 'jabricks/Permition/Response'. Получение сообщений в сервисе Публикация/Подписка касается всех подписавшихся на них бандлов. Т.е. ответ 'jabricks/Permition/Response' получают все бандлы, которые на него подписаны. Поэтому, после получения ответа бандлу необходимо отключиться от подписки, чтобы не обрабатывать сообщения, адресованные другим бандлам.

Чтобы бандл получил разрешение согласно права доступа пользователя должен быть включен в общую систему безопасности; в противном случае на запрос прав доступа утилита вернет ответ 'forbidden' (запрещен).

Примечание.
1. Ниже приводится описание с учетом того, что классы бандла в своей структуре наследует свойства классов ca-common.
2. Все сообщения, касающиеся получения прав доступа, протоколируются системой.
3. Наименования активатора бандла TemplateActivator и панели формирования интерфейса TemplPanel выбраны условно; в реальном бандле они могут отличаться.

## Активатор

В листинге приводится код активатора TemplateActivator, касающееся получения прав доступа. Активатор бандла наследует свойства родительского класса CommonActivator, в котором определен параметр service_permition типа ServiceRegistration<?>. В методе start создается «подписчик» на сообщение 'jabricks/Permition/Response'. В методе stop сервис service_permition отключается от подписки и обнуляется. Конечно же, как сказано выше, данное действие выполнено раньше, после получения ответа от утилиты; этот код приводится для тех, кто будет создавать свой сервис и не будет использовать ca-common.

В листинге приводятся еще методы createPermitionSubscriber (создание подписчика) и getPermition (получение ответа от утилиты), касающиеся подписки; они представлены ниже.

    public class TemplateActivator extends CommonActivator
    {
        //-------------------------------------------------------------------------
        @Override
        public void start(final BundleContext context) throws Exception
        {
            super.start(context);
            // получение контейнера от фреймворка
            sendContainerRequestEvent();
            // подписка на получение Permition (прав доступа)
            createPermitionSubscriber();
        }
        //-------------------------------------------------------------------------
        @Override
        public void stop(BundleContext context) throws Exception
        {
            super.stop(context);
            try {
                if (service_permition != null) {
                    service_permition.unregister();
                    service_permition = null;
                }
            } catch (Exception e) {}
        }
        //-------------------------------------------------------------------------
        private void createPermitionSubscriber()
        {
            // TODO
        }
        //-------------------------------------------------------------------------
        @Override
        public void getPermition(final String permition)
        {
            // TODO
        }
    }

## Подписка на сообщение 'jabricks/Permition/Response'

Подписка на событие 'jabricks/Permition/Response' выполняется в активаторе бандла (BundleActivator). В листинге приводится метод создания подписчика createPermitionSubscriber. В методе создается объект подписки PermitionSubscriber, которому необходимо в качестве параметра передать активатор. После этого, создается сервис service_permition (ServiceRegistration<?>), определенный в родительском классе.

    private void createPermitionSubscriber()
    {
        Dictionary<String, Object> dict = new Hashtable<String, Object>();
        dict.put(EventConstants.EVENT_TOPIC, "jabricks/Permition/Response");
        PermitionSubscriber subscriber = new PermitionSubscriber(this);
        service_permition = context.registerService(EventHandler.class.getName(),
                                                    subscriber, dict);
    }

Примечание. Класс подписки PermitionSubscriber определен в родительском бандле ca_common. Получаемый им в качестве параметра активатор (this) используется для анализа сообщения утилиты; определения получателя (SymbolicName) и прав доступа.

## Получение ответа 'jabricks/Permition/Response'

Подписчик PermitionSubscriber получает от утилиты ответ 'jabricks/Permition/Response' на запрос прав доступа, анализирует его на предмет получателя (SymbolicName) и после этого вызывает метод активатора getPermition (permition), которому передаются права доступа permition [forbidden, guest, granted]. В методе вызывается одноименная процедура getPermition панели (TemplPanel) формирования интерфейса бандла для реализации прав доступа пользователя. После этого, вызывается одноименный родительский метод, в котором бандл отключается от подписки на сообщения прав доступа; т.е. выполняется код, описанный выше в методе stop активатора.

    @Override
    public void getPermition(final String permition)
    {
        // Вызов метода с определением прав доступа
        ((TemplPanel)jpanel).getPermition(permition);
        // Отмена подписки на сообщение 'jabricks/Permition/Response'
        super.getPermition(permition);
    }

На заметку. По умолчанию, если бандл не включен в общую систему безопасности, то при его запросе прав доступа утилита util-permitions возвращает значение 'forbidden' (доступ закрыт).

## Отправка запроса 'jabricks/Permition/Request'

Отправку запроса на получения прав доступа пользователя к информации системы необходимо выполнить после формирования бандлом интерфейса, чтобы избежать коллизий, которые могут возникнуть при одновременном формировании интерфейса и обработкой полученных прав доступа. Поэтому, после того, как TemplPanel завершит построение интерфейса можно вызвать метод активатора sendPermitionRequest, определенный в родительском активаторе (CommonActivator).

    /*
     * Отправка запроса 'jabricks/Permition/Request'
     */
    activator.sendPermitionRequest();