mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-11 13:33:41 +03:00
Add role-guide.md and update README with role skills
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,12 +19,22 @@ allowed-tools:
|
|||||||
/role-compile <RoleName> <RolesDir>
|
/role-compile <RoleName> <RolesDir>
|
||||||
```
|
```
|
||||||
|
|
||||||
- **RoleName** — программное имя роли (например, `ВыполнениеРегламентныхЗаданий`)
|
- **RoleName** — программное имя роли
|
||||||
- **RolesDir** — каталог `Roles/` в исходниках конфигурации или обработки
|
- **RolesDir** — каталог `Roles/` в исходниках конфигурации
|
||||||
|
|
||||||
## Что создать
|
## Файловая структура и регистрация
|
||||||
|
|
||||||
### 1. Файл метаданных: `Roles/<RoleName>.xml`
|
```
|
||||||
|
Roles/
|
||||||
|
ИмяРоли.xml ← метаданные (uuid, имя, синоним)
|
||||||
|
ИмяРоли/
|
||||||
|
Ext/
|
||||||
|
Rights.xml ← определение прав
|
||||||
|
```
|
||||||
|
|
||||||
|
В `Configuration.xml` добавить `<Role>ИмяРоли</Role>` в секцию `<ChildObjects>`.
|
||||||
|
|
||||||
|
## Шаблон метаданных: Roles/ИмяРоли.xml
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
@@ -49,11 +59,9 @@ allowed-tools:
|
|||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
```
|
```
|
||||||
|
|
||||||
**UUID:** Сгенерируй через PowerShell: `[guid]::NewGuid().ToString()`
|
**UUID:** `powershell.exe -Command "[guid]::NewGuid().ToString()"`
|
||||||
|
|
||||||
**Namespace:** Минимальный набор — достаточно `xmlns`, `v8`, `xr`, `xs`, `xsi`. Полный набор из спецификации тоже корректен.
|
## Шаблон прав: Roles/ИмяРоли/Ext/Rights.xml
|
||||||
|
|
||||||
### 2. Файл прав: `Roles/<RoleName>/Ext/Rights.xml`
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
@@ -64,146 +72,136 @@ allowed-tools:
|
|||||||
<setForNewObjects>false</setForNewObjects>
|
<setForNewObjects>false</setForNewObjects>
|
||||||
<setForAttributesByDefault>true</setForAttributesByDefault>
|
<setForAttributesByDefault>true</setForAttributesByDefault>
|
||||||
<independentRightsOfChildObjects>false</independentRightsOfChildObjects>
|
<independentRightsOfChildObjects>false</independentRightsOfChildObjects>
|
||||||
<!-- объекты с правами -->
|
<!-- блоки <object> -->
|
||||||
</Rights>
|
</Rights>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Регистрация в Configuration.xml
|
NB: namespace `http://v8.1c.ru/8.2/roles` (исторически 8.2, не 8.3).
|
||||||
|
|
||||||
Добавь `<Role>ИмяРоли</Role>` в секцию `<ChildObjects>` файла `Configuration.xml`.
|
|
||||||
|
|
||||||
## Формат блока прав
|
## Формат блока прав
|
||||||
|
|
||||||
Каждый объект — отдельный блок `<object>`:
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<object>
|
|
||||||
<name>ТипОбъекта.ИмяОбъекта</name>
|
|
||||||
<right>
|
|
||||||
<name>ИмяПрава</name>
|
|
||||||
<value>true</value>
|
|
||||||
</right>
|
|
||||||
</object>
|
|
||||||
```
|
|
||||||
|
|
||||||
Несколько прав — несколько `<right>` внутри одного `<object>`.
|
|
||||||
|
|
||||||
## Права по типам объектов (краткая справка)
|
|
||||||
|
|
||||||
### Ссылочные объекты данных
|
|
||||||
|
|
||||||
| Тип | Типичные права |
|
|
||||||
|-----|---------------|
|
|
||||||
| `Catalog` | Read, Insert, Update, Delete, View, Edit, InputByString, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractiveDelete |
|
|
||||||
| `Document` | (все Catalog) + Posting, UndoPosting, InteractivePosting, InteractivePostingRegular, InteractiveUndoPosting, InteractiveChangeOfPosted |
|
|
||||||
| `ChartOfAccounts` | (как Catalog) + предопределённые: InteractiveDeletePredefinedData и др. |
|
|
||||||
| `ChartOfCharacteristicTypes` | (как ChartOfAccounts) |
|
|
||||||
| `ChartOfCalculationTypes` | (как ChartOfAccounts) |
|
|
||||||
| `ExchangePlan` | (как Catalog) |
|
|
||||||
| `BusinessProcess` | (как Catalog) + Start, InteractiveStart, InteractiveActivate |
|
|
||||||
| `Task` | (как Catalog) + Execute, InteractiveExecute, InteractiveActivate |
|
|
||||||
|
|
||||||
### Регистры
|
|
||||||
|
|
||||||
| Тип | Права |
|
|
||||||
|-----|-------|
|
|
||||||
| `InformationRegister` | Read, Update, View, Edit, TotalsControl |
|
|
||||||
| `AccumulationRegister` | Read, Update, View, Edit, TotalsControl |
|
|
||||||
| `AccountingRegister` | Read, Update, View, Edit, TotalsControl |
|
|
||||||
| `CalculationRegister` | Read, View |
|
|
||||||
|
|
||||||
### Простые типы
|
|
||||||
|
|
||||||
| Тип | Права |
|
|
||||||
|-----|-------|
|
|
||||||
| `DataProcessor` | Use, View |
|
|
||||||
| `Report` | Use, View |
|
|
||||||
| `Constant` | Read, Update, View, Edit |
|
|
||||||
| `CommonForm` | View |
|
|
||||||
| `CommonCommand` | View |
|
|
||||||
| `Subsystem` | View |
|
|
||||||
| `DocumentJournal` | Read, View |
|
|
||||||
| `Sequence` | Read, Update |
|
|
||||||
| `SessionParameter` | Get, Set |
|
|
||||||
| `CommonAttribute` | View, Edit |
|
|
||||||
| `WebService` / `HTTPService` / `IntegrationService` | Use |
|
|
||||||
|
|
||||||
### Вложенные объекты
|
|
||||||
|
|
||||||
| Вложенный тип | Права | Пример |
|
|
||||||
|--------------|-------|--------|
|
|
||||||
| `*.StandardAttribute.*` | View, Edit | `Document.Реализация.StandardAttribute.Posted` |
|
|
||||||
| `*.Attribute.*` | View, Edit | `Catalog.Контрагенты.Attribute.ИНН` |
|
|
||||||
| `*.TabularSection.*` | View, Edit | `Document.Реализация.TabularSection.Товары` |
|
|
||||||
| `*Register.*.Dimension.*` | View, Edit | `InformationRegister.Цены.Dimension.Номенклатура` |
|
|
||||||
| `*Register.*.Resource.*` | View, Edit | `InformationRegister.Цены.Resource.Цена` |
|
|
||||||
| `*.Command.*` | View | `Catalog.Контрагенты.Command.Открыть` |
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
Права на конфигурацию в целом: `Configuration.ИмяКонфигурации`
|
|
||||||
|
|
||||||
Ключевые: Administration, DataAdministration, ThinClient, WebClient, ThickClient, ExternalConnection, Output, SaveUserData, InteractiveOpenExtDataProcessors, InteractiveOpenExtReports
|
|
||||||
|
|
||||||
## Типичные наборы прав
|
|
||||||
|
|
||||||
### Чтение справочника
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<object>
|
<object>
|
||||||
<name>Catalog.Номенклатура</name>
|
<name>Catalog.Номенклатура</name>
|
||||||
<right><name>Read</name><value>true</value></right>
|
<right><name>Read</name><value>true</value></right>
|
||||||
<right><name>View</name><value>true</value></right>
|
<right><name>View</name><value>true</value></right>
|
||||||
<right><name>InputByString</name><value>true</value></right>
|
|
||||||
</object>
|
</object>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Полные права на документ
|
Имя объекта — dot-нотация: `ТипОбъекта.Имя[.ТипВложенного.ИмяВложенного]`.
|
||||||
|
|
||||||
|
## Практические наборы прав
|
||||||
|
|
||||||
|
### Catalog / ExchangePlan
|
||||||
|
|
||||||
|
| Набор | Права |
|
||||||
|
|-------|-------|
|
||||||
|
| Чтение | Read, View, InputByString |
|
||||||
|
| Полные | Read, Insert, Update, Delete, View, Edit, InputByString, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark |
|
||||||
|
|
||||||
|
### Document
|
||||||
|
|
||||||
|
| Набор | Права |
|
||||||
|
|-------|-------|
|
||||||
|
| Чтение | Read, View, InputByString |
|
||||||
|
| Полные | Read, Insert, Update, Delete, View, Edit, InputByString, Posting, UndoPosting, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractivePosting, InteractivePostingRegular, InteractiveUndoPosting, InteractiveChangeOfPosted |
|
||||||
|
|
||||||
|
### InformationRegister / AccumulationRegister / AccountingRegister
|
||||||
|
|
||||||
|
| Набор | Права |
|
||||||
|
|-------|-------|
|
||||||
|
| Чтение | Read, View |
|
||||||
|
| Полные | Read, Update, View, Edit |
|
||||||
|
|
||||||
|
TotalsControl — только для управления итогами, обычно не нужно.
|
||||||
|
|
||||||
|
### Простые типы
|
||||||
|
|
||||||
|
| Тип | Права |
|
||||||
|
|-----|-------|
|
||||||
|
| `DataProcessor` / `Report` | Use, View |
|
||||||
|
| `Constant` | Read, Update, View, Edit (чтение: Read, View) |
|
||||||
|
| `CommonForm` / `CommonCommand` / `Subsystem` / `FilterCriterion` | View |
|
||||||
|
| `DocumentJournal` | Read, View |
|
||||||
|
| `Sequence` | Read, Update |
|
||||||
|
| `SessionParameter` | Get (+ Set если пишет) |
|
||||||
|
| `CommonAttribute` | View (+ Edit если редактирует) |
|
||||||
|
| `WebService` / `HTTPService` / `IntegrationService` | Use |
|
||||||
|
| `CalculationRegister` | Read, View |
|
||||||
|
|
||||||
|
### Редкие ссылочные типы
|
||||||
|
|
||||||
|
| Тип | Особенности (относительно Catalog) |
|
||||||
|
|-----|-------|
|
||||||
|
| `ChartOfAccounts`, `ChartOfCharacteristicTypes`, `ChartOfCalculationTypes` | + Predefined-права (InteractiveDeletePredefinedData и др.) |
|
||||||
|
| `BusinessProcess` | + Start, InteractiveStart, InteractiveActivate |
|
||||||
|
| `Task` | + Execute, InteractiveExecute, InteractiveActivate |
|
||||||
|
|
||||||
|
### Типы БЕЗ прав в ролях
|
||||||
|
|
||||||
|
Enum, FunctionalOption, DefinedType, CommonModule, CommonPicture, CommonTemplate — не фигурируют в Rights.xml.
|
||||||
|
|
||||||
|
### Вложенные объекты (права: View, Edit)
|
||||||
|
|
||||||
|
```
|
||||||
|
Catalog.Контрагенты.Attribute.ИНН
|
||||||
|
Document.Реализация.StandardAttribute.Posted
|
||||||
|
Document.Реализация.TabularSection.Товары
|
||||||
|
InformationRegister.Цены.Dimension.Номенклатура
|
||||||
|
InformationRegister.Цены.Resource.Цена
|
||||||
|
Catalog.Контрагенты.Command.ОткрытьКарточку ← только View
|
||||||
|
Task.Задача.AddressingAttribute.Исполнитель
|
||||||
|
```
|
||||||
|
|
||||||
|
Используются для точечного запрета: `<value>false</value>` на конкретный реквизит.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Объект: `Configuration.ИмяКонфигурации`. Ключевые права: Administration, DataAdministration, ThinClient, WebClient, ThickClient, MobileClient, ExternalConnection, Output, SaveUserData, InteractiveOpenExtDataProcessors, InteractiveOpenExtReports, MainWindowModeNormal, MainWindowModeWorkplace, MainWindowModeEmbeddedWorkplace, MainWindowModeFullscreenWorkplace, MainWindowModeKiosk, AnalyticsSystemClient.
|
||||||
|
|
||||||
|
> DataHistory-права (ReadDataHistory, UpdateDataHistory и др.) существуют у Catalog, Document, Register, Constant — но используются крайне редко, в типовых ролях практически не встречаются.
|
||||||
|
|
||||||
|
## RLS (ограничения на уровне записей)
|
||||||
|
|
||||||
|
Внутрь `<right>`, после `<value>`. Применяется к Read, Update, Insert, Delete.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<right>
|
||||||
|
<name>Read</name>
|
||||||
|
<value>true</value>
|
||||||
|
<restrictionByCondition>
|
||||||
|
<condition>#ИмяШаблона("Параметр1", "Параметр2")</condition>
|
||||||
|
</restrictionByCondition>
|
||||||
|
</right>
|
||||||
|
```
|
||||||
|
|
||||||
|
Шаблоны — в конце Rights.xml, после всех `<object>`:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<restrictionTemplate>
|
||||||
|
<name>ИмяШаблона(Параметр1, Параметр2)</name>
|
||||||
|
<condition>Текст шаблона</condition>
|
||||||
|
</restrictionTemplate>
|
||||||
|
```
|
||||||
|
|
||||||
|
`&` в условии → `&`. Типичные шаблоны: ДляОбъекта, ПоЗначениям, ДляРегистра.
|
||||||
|
|
||||||
|
## Пример: роль для регламентного задания
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<object>
|
<object>
|
||||||
<name>Document.РеализацияТоваровУслуг</name>
|
<name>Catalog.Валюты</name>
|
||||||
<right><name>Read</name><value>true</value></right>
|
<right><name>Read</name><value>true</value></right>
|
||||||
<right><name>Insert</name><value>true</value></right>
|
|
||||||
<right><name>Update</name><value>true</value></right>
|
|
||||||
<right><name>Delete</name><value>true</value></right>
|
|
||||||
<right><name>Posting</name><value>true</value></right>
|
|
||||||
<right><name>UndoPosting</name><value>true</value></right>
|
|
||||||
<right><name>View</name><value>true</value></right>
|
|
||||||
<right><name>InteractiveInsert</name><value>true</value></right>
|
|
||||||
<right><name>Edit</name><value>true</value></right>
|
|
||||||
<right><name>InteractiveSetDeletionMark</name><value>true</value></right>
|
|
||||||
<right><name>InteractiveClearDeletionMark</name><value>true</value></right>
|
|
||||||
<right><name>InteractivePosting</name><value>true</value></right>
|
|
||||||
<right><name>InteractivePostingRegular</name><value>true</value></right>
|
|
||||||
<right><name>InteractiveUndoPosting</name><value>true</value></right>
|
|
||||||
<right><name>InteractiveChangeOfPosted</name><value>true</value></right>
|
|
||||||
<right><name>InputByString</name><value>true</value></right>
|
|
||||||
</object>
|
</object>
|
||||||
```
|
|
||||||
|
|
||||||
### Использование обработки
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<object>
|
<object>
|
||||||
<name>DataProcessor.ОбновлениеЦен</name>
|
<name>InformationRegister.КурсыВалют</name>
|
||||||
<right><name>Use</name><value>true</value></right>
|
|
||||||
<right><name>View</name><value>true</value></right>
|
|
||||||
</object>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Чтение/запись регистра
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<object>
|
|
||||||
<name>InformationRegister.ЦеныНоменклатуры</name>
|
|
||||||
<right><name>Read</name><value>true</value></right>
|
<right><name>Read</name><value>true</value></right>
|
||||||
<right><name>Update</name><value>true</value></right>
|
<right><name>Update</name><value>true</value></right>
|
||||||
<right><name>View</name><value>true</value></right>
|
</object>
|
||||||
<right><name>Edit</name><value>true</value></right>
|
<object>
|
||||||
|
<name>Constant.ОсновнаяВалюта</name>
|
||||||
|
<right><name>Read</name><value>true</value></right>
|
||||||
</object>
|
</object>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Полная спецификация
|
Фоновые задания не требуют Interactive/View/Edit-прав и прав конфигурации (ThinClient, WebClient и др.) — только программные (Read, Insert, Update, Delete, Posting).
|
||||||
|
|
||||||
См. [1c-role-spec.md](../../docs/1c-role-spec.md) — полный каталог прав, RLS, шаблоны ограничений, версии формата.
|
|
||||||
|
|||||||
@@ -31,11 +31,17 @@ powershell.exe -File .claude\skills\role-info\scripts\role-info.ps1 -RightsPath
|
|||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-RightsPath` | да | Путь к Rights.xml |
|
| `-RightsPath` | да | Путь к Rights.xml |
|
||||||
| `-ShowDenied` | нет | Показать запрещённые права (по умолчанию скрыты) |
|
| `-ShowDenied` | нет | Показать запрещённые права (по умолчанию скрыты) |
|
||||||
| `-MaxPerGroup` | нет | Макс. объектов на группу (по умолчанию 20). `0` = без ограничений |
|
| `-Limit` | нет | Макс. строк вывода (по умолчанию `150`). `0` = без ограничений |
|
||||||
|
| `-Offset` | нет | Пропустить N строк — для пагинации (по умолчанию `0`) |
|
||||||
| `-OutFile` | нет | Записать результат в файл (UTF-8 BOM). Без этого — вывод в консоль |
|
| `-OutFile` | нет | Записать результат в файл (UTF-8 BOM). Без этого — вывод в консоль |
|
||||||
|
|
||||||
**Важно:** Всегда используй `-OutFile` и читай результат через Read tool. Прямой вывод в консоль через bash ломает кириллицу.
|
**Важно:** Всегда используй `-OutFile` и читай результат через Read tool. Прямой вывод в консоль через bash ломает кириллицу.
|
||||||
|
|
||||||
|
Для большой роли при усечении вывода:
|
||||||
|
```powershell
|
||||||
|
... -Offset 150 # пагинация: пропустить первые 150 строк
|
||||||
|
```
|
||||||
|
|
||||||
## Формат вывода
|
## Формат вывода
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -65,8 +71,12 @@ Templates: ДляРегистра, ПоЗначениям
|
|||||||
|
|
||||||
---
|
---
|
||||||
Total: 138 allowed, 18 denied
|
Total: 138 allowed, 18 denied
|
||||||
|
|
||||||
|
[TRUNCATED] Shown 150 of 220 lines. Use -Offset 150 to continue.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Используйте `-Offset N` и `-Limit N` для постраничного просмотра.
|
||||||
|
|
||||||
### Обозначения
|
### Обозначения
|
||||||
|
|
||||||
- `[RLS]` — право с ограничением на уровне записей (restrictionByCondition)
|
- `[RLS]` — право с ограничением на уровне записей (restrictionByCondition)
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)][string]$RightsPath,
|
[Parameter(Mandatory=$true)][string]$RightsPath,
|
||||||
[switch]$ShowDenied,
|
[switch]$ShowDenied,
|
||||||
[int]$MaxPerGroup = 20,
|
[int]$Limit = 150,
|
||||||
[string]$OutFile
|
[int]$Offset = 0,
|
||||||
|
[string]$OutFile
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
# --- Output helper ---
|
# --- Output helper (always collect, paginate at the end) ---
|
||||||
$script:lines = @()
|
$script:lines = @()
|
||||||
function Out([string]$text) {
|
function Out([string]$text) { $script:lines += $text }
|
||||||
if ($OutFile) { $script:lines += $text }
|
|
||||||
else { Write-Host $text }
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Resolve paths ---
|
# --- Resolve paths ---
|
||||||
if (-not [System.IO.Path]::IsPathRooted($RightsPath)) {
|
if (-not [System.IO.Path]::IsPathRooted($RightsPath)) {
|
||||||
$RightsPath = Join-Path (Get-Location).Path $RightsPath
|
$RightsPath = Join-Path (Get-Location).Path $RightsPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $RightsPath)) {
|
if (-not (Test-Path $RightsPath)) {
|
||||||
Out "[ERROR] File not found: $RightsPath"
|
Write-Host "[ERROR] File not found: $RightsPath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Try to find metadata file for role name/synonym ---
|
# --- Try to find metadata file for role name/synonym ---
|
||||||
@@ -34,18 +32,18 @@ $roleFolderName = Split-Path $roleDir -Leaf
|
|||||||
$metaPath = Join-Path $rolesDir "$roleFolderName.xml"
|
$metaPath = Join-Path $rolesDir "$roleFolderName.xml"
|
||||||
|
|
||||||
if (Test-Path $metaPath) {
|
if (Test-Path $metaPath) {
|
||||||
try {
|
try {
|
||||||
[xml]$metaXml = Get-Content -Path $metaPath -Encoding UTF8
|
[xml]$metaXml = Get-Content -Path $metaPath -Encoding UTF8
|
||||||
$ns = New-Object System.Xml.XmlNamespaceManager($metaXml.NameTable)
|
$ns = New-Object System.Xml.XmlNamespaceManager($metaXml.NameTable)
|
||||||
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
||||||
$nameNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Name", $ns)
|
$nameNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Name", $ns)
|
||||||
if ($nameNode) { $roleName = $nameNode.InnerText }
|
if ($nameNode) { $roleName = $nameNode.InnerText }
|
||||||
$synNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Synonym/v8:item[v8:lang='ru']/v8:content", $ns)
|
$synNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Synonym/v8:item[v8:lang='ru']/v8:content", $ns)
|
||||||
if ($synNode) { $roleSynonym = $synNode.InnerText }
|
if ($synNode) { $roleSynonym = $synNode.InnerText }
|
||||||
} catch {
|
} catch {
|
||||||
# Ignore metadata parsing errors
|
# Ignore metadata parsing errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $roleName) { $roleName = $roleFolderName }
|
if (-not $roleName) { $roleName = $roleFolderName }
|
||||||
@@ -70,78 +68,78 @@ $totalDenied = 0
|
|||||||
|
|
||||||
$objects = $root.GetElementsByTagName("object", $rightsNs)
|
$objects = $root.GetElementsByTagName("object", $rightsNs)
|
||||||
foreach ($obj in $objects) {
|
foreach ($obj in $objects) {
|
||||||
$objName = ""
|
$objName = ""
|
||||||
$rights = @()
|
$rights = @()
|
||||||
|
|
||||||
foreach ($child in $obj.ChildNodes) {
|
foreach ($child in $obj.ChildNodes) {
|
||||||
if ($child.LocalName -eq "name" -and $child.NamespaceURI -eq $rightsNs) {
|
if ($child.LocalName -eq "name" -and $child.NamespaceURI -eq $rightsNs) {
|
||||||
$objName = $child.InnerText
|
$objName = $child.InnerText
|
||||||
}
|
}
|
||||||
if ($child.LocalName -eq "right" -and $child.NamespaceURI -eq $rightsNs) {
|
if ($child.LocalName -eq "right" -and $child.NamespaceURI -eq $rightsNs) {
|
||||||
$rName = ""
|
$rName = ""
|
||||||
$rValue = ""
|
$rValue = ""
|
||||||
$hasRLS = $false
|
$hasRLS = $false
|
||||||
foreach ($rc in $child.ChildNodes) {
|
foreach ($rc in $child.ChildNodes) {
|
||||||
if ($rc.LocalName -eq "name") { $rName = $rc.InnerText }
|
if ($rc.LocalName -eq "name") { $rName = $rc.InnerText }
|
||||||
if ($rc.LocalName -eq "value") { $rValue = $rc.InnerText }
|
if ($rc.LocalName -eq "value") { $rValue = $rc.InnerText }
|
||||||
if ($rc.LocalName -eq "restrictionByCondition") { $hasRLS = $true }
|
if ($rc.LocalName -eq "restrictionByCondition") { $hasRLS = $true }
|
||||||
}
|
}
|
||||||
if ($rName -and $rValue) {
|
if ($rName -and $rValue) {
|
||||||
$rights += @{ name = $rName; value = $rValue; rls = $hasRLS }
|
$rights += @{ name = $rName; value = $rValue; rls = $hasRLS }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $objName -or $rights.Count -eq 0) { continue }
|
if (-not $objName -or $rights.Count -eq 0) { continue }
|
||||||
|
|
||||||
# Split into type prefix and short name
|
# Split into type prefix and short name
|
||||||
$dotIdx = $objName.IndexOf(".")
|
$dotIdx = $objName.IndexOf(".")
|
||||||
if ($dotIdx -lt 0) { continue }
|
if ($dotIdx -lt 0) { continue }
|
||||||
$typePrefix = $objName.Substring(0, $dotIdx)
|
$typePrefix = $objName.Substring(0, $dotIdx)
|
||||||
$shortName = $objName.Substring($dotIdx + 1)
|
$shortName = $objName.Substring($dotIdx + 1)
|
||||||
|
|
||||||
foreach ($r in $rights) {
|
foreach ($r in $rights) {
|
||||||
if ($r.value -eq "true") {
|
if ($r.value -eq "true") {
|
||||||
$totalAllowed++
|
$totalAllowed++
|
||||||
if (-not $allowed.Contains($typePrefix)) {
|
if (-not $allowed.Contains($typePrefix)) {
|
||||||
$allowed[$typePrefix] = [ordered]@{}
|
$allowed[$typePrefix] = [ordered]@{}
|
||||||
}
|
}
|
||||||
if (-not $allowed[$typePrefix].Contains($shortName)) {
|
if (-not $allowed[$typePrefix].Contains($shortName)) {
|
||||||
$allowed[$typePrefix][$shortName] = @()
|
$allowed[$typePrefix][$shortName] = @()
|
||||||
}
|
}
|
||||||
$suffix = $r.name
|
$suffix = $r.name
|
||||||
if ($r.rls) {
|
if ($r.rls) {
|
||||||
$suffix += " [RLS]"
|
$suffix += " [RLS]"
|
||||||
$rlsObjects += "$typePrefix.$shortName ($($r.name))"
|
$rlsObjects += "$typePrefix.$shortName ($($r.name))"
|
||||||
}
|
}
|
||||||
$allowed[$typePrefix][$shortName] += $suffix
|
$allowed[$typePrefix][$shortName] += $suffix
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$totalDenied++
|
$totalDenied++
|
||||||
if (-not $denied.Contains($typePrefix)) {
|
if (-not $denied.Contains($typePrefix)) {
|
||||||
$denied[$typePrefix] = [ordered]@{}
|
$denied[$typePrefix] = [ordered]@{}
|
||||||
}
|
}
|
||||||
if (-not $denied[$typePrefix].Contains($shortName)) {
|
if (-not $denied[$typePrefix].Contains($shortName)) {
|
||||||
$denied[$typePrefix][$shortName] = @()
|
$denied[$typePrefix][$shortName] = @()
|
||||||
}
|
}
|
||||||
$denied[$typePrefix][$shortName] += $r.name
|
$denied[$typePrefix][$shortName] += $r.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Restriction templates ---
|
# --- Restriction templates ---
|
||||||
$templates = @()
|
$templates = @()
|
||||||
$tplNodes = $root.GetElementsByTagName("restrictionTemplate", $rightsNs)
|
$tplNodes = $root.GetElementsByTagName("restrictionTemplate", $rightsNs)
|
||||||
foreach ($tpl in $tplNodes) {
|
foreach ($tpl in $tplNodes) {
|
||||||
foreach ($child in $tpl.ChildNodes) {
|
foreach ($child in $tpl.ChildNodes) {
|
||||||
if ($child.LocalName -eq "name") {
|
if ($child.LocalName -eq "name") {
|
||||||
$tName = $child.InnerText
|
$tName = $child.InnerText
|
||||||
# Extract just the name part before parentheses
|
# Extract just the name part before parentheses
|
||||||
$parenIdx = $tName.IndexOf("(")
|
$parenIdx = $tName.IndexOf("(")
|
||||||
if ($parenIdx -gt 0) { $tName = $tName.Substring(0, $parenIdx) }
|
if ($parenIdx -gt 0) { $tName = $tName.Substring(0, $parenIdx) }
|
||||||
$templates += $tName
|
$templates += $tName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
@@ -154,78 +152,91 @@ Out ""
|
|||||||
Out "Properties: setForNewObjects=$setForNew, setForAttributesByDefault=$setForAttrs, independentRightsOfChildObjects=$independentChild"
|
Out "Properties: setForNewObjects=$setForNew, setForAttributesByDefault=$setForAttrs, independentRightsOfChildObjects=$independentChild"
|
||||||
Out ""
|
Out ""
|
||||||
|
|
||||||
# Helper: output group with truncation
|
# Helper: output group
|
||||||
function OutGroup($objMap, [string]$prefix, [switch]$isDenied) {
|
function OutGroup($objMap, [string]$prefix, [switch]$isDenied) {
|
||||||
$keys = @($objMap.Keys)
|
foreach ($shortName in @($objMap.Keys)) {
|
||||||
$shown = 0
|
if ($isDenied) {
|
||||||
foreach ($shortName in $keys) {
|
$rightsList = ($objMap[$shortName] | ForEach-Object { "-$_" }) -join ", "
|
||||||
if ($MaxPerGroup -gt 0 -and $shown -ge $MaxPerGroup) {
|
} else {
|
||||||
$remaining = $keys.Count - $shown
|
$rightsList = $objMap[$shortName] -join ", "
|
||||||
Out " ... ещё $remaining (используй -MaxPerGroup 0 для полного списка)"
|
}
|
||||||
break
|
Out " ${shortName}: $rightsList"
|
||||||
}
|
}
|
||||||
if ($isDenied) {
|
|
||||||
$rightsList = ($objMap[$shortName] | ForEach-Object { "-$_" }) -join ", "
|
|
||||||
} else {
|
|
||||||
$rightsList = $objMap[$shortName] -join ", "
|
|
||||||
}
|
|
||||||
Out " ${shortName}: $rightsList"
|
|
||||||
$shown++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Allowed rights grouped by type
|
# Allowed rights grouped by type
|
||||||
if ($allowed.Count -gt 0) {
|
if ($allowed.Count -gt 0) {
|
||||||
Out "Allowed rights:"
|
Out "Allowed rights:"
|
||||||
Out ""
|
Out ""
|
||||||
foreach ($typePrefix in $allowed.Keys) {
|
foreach ($typePrefix in $allowed.Keys) {
|
||||||
$objMap = $allowed[$typePrefix]
|
$objMap = $allowed[$typePrefix]
|
||||||
Out " $typePrefix ($($objMap.Count)):"
|
Out " $typePrefix ($($objMap.Count)):"
|
||||||
OutGroup $objMap $typePrefix
|
OutGroup $objMap $typePrefix
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Out "(no allowed rights)"
|
Out "(no allowed rights)"
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Denied rights
|
# Denied rights
|
||||||
if ($ShowDenied -and $denied.Count -gt 0) {
|
if ($ShowDenied -and $denied.Count -gt 0) {
|
||||||
Out "Denied rights:"
|
Out "Denied rights:"
|
||||||
Out ""
|
Out ""
|
||||||
foreach ($typePrefix in $denied.Keys) {
|
foreach ($typePrefix in $denied.Keys) {
|
||||||
$objMap = $denied[$typePrefix]
|
$objMap = $denied[$typePrefix]
|
||||||
Out " $typePrefix ($($objMap.Count)):"
|
Out " $typePrefix ($($objMap.Count)):"
|
||||||
OutGroup $objMap $typePrefix -isDenied
|
OutGroup $objMap $typePrefix -isDenied
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ($totalDenied -gt 0) {
|
elseif ($totalDenied -gt 0) {
|
||||||
Out "Denied: $totalDenied rights (use -ShowDenied to list)"
|
Out "Denied: $totalDenied rights (use -ShowDenied to list)"
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# RLS summary
|
# RLS summary
|
||||||
if ($rlsObjects.Count -gt 0) {
|
if ($rlsObjects.Count -gt 0) {
|
||||||
Out "RLS: $($rlsObjects.Count) restrictions"
|
Out "RLS: $($rlsObjects.Count) restrictions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Templates
|
# Templates
|
||||||
if ($templates.Count -gt 0) {
|
if ($templates.Count -gt 0) {
|
||||||
Out "Templates: $($templates -join ', ')"
|
Out "Templates: $($templates -join ', ')"
|
||||||
}
|
}
|
||||||
|
|
||||||
Out ""
|
Out ""
|
||||||
Out "---"
|
Out "---"
|
||||||
Out "Total: $totalAllowed allowed, $totalDenied denied"
|
Out "Total: $totalAllowed allowed, $totalDenied denied"
|
||||||
|
|
||||||
# --- Write to file if requested ---
|
# --- Pagination and output ---
|
||||||
if ($OutFile) {
|
$totalLines = $script:lines.Count
|
||||||
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
$lines = $script:lines
|
||||||
$OutFile = Join-Path (Get-Location).Path $OutFile
|
|
||||||
}
|
if ($Offset -gt 0) {
|
||||||
$utf8 = New-Object System.Text.UTF8Encoding($true)
|
if ($Offset -ge $totalLines) {
|
||||||
[System.IO.File]::WriteAllLines($OutFile, $script:lines, $utf8)
|
Write-Host "[INFO] Offset $Offset exceeds total lines ($totalLines). Nothing to show."
|
||||||
Write-Host "Output written to $OutFile"
|
exit 0
|
||||||
|
}
|
||||||
|
$lines = $lines[$Offset..($totalLines - 1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Limit -gt 0 -and $lines.Count -gt $Limit) {
|
||||||
|
$shown = $lines[0..($Limit - 1)]
|
||||||
|
$remaining = $totalLines - $Offset - $Limit
|
||||||
|
$shown += ""
|
||||||
|
$shown += "[TRUNCATED] Shown $Limit of $totalLines lines. Use -Offset $($Offset + $Limit) to continue."
|
||||||
|
$lines = $shown
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($OutFile) {
|
||||||
|
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
||||||
|
$OutFile = Join-Path (Get-Location).Path $OutFile
|
||||||
|
}
|
||||||
|
$utf8 = New-Object System.Text.UTF8Encoding($true)
|
||||||
|
[System.IO.File]::WriteAllLines($OutFile, $lines, $utf8)
|
||||||
|
Write-Host "Output written to $OutFile"
|
||||||
|
} else {
|
||||||
|
foreach ($l in $lines) { Write-Host $l }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
|--------|--------|----------|------|
|
|--------|--------|----------|------|
|
||||||
| Внешние обработки (EPF) | 10 навыков `/epf-*` | Создание, модификация, сборка обработок из XML-исходников | [Подробнее](docs/epf-guide.md) |
|
| Внешние обработки (EPF) | 10 навыков `/epf-*` | Создание, модификация, сборка обработок из XML-исходников | [Подробнее](docs/epf-guide.md) |
|
||||||
| Табличный документ (MXL) | 4 навыка `/mxl-*` | Анализ, создание, компиляция макетов печатных форм | [Подробнее](docs/mxl-guide.md) |
|
| Табличный документ (MXL) | 4 навыка `/mxl-*` | Анализ, создание, компиляция макетов печатных форм | [Подробнее](docs/mxl-guide.md) |
|
||||||
| Управляемые формы (Form) | 4 навыка `/form-*` | Анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) |
|
| Управляемые формы (Form) | 5 навыков `/form-*` | Анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) |
|
||||||
|
| Роли (Role) | 2 навыка `/role-*` | Анализ прав роли, создание роли из описания | [Подробнее](docs/role-guide.md) |
|
||||||
| Утилиты | `/img-grid` | Наложение сетки на изображение для определения пропорций колонок | — |
|
| Утилиты | `/img-grid` | Наложение сетки на изображение для определения пропорций колонок | — |
|
||||||
|
|
||||||
## Требования
|
## Требования
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
- [Табличный документ (MXL)](docs/1c-spreadsheet-spec.md) — XML-формат SpreadsheetDocument, совместимость версий
|
- [Табличный документ (MXL)](docs/1c-spreadsheet-spec.md) — XML-формат SpreadsheetDocument, совместимость версий
|
||||||
- [MXL DSL](docs/mxl-dsl-spec.md) — JSON-формат описания макета для `/mxl-compile` и `/mxl-decompile`
|
- [MXL DSL](docs/mxl-dsl-spec.md) — JSON-формат описания макета для `/mxl-compile` и `/mxl-decompile`
|
||||||
- [Form DSL](docs/form-dsl-spec.md) — JSON-формат описания формы для `/form-compile`
|
- [Form DSL](docs/form-dsl-spec.md) — JSON-формат описания формы для `/form-compile`
|
||||||
|
- [Роли (Rights.xml)](docs/1c-role-spec.md) — XML-формат прав роли, типы объектов, RLS
|
||||||
|
|
||||||
## Структура репозитория
|
## Структура репозитория
|
||||||
|
|
||||||
@@ -61,16 +63,21 @@
|
|||||||
├── form-compile/ # Компиляция формы из JSON
|
├── form-compile/ # Компиляция формы из JSON
|
||||||
├── form-validate/ # Валидация формы
|
├── form-validate/ # Валидация формы
|
||||||
├── form-add/ # Добавление элементов в форму
|
├── form-add/ # Добавление элементов в форму
|
||||||
|
├── form-patterns/ # Справочник паттернов компоновки форм
|
||||||
|
├── role-info/ # Анализ прав роли
|
||||||
|
├── role-compile/ # Создание роли из описания
|
||||||
└── img-grid/ # Сетка для анализа изображений
|
└── img-grid/ # Сетка для анализа изображений
|
||||||
docs/
|
docs/
|
||||||
├── epf-guide.md # Гайд: внешние обработки
|
├── epf-guide.md # Гайд: внешние обработки
|
||||||
├── mxl-guide.md # Гайд: табличный документ
|
├── mxl-guide.md # Гайд: табличный документ
|
||||||
├── form-guide.md # Гайд: управляемые формы
|
├── form-guide.md # Гайд: управляемые формы
|
||||||
|
├── role-guide.md # Гайд: роли
|
||||||
├── 1c-xml-format-spec.md # Спецификация XML-формата
|
├── 1c-xml-format-spec.md # Спецификация XML-формата
|
||||||
├── 1c-form-spec.md # Спецификация управляемых форм
|
├── 1c-form-spec.md # Спецификация управляемых форм
|
||||||
├── 1c-help-spec.md # Спецификация встроенной справки
|
├── 1c-help-spec.md # Спецификация встроенной справки
|
||||||
├── build-spec.md # Спецификация сборки/разборки
|
├── build-spec.md # Спецификация сборки/разборки
|
||||||
├── 1c-spreadsheet-spec.md # Спецификация табличного документа
|
├── 1c-spreadsheet-spec.md # Спецификация табличного документа
|
||||||
├── mxl-dsl-spec.md # Спецификация MXL DSL
|
├── mxl-dsl-spec.md # Спецификация MXL DSL
|
||||||
└── form-dsl-spec.md # Спецификация Form DSL
|
├── form-dsl-spec.md # Спецификация Form DSL
|
||||||
|
└── 1c-role-spec.md # Спецификация ролей (Rights.xml)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Роли (Role)
|
||||||
|
|
||||||
|
Навыки группы `/role-*` позволяют анализировать и создавать роли 1С — XML-файлы прав доступа (Rights.xml) и метаданных.
|
||||||
|
|
||||||
|
## Навыки
|
||||||
|
|
||||||
|
| Навык | Параметры | Описание |
|
||||||
|
|-------|-----------|----------|
|
||||||
|
| `/role-info` | `<RightsPath>` | Компактная сводка прав: объекты по типам, только разрешённые, RLS, шаблоны |
|
||||||
|
| `/role-compile` | `<RoleName> <RolesDir>` | Создание роли: метаданные + Rights.xml по описанию прав |
|
||||||
|
|
||||||
|
## Сценарии использования
|
||||||
|
|
||||||
|
### Анализ существующей роли
|
||||||
|
|
||||||
|
```
|
||||||
|
> Проанализируй права роли Roles/БазовыеПраваБП/Ext/Rights.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
Claude вызовет `/role-info`, получит компактную сводку (тысячи строк XML → 50–300 строк текста) и опишет:
|
||||||
|
- какие объекты доступны и с какими правами
|
||||||
|
- где есть ограничения RLS
|
||||||
|
- какие шаблоны ограничений используются
|
||||||
|
|
||||||
|
### Создание роли для регламентного задания
|
||||||
|
|
||||||
|
```
|
||||||
|
> Проанализируй модуль регламентного задания ОбновлениеКурсовВалют
|
||||||
|
> и создай роль с минимальными правами для его выполнения
|
||||||
|
```
|
||||||
|
|
||||||
|
Claude проанализирует код, определит используемые объекты метаданных, и вызовет `/role-compile` для создания роли с нужными правами (Read, Update, Posting и т.д.).
|
||||||
|
|
||||||
|
### Создание роли по описанию
|
||||||
|
|
||||||
|
```
|
||||||
|
> Создай роль МенеджерПродаж с правами:
|
||||||
|
> - Документ РеализацияТоваровУслуг: полные права
|
||||||
|
> - Справочник Контрагенты: чтение
|
||||||
|
> - Справочник Номенклатура: чтение
|
||||||
|
> - Регистр ЦеныНоменклатуры: чтение
|
||||||
|
```
|
||||||
|
|
||||||
|
Рабочий цикл:
|
||||||
|
1. Claude генерирует `Roles/МенеджерПродаж.xml` (метаданные с UUID)
|
||||||
|
2. Claude генерирует `Roles/МенеджерПродаж/Ext/Rights.xml` (права)
|
||||||
|
3. Регистрирует роль в `Configuration.xml` (`<ChildObjects>`)
|
||||||
|
4. Проверяет результат через `/role-info`
|
||||||
|
|
||||||
|
## Структура файлов роли
|
||||||
|
|
||||||
|
```
|
||||||
|
Roles/
|
||||||
|
├── ИмяРоли.xml # Метаданные (UUID, синоним)
|
||||||
|
└── ИмяРоли/
|
||||||
|
└── Ext/
|
||||||
|
└── Rights.xml # Права доступа
|
||||||
|
```
|
||||||
|
|
||||||
|
Регистрация в `Configuration.xml`:
|
||||||
|
```xml
|
||||||
|
<ChildObjects>
|
||||||
|
<Role>ИмяРоли</Role>
|
||||||
|
</ChildObjects>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Спецификация
|
||||||
|
|
||||||
|
Полная спецификация формата: [1c-role-spec.md](1c-role-spec.md) — типы объектов, права, RLS, шаблоны ограничений, версии формата.
|
||||||
Reference in New Issue
Block a user