mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-18 15:45:52 +03:00
feat(role-compile): условие RLS и тело шаблона можно взять из файла
Симметрично role-edit: в значении пишется "@путь", текст приходит из файла. Условия типовых занимают десятки строк с кавычками внутри, и в JSON-строке это источник ошибок экранирования — теперь условие живёт отдельным файлом рядом с описанием роли. Работает в rls и в templates[].condition. Отсутствие файла — ошибка до записи, как и прочие ошибки описания прав. 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
9c14715359
commit
121c9c8ad3
@@ -91,6 +91,13 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -
|
||||
|
||||
Ссылка в `rls`: `"#ДляОбъекта(\"\")"`. Символ `&` автоматически экранируется в XML.
|
||||
|
||||
Длинное условие держи в файле — в значении пишется `@путь` (путь от текущего каталога):
|
||||
|
||||
```json
|
||||
"objects": [{"name": "Document.Продажа", "preset": "view", "rls": {"Read": "@условие.txt"}}],
|
||||
"templates": [{"name": "ДляОбъекта(Мод)", "condition": "@шаблон.txt"}]
|
||||
```
|
||||
|
||||
## Примеры
|
||||
|
||||
### Простая роль
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# role-compile v1.39 — Compile 1C role from JSON
|
||||
# role-compile v1.40 — Compile 1C role from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
[CmdletBinding(PositionalBinding=$false)]
|
||||
param(
|
||||
@@ -1072,6 +1072,20 @@ function Validate-RightName {
|
||||
return $true
|
||||
}
|
||||
|
||||
# "@путь" в значении условия — текст берётся из файла: условия RLS типовых занимают десятки
|
||||
# строк с кавычками, и внутри JSON-строки это источник ошибок экранирования. Путь относительный —
|
||||
# от текущего каталога, как в role-edit.
|
||||
function Resolve-TextValue([string]$text) {
|
||||
if (-not $text -or -not $text.StartsWith("@")) { return $text }
|
||||
$valueFile = $text.Substring(1).Trim()
|
||||
if (-not [System.IO.Path]::IsPathRooted($valueFile)) { $valueFile = Join-Path (Get-Location).Path $valueFile }
|
||||
if (-not (Test-Path -LiteralPath $valueFile -PathType Leaf)) {
|
||||
Add-ValidationError "Файл значения не найден: $valueFile"
|
||||
return $text
|
||||
}
|
||||
return [System.IO.File]::ReadAllText($valueFile).Trim()
|
||||
}
|
||||
|
||||
# --- 5a. Service roots: expand to leaves ---
|
||||
|
||||
# Метаданные сервиса читаются один раз на имя: раскрытие и проверка заимствования
|
||||
@@ -1290,7 +1304,7 @@ function Parse-ObjectEntry {
|
||||
foreach ($p in $entry.rls.PSObject.Properties) {
|
||||
$rlsRight = Translate-RightName $p.Name
|
||||
if ($rightsMap.Contains($rlsRight)) {
|
||||
$rightsMap[$rlsRight].Condition = "$($p.Value)"
|
||||
$rightsMap[$rlsRight].Condition = Resolve-TextValue "$($p.Value)"
|
||||
} else {
|
||||
Write-Warning "${objName}: RLS for '$rlsRight' but this right is not in the rights list"
|
||||
}
|
||||
@@ -1478,7 +1492,7 @@ if ($def.templates) {
|
||||
foreach ($tpl in $def.templates) {
|
||||
X "`t<restrictionTemplate>"
|
||||
X "`t`t<name>$(Esc-XmlText "$($tpl.name)")</name>"
|
||||
X "`t`t<condition>$(Esc-XmlText "$($tpl.condition)")</condition>"
|
||||
X "`t`t<condition>$(Esc-XmlText (Resolve-TextValue "$($tpl.condition)"))</condition>"
|
||||
X "`t</restrictionTemplate>"
|
||||
$templateCount++
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# role-compile v1.39 — Compile 1C role from JSON
|
||||
# role-compile v1.40 — Compile 1C role from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -1165,6 +1165,22 @@ def validate_right_name(object_name, right_name):
|
||||
return True
|
||||
|
||||
|
||||
# "@путь" в значении условия — текст берётся из файла: условия RLS типовых занимают десятки
|
||||
# строк с кавычками, и внутри JSON-строки это источник ошибок экранирования. Путь относительный —
|
||||
# от текущего каталога, как в role-edit.
|
||||
def resolve_text_value(text):
|
||||
if not text or not text.startswith("@"):
|
||||
return text
|
||||
value_file = text[1:].strip()
|
||||
if not os.path.isabs(value_file):
|
||||
value_file = os.path.join(os.getcwd(), value_file)
|
||||
if not os.path.isfile(value_file):
|
||||
add_validation_error(f"Файл значения не найден: {value_file}")
|
||||
return text
|
||||
with open(value_file, encoding="utf-8-sig") as f:
|
||||
return f.read().strip()
|
||||
|
||||
|
||||
MD_NS = 'http://v8.1c.ru/8.3/MDClasses'
|
||||
|
||||
# Метаданные сервиса читаются один раз на имя: раскрытие и проверка заимствования
|
||||
@@ -1364,7 +1380,7 @@ def parse_object_entry(entry):
|
||||
for p_name, p_value in entry['rls'].items():
|
||||
rls_right = translate_right_name(p_name)
|
||||
if rls_right in rights_map:
|
||||
rights_map[rls_right]['Condition'] = str(p_value)
|
||||
rights_map[rls_right]['Condition'] = resolve_text_value(str(p_value))
|
||||
else:
|
||||
print(f"WARNING: {obj_name}: RLS for '{rls_right}' but this right is not in the rights list", file=sys.stderr)
|
||||
|
||||
@@ -1724,7 +1740,7 @@ def main():
|
||||
for tpl in defn['templates']:
|
||||
lines.append('\t<restrictionTemplate>')
|
||||
lines.append(f'\t\t<name>{esc_xml_text(str(tpl["name"]))}</name>')
|
||||
lines.append(f'\t\t<condition>{esc_xml_text(str(tpl["condition"]))}</condition>')
|
||||
lines.append(f'\t\t<condition>{esc_xml_text(resolve_text_value(str(tpl["condition"])))}</condition>')
|
||||
lines.append('\t</restrictionTemplate>')
|
||||
template_count += 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user