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

30.09.12

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

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
ПраваНаКатегории.zip
.zip 15,29Kb
22
22 Скачать (1 SM) Купить за 1 850 руб.

Предисловие

Бухгалтерия захотела отражать в 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! 15%

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

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

10000 руб.

02.09.2020    160039    881    399    

864

SALE! 15%

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

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP и т.д.). Поддерживаются управляемые и обычные формы. Может выполнять свертку сразу нескольких баз данных и выполнять их автоматически без непосредственного участия пользователя.

8400 7140 руб.

20.08.2024    8028    60    28    

70

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

Инструмент для написания и отладки кода в режиме «1С:Предприятие». Представляет собой консоль кода с возможностью пошаговой отладки, просмотра значений переменных любых типов, использования процедур и функций, просмотра стека вызовов, вычисления произвольных выражений на встроенном языке в контексте точки останова, синтаксического контроля и остановки по ошибке. В консоли используется удобный редактор кода с подсветкой, контекстной подсказкой, возможностью вызова конструкторов запроса и форматной строки.

9360 руб.

17.05.2024    23599    68    45    

117

SALE! 15%

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

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

10000 8500 руб.

10.11.2023    10518    36    27    

62

SALE! 15%

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

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

22200 19980 руб.

06.10.2023    15490    35    7    

71

SALE! 35%

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

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

4800 3120 руб.

14.01.2013    188153    1140    0    

912

SALE! 15%

Инструментарий разработчика Программист 8.3.14 1С:Конвертация данных Россия Платные (руб)

Расширение для конфигурации “Конвертация данных 3”. Добавляет подсветку синтаксиса, детальную контекстную подсказку, глобальный поиск по коду.

15000 12750 руб.

07.10.2021    17348    6    32    

42

Инструментарий разработчика Программист Платные (руб)

Менеджер конфигураций 1С — альтернативный стартер информационных баз 1С:Предприятие.

1800 руб.

21.02.2023    7745    8    35    

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

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