mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-20 17:25:52 +03:00
fix(role-edit): операции применяются в порядке ввода
Внутри навыка они были сгруппированы по типам, поэтому список [remove-rights, add-rights] для одного права выполнялся наоборот: право сначала добавлялось, потом снималось. В инструкции об этом не было ни слова, а порядок ввода — то, чего ожидает читающий. Заодно: условие RLS со ссылкой на шаблон, которого в роли нет, больше не проходит молча — предупреждение в stderr (отказывать нельзя, шаблон могут добавить следующей операцией). Вычитка инструкций обоих навыков: сказано, что -Operation это одна операция, а несколько разных задают списком в файле (с примером); перечислены все три глобальных флага; про значение из файла вынесено в свой раздел; добавлено, что права реквизитам поштучно платформа не хранит — ограничивают их запретом. Из role-compile убрано объяснение, зачем навык замыкает набор: инструкция про применение. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FGkXwoXTuafcu1SXMsauFq
This commit is contained in:
co-authored by
Claude Opus 5
parent
d425833709
commit
b28c044e06
@@ -63,8 +63,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -
|
|||||||
### Зависимые права
|
### Зависимые права
|
||||||
|
|
||||||
Набор прав дополняется до замыкания: `Edit` тянет `Read`, `Update`, `View`; интерактивные права —
|
Набор прав дополняется до замыкания: `Edit` тянет `Read`, `Update`, `View`; интерактивные права —
|
||||||
свой базовый набор; `View` у обработки и отчёта — `Use`. Дописанное перечисляется в выводе. Так же
|
свой базовый набор; `View` у обработки и отчёта — `Use`. Дописанное перечисляется в выводе.
|
||||||
поступает сама платформа при загрузке, поэтому без этого файл роли и база расходятся.
|
|
||||||
|
|
||||||
### Сервисы
|
### Сервисы
|
||||||
|
|
||||||
@@ -130,6 +129,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -
|
|||||||
|
|
||||||
Права на части объекта задаются точечным путём: `Catalog.Контрагенты.Attribute.ИНН: View, Edit`, `WebService.Обмен.Operation.Загрузить: Use`, `HTTPService.ЭДО.URLTemplate.ЕстьНовыеДокументы.Method.POST: Use`.
|
Права на части объекта задаются точечным путём: `Catalog.Контрагенты.Attribute.ИНН: View, Edit`, `WebService.Обмен.Operation.Загрузить: Use`, `HTTPService.ЭДО.URLTemplate.ЕстьНовыеДокументы.Method.POST: Use`.
|
||||||
|
|
||||||
|
Реквизиты, табличные части, измерения и ресурсы по умолчанию наследуют права своего объекта:
|
||||||
|
выдавать их отдельно бессмысленно, платформа такую запись не сохранит. Поштучные права на них
|
||||||
|
имеют смысл только при `"setForAttributesByDefault": false`; ограничить реквизит в обычной роли
|
||||||
|
можно запретом — `{"name": "Catalog.Товары.Attribute.Цена", "rights": {"View": false}}`.
|
||||||
|
|
||||||
Роль расширения, включённая в основные (`DefaultRoles`), прав на заимствованные объекты давать не может — платформа это запрещает. Такие права выноси в отдельную роль вне основных.
|
Роль расширения, включённая в основные (`DefaultRoles`), прав на заимствованные объекты давать не может — платформа это запрещает. Такие права выноси в отдельную роль вне основных.
|
||||||
|
|
||||||
Полные таблицы «тип → права», виды вложенности (включая внешние источники данных), список типов без прав, таблицы пресетов и дополнительные примеры — в `dsl-reference.md`.
|
Полные таблицы «тип → права», виды вложенности (включая внешние источники данных), список типов без прав, таблицы пресетов и дополнительные примеры — в `dsl-reference.md`.
|
||||||
|
|||||||
@@ -19,15 +19,17 @@ allowed-tools:
|
|||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `RolePath` | Каталог роли, `Roles/Имя.xml` или `Roles/Имя/Ext/Rights.xml` |
|
| `RolePath` | Каталог роли, `Roles/Имя.xml` или `Roles/Имя/Ext/Rights.xml` |
|
||||||
| `Operation` | Операция из таблицы ниже (альтернатива `DefinitionFile`) |
|
| `Operation` | Одна операция из таблицы ниже |
|
||||||
| `Value` | Значение операции. Пакет через `;;`. Текст можно взять из файла: `@путь` в позиции значения |
|
| `Value` | Значение операции; несколько значений — через `;;` |
|
||||||
| `DefinitionFile` | JSON-массив операций `[{ "operation": "...", "value": "..." }]` |
|
| `DefinitionFile` | JSON-массив операций (альтернатива `Operation`) — так задают несколько разных операций |
|
||||||
| `NoValidate` | Не запускать `role-validate` после правки |
|
| `NoValidate` | Не запускать `role-validate` после правки |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -RolePath "<роль>" -Operation <op> -Value "<значение>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -RolePath "<роль>" -Operation <op> -Value "<значение>"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Операции применяются в том порядке, в котором перечислены.
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
|
|
||||||
| Операция | Формат `Value` | Описание |
|
| Операция | Формат `Value` | Описание |
|
||||||
@@ -35,14 +37,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -Rol
|
|||||||
| `add-rights` | `Тип.Имя: Право1, Право2` или `Тип.Имя: @пресет` | Добавить права, прежние сохранить |
|
| `add-rights` | `Тип.Имя: Право1, Право2` или `Тип.Имя: @пресет` | Добавить права, прежние сохранить |
|
||||||
| `set-rights` | то же | Заменить набор прав объекта целиком |
|
| `set-rights` | то же | Заменить набор прав объекта целиком |
|
||||||
| `remove-rights` | `Тип.Имя: Право1, Право2` — снять права<br>`Тип.Имя` — удалить объект целиком | Снять права |
|
| `remove-rights` | `Тип.Имя: Право1, Право2` — снять права<br>`Тип.Имя` — удалить объект целиком | Снять права |
|
||||||
| `deny-rights` | `Тип.Имя: Право1, Право2` | Запретить права явно (`false`) |
|
| `deny-rights` | `Тип.Имя: Право1, Право2` | Запретить права явно |
|
||||||
| `set-rls` | `Тип.Имя.Право: условие`<br>`Тип.Имя.Право[Поле1, Поле2]: условие` | Ограничение доступа к данным |
|
| `set-rls` | `Тип.Имя.Право: условие`<br>`Тип.Имя.Право[Поле1, Поле2]: условие` | Ограничение доступа к данным |
|
||||||
| `remove-rls` | `Тип.Имя.Право` — снять все<br>`Тип.Имя.Право[Поле1]` — снять одну строку | Снять ограничение, право оставить |
|
| `remove-rls` | `Тип.Имя.Право` — снять все<br>`Тип.Имя.Право[Поле1]` — снять одну строку | Снять ограничение, право оставить |
|
||||||
| `add-template` | `Имя(Параметры): условие` | Добавить шаблон ограничения |
|
| `add-template` | `Имя(Параметры): условие` | Добавить шаблон ограничения |
|
||||||
| `set-template` | то же | Заменить шаблон, а если его нет — добавить |
|
| `set-template` | то же | Заменить шаблон, а если его нет — добавить |
|
||||||
| `remove-template` | `Имя(Параметры)` или `Имя` | Удалить шаблон |
|
| `remove-template` | `Имя(Параметры)` или `Имя` | Удалить шаблон |
|
||||||
| `modify-property` | `setForNewObjects=true` | Глобальные флаги роли |
|
| `modify-property` | `setForNewObjects=true`<br>`setForAttributesByDefault=false`<br>`independentRightsOfChildObjects=true` | Глобальные флаги роли |
|
||||||
| `set-synonym` | текст | Синоним роли (правит `Roles/Имя.xml`) |
|
| `set-synonym` | текст | Синоним роли |
|
||||||
| `set-comment` | текст | Комментарий роли |
|
| `set-comment` | текст | Комментарий роли |
|
||||||
|
|
||||||
## Быстрые примеры
|
## Быстрые примеры
|
||||||
@@ -51,7 +53,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -Rol
|
|||||||
# Добавить права нового регистра, ничего не потеряв
|
# Добавить права нового регистра, ничего не потеряв
|
||||||
... -RolePath "src/Roles/Менеджер" -Operation add-rights -Value "InformationRegister.Цены: Read, Update"
|
... -RolePath "src/Roles/Менеджер" -Operation add-rights -Value "InformationRegister.Цены: Read, Update"
|
||||||
|
|
||||||
# Пресет и пакет в одном вызове
|
# Пресет и несколько объектов в одном вызове
|
||||||
... -RolePath "src/Roles/Менеджер" -Operation add-rights -Value "Catalog.Товары: @view ;; Document.Заказ: @edit"
|
... -RolePath "src/Roles/Менеджер" -Operation add-rights -Value "Catalog.Товары: @view ;; Document.Заказ: @edit"
|
||||||
|
|
||||||
# Снять права; объект без разрешающих прав удаляется целиком
|
# Снять права; объект без разрешающих прав удаляется целиком
|
||||||
@@ -61,6 +63,19 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -Rol
|
|||||||
... -RolePath "src/Roles/Менеджер" -Operation deny-rights -Value "Catalog.Товары.Attribute.Цена: View"
|
... -RolePath "src/Roles/Менеджер" -Operation deny-rights -Value "Catalog.Товары.Attribute.Цена: View"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Несколько разных операций — списком в файле:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{ "operation": "add-rights", "value": "Catalog.Товары: @view" },
|
||||||
|
{ "operation": "set-rls", "value": "Catalog.Товары.Read: #ПоОрганизации(\"\")" }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
... -RolePath "src/Roles/Менеджер" -DefinitionFile "операции.json"
|
||||||
|
```
|
||||||
|
|
||||||
## Права
|
## Права
|
||||||
|
|
||||||
Имена объектов и прав — те же, что в `/role-compile`: английские (`Catalog`, `Read`) или русские
|
Имена объектов и прав — те же, что в `/role-compile`: английские (`Catalog`, `Read`) или русские
|
||||||
@@ -72,16 +87,22 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -Rol
|
|||||||
отчёта — `Use`. Снятие работает в обратную сторону: снимаешь `Read` — уходят и права, которые его
|
отчёта — `Use`. Снятие работает в обратную сторону: снимаешь `Read` — уходят и права, которые его
|
||||||
требуют. Дописанное и снятое каскадом перечисляется в выводе.
|
требуют. Дописанное и снятое каскадом перечисляется в выводе.
|
||||||
|
|
||||||
|
Реквизиты, табличные части, измерения и ресурсы по умолчанию наследуют права своего объекта, и
|
||||||
|
выдавать их отдельно бессмысленно — платформа такую запись не сохранит. Ограничивают их через
|
||||||
|
`deny-rights`. Выдавать права реквизитам поштучно имеет смысл только в роли с
|
||||||
|
`setForAttributesByDefault=false`.
|
||||||
|
|
||||||
Тип или имя права вне допустимого списка — отказ: файл не меняется, ошибки печатаются все разом.
|
Тип или имя права вне допустимого списка — отказ: файл не меняется, ошибки печатаются все разом.
|
||||||
Полные таблицы «тип → права» и виды вложенности — в `role-compile/dsl-reference.md`.
|
Полные таблицы «тип → права» и виды вложенности — в справке `/role-compile`.
|
||||||
|
|
||||||
## RLS
|
## RLS
|
||||||
|
|
||||||
Ограничения права — это список строк, как в таблице «Ограничения доступа к данным» редактора.
|
Ограничения права — это список строк, как в таблице «Ограничения доступа к данным» редактора.
|
||||||
Строка без списка полей действует на все прочие поля, строка со списком — только на них:
|
Строка без списка полей действует на все прочие поля, строка со списком — только на них.
|
||||||
|
Типовой приём: закрыть данные целиком, но оставить поля представления ссылки открытыми, иначе
|
||||||
|
ссылки на объект превратятся в «объект не найден»:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Закрыть таблицу, но оставить ссылку живой: ссылочные поля без ограничения
|
|
||||||
... -Operation set-rls -Value "Catalog.Товары.Read: ГДЕ ЛОЖЬ"
|
... -Operation set-rls -Value "Catalog.Товары.Read: ГДЕ ЛОЖЬ"
|
||||||
... -Operation set-rls -Value "Catalog.Товары.Read[Ссылка, Код, Наименование]: "
|
... -Operation set-rls -Value "Catalog.Товары.Read[Ссылка, Код, Наименование]: "
|
||||||
```
|
```
|
||||||
@@ -89,18 +110,20 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-edit.ps1" -Rol
|
|||||||
Строка с тем же набором полей заменяется, с другим — добавляется.
|
Строка с тем же набором полей заменяется, с другим — добавляется.
|
||||||
Ограничение на невыданное право — ошибка: платформа такое молча игнорирует.
|
Ограничение на невыданное право — ошибка: платформа такое молча игнорирует.
|
||||||
|
|
||||||
Длинное условие держи в файле — адрес остаётся в команде, из файла приходит только текст:
|
Ссылка на шаблон — `#ИмяШаблона("")`; `&` в условиях экранируется автоматически.
|
||||||
|
|
||||||
|
## Значение из файла
|
||||||
|
|
||||||
|
Вместо текста можно указать `@путь` — условие RLS, тело шаблона, синоним и комментарий берутся из
|
||||||
|
файла. Относительный путь ищется рядом с `DefinitionFile`, затем в текущем каталоге. Разделитель
|
||||||
|
`;;` внутри файла остаётся обычным текстом.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
... -Operation set-rls -Value "Catalog.Товары.Read: @условие.txt"
|
... -Operation set-rls -Value "Catalog.Товары.Read: @условие.txt"
|
||||||
... -Operation add-template -Value "ПоОрганизации(Мод): @условие.txt"
|
... -Operation add-template -Value "ПоОрганизации(Мод): @условие.txt"
|
||||||
|
... -Operation set-comment -Value "@комментарий.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
Так же берётся текст у `set-synonym` и `set-comment`: `-Value "@текст.txt"`. Разделитель пакета
|
|
||||||
`;;` внутри файла остаётся обычным текстом.
|
|
||||||
|
|
||||||
Ссылка на шаблон — `#ИмяШаблона("")`; `&` в условиях экранируется автоматически.
|
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# role-edit v1.1 — Edit existing 1C role rights in place
|
# role-edit v1.2 — Edit existing 1C role rights in place
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -1715,7 +1715,7 @@ function Do-AddRights([string]$batchVal) {
|
|||||||
$spec = Parse-RightsSpec $item
|
$spec = Parse-RightsSpec $item
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
foreach ($expanded in (Expand-ServiceEntry -parsed @{ Name = $spec.Name; Rights = @($spec.Rights | ForEach-Object { @{ Name = $_; Value = "true"; Condition = $null } }) } -configRoot $script:configRoot -name $script:paths.RoleName)) {
|
foreach ($expanded in (Expand-ServiceEntry -parsed @{ Name = $spec.Name; Rights = @($spec.Rights | ForEach-Object { @{ Name = $_; Value = "true"; Condition = $null } }) } -configRoot $script:configRoot -name $script:paths.RoleName)) {
|
||||||
$script:pendingAdds += ,@{ Name = $expanded.Name; Rights = @($expanded.Rights | ForEach-Object { $_.Name }) }
|
$script:pending += ,@{ Kind = 'add-rights'; Spec = @{ Name = $expanded.Name; Rights = @($expanded.Rights | ForEach-Object { $_.Name }) } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1771,7 +1771,7 @@ function Do-SetRights([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-RightsSpec $item
|
$spec = Parse-RightsSpec $item
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingSets += ,$spec
|
$script:pending += ,@{ Kind = 'set-rights'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1804,7 +1804,7 @@ function Do-RemoveRights([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-RightsSpec $item -AllowNoRights
|
$spec = Parse-RightsSpec $item -AllowNoRights
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingRemoves += ,$spec
|
$script:pending += ,@{ Kind = 'remove-rights'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1853,7 +1853,7 @@ function Do-DenyRights([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-RightsSpec $item
|
$spec = Parse-RightsSpec $item
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingDenies += ,$spec
|
$script:pending += ,@{ Kind = 'deny-rights'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1935,7 +1935,7 @@ function Do-SetRls([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-RlsAddress $item -ConditionRequired
|
$spec = Parse-RlsAddress $item -ConditionRequired
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingRls += ,$spec
|
$script:pending += ,@{ Kind = 'set-rls'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1956,6 +1956,15 @@ function Apply-SetRls($spec) {
|
|||||||
foreach ($node in $existing) {
|
foreach ($node in $existing) {
|
||||||
if (Test-SameFieldSet (Get-RestrictionFields $node) $spec.Fields) { $target = $node; break }
|
if (Test-SameFieldSet (Get-RestrictionFields $node) $spec.Fields) { $target = $node; break }
|
||||||
}
|
}
|
||||||
|
# Ссылка на шаблон, которого в роли нет, — тихая ошибка в рантайме 1С. Отказывать нельзя:
|
||||||
|
# шаблон могут добавить следующей операцией или следующим вызовом.
|
||||||
|
foreach ($m in [regex]::Matches("$($spec.Condition)", '#([A-Za-zА-Яа-яЁё0-9_]+)\s*\(')) {
|
||||||
|
$templateName = $m.Groups[1].Value
|
||||||
|
if ($templateName -in @('Если', 'Тогда', 'Иначе', 'КонецЕсли')) { continue }
|
||||||
|
if (-not (Find-TemplateNode $templateName)) {
|
||||||
|
[Console]::Error.WriteLine("[role-edit] $($spec.Object).$($spec.Right): условие ссылается на шаблон '$templateName', которого в роли нет")
|
||||||
|
}
|
||||||
|
}
|
||||||
$new = New-RestrictionNode $indent $spec.Fields $spec.Condition
|
$new = New-RestrictionNode $indent $spec.Fields $spec.Condition
|
||||||
if ($target) {
|
if ($target) {
|
||||||
$rightNode.ReplaceChild($new, $target) | Out-Null
|
$rightNode.ReplaceChild($new, $target) | Out-Null
|
||||||
@@ -1978,7 +1987,7 @@ function Do-RemoveRls([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-RlsAddress $item
|
$spec = Parse-RlsAddress $item
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingRlsRemovals += ,$spec
|
$script:pending += ,@{ Kind = 'remove-rls'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2039,7 +2048,7 @@ function Do-AddTemplate([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-TemplateSpec $item
|
$spec = Parse-TemplateSpec $item
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingTemplateAdds += ,$spec
|
$script:pending += ,@{ Kind = 'add-template'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2067,14 +2076,14 @@ function Do-SetTemplate([string]$batchVal) {
|
|||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-TemplateSpec $item
|
$spec = Parse-TemplateSpec $item
|
||||||
if (-not $spec) { continue }
|
if (-not $spec) { continue }
|
||||||
$script:pendingTemplateSets += ,$spec
|
$script:pending += ,@{ Kind = 'set-template'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Do-RemoveTemplate([string]$batchVal) {
|
function Do-RemoveTemplate([string]$batchVal) {
|
||||||
foreach ($item in (Parse-BatchValue $batchVal)) {
|
foreach ($item in (Parse-BatchValue $batchVal)) {
|
||||||
$spec = Parse-TemplateSpec $item -NameOnly
|
$spec = Parse-TemplateSpec $item -NameOnly
|
||||||
$script:pendingTemplateRemovals += ,$spec
|
$script:pending += ,@{ Kind = 'remove-template'; Spec = $spec }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2127,7 +2136,7 @@ function Do-ModifyProperty([string]$batchVal) {
|
|||||||
Add-ValidationError "$item : значение должно быть true или false"
|
Add-ValidationError "$item : значение должно быть true или false"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
$script:pendingProperties += ,@{ Name = $canonical; Value = $value }
|
$script:pending += ,@{ Kind = 'modify-property'; Spec = @{ Name = $canonical; Value = $value } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2194,17 +2203,8 @@ function Edit-RoleMetadata([string]$field, [string]$text) {
|
|||||||
|
|
||||||
# --- Сбор и выполнение операций ---
|
# --- Сбор и выполнение операций ---
|
||||||
|
|
||||||
$script:pendingAdds = @()
|
# Очередь одна: операции применяются в том порядке, в котором их перечислили.
|
||||||
$script:pendingSets = @()
|
$script:pending = @()
|
||||||
$script:pendingRemoves = @()
|
|
||||||
$script:pendingDenies = @()
|
|
||||||
$script:pendingRls = @()
|
|
||||||
$script:pendingRlsRemovals = @()
|
|
||||||
$script:pendingTemplateAdds = @()
|
|
||||||
$script:pendingTemplateSets = @()
|
|
||||||
$script:pendingTemplateRemovals = @()
|
|
||||||
$script:pendingProperties = @()
|
|
||||||
$script:pendingMeta = @()
|
|
||||||
|
|
||||||
$operations = @()
|
$operations = @()
|
||||||
if ($DefinitionFile) {
|
if ($DefinitionFile) {
|
||||||
@@ -2233,8 +2233,8 @@ foreach ($op in $operations) {
|
|||||||
"set-template" { Do-SetTemplate $opValue }
|
"set-template" { Do-SetTemplate $opValue }
|
||||||
"remove-template" { Do-RemoveTemplate $opValue }
|
"remove-template" { Do-RemoveTemplate $opValue }
|
||||||
"modify-property" { Do-ModifyProperty $opValue }
|
"modify-property" { Do-ModifyProperty $opValue }
|
||||||
"set-synonym" { $script:pendingMeta += ,@{ Field = 'Synonym'; Text = (Resolve-TextFromFile $opValue $script:textBaseDir) } }
|
"set-synonym" { $script:pending += ,@{ Kind = 'set-meta'; Spec = @{ Field = 'Synonym'; Text = (Resolve-TextFromFile $opValue $script:textBaseDir) } } }
|
||||||
"set-comment" { $script:pendingMeta += ,@{ Field = 'Comment'; Text = (Resolve-TextFromFile $opValue $script:textBaseDir) } }
|
"set-comment" { $script:pending += ,@{ Kind = 'set-meta'; Spec = @{ Field = 'Comment'; Text = (Resolve-TextFromFile $opValue $script:textBaseDir) } } }
|
||||||
default {
|
default {
|
||||||
Add-ValidationError "Неизвестная операция: $opName"
|
Add-ValidationError "Неизвестная операция: $opName"
|
||||||
}
|
}
|
||||||
@@ -2249,17 +2249,21 @@ if ($script:validationErrors.Count -gt 0) {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($spec in $script:pendingAdds) { Apply-AddRights $spec }
|
foreach ($item in $script:pending) {
|
||||||
foreach ($spec in $script:pendingSets) { Apply-SetRights $spec }
|
switch ($item.Kind) {
|
||||||
foreach ($spec in $script:pendingDenies) { Apply-DenyRights $spec }
|
'add-rights' { Apply-AddRights $item.Spec }
|
||||||
foreach ($spec in $script:pendingRemoves) { Apply-RemoveRights $spec }
|
'set-rights' { Apply-SetRights $item.Spec }
|
||||||
foreach ($spec in $script:pendingTemplateAdds) { Apply-AddTemplate $spec }
|
'deny-rights' { Apply-DenyRights $item.Spec }
|
||||||
foreach ($spec in $script:pendingTemplateSets) { Apply-AddTemplate $spec -AllowReplace }
|
'remove-rights' { Apply-RemoveRights $item.Spec }
|
||||||
foreach ($spec in $script:pendingRls) { Apply-SetRls $spec }
|
'add-template' { Apply-AddTemplate $item.Spec }
|
||||||
foreach ($spec in $script:pendingRlsRemovals) { Apply-RemoveRls $spec }
|
'set-template' { Apply-AddTemplate $item.Spec -AllowReplace }
|
||||||
foreach ($spec in $script:pendingTemplateRemovals) { Apply-RemoveTemplate $spec }
|
'remove-template' { Apply-RemoveTemplate $item.Spec }
|
||||||
foreach ($spec in $script:pendingProperties) { Apply-ModifyProperty $spec }
|
'set-rls' { Apply-SetRls $item.Spec }
|
||||||
foreach ($spec in $script:pendingMeta) { Edit-RoleMetadata $spec.Field $spec.Text }
|
'remove-rls' { Apply-RemoveRls $item.Spec }
|
||||||
|
'modify-property' { Apply-ModifyProperty $item.Spec }
|
||||||
|
'set-meta' { Edit-RoleMetadata $item.Spec.Field $item.Spec.Text }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Ошибка могла всплыть и на применении (RLS без права) — файл в этом случае не трогаем.
|
# Ошибка могла всплыть и на применении (RLS без права) — файл в этом случае не трогаем.
|
||||||
if ($script:validationErrors.Count -gt 0) {
|
if ($script:validationErrors.Count -gt 0) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# role-edit v1.1 — Edit existing 1C role rights in place
|
# role-edit v1.2 — Edit existing 1C role rights in place
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
@@ -1908,6 +1908,15 @@ class Editor:
|
|||||||
if self.same_field_set(self.restriction_fields(node), spec["Fields"]):
|
if self.same_field_set(self.restriction_fields(node), spec["Fields"]):
|
||||||
target = node
|
target = node
|
||||||
break
|
break
|
||||||
|
# Ссылка на шаблон, которого в роли нет, — тихая ошибка в рантайме 1С. Отказывать нельзя:
|
||||||
|
# шаблон могут добавить следующей операцией или следующим вызовом.
|
||||||
|
for m in re.finditer(r'#([A-Za-zА-Яа-яЁё0-9_]+)\s*\(', spec["Condition"] or ""):
|
||||||
|
template_name = m.group(1)
|
||||||
|
if template_name in ("Если", "Тогда", "Иначе", "КонецЕсли"):
|
||||||
|
continue
|
||||||
|
if self.find_template(template_name) is None:
|
||||||
|
print(f"[role-edit] {spec['Object']}.{spec['Right']}: условие ссылается на шаблон "
|
||||||
|
f"'{template_name}', которого в роли нет", file=sys.stderr)
|
||||||
new_el = self.make_restriction(indent, spec["Fields"], spec["Condition"])
|
new_el = self.make_restriction(indent, spec["Fields"], spec["Condition"])
|
||||||
if target is not None:
|
if target is not None:
|
||||||
new_el.tail = target.tail
|
new_el.tail = target.tail
|
||||||
@@ -2178,8 +2187,6 @@ def main():
|
|||||||
|
|
||||||
refuse_if_errors()
|
refuse_if_errors()
|
||||||
|
|
||||||
order = ["add-rights", "set-rights", "deny-rights", "remove-rights", "add-template", "set-template",
|
|
||||||
"set-rls", "remove-rls", "remove-template", "modify-property", "set-synonym", "set-comment"]
|
|
||||||
handlers = {
|
handlers = {
|
||||||
"add-rights": ed.apply_add_rights,
|
"add-rights": ed.apply_add_rights,
|
||||||
"set-rights": ed.apply_set_rights,
|
"set-rights": ed.apply_set_rights,
|
||||||
@@ -2194,10 +2201,9 @@ def main():
|
|||||||
"set-synonym": lambda s: ed.edit_role_metadata(s["Field"], s["Text"]),
|
"set-synonym": lambda s: ed.edit_role_metadata(s["Field"], s["Text"]),
|
||||||
"set-comment": lambda s: ed.edit_role_metadata(s["Field"], s["Text"]),
|
"set-comment": lambda s: ed.edit_role_metadata(s["Field"], s["Text"]),
|
||||||
}
|
}
|
||||||
for key in order:
|
# Операции применяются в том порядке, в котором их перечислили.
|
||||||
for op_key, spec in pending:
|
for op_key, spec in pending:
|
||||||
if op_key == key:
|
handlers[op_key](spec)
|
||||||
handlers[key](spec)
|
|
||||||
|
|
||||||
# Ошибка могла всплыть и на применении (RLS без права) — файл в этом случае не трогаем.
|
# Ошибка могла всплыть и на применении (RLS без права) — файл в этом случае не трогаем.
|
||||||
refuse_if_errors()
|
refuse_if_errors()
|
||||||
|
|||||||
Reference in New Issue
Block a user