07.02.2019, 10:39 | #1 |
Участник
|
Хранение настроек плагинов
Коллеги, поделитесь опытом, кто как реализует хранение настроек плагинов. Я имею в виду, например, параметры доступа к внешним ресурсам, вроде строк подключения к БД и пр.
Для себя выделил несколько возможных вариантов, все со своими плюсами и минусами. Да и кстати, речь идет об on-premises (с онлайном, понятно будут другие варианты). |
|
07.02.2019, 11:28 | #2 |
Moderator
|
Однозначно не рекомендую варианты с файлом и внешним сервисом. Файл нельзя достать из песочницы + возникают дополнительные сложности с мульти-тенант развертыванием (несколько баз организации на одном сервере) и переносом решения. Кроме того, будет серьезная просадка производительности за счет чтения из файла. Для плагинов это не столь критично, так как каждый инстанс создается один раз, а вот для рабочих процессов ситуация будет однозначно хуже.
MS использует сущности с атрибутами (отдельные объекты под группу настроек). Перенос рекомендуется делать через Package Deployer / Configaration Migration. Не совсем понятно, почему Action не защищен от пользователей? C лукапами, пожалуй, тоже нет проблем. Вцелом, я рассматривую Action как альтернативу сущностям, но они создают определенные сложности при обновлении:
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
07.02.2019, 12:04 | #3 |
Участник
|
Цитата:
По поводу сущностей, есть одна проблема. Давай всем пользователям доступ к сущности настроек - это значит любой пользователь через расширенный поиск или импорт сможет все посмотреть. Если права на чтение будут только у админа, значит для каждого шага плагина, который использует настройки нужно указывать этого пользователя в Run in user's context, чтобы от имени этого пользователя можно было обратиться к настройкам. А значение этого поля при переносе со среды на среду может слетать. |
|
07.02.2019, 13:16 | #4 |
Moderator
|
Вы можете использовать пользователя SYSTEM он один на все CRM в мире.
p.s. Альтернатива, как всегда, утки - для этого и существует secure config. Есть готовые скрипты PowerShell чтобы можно было править их автоматизированно: https://github.com/WaelHamze/xrm-ci-framework
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
07.02.2019, 15:59 | #5 |
Чайный пьяница
|
Цитата:
Сообщение от ZooY
Потому что вызвать его может любой пользователь. Защита основана только на том, что пользователь не знает ключей настроек.
По поводу сущностей, есть одна проблема. Давай всем пользователям доступ к сущности настроек - это значит любой пользователь через расширенный поиск или импорт сможет все посмотреть. Если права на чтение будут только у админа, значит для каждого шага плагина, который использует настройки нужно указывать этого пользователя в Run in user's context, чтобы от имени этого пользователя можно было обратиться к настройкам. А значение этого поля при переносе со среды на среду может слетать. 1. Все настройки хранятся в кастономной сущности (одна запись и много полей или много записей типа пара ключ/значение - на ваше усмотрение). 2. У обычных пользователей нет прав на зачитку этих сущностей. 3. В коде плагинов при помощи подхода, указанного ранее, получаете доступ к настройкам вне зависимости от того, кто вызвал запуск плагина - простой юзер или юзер с доступом к настройкам.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
07.02.2019, 16:22 | #6 |
Участник
|
Цитата:
Если пользователь не указан явно, то подставляется Calling User, т.е. в контексте плагина свойства UserId и InitiatingUserId равны и ссылаются на конченого пользователя (прав на чтение настроек у которого нет). Это логично с точки зрения безопасности, но создает проблему в случае с настройками. В принципе, нет проблемы указать привилегированного пользователя при настройках шага плагина, но проблема в том, что порой эта настройка не переноситься при переносе плагина решением. Возможно дело в каких то отличиях в именовании пользователя и возможно этот момент можно отладить. |
|
07.02.2019, 16:46 | #7 |
Чайный пьяница
|
Читаем внимательно это - https://docs.microsoft.com/en-us/dot...s-general-ce-9
А именно, цитирую: Код: When called in a plug-in, a null value indicates the SYSTEM user
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
За это сообщение автора поблагодарили: ZooY (1). |
11.02.2019, 17:20 | #8 |
Участник
|
У меня какой то взрыв мозга... Попытался проверить поведение Organization Service в плагине при разных идентификаторах пользователя...
Попробовал получать экземпляр сервиса с разными идентификаторами пользователей, для каждого экземпляра выполнял WhoAmIRequest и надеялся получить разных пользователей на выходе. Собственно, вот код плагина: X++: public class GetUsers : IPlugin { public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); var result = ""; var service1 = factory.CreateOrganizationService(null); result += $"null = {GetUserInfo(service1)}"; var service2 = factory.CreateOrganizationService(Guid.Empty); result += $"Guid.Empty ({Guid.Empty}) = {GetUserInfo(service2)}"; var service3 = factory.CreateOrganizationService(context.UserId); result += $"UserId ({context.UserId}) = {GetUserInfo(service3)}"; var service4 = factory.CreateOrganizationService(context.InitiatingUserId); result += $"InitiatingUserId ({context.InitiatingUserId}) = {GetUserInfo(service4)}"; throw new InvalidPluginExecutionException(result); } private static string GetUserInfo(IOrganizationService service) { var request = new WhoAmIRequest(); var response = (WhoAmIResponse)service.Execute(request); var userId = response.UserId; var user = service.Retrieve("systemuser", userId, new ColumnSet("fullname")); var data = $"{userId} | {user.GetAttributeValue<string>("fullname")}{Environment.NewLine}"; return data; } } X++: null = 34248a5f-bf3e-4f3c-95c2-882424d25d37 | SYSTEM
Guid.Empty (00000000-0000-0000-0000-000000000000) = 34248a5f-bf3e-4f3c-95c2-882424d25d37 | SYSTEM
InitiatingUserId (c69c88fb-4e41-e811-a214-83daa2756e35) = 34248a5f-bf3e-4f3c-95c2-882424d25d37 | SYSTEM
UserId (e73922d1-d7ec-e811-a224-ddda898a939f) = 34248a5f-bf3e-4f3c-95c2-882424d25d37 | SYSTEM Как так? |
|
11.02.2019, 17:36 | #9 |
Чайный пьяница
|
Покажите, пожалуйста, настройку шага из Plugin Registration Tool-а.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
11.02.2019, 17:42 | #10 |
Участник
|
Вот...
|
|
11.02.2019, 18:07 | #11 |
Участник
|
Еще попробовал посоздовать записи от имени разных сервисов... Результат - все записи созданы от имени SYSTEM. Попробовал на двух системах - 2016 и 365
|
|
11.02.2019, 19:32 | #12 |
Чайный пьяница
|
Попробуйте сменить "Run in User's Context" на "Calling User".
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
11.02.2019, 23:09 | #13 |
Участник
|
Попробовал. Ничего не поменялось (кроме того что UserId и InitiatingUserId стали ровны).
|
|
12.02.2019, 09:04 | #14 |
Moderator
|
Я наблюдал похожее, когда службы CRM (в частности, application pool) были запущены под учетными записями пользователей. Вы точно ничего не запустили под Натальей Вороновой?
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
12.02.2019, 09:44 | #15 |
Участник
|
Цитата:
Кроме того я проверял на 2 системах вообще в двух разных компаниях. Даже способ развертывания и версии CRM отличаются. Картина одинаковая - все что делает сервис в плагине делается от имени SYSTEM. Может кто-то у себя сможет проверить, код плагина в посте выше... Сравним результаты... |
|
12.02.2019, 11:07 | #16 |
Участник
|
Попробуйте вот так, без WhoAmIRequest
X++: result += string.Format("Caller User Id = {0}",((OrganizationServiceProxy)factory.CreateOrganizationService(context.UserId)).CallerId); result += string.Format("User System Id = {0}", ((OrganizationServiceProxy)factory.CreateOrganizationService(null)).CallerId);
__________________
Читайте SDK!!! |
|
12.02.2019, 15:50 | #17 |
Участник
|
У меня задача не ID верные получить, а убедиться, что имперсонализация в сервисе работает и сервис выполняет действия от имени указанных пользователей. А он почему то этого не делает.
|
|
12.02.2019, 16:22 | #18 |
Участник
|
Цитата:
Использовать из плагина WhoAmIRequest нет смысле, он всегда вернет SYSTEM СРМ же работает на основании CallerId поэтому я и хотел что бы ва проверили Я такой трик с SYSTEM использую очень часто и все работает в соответствии с правами эзера, систем видит все, остальные юзеры только то что положено
__________________
Читайте SDK!!! |
|
12.02.2019, 17:12 | #19 |
Участник
|
CallerId я проверил - он совпадает с ID пользователя (в случае null - нулевой GUID, в случае с Empty - равен UserId).
То есть вы проверяли и импенсонализация все таки работает и на запросы накладываются все ограничения в соответствии с ролями пользователей, даже не смотря на то, что везде (даже в createdby, modifiedby) фигурирует SYSTEM? |
|