Услуга в NoDeny - это запись в таблице users_services, которая наделяет учетную запись клиента определенными характеристиками, например, разрешает доступ в интернет.
Поле tags хранит через запятую теги, указывающие на характер действия услуги, например, стандартные:
SELECT uid FROM users_services WHERE tags LIKE '%,inet,%';
На одну учетную запись можно активировать несколько разных услуг, например, клиент может заказать услугу «доступ в интернет 2 Мбит/сек», а через время «повышение скорости в 2 раза на 1 день». Эти услуги могут сосуществовать вместе, при этом первая будет иметь теги inet и speed, а вторая только speed.
В таблице users_services хранятся персональные для клиента свойства услуги, а общие в таблице services. Связь по полю service_id. В свою очередь в таблице services поле module ссылается на модуль, который обрабатывает данный тип услуг.
Персональные свойства услуги: время старта услуги, время окончания услуги, теги, id услуги, которая будет подключена после окончания текущей и id платежа, в котором происходит списание денег за услугу.
Услуга может быть «вечной», т.е. не иметь времени окончания, пока администратор не удалит ее. Услуга может быть бесплатной, т.е id платежа = 0. Услуга может не иметь автопродления, т.е. id услуги, которая будет установлена после завершения текущей, = 0.
Общие свойства услуги задаются в таблице services: имя, описание, группы клиентов, которые могут заказать услугу, стоимость. Также в закодированном виде содержатся параметры, специфичные для конкретного модуля услуг. Поскольку невозможно предусмотреть абсолютно все возможные свойства для всех услуг, специфичные параметры хранятся в виде perl-дампа в поле param.
Поле module ссылается на файл, обрабатывающего услугу. Пример такого файла:
#!/usr/bin/perl package services::test; use strict; sub description { return 'Услуга ничего не делает, просто снимает деньги'; } sub tunes { return []; } sub set_service { my(undef, %p) = @_; my $service_new = $p{service_new}; my $actions = $p{actions}; $actions->{pay} = { cash => 0 - $service_new->{price}, comment => $service_new->{description}, category=> 100, discount=> $service_new->{discount}, }; } 1;
Модуль услуги должен иметь такие подпрограммы:
В примере подпрограмма tunes возвращает ссылку на пустой массив, т.е дополнительных полей нет. set_service указывает сделать всего одно действие: платеж с категорией 100.
Подпрограмма set_service должна вернуть список действий, которые будут выполнены при подключении услуги:
$actions->{sql}{1} = [ 'INSERT INTO tbl SET field=?', 'xxx' ];
$actions->{pay} = { cash => 10, comment => 'Пополнение счета на 10$', category=> 2, };
$actions->{set_service} = { period => 60*60, mode => 0, tags => ',x-tag,', };
Здесь в массиве @$fields хранятся те специфичные параметры, о которых было сказано выше: срок действия, входящая и исходящая скорости. В описании полей ключ type указывает на тип поля по классу Data, например, 1 - целое положительное число. Значение value будет предложено администратору при создании услуги.
Метод set_service должен вернуть хеш - список действий, которые выполнит модуль services при подключении услуги. В примере:
Любое из действий необязательно, однако формат конкретных действий строг.