Как подменить хранимку, которая является источником формы?

Шандор

Access 2007 (ADP) - SQL 2005На SQL заведены пользователи (название компании тчк имя юзера):company1.user1company1.user2company1.user3company2.user1company2.user2company2.user3Есть хранимые процедуры, которые по сути являются источником главной формы с данными:******************************************************** вопрос: как сделать так, чтобы в зависимости от того, какой юзверь залогинился (например company1.user1), источник формы подменялся на соответствующую хранимку - в нашем данном случае Procedure1_for_Company1?Это для того, чтобы юзеры одной компании видели только свои вводимые записи.
16 ответов

Шандор

Я решил ровно такую же проблему горизонтального разграничения видимости данных в увязке с картотекой в зависимости от роли. Т.е. есть роль - бухгалтер, для которой уже имеются ролевые ограничения. Например, вовсе не видеть переписку с банками. Но помиммо этого надо тонко разгранияить чтобы каждый бухгалтер видел операции "своих" компаний, учет которых он ведет.Основные идеи следующие.1. Каждая прикладная форма получает свой источник данных при открытии.Он зависит от роли, т.е. разным ролям можно назначить разные процедуры, или одной роли - процедуру П, другой - вью В.2. Этого оказалось недостаточно. Нужно было иметь один кран, которым можно перекрывать достпуп ко всем похожим формам, имеющим сходные источники данных. Для этого былоа заведена система ограничений - по принципам текстового препроцессора. В источнике данных, уже сформированному по принципу 1, можно использовать зарезервированные слова в {RESTRICTION_NAME}, которые потом разворачиваются в SQL код. Картинку и примеры могу запостить завтра с работы. 2003 АДП + МС СКЛ 2005.


Шандор

Простое решение, но не шибко грамотное:на событие form_open проверять имя текущего пользователя, например
dim us as string
us=currentproject.connection.execute("select current_user()").fields(<b>0</b>)
us=split(us,".")(<b>0</b>) 'выделили компанию
'и менять me.recordsource формы на нужное, например:
me.recordsource="exec Procedure1_for_" & us
Но лучше у формы рекордсоурс не менять, а в хранимке формировать нужный селект исходя из текущего пользователя, или принадлежности пользователя нужной роли - функцией is_member(N'company1')


Шандор

Картинку и примеры могу запостить завтра с работы. 2003 АДП + МС СКЛ 2005.
Конечно покажите, буду ждать!


Шандор

Простое решение, но не шибко грамотное:на событие form_open проверять имя текущего пользователя, например
dim us as string
us=currentproject.connection.execute("select current_user()").fields(<b>0</b>)
us=split(us,".")(<b>0</b>) 'выделили компанию
'и менять me.recordsource формы на нужное, например:
me.recordsource="exec Procedure1_for_" & us
Но лучше у формы рекордсоурс не менять, а в хранимке формировать нужный селект исходя из текущего пользователя, или принадлежности пользователя нужной роли - функцией is_member(N'company1')
Интересное решение. А в чем проявляется неграмотность-то?Недавно, здесь в форуме, задавал вопрос, как хранимкой вытащить значение второго (скрытого) столбца из выпадающего списка. Цель была именно в том, что на форме есть выпадающий список, второй столбец которого содержит именно то условие, которое необходимо для хранимки - company1. Тоесть как Вы и предложили - в самой хранимке этот параметр "тянулся" из самой формы, и соотвественно форма фильтровала все значения company1.Но внутренний голос говорит, что есть какое-то элементарное решение, но нужно его отыскать :)


Шандор

Мысли вслух:Есть:1. основная таблица - MainTable (которую нужно от всех скрыть).2. хранимка, которая вытягивает данные с MainTable, но с параметром, как и говорил, чтобы агент из company1 видел только свои записи
SELECT dbo.MainTable.*
FROM dbo.MainTable
WHERE (КодовоеИмяАгента = N'company1')
ORDER BY ID
3. есть такой неплохой параметр, который может нам показать нашего подключенного пользователя - company1.user1 - вот он: suser_sname()4. как можно использовать вышеприведенный пример в хранимке для отсечения company1 от user1 и попытаться "всунуть" company1 в хранимку? :)Тоесть в запросе (хранимке) определить текущего, подключенного пользователя, отсечь название компании, и вытянуть из MainTable все данные, которые относятся к company1


Шандор

Проще и правильнее (IMHO) - рулить ролями а не пользователямиОтвет:Создать роль базы данных - company1 Создать пользователя базы - user1 Засунуть пользователя в рольХранимку переписать
SELECT a.*
FROM dbo.MainTable as a
WHERE IS_MEMBER(КодовоеИмяАгента)
ORDER BY a.ID
Или хранимка с параметром
create procedure dbo.My_SP(@Company nvarchar(<b>50</b>))
as
begin

 SELECT a.*
 FROM dbo.MainTable as a
 WHERE КодовоеИмяАгента = @Company
 ORDER BY a.ID
end


Шандор

Проще и правильнее (IMHO) - рулить ролями а не пользователямиОтвет:Создать роль базы данных - company1 Создать пользователя базы - user1 Засунуть пользователя в рольХранимку переписать
SELECT a.*
FROM dbo.MainTable as a
WHERE IS_MEMBER(КодовоеИмяАгента)
ORDER BY a.ID
[/src]
Первый вариант мне больше нравится, и так правильней. Спасибо, буду пробовать!


Шандор

Недописал!!!
SELECT a.*
FROM dbo.MainTable as a
WHERE IS_MEMBER(КодовоеИмяАгента)=<b>1</b>
ORDER BY a.ID


Шандор

Ёжик`,Ага, то-то он мне ябедничает
Ошибка в списке аргументов функции: не опознано "IS_MEMBER".
Не удается выполнить синтаксический разбор текста запроса.
Пошел дальше экспериментировать! :)


Шандор

Ёжик`,Работает шикарно! :) Заодно с ролями разобрался :) С меня пиво, говорите куда посылать :)


Шандор

Проще и правильнее (IMHO) - рулить ролями а не пользователями
молоца :)правильнее рулить /ролями/пользователями и /сессиями


Шандор

молоца :)правильнее рулить /ролями/пользователями и /сессиями
....ыыыы,...и где нада начинать НЕ соглашатся с уважаемым Ёжик`-ом ?


Шандор

....ыыыы,...и где нада начинать НЕ соглашатся с уважаемым Ёжик`-ом ?
конетчно! нуно соглашаться ... ыыыыв минимум минимореправатранзакциипользователиролисессии


Шандор

....конетчно! нуно соглашаться ... ыыыыв минимум минимореправатранзакциипользователиролисессии
....мы, это, тавоб - играимся в терминЫ ?...причём здесь это ?...была идея - всё реализуется через роли... объясни мне минусы - я их - в упор не вижу...


Шандор

объясни мне минусы - я их - в упор не вижу...
извини, я не говорил про минусы, я говорил про плюсы.все правильно ёжик говорит я чуть-чуть дополнилроль это конкретно объявленный (назначенный) шаблон суммы прав пользователя распоряжаться транзакциями в системе на протяжении некоторой сессиисессия либо период между транзакциями (разной глубины вложенности - это отдельная тема) - с AutoCheck этого перида по фронту транзакций и/или администрируемые периоды обращений к системе (как вышибить заснувшего пользователя - это тоже отдельная тема)по большому буфету "роль" это сформулированный по шаблону паттерн - конкретный пользователь + конкретные права + конкретные транзакции + на протяжении некоторого периода (по простою например он может хотя бы засейвить данные хотя бы в темпорари и хотя бы имеет право выйти с сохранением личных настроек системы если их менял - обычно по-умолчанию)но это уже не про Access :)


Шандор

/*
0. Получение для заданых текущей роли и источника прикладной формы зарчастей 
 для форомировани SQL выражения SELECT * FROM qrData WHERE (1=1) ORDER BY f1, f2 DESC
*/ 
SELECT TOP <b>1</b> * FROM qrSYS_SourceRole WHERE sSourceCode='Источник прикладной формы' AND sRoleName='Некая роль' ORDER BY iRoleRank DESC
/*
iRoleSourceID iRoleID	sRoleName iRoleRank iSourceID	 sSourceCode	 sFromSQL sWhereSQL sOrderBySQL sParameterList iSourceTypeID sSourceTypeCode	
------------- ------- ---------- --------- --------- ------------------------- -------- --------- ----------- -------------- ------------- ---------------
496 1 Некая роль 0 270 Источник прикладной формы qrData 1=1 f1, f2 DESC NULL 1 VIEW
*/

/* 
1. Получение роли iRoleID=5 
*/
SELECT TOP <b>1</b> * FROM qrSYS_Role WHERE sRoleName='Некая роль' ORDER BY iRoleRank DESC
/*
iRoleID sRoleName iRoleRank 
----------- ---------- ----------- 
5 Некая роль 800 
*/

/* 
2. Получение ограничения iRestrictionID=17 по источнику прикладной формы, если таковое есть 
*/
SELECT TOP <b>1</b> * FROM qrSYS_SourceRestriction WHERE sSourceCode='Источник прикладной формы' ORDER BY iSourceRestrictionID DESC
/*
iSourceRestrictionID iSourceID sSourceCode iRestrictionID sRestrictionCode sRestrictionName 
-------------------- ----------- ------------------------- -------------- ---------------- -------------------------------- 
35 270 Источник прикладной формы 17 {Ограничение} {Имя ограничения}
*/

/* 
3. Чтение SQL строки ограничени. 
 Получение вместо условия WHERE для SELECTа имени другой роли в скобках sRoleRestrictionWhereSQL={Другая роль}
*/
SELECT TOP <b>1</b> * FROM SYS_RoleRestriction WHERE iRestrictionID=<b>17</b> AND iRoleID=<b>5</b> ORDER BY iRestrictionID
/*
iRoleRestrictionID iRoleID iRestrictionID sRoleRestrictionWhereSQL
------------------ ----------- -------------- ------------------------
92 5 17 {Другая роль}
*/

/* 
4. Из-за того, что на предыдущем этапе была получена новая роль, выполнение переключения на новую роль,
 аналогично п. 1
*/
SELECT TOP <b>1</b> * FROM qrSYS_Role WHERE sRoleName='Другая роль' ORDER BY iRoleRank DESC
/*
iRoleID sRoleName iRoleRank 
----------- -------------------------------- ----------- 
4 Другая роль 600 
*/

/*
5. Повтор п.3 для новой роли iRoleID=4. Получение sRoleRestrictionWhereSQL={Ограничение источника}
*/
SELECT TOP <b>1</b> * FROM SYS_RoleRestriction WHERE iRestrictionID=<b>17</b> AND iRoleID=<b>4</b> ORDER BY iRestrictionID
/*
iRoleRestrictionID iRoleID iRestrictionID sRoleRestrictionWhereSQL
------------------ ----------- -------------- ------------------------
91 4 17 {Ограничение источника}
*/

/*
6. Поучение SQL части WHERE ограничения источника данных 
 sRoleHoldingRestrictionString = '(iInvestmentCustomerID IN (SELECT iCustomerID FROM TAB_Customer WHERE iCustomerFilialLevel>0)) 
 OR (iInvestmentCustomerID IN ({HOLDING_LIST}) OR iAssetCustomerID IN ({HOLDING_LIST}))'
*/
SELECT * FROM SYS_RoleHoldingRestriction WHERE iRoleID=<b>4</b> AND sRestrictionTypeCode='Ограничение источника'
/*
iRoleID iRoleHoldingRestrictionID sRestrictionTypeCode sRoleHoldingRestrictionString 
------- ------------------------- --------------------- ----------------------------- 
4 7 Ограничение источника (iInvestmentCustomerID IN (SELECT iCustomerID FROM TAB_Customer WHERE iCustomerFilialLevel>0)) 
 OR (iInvestmentCustomerID IN ({HOLDING_LIST}) OR iAssetCustomerID IN ({HOLDING_LIST}))	
*/

/*
7. Формирование {HOLDING_LIST} путем склейки через запятую отдельных ID компаний, 
 к данным которых есть доступ для данного пользователя
*/
SELECT * FROM qrSYS_RoleUser WHERE sUserName='Логин пользователя' AND sRoleName LIKE '[_]Customer[_]%' ORDER BY iRoleRank DESC, sUserName
/*
iUserID sUserName sUserName1 sDepartmentName iRoleUserID iRoleID sRoleName sRoleCustomerList
----------- ------------------ ---------- ---------------- ----------- ----------- ------------- -----------------
87 Логин пользователя Aaaaaaa Департамент Бббб 1110 18 _Customer_Aaa 1500
87 Логин пользователя Aaaaaaa Департамент Бббб 1111 21 _Customer_Bbb 1486
87 Логин пользователя Aaaaaaa Департамент Бббб 1112 22 _Customer_Ccc 1527
*/

/* 0. Исходная инструкция */
SELECT * FROM qrData WHERE (<b>1</b>=<b>1</b>) ORDER BY f1, f2 DESC

/* После выполнения п.2 - нахождения ограничения */
SELECT * FROM qrData WHERE (<b>1</b>=<b>1</b>) AND {Ограничение} ORDER BY f1, f2 DESC

/* После расшифровки ограничения, в том числе переключения на другую роль в процессе расшифорвки */
SELECT * FROM qrData WHERE 
 (
 -- Изначальный фильтр для источника и роли
 (<b>1</b>=<b>1</b>)
 ) AND (
 -- Добавленное расшифрованное ограничение
 (iInvestmentCustomerID IN (SELECT iCustomerID FROM TAB_Customer WHERE iCustomerFilialLevel><b>0</b>)) 
 OR (iInvestmentCustomerID IN (<b>1</b>, <b>1500</b>, <b>1486</b>, <b>1527</b>) 
 OR iAssetCustomerID IN (<b>1</b>, <b>1500</b>, <b>1486</b>, <b>1527</b>))
 ) 
ORDER BY f1, f2 DESC

/* После добавления условий фильтрации из контролов формы "управляющие списки" */
SELECT * FROM qrData WHERE 
 (
 -- Изначальный фильтр для источника и роли
 (<b>1</b>=<b>1</b>)
 ) AND (
 -- Добавленное расшифрованное ограничение
 (iInvestmentCustomerID IN (SELECT iCustomerID FROM TAB_Customer WHERE iCustomerFilialLevel><b>0</b>)) 
 OR (iInvestmentCustomerID IN (<b>1</b>, <b>1500</b>, <b>1486</b>, <b>1527</b>) 
 OR iAssetCustomerID IN (<b>1</b>, <b>1500</b>, <b>1486</b>, <b>1527</b>))
 ) AND (
 -- Добавлено из услвий фильтрации на форме
 (sInstrumentTypeCode LIKE '%вексель%') 
 AND (<b>1</b>=<b>1</b>) 
 AND (sAssetMoscowFilialFlag='M' AND iInternalDealFlag<><b>1</b>) 
 AND (<b>1</b>=<b>1</b>)
 ) 
ORDER BY f1, f2 DESC