Контроль прав пользователей при изменении категорий объектов

30.09.12

Разработка - Инструментарий разработчика

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

Скачать файлы

Наименование Файл Версия Размер
ПраваНаКатегории.zip
.zip 15,29Kb
22
.zip 15,29Kb 22 Скачать

Предисловие

Бухгалтерия захотела отражать в 1С:УПП факт того, что она получила бумажные оригиналы документов. Желание в целом законное и очень даже правильное. Наличие такого признака у документов в программе позволяет отслеживать наличие первички и вовремя принимать меры к взысканию оной с контрагентов, которые её задерживают.
Первой мыслью было добавить нужным документам реквизит или категорию "Оригинал получен". Идея с заведением категории нравилась больше, т.к. одну категорию можно навесить сразу на все нужные виды документов, не нужно корёжить формы документов чтобы вывести на них реквизит (или править модули форм чтобы сделать это программно), при установке категории не нужно пересохранять (перепроводить) документ, что особенно актуально для закрытых периодов. Но было одно отягчающее обстоятельство - нужно чтобы этот признак могли установить только уполномоченные на то пользователи.

Задача

Обеспечить возможность разграничения прав пользователей для работы с категориями объектов в 1С: УПП.

Шаг 1. Добавляем регистр для хранения сведений о правах пользователей и код для работы с ним.

Вообще таких велосипедов, как регистр сведений, хранящий права пользователей, наделано уже великое множество. И каждый волен выбрать себе тот велосипед, который ему больше по душе. Для нашей задачи главное чтобы имелась в наличии экспортная функция общего модуля Функция ПолучитьРазрешенныеСвойстваИКатегории(Пользователь, СписокСвойствИКатегорий = Неопределено) Экспорт, которая будет возвращать массив категорий, которые Пользователь имеет право изменять (в параметре СписокСвойствИКатегорий передаётся интересующая нас категория или массив категорий; Неопределено в этом параметре означает что нас интересуют права на все категории). Если такая функция у вас уже есть - можно переходить к шагу 2.

Мой "велосипед" таков (в моём регистре помимо прав на изменение категорий можно также задавать права на изменение свойств объектов - это задел на будущее когда понадобится ещё разграничивать права пользователей на установку свойств объектов):


1. Непериодический независимый регистр сведений Префикс_ПраваДоступаДляДопСвойств ("Префикс" замените на свой префикс разработчика), имеющий
Измерения

- Субъект - тип {СправочникСсылка.Пользователи, СправочникСсылка.ГруппыПользователей}, Ведущее, Основной отбор;
- ОбъектДоступа - тип {СправочникСсылка.КатегорииОбъектов, ПланВидовХарактеристикСсылка.СвойстваОбъектов}, Ведущее, Основной отбор, Запрет незаполненных значений;

Ресурсы

- ДоступРазрешен - тип Булево.

Определение прав пользователя осуществляется следующим образом. Самым высоким приоритетом обладает право установленное для конкретного пользователя, более низким приоритетом обладает право установленное для группы, в которую входит данный пользователь, и, наконец, самым низким приоритетом обладает право установленное для всех пользователей (в качестве Субъекта указана предопределённая группа "Все пользователи" или Субъект не заполнен). В качестве права пользователя берётся право с максимальным приоритетом (пользователь->группа->все). Если право для пользователя не найдено, то считается что доступ пользователю запрещён.

 

В приведённом примере Пользователь1 не имеет прав на изменение категории "Категория1" (запрет задан явно для этого пользователя), хотя все остальные пользователи имеют право на изменение этой категории (право дано через группу "Все пользователи"). Пользователь1 имеет право на изменение категории "Категория3" (право дано всем пользователям, т.к. не указан Субъект) и изменение свойства "Торговая марка" (право задано явно для этого пользователя). Все пользователи группы Группа1 имеют право изменять категорию "Категория2".

2. Функция ПолучитьРазрешенныеСвойстваИКатегории() для получения массива категорий, которые пользователь имеет право изменять:

Функция ПолучитьРазрешенныеСвойстваИКатегории(Пользователь, СписокСвойствИКатегорий = Неопределено) Экспорт
	
	// 
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Пользователь", Пользователь);
	Запрос.УстановитьПараметр("СписокСвойствИКатегорий", СписокСвойствИКатегорий);

	ВсеСубъекты = Новый Массив; // через этих субъектов устанавливаются права вообще всем пользователям
	ВсеСубъекты.Добавить(Неопределено);
	ВсеСубъекты.Добавить(Справочники.Пользователи.ПустаяСсылка());
	ВсеСубъекты.Добавить(Справочники.ГруппыПользователей.ПустаяСсылка());
	ВсеСубъекты.Добавить(Справочники.ГруппыПользователей.ВсеПользователи);	
	Запрос.УстановитьПараметр("ВсеСубъекты", ВсеСубъекты);
	
	Запрос.Текст =
	"ВЫБРАТЬ
 | ГруппыПользователейПользователиГруппы.Ссылка
 |ПОМЕСТИТЬ ВТ_ГруппыПользователя
 |ИЗ
 | Справочник.ГруппыПользователей.ПользователиГруппы КАК ГруппыПользователейПользователиГруппы
 |ГДЕ
 | ГруппыПользователейПользователиГруппы.Пользователь = &Пользователь
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ
 | ВЫБОР
 | КОГДА ПраваДоступаДляДопСвойств.Субъект = &Пользователь
 | ТОГДА 3
 | КОГДА ПраваДоступаДляДопСвойств.Субъект ССЫЛКА Справочник.ГруппыПользователей
 | И НЕ ПраваДоступаДляДопСвойств.Субъект В (&ВсеСубъекты)
 | ТОГДА 2
 | ИНАЧЕ 1
 | КОНЕЦ КАК Приоритет,
 | ПраваДоступаДляДопСвойств.ОбъектДоступа КАК ОбъектДоступа,
 | ПраваДоступаДляДопСвойств.ДоступРазрешен КАК ДоступРазрешен
 |ПОМЕСТИТЬ ВТ_ПраваДоступаСПриоритетами
 |ИЗ
 | РегистрСведений.Префикс_ПраваДоступаДляДопСвойств КАК ПраваДоступаДляДопСвойств
 |ГДЕ
 | (ПраваДоступаДляДопСвойств.Субъект = &Пользователь
 | ИЛИ ПраваДоступаДляДопСвойств.Субъект В
 | (ВЫБРАТЬ
 | ВТ_ГруппыПользователя.Ссылка
 | ИЗ
 | ВТ_ГруппыПользователя)
 | ИЛИ ПраваДоступаДляДопСвойств.Субъект В (&ВсеСубъекты))
 | И &УсловиеСписокСвойствИКатегорий
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ
 | ВТ_ПраваДоступаСПриоритетами.ОбъектДоступа КАК ОбъектДоступа
 |ИЗ
 | ВТ_ПраваДоступаСПриоритетами КАК ВТ_ПраваДоступаСПриоритетами
 | ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
 | ВТ_ПраваДоступаСПриоритетами.ОбъектДоступа КАК ОбъектДоступа,
 | МАКСИМУМ(ВТ_ПраваДоступаСПриоритетами.Приоритет) КАК Приоритет
 | ИЗ
 | ВТ_ПраваДоступаСПриоритетами КАК ВТ_ПраваДоступаСПриоритетами
 | 
 | СГРУППИРОВАТЬ ПО
 | ВТ_ПраваДоступаСПриоритетами.ОбъектДоступа) КАК ВложенныйЗапрос
 | ПО ВТ_ПраваДоступаСПриоритетами.ОбъектДоступа = ВложенныйЗапрос.ОбъектДоступа
 | И ВТ_ПраваДоступаСПриоритетами.Приоритет = ВложенныйЗапрос.Приоритет
 |ГДЕ
 | ВТ_ПраваДоступаСПриоритетами.ДоступРазрешен";
	
	
	УсловиеСписокСвойствИКатегорий = ?(СписокСвойствИКатегорий = Неопределено, 
				"ИСТИНА", 
				"ПраваДоступаДляДопСвойств.ОбъектДоступа В (&СписокСвойствИКатегорий)");
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеСписокСвойствИКатегорий", УсловиеСписокСвойствИКатегорий);
	
	Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ОбъектДоступа");
	
КонецФункции

Шаг 2. Добавляем подписку на событие ПередЗаписью для регистра сведений КатегорииОбъектов.

Сам контроль прав будем осуществлять через подписку на событие ПередЗаписью для регистра сведений КатегорииОбъектов (Источник события РегистрСведенийНаборЗаписей.КатегорииОбъектов):

Обработчик события такой:

Процедура Префикс_ПередЗаписьюКатегорийОбъекта(Источник, Отказ, Замещение) Экспорт
	
	Если Источник.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
	Заголовок = "Запись регистра сведений " + Источник.Метаданные().Имя + ":";
	
	ОтборИсточника = Источник.Отбор;
	Если НЕ ОтборИсточника.Категория.Использование Тогда
		ТекстСообщения = "Не установлен отбор по измерению ""Категория""!";
		ОбщегоНазначения.СообщитьОбОшибке(ТекстСообщения, Отказ, Заголовок);
		Возврат;
	КонецЕсли;
	
	ТекПользователь		= глЗначениеПеременной("глТекущийПользователь");
	Категория			= ОтборИсточника.Категория.Значение;
	РазрешенныеКатегории	= ПолучитьРазрешенныеСвойстваИКатегории(ТекПользователь, Категория);
	Если РазрешенныеКатегории.Найти(Категория) = Неопределено Тогда
		ТекстСообщения = "Недостаточно прав для изменения категории """ + Категория + """!";
		ОбщегоНазначения.СообщитьОбОшибке(ТекстСообщения, Отказ, Заголовок);
		Возврат;
	КонецЕсли;
	
КонецПроцедуры

Шаг 3. Модифицируем штатную обработку КатегорииОбъектов.

К сожалению, совсем обойтись без изменения штатных объектов не удалось. Дело в том, что штатная обработка КатегорииОбъектов, которая вызывается из форм справочников и документов по соответствующей кнопке, записывает регистр сведений КатегорииОбъектов набором записей с отбором только по Объекту. Если в записываемом наборе записей будут категории, которые пользователь не имеет права изменять и одновременно с этим в нём будут категории, которые пользователь изменять может, то мы не сможем ни записать такой набор, ни отказаться от его записи. Да, конечно можно просмотреть записываемый набор записей, найти в нём те категории, которые пользователь изменять не имеет права, прочитать значения этих категорий из базы и если прочитанные из базы значения отличаются от значений в наборе записей, то подменить значения изменённых категорий в наборе на значения  из базы, а пользователю сказать  "Ай-яй-яй!", но по-моему это излишне усложнит алгоритм. Тем более что другие обработки (в частности, "Групповая обработка ..."), пишут наборы записей с полным отбором по Объект+Категория.

Для исправления ситуации в модуле обработки КатегорииОбъектов была модифицирована Функция ЗаписатьКатегорииОбъекта() Экспорт так, чтобы запись регистра сведений осуществлялась с отбором по Объект+Категория.

// Функция записывеет категории объекта в информационную базу.
//
// Параметры:
// Нет.
//
// Возвращаемое значение:
// Истина - если категории объекта были записаны, или их не требуется записывать
// Ложь - если категории объекта не удалось записать.
//
Функция ЗаписатьКатегорииОбъекта() Экспорт

	// *** Разграничение прав пользователей на установку категорий объектов
	//НаборЗаписейКатегорииОбъекта = РегистрыСведений.КатегорииОбъектов.СоздатьНаборЗаписей();

	//Для каждого Строка Из КатегорииОбъекта Цикл
	// Если Строка.Принадлежность Тогда
	// Запись = НаборЗаписейКатегорииОбъекта.Добавить();

	// Запись.Объект = ОбъектОтбораКатегорий;
	// Запись.Категория = Строка.Категория;
	// КонецЕсли;
	//КонецЦикла;

	//НаборЗаписейКатегорииОбъекта.Отбор.Объект.Установить(ОбъектОтбораКатегорий);

	//Попытка
	// НаборЗаписейКатегорииОбъекта.Записать();
	//Исключение
	// #Если Клиент Тогда
	// Предупреждение("Не удалось записать категории объекта:" + Символы.ПС + ОписаниеОшибки());
	// #КонецЕсли
	// Возврат Ложь;
	//КонецПопытки;
	
	// ---------- заменено на:
	
	НачатьТранзакцию();
	
	// Прочитаем категории из БД
	НаборЗаписейБД = РегистрыСведений.КатегорииОбъектов.СоздатьНаборЗаписей();
	НаборЗаписейБД.Отбор.Объект.Установить(ОбъектОтбораКатегорий);
	НаборЗаписейБД.Прочитать();
	УстановленныеКатегорииБД = НаборЗаписейБД.ВыгрузитьКолонку("Категория");
	
	// Получим разрешенные категории
	ТекПользователь			= глЗначениеПеременной("глТекущийПользователь");
	РазрешенныеКатегории	= Префикс_ПраваДоступаДляДопСвойств.ПолучитьРазрешенныеСвойстваИКатегории(ТекПользователь, КатегорииОбъекта.ВыгрузитьКолонку("Категория"));
	
	Для каждого Строка Из КатегорииОбъекта Цикл
	
		ПринадлежностьПоДаннымБД = (УстановленныеКатегорииБД.Найти(Строка.Категория) <> Неопределено);
		
		Если ПринадлежностьПоДаннымБД = Строка.Принадлежность Тогда
			// значение данной категории не изменилась
			Продолжить;
		ИначеЕсли РазрешенныеКатегории.Найти(Строка.Категория) = Неопределено Тогда
			// у пользователя нет прав
			ОтменитьТранзакцию();
			ТекстСообщения = "Недостаточно прав для изменения категории """ + Строка.Категория + """!";
 #Если Клиент Тогда
				Предупреждение(ТекстСообщения);
 #Иначе
				Сообщить(ТекстСообщения, СтатусСообщения.Важное);
 #КонецЕсли
			Возврат Ложь;
		КонецЕсли;
		
		НаборЗаписейКатегорииОбъекта = РегистрыСведений.КатегорииОбъектов.СоздатьНаборЗаписей();

		НаборЗаписейКатегорииОбъекта.Отбор.Объект.Установить(ОбъектОтбораКатегорий);
		НаборЗаписейКатегорииОбъекта.Отбор.Категория.Установить(Строка.Категория);
		
		Если Строка.Принадлежность Тогда
			Запись = НаборЗаписейКатегорииОбъекта.Добавить();

			Запись.Объект    = ОбъектОтбораКатегорий;
			Запись.Категория = Строка.Категория;
		КонецЕсли;		
		
		Попытка
			НаборЗаписейКатегорииОбъекта.Записать();
		Исключение
			ОтменитьТранзакцию();
			Сообщить("Не удалось записать категории объекта:" + Символы.ПС + ОписаниеОшибки(), СтатусСообщения.Важное);
			Возврат Ложь;
		КонецПопытки;
		
	КонецЦикла;
	
	ЗафиксироватьТранзакцию();
	
	Возврат Истина;
	// Разграничение прав пользователей на установку категорий объектов ***
	
КонецФункции

Заключение

В прилагаемом архиве текстовые файлы с кодом процедур и функций, приведённых выше, а также модифицированная обработка КатегорииОбъектов с изменённиями в функции ЗаписатьКатегорииОбъекта(), описанными в разделе "Шаг 3".

Буду рад дельным замечаниям и предложениям по теме в комментариях (если кто знает как более просто и изящно решить задачу с добавлением признака "Оригинал получен" - обязательно поделитесь опытом).

Все права на код обработки КатегорииОбъектов принадлежат фирме 1С.

Весь остальной код - под GPLv3, а текст под CC-BY.

P.S. Возможно, обработку КатегорииОбъектов имеет смысл ещё немного допилить чтобы в табличную часть КатегорииОбъекта выводились только те категории, которые пользователь имеет право изменять (ну или выводить все, но строки с запрещёнными для изменения категориями делать недоступными для редактирования).

См. также

SALE! 20%

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 10400 руб.

02.09.2020    122180    670    389    

714

SALE! 25%

Infostart PrintWizard

Пакетная печать Печатные формы Инструментарий разработчика Платформа 1С v8.3 Запросы 1С:Зарплата и кадры бюджетного учреждения 1С:Конвертация данных 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Платные (руб)

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

18000 15300 руб.

06.10.2023    7298    21    6    

39

SALE! 20%

Infostart УДиФ: Управление данными и формами

Инструменты администратора БД Инструментарий разработчика Роли и права Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

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

10000 8000 руб.

10.11.2023    3545    11    1    

34

SALE! 30%

PowerTools

Инструментарий разработчика Инструменты администратора БД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Платные (руб)

Универсальный инструмент программиста для администрирования конфигураций. Сборник наиболее часто используемых обработок под единым интерфейсом.

3600 2520 руб.

14.01.2013    177760    1073    0    

849

Многопоточность. Универсальный «Менеджер потоков» 2.1

Инструментарий разработчика Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

Восстановление партий или взаиморасчетов, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее. * Есть желание повысить скорость работы медленных алгоритмов! Но... * Нет времени думать о реализации многопоточности? * о запуске и остановке потоков? * о поддержании потоков в рабочем состоянии? * о передаче данных в потоки и как получить ответ из потока? * об организации последовательности? Тогда ЭТО - то что надо!!!

5000 руб.

07.02.2018    99349    239    97    

296

[ЕХТ] Фреймворк для Расширений 1С

Инструментарий разработчика Платформа 1С v8.3 Управляемые формы Платные (руб)

"Фреймворк для Расширений 1С" это универсальное и многофункциональное решение, упрощающее разработку и поддержку создаваемых Расширений. Поставляется в виде комплекта из нескольких Расширений с открытым исходным кодом. Работает в любых Конфигурациях в режиме Управляемого приложения с режимом совместимости 8.3.12 и выше без необходимости внесения изменений в Конфигурацию.

3000 руб.

27.08.2019    18118    6    8    

40

1С HTML Шаблоны / HTML Templates

Инструментарий разработчика Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Быстрая и удобная обработка для работы с шаблонами HTML. Позволяет легко и быстро формировать код HTML.

2040 руб.

27.12.2017    28111    3    10    

15

Выполнение произвольного кода или запроса с параметрами через Web-сервис (замена COM-подключений)

Инструментарий разработчика Обмен между базами 1C Платформа 1С v8.3 Платные (руб)

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

2400 руб.

24.09.2019    23605    15    15    

32
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. iov 406 30.09.12 22:54 Сейчас в теме
А тоже самое без вмешательства в штатный код?
2. q_i 577 30.09.12 23:08 Сейчас в теме
(1) iov, с удовольствием бы, но пока увы. есть идеи? ;)
3. iov 406 30.09.12 23:21 Сейчас в теме
(2) Есть - но не поделюсь... Ибо последствия решения задачи разными способами - на совести "решателя".
Просто хотел натолкнуть на мысль решения проблемы с минимальным изменением конфы.
4. q_i 577 30.09.12 23:43 Сейчас в теме
(3) iov,
Есть - но не поделюсь...
Просто хотел натолкнуть на мысль решения проблемы с минимальным изменением конфы.

Ну теперь даже и не знаю стоит ли мне браться за решение данной задачи - вдруг тоже решу, а потом делиться не захочется. ))
5. iov 406 30.09.12 23:50 Сейчас в теме
(5) Нет я не за жадность - просто я не считаю это чем-то что поможет кому-то и потому нет желания захламлять ресурс... Так что если Вы не захотите делится - это вполне нормально... Не все мысли должны покидать голову.
6. q_i 577 01.10.12 11:22 Сейчас в теме
(5) iov, успокоили. спасибо!
7. iov 406 01.10.12 15:21 Сейчас в теме
(6) За успокоительное 50 руб - в кассу :)
8. q_i 577 02.10.12 11:40 Сейчас в теме
(7) iov, держите:
Дт 50 Кт 66 Сумма 50 руб.
(мог бы конечно оформить как безвозмездную передачу, но "я не за жадность - просто я не считаю это чем-то что поможет кому-то" (с))
9. iov 406 02.10.12 13:04 Сейчас в теме
(8) А можно акт сверочки? А то у меня бухгалтерия не готова для приема не национальной валюты (плюсы в карму). :)
Оставьте свое сообщение