diff --git a/.claude/skills/role-edit/scripts/role-edit.ps1 b/.claude/skills/role-edit/scripts/role-edit.ps1 index c29e86061..a1becdfbe 100644 --- a/.claude/skills/role-edit/scripts/role-edit.ps1 +++ b/.claude/skills/role-edit/scripts/role-edit.ps1 @@ -1,4 +1,4 @@ -# role-edit v1.5 — Edit existing 1C role rights in place +# role-edit v1.6 — Edit existing 1C role rights in place # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills [CmdletBinding(PositionalBinding=$false)] param( @@ -1713,12 +1713,15 @@ function New-ObjectNode([string]$objName) { return $nodes[0] } -# Узел без единого разрешающего права платформа не производит: остаточные запреты уходят с ним. -function Remove-ObjectIfNoTrueRights($objNode) { - if ((Get-TrueRightNames $objNode).Count -gt 0) { return $false } +# Пустых узлов платформа не производит. Узел с одними запретами — производит (так закрывают +# реквизит), поэтому смотрим на наличие прав вообще, а не только разрешающих. +function Remove-ObjectIfEmpty($objNode) { + # @() на месте использования: return из функции разворачивает массив из одного элемента, + # и .Count у него $null — узел с единственным правом считался бы пустым. + if (@(Get-RightNodes $objNode).Count -gt 0) { return $false } $name = Get-ObjectNodeName $objNode Remove-NodeWithWhitespace $objNode - Add-Note " ${name}: разрешающих прав не осталось — узел объекта удалён" + Add-Note " ${name}: прав не осталось — узел объекта удалён" return $true } @@ -1852,7 +1855,7 @@ function Apply-SetRights($spec) { $script:rightsDirty = $true Add-Note " $($spec.Name): набор прав заменён" if ($droppedRls -gt 0) { Add-Note "[WARN] $($spec.Name): снято ограничений RLS: $droppedRls" } - Remove-ObjectIfNoTrueRights $objNode | Out-Null + Remove-ObjectIfEmpty $objNode | Out-Null } function Do-RemoveRights([string]$batchVal) { @@ -1901,7 +1904,7 @@ function Apply-RemoveRights($spec) { $note = " $($spec.Name): снято — $($removed -join ', ')" if ($cascade.Count -gt 0) { $note += " (каскадом: $($cascade -join ', '))" } Add-Note $note - Remove-ObjectIfNoTrueRights $objNode | Out-Null + Remove-ObjectIfEmpty $objNode | Out-Null } function Do-DenyRights([string]$batchVal) { @@ -1914,9 +1917,11 @@ function Do-DenyRights([string]$batchVal) { function Apply-DenyRights($spec) { $objNode = Find-ObjectNode $spec.Name + $created = $false if (-not $objNode) { $objNode = New-ObjectNode $spec.Name Insert-ObjectNode $objNode $spec.Name + $created = $true } $toDeny = @() foreach ($rightName in $spec.Rights) { @@ -1943,6 +1948,7 @@ function Apply-DenyRights($spec) { $script:rightsDirty = $true } if ($denied.Count -eq 0) { + if ($created) { Remove-NodeWithWhitespace $objNode } $reason = if ($script:droppedByDefault -match [regex]::Escape($spec.Name)) { "запрет совпадает с умолчанием роли и платформой не хранится" } else { "права уже запрещены" } Add-Note " $($spec.Name): $reason, изменений нет" return @@ -2031,7 +2037,7 @@ function Apply-SetRls($spec) { # Строка без полей («прочие поля») идёт первой, строки с полями — после неё. $refNode = $null if ($spec.Fields.Count -eq 0) { - foreach ($node in $existing) { if ((Get-RestrictionFields $node).Count -gt 0) { $refNode = $node; break } } + foreach ($node in $existing) { if (@(Get-RestrictionFields $node).Count -gt 0) { $refNode = $node; break } } } Insert-BeforeElement $rightNode $new $refNode $indent $script:addCount++ @@ -2062,7 +2068,7 @@ function Apply-RemoveRls($spec) { $removed = 0 foreach ($node in @($rightNode.SelectNodes("rt:restrictionByCondition", $script:ns))) { # Адрес без скобок снимает все ограничения права, со скобками — строку с этим набором полей. - if ($spec.Fields.Count -gt 0 -and -not (Test-SameFieldSet (Get-RestrictionFields $node) $spec.Fields)) { continue } + if (@($spec.Fields).Count -gt 0 -and -not (Test-SameFieldSet (Get-RestrictionFields $node) $spec.Fields)) { continue } Remove-NodeWithWhitespace $node $removed++ } diff --git a/.claude/skills/role-edit/scripts/role-edit.py b/.claude/skills/role-edit/scripts/role-edit.py index 9c4749680..3af839f3c 100644 --- a/.claude/skills/role-edit/scripts/role-edit.py +++ b/.claude/skills/role-edit/scripts/role-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-edit v1.5 — Edit existing 1C role rights in place +# role-edit v1.6 — Edit existing 1C role rights in place # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -1740,13 +1740,14 @@ class Editor: ref = templates[0] self.insert_child(self.root, new_el, ref, indent) - # Узел без единого разрешающего права платформа не производит. - def remove_object_if_no_true_rights(self, obj_node): - if self.true_right_names(obj_node): + # Пустых узлов платформа не производит. Узел с одними запретами — производит (так закрывают + # реквизит), поэтому смотрим на наличие прав вообще, а не только разрешающих. + def remove_object_if_empty(self, obj_node): + if self.right_nodes(obj_node): return name = node_text(obj_node, "name") self.remove_child(obj_node) - self.note(f" {name}: разрешающих прав не осталось — узел объекта удалён") + self.note(f" {name}: прав не осталось — узел объекта удалён") # --- Зависимости --- @@ -1857,7 +1858,7 @@ class Editor: self.note(f" {spec['Name']}: набор прав заменён") if dropped_rls: self.note(f"[WARN] {spec['Name']}: снято ограничений RLS: {dropped_rls}") - self.remove_object_if_no_true_rights(obj_node) + self.remove_object_if_empty(obj_node) def apply_remove_rights(self, spec): obj_node = self.find_object(spec["Name"]) @@ -1894,13 +1895,15 @@ class Editor: if cascade: note += f" (каскадом: {', '.join(cascade)})" self.note(note) - self.remove_object_if_no_true_rights(obj_node) + self.remove_object_if_empty(obj_node) def apply_deny_rights(self, spec): obj_node = self.find_object(spec["Name"]) + created = False if obj_node is None: obj_node = self.make_object(spec["Name"], self.child_indent(self.root)) self.insert_object_node(obj_node, spec["Name"]) + created = True to_deny = [] for right_name in spec["Rights"]: to_deny.append(right_name) @@ -1925,6 +1928,8 @@ class Editor: denied.append(right_name) self.rights_dirty = True if not denied: + if created: + self.remove_child(obj_node) reason = ("запрет совпадает с умолчанием роли и платформой не хранится" if any(d.startswith(spec['Name'] + '.') for d in self.dropped_by_default) else "права уже запрещены") diff --git a/tests/skills/cases/role-edit/deny-dropped-no-empty-node.json b/tests/skills/cases/role-edit/deny-dropped-no-empty-node.json new file mode 100644 index 000000000..0fb0576b0 --- /dev/null +++ b/tests/skills/cases/role-edit/deny-dropped-no-empty-node.json @@ -0,0 +1,23 @@ +{ + "name": "Отброшенный запрет не оставляет пустой узел, когда файл меняет соседняя операция", + "setup": "fixture:role-base", + "params": { + "rolePath": "Roles/Менеджер" + }, + "input": [ + { + "operation": "deny-rights", + "value": "InformationRegister.Цены: Read" + }, + { + "operation": "add-rights", + "value": "Catalog.Товары: Insert" + } + ], + "expect": { + "fileNotContains": { + "file": "Roles/Менеджер/Ext/Rights.xml", + "text": "InformationRegister.Цены" + } + } +} diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Catalogs/Товары.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Catalogs/Товары.xml new file mode 100644 index 000000000..292de84c4 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Catalogs/Товары.xml @@ -0,0 +1,137 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + + Товары + + + ru + Товары + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.Товары.StandardAttribute.Description + Catalog.Товары.StandardAttribute.Code + + Begin + DontUse + Directly + + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + + + + Цена + + + ru + Цена + + + + + xs:decimal + + 15 + 2 + Any + + + false + + + + false + + false + false + + + false + 0 + DontCheck + Items + + + Auto + Auto + + + Auto + ForItem + DontIndex + Use + Use + + + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Catalogs/Товары/Ext/ObjectModule.bsl b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Catalogs/Товары/Ext/ObjectModule.bsl new file mode 100644 index 000000000..e69de29bb diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Configuration.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Configuration.xml new file mode 100644 index 000000000..880e20b87 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Configuration.xml @@ -0,0 +1,256 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Менеджер + Товары + Заказ + Загрузка + Цены + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка.xml new file mode 100644 index 000000000..fa5caaf26 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка.xml @@ -0,0 +1,32 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + + Загрузка + + + ru + Загрузка + + + + true + + + false + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка/Ext/ManagerModule.bsl b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка/Ext/ManagerModule.bsl new file mode 100644 index 000000000..e69de29bb diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка/Ext/ObjectModule.bsl b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/DataProcessors/Загрузка/Ext/ObjectModule.bsl new file mode 100644 index 000000000..e69de29bb diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Documents/Заказ.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Documents/Заказ.xml new file mode 100644 index 000000000..32fa05878 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Documents/Заказ.xml @@ -0,0 +1,82 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + + Заказ + + + ru + Заказ + + + + true + + String + 11 + Variable + Year + true + true + + + + Document.Заказ.StandardAttribute.Number + + Use + Begin + DontUse + Directly + + + + + + + Allow + Deny + AutoDelete + WriteSelected + AutoFill + + true + true + false + + Managed + Use + + + + + + Auto + DontUse + false + false + + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Documents/Заказ/Ext/ObjectModule.bsl b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Documents/Заказ/Ext/ObjectModule.bsl new file mode 100644 index 000000000..e69de29bb diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Ext/ClientApplicationInterface.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Ext/ClientApplicationInterface.xml new file mode 100644 index 000000000..3c1161b2d --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/InformationRegisters/Цены.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/InformationRegisters/Цены.xml new file mode 100644 index 000000000..092bf1d11 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/InformationRegisters/Цены.xml @@ -0,0 +1,261 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + Цены + + + ru + Цены + + + + true + InDialog + + + + + + + + DontCheck + false + false + Auto + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + Nonperiodical + Independent + false + false + Managed + Use + false + false + + + + + + DontUse + false + false + + + + + Цена + + + ru + Цена + + + + + xs:decimal + + 15 + 2 + Any + + + false + + + + false + + false + false + + + false + 0 + DontCheck + Items + + + Auto + Auto + + + Auto + DontIndex + Use + Use + + + + + Товар + + + ru + Товар + + + + + cfg:CatalogRef.Товары + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + false + false + false + DontIndex + Use + Use + + + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/InformationRegisters/Цены/Ext/RecordSetModule.bsl b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/InformationRegisters/Цены/Ext/RecordSetModule.bsl new file mode 100644 index 000000000..e69de29bb diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Languages/Русский.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Languages/Русский.xml new file mode 100644 index 000000000..37c60d786 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Roles/Менеджер.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Roles/Менеджер.xml new file mode 100644 index 000000000..001d4535b --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Roles/Менеджер.xml @@ -0,0 +1,15 @@ + + + + + Менеджер + + + ru + Менеджер + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Roles/Менеджер/Ext/Rights.xml b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Roles/Менеджер/Ext/Rights.xml new file mode 100644 index 000000000..a20e853c4 --- /dev/null +++ b/tests/skills/cases/role-edit/snapshots/deny-dropped-no-empty-node/Roles/Менеджер/Ext/Rights.xml @@ -0,0 +1,96 @@ + + + false + true + false + + Catalog.Товары + + Read + true + + + Insert + true + + + View + true + + + InputByString + true + + + + Document.Заказ + + Read + true + + + Insert + true + + + Update + true + + + Delete + true + + + Posting + true + + + UndoPosting + true + + + View + true + + + InteractiveInsert + true + + + Edit + true + + + InteractiveSetDeletionMark + true + + + InteractiveClearDeletionMark + true + + + InteractivePosting + true + + + InteractivePostingRegular + true + + + InteractiveUndoPosting + true + + + InteractiveChangeOfPosted + true + + + InputByString + true + + + + ДляОбъекта(Мод) + ГДЕ Организация = &ТекОрг + + \ No newline at end of file