Правильная ссылка на эту страницу
http://az-design.ru/Projects/AzBook/AZMicro/AZMicroB4.shtml

Назначение прав доступа объектам базы данных

       Теперь можно приступать к назначению прав доступа объектам базы данных. И тут нас ждет большая неприятность. Первое, что мы хотели защитить — журнал операций, но механизм Grant'ов позволяет защитить только ВСЮ таблицу, а нам нужно защитить отдельные записи. И тут на помощь приходят представления.

View (представления)
       — это таблицы, содержимое которых берется или выводится из других таблиц. Они используются в запросах и в предложениях DML так же, как и обычные таблицы, но они не содержат своих собственных данных. Представления подобны окнам, через которые просматривается информация, реально хранимая (содержащаяся) в базовых таблицах. В действительности же это запросы, выплняемые всякий раз, когда представление является объектом команды. В этот момент выходные данные запроса и становятся содержимым представления.

       Вот и построим представление для таблицы Journal, например для роли Manager:

CREATE VIEW JournalT3
AS Select JrnID, JrnDate, JrCredit, JrDebit, JrAmount, JrCount, JrLegend,
          DocID, PrtID, GdID, PrsID,
          USRGroup, USRLevel
   from   Journal
   where  USRGroup='T' and USRLevel>=3 and USRWhite='W';
Commit;

       И назначим ему права доступа для этой роли:

GRANT Select,Insert,Update on JournalT3 to Manager;
Commit;

       Таким образом, пользователь с ролью Manager может обратится только к представлению JournalT3, причем не имеет права удалять записи. А напрямую к таблице Journal могут обращаться только Администратор и Разработчик. И так нужно сделать для каждой роли, которую мы создали. При этом для каждой роли в представлении можно указывать не все поля базовой таблицы.
       Для приложения это тоже удобно, так как запрос в Журналу операций теперь строится следующим образом:

Select * from Journal+Role
 where  JrAmount=100.00

       Где Role — это значение USRRole из таблицы Users, для текущего пользователя.
       И теперь становятся понятны уровни доступа:
       — уровень 5 (самый младший) имеет право только вставлять записи. Действительно кассир только выбивает чеки и тем самым вставляет записи в БД. Никаких исправлений он делать не может. Для этого он должен обратиться к старшему товарищу.
       — уровень 4 позволяет вставлять и изменять записи. Но в нормальной системе все изменения протоколируются и всегда можно вычислить, кто и в каких целях изменил запись. Для того чтобы удалить запись он должен обратиться к старшему товарищу.
       — уровень 3 позволяет вставлять, изменять и удалять записи, но не позволяет видеть операции из "черной" бухгалтерии.
       — уровень 2 позволяет позволяет выполнять все операции в рамках своего подразделения.
       — уровень 1 (самый высокий) позволяет выполнять все операции в рамках всего предприятия.

       Но для того чтобы вся эта схема заработала нужно изменить таблицу Journal:

Create table Journal
  (JrnID        AZSID not null primary key,
   JrnDate      AZDate not null,
   JrCredit     CRDB references ChartAcc on update cascade,
   JrDebit      CRDB references ChartAcc on update cascade,
   JrAmount     AZMoney not null,
   JrCount      AZNumber default 0.0,
   JrLegend     AZLegend,
-- Аналитика
   DocID        AZSID0 references Documents on update cascade,
   PrtID        AZSID0 references Partners on update cascade,
   GdID         AZSID0 references Goods on update cascade,
   PrsID        AZSID0 references Persons on update cascade,
-- протоколирование и безопасность
   DtCreate     AZTStamp,
   UsrCreate    AZMID0 references USERS on UPDATE cascade,
   DtModify     AZTStamp,
   UsrModify    AZMID0 references USERS on UPDATE cascade,
   USRGroup     CHAR(1) character set WIN1251 default 'G',
   USRLevel     AZInt16 default 6,
   USRBLACK     CHAR(1) character set WIN1251 default 'B',
   USRWHITE     CHAR(1) character set WIN1251 default 'W');
Commit;

       Т.е. дополнительно к полям аналитики нужно добавить поля для протокола и прав доступа. А в триггеры добавить действия, по автоматическому заполнению этих полей:

Set term !! ;
Create trigger Journal_Insert for Journal
active before insert position 1
as
DECLARE VARIABLE USR SmallInt;
DECLARE VARIABLE Lev SmallInt;
DECLARE VARIABLE Grp CHAR(1) character set WIN1251;
Begin
   Select USERID,USRGroup,USRLevel from USERS where USERNAME=USER into :USR,:Grp,:Lev;
   new.USRGroup = Grp;
   new.USRLevel = Lev;
   new.UsrCreate = Usr;
   new.UsrModify = Usr;
end !!
Set term ; !!
Commit;

       При вставке записи определяем права текущего пользователя и записываем их в соответствующие поля — USRGroup, USRLevel, USRCreate, USRModify.

SET TERM ^ ;
Create trigger Journal_UPDATE for Journal
active before update position 0 as 
DECLARE VARIABLE USR SmallInt;
BEGIN
If ((old.JrnDate<>new.JrnDate) or (old.JrCredit<>new.JrCredit) or
    (old.JrDebit<>new.JrDebit) or (old.JrAmount<>new.JrAmount) or
    (old.DocID<>new.DocID)     or (old.PrtID<>new.PrtID) or
    (old.GdID<>new.GdID)       or (old.PrsID<>new.PrsID)) then
   begin
     Select USERID from USERS where USERNAME=USER into :USR;
     new.DtModify = Current_TIMESTAMP(3);
     new.USRModify = USR;
   end
END ^
SET TERM ; ^
Commit;

       Во-первых, протоколирование ведется только для определенных полей, которые указаны в условии IF ... THEN.
       Во-вторых, установка новых прав доступа в зависимости от прав пользователя, который изменяет данную запись, вынесена в приложение и оставляется на усмотрение самого пользователя. Следовательно в приложении должна быть соответствующая функция.
       Все бы было хорошо, но так как изменился механизм доступа к журналу операций, то необходимо изменить и процедуры "Оборотная ведомость", "Главная книга" и "Сводная ведомость", которые работают с журналом операций. К сожалению, в процедуру нельзя передать в качестве параметра имя таблицы (представления) и, следовательно, нужно создать копии этих процедур по тем же принципам, которые использовались для создания представлений "Журнала операций".
       Например, процедуры "Оборотная ведомость" теперь будут выглядеть так:

SET TERM ^ ;
CREATE PROCEDURE TurnSheetDocumentsS3 (
       DtBeg    DATE,     -- Дата начала периода
       DtEnd    DATE,     -- Дата конца периода
       DocID    Integer)  -- ID Документа
as
Declare variable Usr    SmallInt;
Begin
  Select USERID from USERS where USERNAME=USER into :USR;
  Delete from TurnSheet where UsrID=:USR;
  Insert into TurnSheet(UsrID,TRNAccnt,TCLs,MSldBeg,MSldEnd,NSldBeg,NSldEnd)
       Select :Usr,JrCREDIT,1,-SUM(JrAmount),-SUM(JrAmount),-SUM(JrCount),-SUM(JrCount)
         from JournalS3  where JrnDATE<:DTBEG 
          and DocID=:DocID 
        group by JrCREDIT;
  Insert into TurnSheet(UsrID,TRNAccnt,TCLs,MSldBeg,MSldEnd,NSldBeg,NSldEnd)
       Select :Usr,JrDEBIT,2,SUM(JrAmount),SUM(JrAmount),SUM(JrCount),SUM(JrCount)
         from JournalS3  where JrnDATE<:DTBEG
          and DocID=:DocID 
       group by JrDEBIT;
  Insert into TurnSheet(UsrID,TRNAccnt,TCLs,MTrnCrd,MSldEnd,NTrnCrd,NSldEnd)
       Select :Usr,JrCREDIT,3,-SUM(JrAmount),-SUM(JrAmount),-SUM(JrCount),-SUM(JrCount)
         from JournalS3

        where (JrnDATE>=:DTBEG AND JrnDATE<:DTEND)
          and DocID=:DocID 
       group by JrCREDIT;
  Insert into TurnSheet(UsrID,TRNAccnt,TCLs,MTrnDbt, MSldEnd,NTrnDbt,NSldEnd)
       Select :Usr,JrDEBIT,4,SUM(JrAmount),SUM(JrAmount),SUM(JrCount),SUM(JrCount)
         from JournalS3

        where (JrnDATE>=:DTBEG AND JrnDATE<:DTEND)
          and DocID=:DocID 
        group by JrDEBIT;
Insert into TurnSheet(UsrID,TrnAccnt,TRAParnt,TCls,
             MSldBeg,MTrnCrd,MTrnDbt,MSldEnd,
             NSldBeg,NTrnCrd,NTrnDbt,NSldEnd,TRNDtBeg,TRNDtEnd, DocID)
Select :Usr,TRNAccnt,TRNAccnt as TRAParnt,0,
       Sum(MSldBeg),Sum(MTrnCrd),Sum(MTrnDbt),Sum(MSldEnd),
       Sum(NSldBeg),Sum(NTrnCrd),Sum(NTrnDbt),Sum(NSldEnd),:DtBeg,:DtEnd,:DocID
  from TurnSheet
  where TCls>0 and UsrID=:USR
  group by TRNAccnt;
  Delete from TurnSheet where TCls>0 and UsrID=:USR;
END ^
SET TERM ; ^
Commit;

       т.е. имя процедуры создается по правилу:

TurnSheet+Analitic+Role

       А изменения в процедуре показаны красным цветом. И так для каждой роли и каждого вида аналитики. А в заключении нужно дать права доступа для выполнения этой процедуры соответствующей роли:

Grant execute on procedure TurnSheetDocumentsS3 to Storeman;
Commit;

       Таким образом, каждый пользователь видит в журнале операций только то, что ему разрешено, и может выполнять анализ и отчеты только в пределах разрешенных операций.
       Остается рассмотреть как нужно защищать таблицы объектов аналитического учета — Documents, Partners, Goods, Persons. Вопрос не праздный. Что будет если запись в журнале операций для текущего пользователя разрешена, а Документ, на который она ссылается запрещен? Программы, которые отдают эти вопросы на откуп конечного пользователя, обычно предлагают назначить каждой записи некоторые признаки, по типу прав доступа в файловой системе, а остальное пусть делает конечный пользователь. Это жульничество и конечный пользователь получает пустышку, которая не работает. При множественных связях невозможно построить правильную систему безопасности не зная структуры этих связей. Следовательно проектирование системы безопасности должен полностью выполнять разработчик.
       В данном случае оставим доступ к таблицам аналитики для всех, а в дальнейшем разберем этот вопрос более подробно.

Архангельский Андрей




<<< Пред. Оглавление
Начало раздела
След. >>>

Дата последнего изменения:
Thursday, 21-Aug-2014 09:10:56 MSK


Постоянный адрес статьи:
http://az-design.ru/Projects/AzBook/AZMicro/AZMicroB4.shtml