Добрый день!

Периодически в разделах создаются объекты без прав доступа. Оба разделы  не  базовые. 

Все объекты создаются одинаковым способом и тем не менее, периодически выпадают записи у которых записи прав вообще пустые. Приходится потом раздавать руками.

Может у кого то есть идеи, с чем это может быть связано?

 

Благодарю!

Нравится

1 комментарий
Лучший ответ

Добрый день.

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

Можно только предположить, какие причины наиболее вероятны в Вашем случае.

1. Некорректно настроена раздача прав доступа и права не раздаются на этапе создания записи.

2. Если у Вас есть процессы, которые вносят изменения в права доступа, то может быть они удаляют существующие права, а новые не раздают.

Для поиска ошибки начните с анализа настроек прав доступа и пользовательских бизнес-процессов в конфигурации срм.

Также, как вариант, если у Вас приложение on-site, Вы можете запустить sql-профайлер, чтобы он некоторое время поработал, а потом проанализируйте запросы к таблицам прав доступа Ваших разделов.

Добрый день.

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

Можно только предположить, какие причины наиболее вероятны в Вашем случае.

1. Некорректно настроена раздача прав доступа и права не раздаются на этапе создания записи.

2. Если у Вас есть процессы, которые вносят изменения в права доступа, то может быть они удаляют существующие права, а новые не раздают.

Для поиска ошибки начните с анализа настроек прав доступа и пользовательских бизнес-процессов в конфигурации срм.

Также, как вариант, если у Вас приложение on-site, Вы можете запустить sql-профайлер, чтобы он некоторое время поработал, а потом проанализируйте запросы к таблицам прав доступа Ваших разделов.

Показать все комментарии

Добрый день.

В разделе "Администрирование. Доступ к объектам. Доступ к записям по умолчанию" указано, что пользователи определенной группы имеют право на чтение Обращения созданных только членами этой группы.

Данное правило работает только в том случае, если обращение создавалось членами данной группы через портал.
Если же оно приходит на электронную почту (Контакт и Контрагент распознаются и он входит в группу), то правило Доступа к записям по умолчанию для такого Обращения не работает.

Возможно решить данную проблему средствами конфигурирования, или необходимо задействовать бизнес-процесс?

Нравится

2 комментария

Добрый день, Маргарита!

В данном случае Ваш процесс должен содержать подобные элементы:

1. Стартовый сигнал (создано Обращение, с происхождением <> Портал).
2. Чтение данных Обращения.
3. Чтение данных Заявителя.
4. Скрипт (который будет формировать выборку Контактов по Контрагенту Заявителя и раздавать им права на Обращение, по которому стартовал данный процесс).

Показать все комментарии

В Террасофт реализована вполне удобная система раздачи прав. По крайней мере, если разобраться :wink:

Но она позволяет настраивать только права на будущие записи. Те, которые уже созданы, приходится обрабатывать поштучно (в 3.4.1 можно уже постранично :biggrin:).
Что же делать бедным администраторам или CRM-координаторам, когда надо, например, ввести новую группу пользователей или переопределить права для старой - ведь это должно касаться, как новых, так и уже созданных записей.

В моей практике подобные ситуации встречались уже не раз. В конце концов, я устал мастерить костыли и сделал себе несколько скриптов для решения подобных задач.

Делюсь с вами.
Считаю, что если Вы читаете это, значит Вы уже знаете, что такое tbl_AccountGroupRight, sq_Service, ds_ItemRight, Dataset.IsEOF, declare cursor и т.д. Хотя это вовсе необязательно, чтобы использовать скрипты - просто мне лень их полностью комментировать :redface:

1. С чего я начал - скорее для истории, чем для нужд населения
2. проходной вариант
3. Уже что-то полезное (Скрипт JS)
4. Самое вкусное для терпеливых

Нравится

Поделиться

7 комментариев

1. С чего я начал - скорее для истории, чем для нужд населения :smile:

Добавление прав на продажи_контакты_контрагенты для пользователя\группы

CREATE TABLE #tbl_OpportunityRight(
	[ID] [uniqueidentifier] NULL,
	[RecordID] [uniqueidentifier] NULL,
	[AdminUnitID] [uniqueidentifier] NULL,
	[CanRead] [int] NULL,
	[CanWrite] [int] NULL,
	[CanDelete] [int] NULL,
	[CanChangeAccess] [int] NULL)
go 
 
insert into #tbl_OpportunityRight (RecordID) (select ID from tbl_Opportunity where ID in (select OpportunityID from tbl_OpportunityInGroup where GroupID = 'B66CAAD9-AF6B-4F12-B88C-1E3453F591C4'))
 
go
 
update #tbl_OpportunityRight set ID = NEWID(), AdminUnitID = '687D0624-5B5E-4F19-961E-D9F03A96939A', CanRead = '1', CanWrite = '1', CanDelete = '0', CanChangeAccess = '0';
 
insert into tbl_OpportunityRight select * from #tbl_OpportunityRight

Выставить прав для определенного пользователя\группы в конкретной таблице

update tbl_OpportunityRight set CanDelete = '0', CanWrite = '0', CanChangeAccess = '0'
	where ID in (select ID from tbl_OpportunityRight where AdminUnitID = 'D268BFB9-8118-4E3B-9F06-1D703D25C23E' and CanWrite = '1') 

_service.rar

2. В контексте решения одной задачи и после долгих мучений была создана процедура:
особого внимания ей уделять не стоит - это проходной вариант

В конкретной таблице (параметр) для конкретной записи (параметр) выставляет права, как будто она была создана от имени конкретного пользователя (параметр) входящего в конкретную группу (не параметр)

USE [Our_backup]
GO
/****** Object:  StoredProcedure [dbo].[tsp_UpdateRightsByDefaults]    Script Date: 07/25/2013 16:57:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE procedure [dbo].[tsp_UpdateRightsByDefaults] 
	@ARightTableName sysname,
	@Owner_ID uniqueidentifier,
	@Record_ID uniqueidentifier,
	@ADBSchema sysname = 'dbo'
with execute as 'fkeys'
AS
BEGIN
	SET NOCOUNT ON;
  DECLARE @ServiceTableID uniqueidentifier
  DECLARE @AdminUnitID uniqueidentifier
  DECLARE @RecordID uniqueidentifier
  DECLARE @TableRightsName varchar(250)
  DECLARE @DefaultGroupID uniqueidentifier
  set @DefaultGroupID = (select ID from [tbl_AdminUnit] where Name = 'продажники') -- меняем имя или пишем конкретный ИД
 
  SET @ServiceTableID = (SELECT [ID] 
  FROM [dbo].[tbl_Service] 
	   WHERE [Code] = (replace(@ARightTableName, 'Right', ''))
    AND [ServiceTypeCode] = N'Table')
 
  SET @AdminUnitID = (SELECT ID from [dbo].[tbl_AdminUnit] where UserContactID = @Owner_ID)
  SET @TableRightsName = '[' + @ADBSchema + '].[' + @ARightTableName +']'
  SET @RecordID = @Record_ID
 
 exec(' DELETE' +@TableRightsName + ' where RecordID = ''' + @RecordID + ''' 
 
  INSERT INTO ' +@TableRightsName + ' (
    [ID]
    ,[RecordID]
    ,[AdminUnitID]
    ,[CanRead]
    ,[CanWrite]
    ,[CanDelete]
    ,[CanChangeAccess])
  SELECT
    newid()
    ,''' + @RecordID + '''
    ,''' + @AdminUnitID + '''
    ,1
    ,1
    ,0
    ,0
 
  INSERT INTO ' + @TableRightsName + ' (
    [ID]
    ,[RecordID]
    ,[AdminUnitID]
    ,[CanRead]
    ,[CanWrite]
    ,[CanDelete]
    ,[CanChangeAccess])
  SELECT
    newid()
    ,''' + @RecordID + '''
    ,[D].[SubjectAdminUnitID]
    ,[D].[CanRead]
    ,[D].[CanWrite]
    ,[D].[CanDelete]
    ,[D].[CanChangeAccess]
  FROM (
    SELECT
      [D].[SubjectAdminUnitID]
      ,MAX([D].[CanRead]) AS [CanRead]
      ,MAX([D].[CanWrite]) AS [CanWrite]
      ,MAX([D].[CanDelete]) AS [CanDelete]
      ,MAX([D].[CanChangeAccess]) AS [CanChangeAccess]
    FROM [dbo].[tbl_TableDefaultRight] AS [D]
    WHERE ([D].[TableServiceID] = ''' + @ServiceTableID + ''')
    AND ([D].[AdminUnitID] = ''' + @DefaultGroupID + ''' 
		 )
  GROUP BY [D].[SubjectAdminUnitID])
	AS [D]
 ')
	SET NOCOUNT OFF;
END

tsp_updaterightsbydefaults.rar

PS. Не забываем - на процедуры надо давать права на исполнения для роли public

3. Уже что-то полезное
Скрипт (JS для клиента - не SQL!!)

Добавляет во все записи все таблиц прав права для конкретного пользователя\группы. Либо редактирует, если уже есть такие права.
Опустил из скрипта таблицы прав на записи групп (например tbl_AccountGroupRight) - т.к. это было не надо, и там немного запутанно - не стал тратить время

ВАЖНО:
* создавался на версии 3.4.1
* для sq_Service надо добавить фильтр IsRightsTable:

//см приложение

scr_recreaterigths.rar

4. Самое вкусное для терпеливых :biggrin:
основано на скриптах от техподдержки, которые (в связи со спецификой :wink:) у меня работали неправильно или вообще не.
делал на 3.4.1 XRM

Раздает, используя механизм аналогичный базовому из триггеров для прав, права по-умолчанию для ВСЕХ записей ВСЕХ таблиц, для которых есть таблица прав. Таблицы берутся по принципу:

SELECT
	s1.[Code] AS [Code]
FROM
	[tbl_Service] AS s1
WHERE s1.[ServiceTypeCode] = 'Table'
and s1.Code <> 'tbl_TableField'
and exists( 
  select * from tbl_Service as s2
  where s2.Code = s1.Code + 'Right'
)

В двух вариантах:
1. как будто запись создал тот, кто ее создал :lol: (CreatedByID), если есть такой юзер, иначе подставляется из переменной @DefaultGroupID - не забудьте поставить свое
2. как будто запись создал ответственный (OwnerID), если есть такое поле в таблице и такой юзер, иначе - как в п.1

есть такой юзер означает, что заведен (и не удален, как было в моем случае) пользователь с таким контактом и он активен (активность необязательна - смотрите сами, надо ли):

	set @UserIsActive = (SELECT COUNT (*) FROM tbl_AdminUnit WHERE UserContactID = @OwnerID and UserIsEnabled = 1) -- UserIsEnabled = 1 опционально
	if (@UserIsActive != 0)
		set @AdminUnitID = (SELECT ID FROM tbl_AdminUnit WHERE UserContactID = @OwnerID)
	else set @AdminUnitID = @DefaultGroupID

prava_po-umolchaniyu_po_otvetstvennomu.rar
prava_po-umolchaniyu_po_sozdatelyu.rar

осторожнее с правами на записи, созданные Supervisor'ом (такие, как например, корневые группы типа Все контрагенты) - создайте для него права по-умолчанию, чтобы не было проблем

я бы даже советовал вообще исключить группы записей из этого процесса

актуальная версия сервисов
извините, нет времени описывать
defaultrigths.rar

Показать все комментарии

Для BPMonline Service Desk. Подскажите, как технически реализуется возможность сортировки и прав доступа новых обращений в зависимости от сервиса/подсервиса для конечного исполнителья. Т.е. чтобы ряд групп исполнителей мог видеть обращения исключительно указанной для нее специфики. Если возможно в качестве детальной инструкции. Спасибо!

Нравится

5 комментариев

Добрый день.

В свойствах объекта ServiceRequest укажите значение колонки Группа и опубликуйте объект.

Таким образом, группа пользователей, назначенная ответственной по инциденту/запросу на обслуживание получит права на запись.

Не совсем то, что я хотел. Допустим, что есть 10 предоставляемых видов сервисов. 2 из них делает одна группа, 2 из них другая, 2 из них третья и так далее. В разделе обращений каждая из групп может видеть только обращения предназначенные именно им(зависимость от выбранного типа сервиса при создании обращения для конкретной группы). Может быть создать несколько папок до раздела обращений и на них дать права? Тем не менее как нацелить на них необходимые сервисы? Пожалуйста, подскажите.

Если вопрос удобства, то корректнее всего было бы создать динамические группы с фильтрами по сервисам, выбранным в инциденте/запросе на обслуживание.
Если вопрос безопасности, то необходимо дописывать логику на сохранении записи. В объекте ServiceRequest, в процессе, на событии ServiceRequestInserted в задании-сценарии ServiceRequestInsertedScriptTask дописать insert, наподобие уже существующего:

var portalUsersSysAdminUnitUId = new Guid("f858d1b9-334b-e111-b408-00155d054c02");
Guid recordUId = Entity.PrimaryColumnValue;
int defPosition = 0;
var defaultSourceUId = new Guid("f41e0268-e324-4228-9e9e-5cb7cc906398");
var nowParameter = new QueryParameter("now", DateTime.Now, "DateTime");
var currentUserContactIdParameter = new QueryParameter("currentUserId", UserConnection.CurrentUser.ContactId);		
for (int operation = 0; operation <= 2; operation++) {
	var insertRight = new Insert(UserConnection)
		.Into("SysServiceRequestRight")
			.Set("CreatedOn", nowParameter)
			.Set("CreatedById", currentUserContactIdParameter)
			.Set("ModifiedOn", nowParameter)
			.Set("ModifiedById", currentUserContactIdParameter)				
			.Set("RecordId", Column.Parameter(recordUId))
			.Set("SysAdminUnitId", Column.Parameter(portalUsersSysAdminUnitUId))
			.Set("Operation", Column.Parameter(operation))
			.Set("RightLevel", Column.Parameter(true))
			.Set("Position", Column.Parameter(defPosition))
			.Set("SourceId", Column.Parameter(defaultSourceUId))
		as Insert;
	insertRight.Execute();
}

Только вместо portalUsersSysAdminUnitUId использовать идентификатор конкретной группы, который будет присваиваться переменной в зависимости от предоставляемого сервиса.

Данный вопрос рассматривается из соображений безопасности. Не могли бы вы предоставить мне наглядный пример реализации, с необходимыми для замены значениями и комментариями?

Guid groupId;
Guid subserviceId = Entity.SubserviceId;
switch (subserviceId.ToString()) {
	case "d79f2070-f36b-1410-f18a-0050ba5d6c38": //если такой-то подсервис
	groupId = new Guid("f15d4059-e23e-4ed9-9041-88a12736c031"); //то, даем права такой-то группе
	break;
	case "jf75j070-f36b-1410-f18a-hr7dj45d6c38": //а если такой-то подсервис
	groupId = new Guid("r45d4059-e23e-4ed9-9041-88a12736c741"); //то, даем права другой группе
	break;
	default: //условие по умолчанию
	groupId = new Guid("6e0a1b5e-7738-4a9c-9d2d-995f62e51e26"); //даем права группе такой-то
	break;
}
var defaultSource = new Guid("f41e0268-e324-4228-9e9e-5cb7cc906398");
var now = new QueryParameter("now", DateTime.Now, "DateTime");
var currentUserContactId = new QueryParameter("currentUserId", UserConnection.CurrentUser.ContactId);		
for (int operation = 0; operation <= 2; operation++) {
	var insertRight1 = new Insert(UserConnection)
		.Into("SysServiceRequestRight")
			.Set("CreatedOn", now)
			.Set("CreatedById", currentUserContactId)
			.Set("ModifiedOn", now)
			.Set("ModifiedById", currentUserContactId)				
			.Set("RecordId", Column.Parameter(Entity.PrimaryColumnValue))
			.Set("SysAdminUnitId", Column.Parameter(groupId))
			.Set("Operation", Column.Parameter(operation))
			.Set("RightLevel", Column.Parameter(true))
			.Set("Position", Column.Parameter(0))
			.Set("SourceId", Column.Parameter(defaultSource))
		as Insert;
	insertRight1.Execute();
}
Показать все комментарии

Добрый день!

Уважаемые гуру bpm, а не подскажете ли вы то таинственное место в системе, где можно посмотреть, а может быть и изменить работу стандартного функционала по раздаче прав на создаваемые записи по умолчанию? Откуда берутся данные для назначения прав понятно, а вот "кто" дальше их применяет неясно.
Триггеров на таблицах нет (как это было в 3.х), остается два варианта - функция эта зашита в ядро (грустно, но хотя бы буду знать об этом), или доступна и вызывается в каком-либо процессе в системе (и можно ее поправить/использовать/доработать/изучить!)
Характер вопроса познавательно-теоретический:smile:
Заранее безмерно благодарен...

Нравится

2 комментария

Здравствуйте, Александр!

Боюсь, дам Вам повод для грусти, однако же данная функция зашита в ядро.

Есть и отрадная новость: права по умолчанию гибко настраиваются. В частности, можно для объекта установить так называемого Владельца. Для этого следует выбрать в расширенных свойствах объекта одно из полей (Ответственный, Автор, Создал) и выпадающем меню поля Владелец.

В этом случае соответствующий пользователь не будет виден на детали Доступ, однако будет иметь полные права на запись.

Кроме того, BPMonline также поддерживает различный уровень вложенности при работе с записями. Рекомендую обратить Ваши взоры к системной настройке Способ администрирования связанных объектов (QueryJoinRightLevel)

[Способ администрирования связанных объектов] — позволяет определить способ администрирования связанных объектов, например, при отображении информации об основном контакте (должности или дате рождения) из раздела [Контрагенты]. Тип: целое число. Значение по умолчанию: 0. Настройке можно присвоить следующие значения:

0 — отображать данные только по записям связанного объекта, к которым у текущего пользователя есть доступ;
1 — отображать данные только по записям связанного объекта, к которым у текущего пользователя есть доступ, но в случае отсутствия доступа к записи, отображать данные основного отображаемого поля;
2 — отображать данные по всем записям связанного объекта независимо от распределения прав доступа.

А вообще, поделитесь прикладной задачей, возможно, ее решение уже давно предусмотрено в системе, и ждет вашего правильно сформулированного вопроса :)

Спасибо за ответ, Анна! Принцип понял.
Вопрос на данный момент имеет, как и писал, теоретически-образовательный характер.

Показать все комментарии

При выделении к примеру всего списка вкладки "Права доступа по умолчанию", после нажав добавить пользователя

Права добавляются только на последний элемент выделенного списка

При редактирования большого числа груповых политик, это просто Адский труд

TS_XRM+ServiceDesk_SoftKey_RUS_Firebird_3.4.0.126

Нравится

7 комментариев

Добрый день, Андрей!

Массовое изменение прав доступа работает несколько иным способом:

  1. Встаньте на группу пользователей, в модуле групп раздела Администрирование на представлении "Права доступа по умолчанию"
  2. Выделите ряд таблиц, которые администрируются по записям
  3. На детали "Права доступа" сфокусируйтесь на группе или пользователе, предварительно добавленным в деталь доступа по всем выделенным таблицам и измените доступ массово для одной роли во всех выделенных таблицах сразу.

Таким образом, логика работы массового изменения прав доступа следующая: одному пользователю или группе (запии группы) мы меняем права доступа для множества (выделенных) таблиц.

Такое действие, как массовое добавление одного пользователя или группы в деталь доступа, не предусмотрена базовой логикой.

Здравствуйте, Андрей!

Групповое изменение при необходимости можно реализовать на уровне конфигурации.

Для этого следует добавить в функцию обработку выделенных записей реестра, например, заменив функцию SwitchTableGroupRightFieldValue на следующую:

function SwitchTableGroupRightFieldValues(FieldName) {
	var SelectedIDs = grdData.SelectedIDs.CreateCopy();
    if (!Assigned(SelectedIDs)) {
        return;
    }
    var RecordsCount = SelectedIDs.Count;
    if (RecordsCount <= 0) {
        return;
    }
    var Dataset = dlData.Dataset;
	Dataset.DisableEvents();
	try {
	    if (RecordsCount == 1) {
	        Dataset.Locate('ID', SelectedIDs.Items(0));
      	    Dataset.Edit();
       		Dataset.ValAsBool(FieldName) = !Dataset.ValAsBool(FieldName);
       		Dataset.Post();
			return;
	    }
		Dataset.Edit();
	    for (var i = 0; i <= RecordsCount - 1; i++) {
	  		Dataset.Locate(IDFieldName, SelectedIDs.Items(i));
			Dataset.ValAsBool(FieldName) = !Dataset.ValAsBool(FieldName);
		}
	  	Dataset.Post();	
		RefreshDataset(Dataset);  	
	} finally {
	    Dataset.EnableEvents();
	}	    
}

Обратите внимание, добавление прав будет касаться только пользователей, выделенных в нижнем окне:

defrights

Для того, чтобы учитывать записи, выбранные в верхнем реестре (Права доступа по умолчанию) необходимо реализовать дополнительную вложенность функции.

Анна Алимова а можно подробнее где найти эту функцию ?

Искал в users/ безуспешно :(

Андрей, этой функции в коробочной версии нет, я ее написала. Поэтому и привела полный текст функции в предыдущем посте.

Ее следует добавить в скрипт scr_TableDefaultRightGridArea и заменить везде. где в скрипте вызывается SwithTableDefaultRightFieldValue на SwithTableDefaultRightFieldValues:

SwithTableDefaultRightFieldValue

всё сделал, перезапустил FireBird, клиент тоже , не помогло всё по старому :sad:

Андрей, это именно то, на что я просила обратить внимание в комментарии

"Alimova Anna" написал:Обратите внимание, добавление прав будет касаться только пользователей, выделенных в нижнем окне:

defrights

Для того, чтобы учитывать записи, выбранные в верхнем реестре (Права доступа по умолчанию) необходимо реализовать дополнительную вложенность функции.

Для того, чтобы учитывались выбранные в верхнем реестре записи, необходимо по аналогии реализовать вложенную функцию, которая будет также в цикле проверять выделенные записи верхнего реестра, и применять изменения к ним.

Показать все комментарии

Добрый день.

При текущей настройке прав доступа, автор записи получает все права на эту запись (чтение, изменение, удаление, изменение доступа).
Допустим пользователи входят в две группы "Менеджеры" и "Руководство".

Мне необходимо было настроить права так, чтобы все созданные отдельным менеджером Контакты видел только менеджер создатель контакта и все члены группы "Руководство" (это я сделал). Однако у создателя есть право на изменение доступа. Как сделать так, чтоб по умолчанию на создание новой записи этого права у создателя не было (если он входит в группу "Менеджеры").

Сейчас у меня:
Запись Контакта (Доступ):
Гарри Потер (член группы менеджеров, автор записи): Чтение, Изменение, Удаление, Изменение Доступа
Руководство: Чтение, Изменение.

А хочется вот так:

Запись Контакта (Доступ):
Гарри Потер (член группы менеджеров, автор записи): Чтение, Изменение, Удаление
Руководство: Чтение, Изменение.

Нравится

2 комментария

По умолчанию автор записи всегда имеет полный доступ к созданным записям. Нигде из клиента это не настроить. Если для конкретного раздела Вы хотите ограничить ему доступ, то это делается в триггере по раздаче прав доступа по умолчанию. Если идет речь о таблице контактов, то найдите триггер tr_tbl_Contact_I. Для всех таблиц, которые администрируются по записям есть такой триггер на вставку. Найдите в нем строчки

INSERT INTO [dbo].[tbl_AccountRight] (
    [ID]
    ,[RecordID]
    ,[AdminUnitID]
    ,[CanRead]
    ,[CanWrite]
    ,[CanDelete]
    ,[CanChangeAccess])
  SELECT
    newid()
    ,[ID]
    ,@AdminUnitID
    ,1
    ,1
    ,1
    ,1
  FROM INSERTED

и замените последнюю единичку на ноль. Но хочу заметить, что после пересохранения сервиса таблицы контактов(tbl_Contact) этот триггер перетерется на стандартный и Ваши изменения исчезнут(а сервис пересохраняется и в случае создания доп. полей). Так что нужно либо всегда помнить об этом и изменять триггер, если он изменится, либо поступить более радикально и изменить процедуру создания этих триггеров. Но в этом случае при пересохранении любого сервиса таблицы администруруемой по записям будет создаваться триггер, который раздает права с учетом Ваших пожеланий ограничения прав для автора записи. Хранимая процедура называется tsp_AdministratedByRecords. В ней очень похожий блок кода

	'  INSERT INTO ' + @RightTableName + ' (' + @NL +
	'    [ID]' + @NL +
	'    ,[RecordID]' + @NL +
	'    ,[AdminUnitID]' + @NL +
	'    ,[CanRead]' + @NL +
	'    ,[CanWrite]' + @NL +
	'    ,[CanDelete]' + @NL +
	'    ,[CanChangeAccess])' + @NL +
	'  SELECT' + @NL +
	'    newid()' + @NL +
	'    ,[ID]' + @NL +
	'    ,@AdminUnitID' + @NL +
	'    ,1' + @NL +
	'    ,1' + @NL +
	'    ,1' + @NL +
	'    ,1' + @NL +
	'  FROM INSERTED' + @NL +

Опять же, вместо последней единицы, вставляете ноль.

С переделыванием триггеров таблицы есть нюансы - в случае, если Вами будет пересохранена таблица из конфигурации, триггер восстановится к коробочному состоянию. Для того, чтобы он не менялся, необходимо вносить изменения в хранимую процедуру, генерирующую триггеры - отдельно описывать данный конкретный триггер, а эта задача чересчур трудоемкая.

Рекомендую реализовать обходное решение на уровне конфигурации - при добавлении записи на AfterPost (т.е., когда уже сработали все триггеры) фильтровать в таблице прав нужную запись, и менять для нее право на раздачу доступа на false.

Показать все комментарии

Как автоматически скорректировать права на все существующие записи при изменении прав по умолчанию?

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

Представьте, что сдали заказчику проект, он поработал и вдруг осознаёт: права по умолчанию надо поменять. И поменял. Система легко кастомизируется, о настройках прав в ТС тонны отличных руководств. Но на уже созданные по «старым» настройкам записи, понятное дело, эти изменения не повлияли. И вот тогда заказчик может обратиться к разработчику с пожеланием сделать так, чтобы на уже созданные записи права были розданы точно так же, как он настроил.

К сожалению далеко не всегда известно, что именно менялось и для каких таблиц. Выяснить это можно, но время, время…. Требовалось такое решение, которое позволило бы быстро, одним щелчком раздать права на все существующие записи всех таблиц в точности так, как настроены права по умолчанию сейчас.

В предлагаемом скрипте происходит перебор всех администрируемых по записям таблиц и перенастройка прав согласно существующим правам по-умолчанию. Подразумевается, что таблицы прав называются по схеме ‘имя администрируемой таблицы + ’Right’.

[tbl_Service].[Code] + 'Right'

Права нарочно не перераздаются на записи в таблицах групп, так как по умолчанию права на группы имеют только авторы записей. Следовательно из выборки исключены все таблицы, оканчивающиеся на ‘Group’. Если такое ограничение не требуется – закомментируйте строку

NOT [tbl_Service].[Code] LIKE '%Group'

В выборке учитывается и тот момент, что [tbl_TableDefaultRight] может содержать различный «мусор» от таблиц, у которых снят признак администрирования.
Предлагаемый скрипт в его нынешнем виде генерирует строки insert и update, которые можно проанализировать прежде чем выполнять. Но если требуется сразу выполнить – снимите комментарий в обоих строках

EXECUTE sp_executesql @InsertQueryExecutable
....
EXECUTE sp_executesql @UpdateQueryExecutable

Надеюсь, предлагаемое решение окажется полезным всем, кто в будущем столкнётся с похожей ситуацией.

/* ---------------------------------------------
Установка прав на все администрируемые таблицы
        согласно текущим правам по умолчанию
==============================================*/

declare @Code nvarchar(250)
declare @AdminUnitID uniqueidentifier
declare @CanRead int
declare @CanWrite int
declare @CanDelete int
declare @CanChangeAccess int

declare @UpdateQueryExecutable nvarchar(4000)
declare @UpdateQuery nvarchar(4000)
SET @UpdateQuery =
'update [@CodeRight]
set  [CanRead] = @CanRead
        , [CanWrite] = @CanWrite
        , [CanDelete] = @CanDelete
        , [CanChangeAccess] = @CanChangeAccess
where [AdminUnitID] = '
'@AdminUnitID'''

declare @InsertQueryExecutable nvarchar(4000)
declare @InsertQuery nvarchar(4000)
SET @InsertQuery =
'insert into [@CodeRight]
(
        [RecordID]
        , [AdminUnitID]
        , [CanRead]
        , [CanWrite]
        , [CanDelete]
        , [CanChangeAccess]
)
select [ID]
        , '
'@AdminUnitID''
        , @CanRead
        , @CanWrite
        , @CanDelete
        , @CanChangeAccess
from [@Code]
where
not exists
(       select [a].[ID]
        from [@CodeRight] as [a]
        where [AdminUnitID] = '
'@AdminUnitID''
        and [a].[RecordID] = [@Code].[ID]
)'


declare DefaultRightCursor cursor FOR
        SELECT
                  [tbl_Service].[Code]
                , [tbl_TableDefaultRight].[SubjectAdminUnitID]
                , MAX([tbl_TableDefaultRight].[CanRead])
                , MAX([tbl_TableDefaultRight].[CanWrite])
                , MAX([tbl_TableDefaultRight].[CanDelete])
                , MAX([tbl_TableDefaultRight].[CanChangeAccess])
        FROM [tbl_TableDefaultRight]
        INNER JOIN [tbl_Service]
        ON
                [tbl_Service].[ID] = [tbl_TableDefaultRight].[TableServiceID]
        INNER JOIN [tbl_AdminUnit]
        ON
                [tbl_AdminUnit].[ID] = [tbl_TableDefaultRight].[SubjectAdminUnitID]
        WHERE
        --Не использовать для групп - у них права по-умолчанию имеет только автор
        NOT [tbl_Service].[Code] LIKE '%Group'
        AND
        --Учитывать только существующие таблицы прав
        --(иногда бывает "мусор" от таблиц, на которые раньше раздавались права, а теперь нет)
        EXISTS (
                SELECT * FROM
                INFORMATION_SCHEMA.TABLES
                WHERE INFORMATION_SCHEMA.TABLES.TABLE_NAME = [tbl_Service].[Code] + 'Right'
        )
        GROUP BY [tbl_Service].[Code], [tbl_TableDefaultRight].[SubjectAdminUnitID]
        ORDER BY [tbl_Service].[Code]

open DefaultRightCursor
fetch next FROM DefaultRightCursor INTO
  @Code
, @AdminUnitID
, @CanRead
, @CanWrite
, @CanDelete
, @CanChangeAccess
while @@fetch_status = 0
begin
        SET @InsertQueryExecutable = REPLACE(@InsertQuery, '@Code', @Code)
        SET @InsertQueryExecutable = REPLACE(@InsertQueryExecutable, '@AdminUnitID', @AdminUnitID)
        SET @InsertQueryExecutable = REPLACE(@InsertQueryExecutable, '@CanRead', @CanRead)     
        SET @InsertQueryExecutable = REPLACE(@InsertQueryExecutable, '@CanWrite', @CanWrite)   
        SET @InsertQueryExecutable = REPLACE(@InsertQueryExecutable, '@CanDelete', @CanDelete) 
        SET @InsertQueryExecutable = REPLACE(@InsertQueryExecutable, '@CanChangeAccess', @CanChangeAccess)     
        print @InsertQueryExecutable
        --EXECUTE sp_executesql @InsertQueryExecutable
        print '---------------------------------------'
        SET @UpdateQueryExecutable = REPLACE(@UpdateQuery, '@Code', @Code)
        SET @UpdateQueryExecutable = REPLACE(@UpdateQueryExecutable, '@AdminUnitID', @AdminUnitID)
        SET @UpdateQueryExecutable = REPLACE(@UpdateQueryExecutable, '@CanRead', @CanRead)     
        SET @UpdateQueryExecutable = REPLACE(@UpdateQueryExecutable, '@CanWrite', @CanWrite)   
        SET @UpdateQueryExecutable = REPLACE(@UpdateQueryExecutable, '@CanDelete', @CanDelete) 
        SET @UpdateQueryExecutable = REPLACE(@UpdateQueryExecutable, '@CanChangeAccess', @CanChangeAccess)     
        print @UpdateQueryExecutable
        --EXECUTE sp_executesql @UpdateQueryExecutable
        print '--===================================--'

fetch next FROM DefaultRightCursor INTO
  @Code
, @AdminUnitID
, @CanRead
, @CanWrite
, @CanDelete
, @CanChangeAccess
end
close DefaultRightCursor
deallocate DefaultRightCursor

Нравится

Поделиться

6 комментариев

Анатолий, у вас два существенных недочета:
1. Вы никак не анализируете, кто создал запись, на которую вы раздаете записи по умолчанию - через колонку RecordId, необходимо смотреть значение CreatedBy. Ведь это самое важно в них - права по умолчанию, могут существенно отличаться от того в какие роли входит текущий пользователь. Возможно конечно это было желание заказчика, но я не у видел в ТЗ этого пункта :) Или у заказчика права по умолчанию настраивались только на корневую роль?
2. Вы обновляете доступ по записям, которые возможно кто-то добавил сам - не через механизм прав по умолчанию. В таком случае, если это опять же было требование заказчика, то вы должны были удалить весь доступ на записи и просто выполнить вставку, новых записей по умолчанию, но с учетом п. 1

Здравствуйте, Александр!

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

А вот о втором пункте я думал, но смирился с неизбежным. Я просто не представляю как отличить добавленные вручную записи от записей, созданных автоматически. Поэтому счёл что вручную добавляют именно то, чего по умолчанию нет - потому и не очищал все права по RecordID, а только обновлял и добавлял.

Анатолий, думаю во втором пункте намного проще удалить все записи с детали доступ и просто вставлять все согласно настроек доступа по умолчанию.

Выкладываю свой вариант перераздачи прав на записи согласно правам по умолчанию (может кому пригодиться и сэкономит время).

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

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

Сначала удаляются все права на записи для групп пользователей (см. деталь "Доступ" контрагента, счета, продажи и т.д.)
Далее добавляются права на все записи на группы пользователей согласно правам доступа по умолчанию (см. раздел "Администрирование" вкладку "Права доступа по умолчанию").

И вот сам SQL-код, в котором я использую транзакции для отката изменений в случае ошибки, а также вывожу какие таблицы были обработаны и информацию об ошибке, если таковая возникла.

Как и в примере из топика, нужно снять комментарии из строк с EXECUTE.

DECLARE @RightsTableCode nvarchar(100);
DECLARE @TableCode nvarchar(100);
 
DECLARE @DeleteQuery nvarchar(4000);
DECLARE @DeleteQueryExec nvarchar(4000);
 
DECLARE @InsertQuery nvarchar(max);
DECLARE @InsertQueryExec nvarchar(max);
 
DECLARE @ServiceTableID uniqueidentifier;
 
SET @DeleteQuery = 'DELETE FROM @RightsTableCode
	WHERE EXISTS (SELECT ID FROM tbl_AdminUnit AS AU WHERE AU.IsGroup = 1 AND AU.ID = @RightsTableCode.AdminUnitID)';
 
SET @InsertQuery = 'INSERT INTO @RightsTableCode(
    ID
    ,RecordID
    ,AdminUnitID
    ,CanRead
    ,CanWrite
    ,CanDelete
    ,CanChangeAccess)
  SELECT
    newid()
    ,I.ID
    ,D.SubjectAdminUnitID
    ,D.CanRead
    ,D.CanWrite
    ,D.CanDelete
    ,D.CanChangeAccess
  FROM (
    SELECT
      D.SubjectAdminUnitID
      ,MAX(D.CanRead) AS CanRead
      ,MAX(D.CanWrite) AS CanWrite
      ,MAX(D.CanDelete) AS CanDelete
      ,MAX(D.CanChangeAccess) AS CanChangeAccess
    FROM tbl_TableDefaultRight AS D
    LEFT OUTER JOIN tbl_AdminUnit AS AU ON AU.ID = D.SubjectAdminUnitID
    WHERE (D.TableServiceID = ''@ServiceTableID'')
		AND (AU.IsGroup = 1)
  GROUP BY D.SubjectAdminUnitID)
	AS D, @TableCode I';
 
DECLARE c_Something CURSOR FOR
	SELECT Code FROM tbl_Service
	WHERE ServiceTypeCode = 'Table' AND Code LIKE 'tbl_%Right' AND Code NOT LIKE 'tbl_%GroupRight';
 
OPEN c_Something;
FETCH NEXT FROM c_Something INTO @RightsTableCode
WHILE @@FETCH_STATUS =0
BEGIN
	PRINT @RightsTableCode;
	SET @TableCode = REPLACE(@RightsTableCode, 'Right', '');
	PRINT @TableCode;
 
	SET @ServiceTableID = (SELECT ID FROM tbl_Service WHERE Code = @TableCode AND ServiceTypeCode = N'Table');
 
	IF (@ServiceTableID IS NOT NULL) 
		BEGIN
		BEGIN TRAN
		BEGIN TRY
 
			-- delete group rights
			SET @DeleteQueryExec = REPLACE(@DeleteQuery, '@RightsTableCode', @RightsTableCode);
			PRINT @DeleteQueryExec;
			--EXECUTE sp_executesql @DeleteQueryExec;
 
			-- insert group rights
			SET @InsertQueryExec = REPLACE(@InsertQuery, '@RightsTableCode', @RightsTableCode);
			SET @InsertQueryExec = REPLACE(@InsertQueryExec, '@TableCode', @TableCode);
			SET @InsertQueryExec = REPLACE(@InsertQueryExec, '@ServiceTableID', @ServiceTableID);
			PRINT @InsertQueryExec;
			--EXECUTE sp_executesql @InsertQueryExec;
 
		COMMIT TRAN
		END TRY
		BEGIN CATCH
			SELECT 
				ERROR_NUMBER() AS ErrorNumber,
				ERROR_SEVERITY() AS ErrorSeverity,
				ERROR_STATE() as ErrorState,
				ERROR_PROCEDURE() as ErrorProcedure,
				ERROR_LINE() as ErrorLine,
				ERROR_MESSAGE() as ErrorMessage;
 
			ROLLBACK TRAN
		END CATCH 
		END;
 
    FETCH NEXT FROM c_Something INTO @RightsTableCode;
END
CLOSE c_Something
DEALLOCATE c_Something

Далее есть идея добавить действие в разделе "Администрирование", назвать его "Обновить/перераздать права на записи согласно правам по умолчанию". Перебор таблиц и записей вынести в Террасофт, чтобы иметь возможность отображать прогресс бар с двумя полосами:
первая - прогресс по таблицам (вывод названия таблицы и кол/общ_кол)
вторая - прогресс по записям текущей таблицы (вывод кол/общ_кол)

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

Реализованная идея описана здесь.

Показать все комментарии

Добрый день всем!
У всех ли так ведет себя Терасофт (3.3.1.124) с правами доступа по умолчанию и является ли это нормальным его поведением?
Ситуация в следующем: есть группа пользователей, этой группе пользователей на раздел Контакты даны права по умолчанию. Пользователь входил в эту группу. Таким образом когда пользователь создаёт Контакт, то вся его группа имеет на этот контакт расширенные права. В дальнейшем пользователя удаляю из этой группы и добавляю в другую, у которой тоже есть свои права по умолчанию. Когда теперь пользователь создаёт контакт, то права по умолчанию даются той группе в которой он находится сейчас и (!!!) той группе, в которой он находился раньше.
Мне кажется такое поведение прав доступа по умолчанию некорректным. Как его исправить? У кого какие возражения?

Нравится

14 комментариев

Ну как бы это нехорошо работает... вроде не должно такого быть
а группа "Все пользователи" у вас кому права по-умолчанию дает? может отсюда ноги растут если этот пользователь в ней еще состоит... и сам он лично кому права по-умолчанию дает, надо все варианты проверить
вообще скрины настройки прав и детали "группы" для пользователя в студию:smile:

Как видно из прикрепленных картинок группа Все пользователи(pic1) дает ограниченные права всем пользователям и полные права группе администраторов. Аналогичные скрины с правами по умолчанию для групп Call-центр(pic2) и Бронисты(pic3). Скрин с группами, в которые входит пользователь - pic4. Результат создания записи в разделе контакты - деталь Права доступа - pic5. Явно здесь строка Бронисты лишняя.

А скрин где права по умолчанию для самого пользователя (не для группы)? вот если и там Бронисты не фигурируют...

Права по умолчанию конкретных пользователей пока не было надобности настраивать, поэтому про этот скрин забыл. Но и там бронисты не фигурируют (pic6).

"Ozzy" написал:Права по умолчанию конкретных пользователей пока не было надобности настраивать, поэтому про этот скрин забыл. Но и там бронисты не фигурируют (pic6).

я надеялся может там оно(( видимо вопрос теперь осилят только великие кудесники технической поддержки...

Посмотрите, пожалуйста, с помощью профайлера, какие запросы выполняются при добавлении нового контакта этим пользователем. Особенно интересуют запросы на вставку (Insert).

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

Пользователя из одной группы в другую я перенес давно (около месяца назад). Просто проблему заметил только сейчас. Пользователь просто добавляет Контакт.
SQLMonitor'ом удалось отследить что вставка происходит в две таблицы "tbl_CompetitiveSession" и "vw_Contact". К правам доступа они не имеют никакого отношения. Делаем вывод, что раздача прав происходит на уровне триггеров сервера, генерируемыми автоматически Администратором. Сервер Oracle.
В триггере права берутся из таблицы "tbl_ContactRight". А вот почему при удалении пользователя из группы не удалились права по умолчанию для этого (и для других тоже) пользователя я не скажу. Что и где надо исправить чтобы в дальнейшем работало всё корректно и как привести права по умолчанию в соответствие с текущими настройками пользователей и групп?

Проблема только при добавлении контактов, или возникает также и при добавлении записей в другие разделы? Если только с контактами, проверьте, пожалуйста, тексты триггеров на вставку у tbl_Contact и vw_Contact. Если с ними всё в порядке (принципиально не отличаются от других триггеров), значит, необходимо анализировать записи таблиц tbl_AdminUnit, tbl_UserAdminUnit, tbl_UserInGroup, связанные с пользователем.

Может помочь отвязка пользователя от всех групп и привязка заново. Если не поможет, попробуйте выполнить хранимую процедуру tsp_UpdateAllUsersGroup, которая восстановит актуальную информацию по пользователям в группах. Крайне желательно перед выполнением сделать резервную копию базы.

Аналогичная проблема возникает и с Контрагентами. На других разделах не проверял, потому что права по умолчанию не раздавались. В триггерах на представление vw_Contact права не выставляются. А вот в триггере на tbl_Account (tbl_Contact тоже) права берутся из таблицы tbl_TableDefaultRight. В предыдущем посте

"Ozzy" написал:В триггере права берутся из таблицы "tbl_ContactRight". А вот почему при удалении пользователя из группы не удалились права по умолчанию для этого (и для других тоже) пользователя я не скажу.

закралась неточность. Вместо tbl_ContactRight следует читать tbl_TableDefaultRight.
Триггеры для таблицы контактов и контрагентов принципиально не отличаются от других триггеров. Они были созданы автоматически системой и не изменялись. Отвязка пользователя от всех групп и привязка заново с перезаходом пользователя в систему (хотя это лишне) не привели к желаемому результату.
Поэтому смею предположить что проблема в базовой конфигурации и требует исправления: при удалении пользователя из группы не происходит удаление прав по умолчанию из таблицы tbl_TableDefaultRight для этого пользователя.
Процедуру tsp_UpdateAllUsersGroup не выполнял, потому что, во-первых, если она и решит эту проблему, то только на один раз и, во-вторых, она не исправит права доступа на уже созданные записи в таблицах контактов, контрагентов. Считаю что сперва необходимо устранить источник такой ошибки.

Можете выгрузить из Вашей конфигурации все сервисы и выслать на адрес support@tscrm.com для сравнения с базовыми? Дело в том, что при попытке воспроизвести ситуацию на конфигурации, на которой изначально велась разработка Вашего проекта, права по умолчанию раздались корректно. Если Вы не вносили изменений в базовые хранимые процедуры, тогда причина в сервисах.

Сервисы лучше выгружать утилитой tsmergeservices.exe с параметрами: /cfg="<Название конфигурации>" /usr="<Имя пользователя>" /pwd=<Пароль> /fmt=true /js=true

Ушло письмо на сапорт с сервисами.

Как оказалось, проблема была в том, что не отрабатывало удаление в конце процедуры tsp_LoadUserAdminUnit:

DELETE FROM "tbl_UserAdminUnit"
  WHERE UPPER("UserName") = RoleName
    AND NOT EXISTS(
      SELECT *
      FROM (
        SELECT DISTINCT
         au."ID" AS "AdminUnitID",
         drp.granted_role AS "AdminUnitName",
         RoleName AS "UserName"
	 FROM DBA_ROLE_PRIVS drp,
       "tbl_AdminUnit" au
	 WHERE UPPER(au."SQLObjectName") = UPPER(drp.granted_role)
   START WITH UPPER(drp.grantee) = RoleName
	 CONNECT BY PRIOR drp.granted_role = drp.grantee
	 UNION
	 SELECT AdminUnitID, RoleName, RoleName
 	 FROM dual) t
   WHERE t."AdminUnitID" = "tbl_UserAdminUnit"."AdminUnitID"
   AND UPPER("tbl_UserAdminUnit"."UserName") = RoleName);

А именно, хотя внутренний запрос (SELECT DISTINCT) возвращал корректные значения, но выборка из этого результата внешним запросом (SELECT *) возвращала пустой набор данных. Почему так происходило, определить не удалось. Александр, у наших разработчиков возникло предположение, что на Вашей версии Oracle установлены не все обновления, которые есть на текущий момент. Возможно, проблема была в этом.

Решить удалось путём изменения запроса таким образом, чтобы убрать внешний SELECT:

DELETE FROM "tbl_UserAdminUnit"
  WHERE UPPER("UserName") = RoleName
    AND "AdminUnitID" NOT IN (
        SELECT DISTINCT
         au."ID"
     FROM DBA_ROLE_PRIVS drp,
       "tbl_AdminUnit" au
     WHERE UPPER(au."SQLObjectName") = UPPER(drp.granted_role)
   START WITH UPPER(drp.grantee) = RoleName
     CONNECT BY PRIOR drp.granted_role = drp.grantee
     UNION
     SELECT AdminUnitID
      FROM dual);

Спасибо, всё заработало как надо.

Показать все комментарии

Создаю раздел с помощью конструктора, затем пользователи начинают им пользоваться (логично).
Но. Пользователи по умолчанию создают в нем записи с закрытым доступом (только для себя).

Подскажите пожалуйста, как сделать так, чтобы по умолчанию пользователь создавал в новоиспеченном разделе записи с доступом "Все пользователи"?

Нравится

3 комментария

А в разделе "Администрирование" во вкладке "Права по умолчанию" для этого раздела у вас какой доступ стоит? Попробуйте поставить "Все пользователи"

Если Вы создали новый раздел конструктором, то после этого Вам необходимо:

1. Выставить права на новый раздел в "Администрирование" - "Права доступа к группе таблиц"
2. Выставить права в "Администрирование" - "Права доступа по умолчанию"

Спасибо, права по умолчанию помогли.

Показать все комментарии