Управление разрешениями
Univer позволяет управлять разрешениями и ограничивать действия пользователей с книгами, листами и диапазонами. Если пользователь пытается выполнить действие без необходимого разрешения, операция прерывается, а пользователь получает уведомление. Например, можно защитить диапазон и определить, смогут ли участники редактировать, просматривать, копировать или фильтровать данные в нём.
Сервис должен сохранять правила защиты и изменения участников, возвращать права текущего пользователя и передавать ошибки запросов вызывающему коду. Пустые списки в заглушке не обеспечивают сохранение данных. При совместной работе сервер отдельно проверяет чтение, JOIN и изменение; см. Идентификация и авторизация. Защита интерфейса и скрытие затенения не заменяют серверную авторизацию.
Перейдите к разделу по своей задаче. Базовые операции, расширенные примеры, настройки и устранение проблем остаются на этой странице; полные контракты API поддерживаются в Reference.
Основные понятия
- Область действия: разрешения применяются на трёх уровнях — книга, лист и диапазон.
- Точки разрешений: каждой функции соответствует точка разрешения. Изменяя её, можно управлять доступностью функции.
- Правила защиты: прежде чем настраивать точки разрешений для листов и диапазонов, необходимо создать правило защиты.
Локальные права без сохранения изменяются через точки прав. Для сохранения см. Интеграция сервиса авторизации
При совместном редактировании обновление точки разрешения синхронизирует состояние сервера:
false: для точки разрешения требуется роль не нижеownertrue: для точки разрешения требуется роль не нижеreader
Базовый пример
Перед использованием примеров allowedUsers замените user1 и user2 реальными идентификаторами участников, возвращаемыми вашим сервисом авторизации.
Ниже показаны наиболее распространённые способы настройки разрешений на трёх уровнях: книги, листа и диапазона.
Пример разрешений для книги
Разрешения на уровне книги можно настроить напрямую через Facade API.
В следующем примере редактирование отключается для всей книги. Для управления другими функциями замените точку разрешения на соответствующую (см. список точек разрешений книги):
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const workbookPermission = fWorkbook.getWorkbookPermission()// Set the workbook to be non-editableawait workbookPermission.setPoint(univerAPI.Enum.WorkbookPermissionPoint.Edit, false)Важно:
- точки разрешений книги можно настраивать напрямую, не создавая правил защиты.
Пример разрешений для листа
Разрешения листа и диапазона можно настраивать через Facade API или команды. В следующем примере задаётся разрешение на редактирование листа. Для других функций замените точку разрешения на соответствующую (см. список точек разрешений листа):
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const fWorksheet = fWorkbook.getActiveSheet()const worksheetPermission = fWorksheet.getWorksheetPermission()// Create worksheet protection, allow specified users to editconst permissionId = await worksheetPermission.protect({ allowedUsers: ['user1', 'user2'], name: 'My Worksheet Protection',})// To set permission points, you must first protect the worksheetawait worksheetPermission.setPoint(univerAPI.Enum.WorksheetPermissionPoint.Edit, false)Удаление разрешений листа
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const fWorksheet = fWorkbook.getActiveSheet()const worksheetPermission = fWorksheet.getWorksheetPermission()// Remove worksheet protectionawait worksheetPermission.unprotect()Пример пользовательских разрешений диапазона
Разрешения диапазона также можно настраивать через API и команды. Здесь в качестве примера используется разрешение на редактирование диапазона. Для других функций диапазона замените точки разрешений; подробности см. в списке точек разрешений диапазона.
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const fWorksheet = fWorkbook.getActiveSheet()const fRange = fWorksheet.getRange('A1:B2')const rangePermission = fRange.getRangePermission()// Set range protection permission, allow specified users to edit but not allow others to viewconst rule = await rangePermission.protect({ name: 'My protected range', allowViewByOthers: false, allowedUsers: ['user1', 'user2'],})console.log(rule)// To set permission points, you must first create a range protection rule.await rule.setPoint(univerAPI.Enum.RangePermissionPoint.Edit, false)await rule.setPoint(univerAPI.Enum.RangePermissionPoint.View, true)Удаление разрешений защиты диапазона
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const fWorksheet = fWorkbook.getActiveSheet()const fRange = fWorksheet.getRange('A1:B2')const rangePermission = fRange.getRangePermission()// delete all rules within the rangeawait rangePermission.unprotect()// Or delete specific rules within the rangeconst rules = await rangePermission.listRules()if (rules.length > 0) { await rules[0].remove()}Типовые задачи
Перевести книгу в режим чтения
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const permission = fWorkbook.getWorkbookPermission()await permission.setMode('viewer')console.log(permission.getSnapshot())Управлять защищёнными диапазонами
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const fWorksheet = fWorkbook.getActiveSheet()const permission = fWorksheet.getWorksheetPermission()const createdRules = await permission.protectRanges([ { ranges: [fWorksheet.getRange('A1:B2')], options: { name: 'Public area', allowViewByOthers: true }, }, { ranges: [fWorksheet.getRange('C3:D4')], options: { name: 'Private area', allowViewByOthers: false, allowedUsers: ['user1'] }, },])console.log(createdRules)const rules = await permission.listRangeProtectionRules()const firstRule = rules[0]if (firstRule) { await firstRule.updateRanges([fWorksheet.getRange('A1:B3')])}Проверить права ячейки
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const permission = fWorkbook.getActiveSheet().getWorksheetPermission()console.log(permission.debugCellPermission(0, 0))Список точек разрешений
Исходный код всех точек разрешений доступен здесь.
Если разрешения книги пересекаются с разрешениями листа или диапазона, для использования функции все соответствующие разрешения должны иметь значение true.
Разрешения книги
| Перечисление API | Соответствующий класс точки разрешения | Описание |
|---|---|---|
| univerAPI.Enum.WorkbookPermissionPoint.Edit | WorkbookEditablePermission | Редактирование |
| univerAPI.Enum.WorkbookPermissionPoint.View | WorkbookViewPermission | Просмотр |
| univerAPI.Enum.WorkbookPermissionPoint.Print | WorkbookPrintPermission | Печать |
| univerAPI.Enum.WorkbookPermissionPoint.Export | WorkbookExportPermission | Экспорт |
| univerAPI.Enum.WorkbookPermissionPoint.Share | WorkbookSharePermission | Общий доступ |
| univerAPI.Enum.WorkbookPermissionPoint.CopyContent | WorkbookCopyPermission | Копирование |
| univerAPI.Enum.WorkbookPermissionPoint.DuplicateFile | WorkbookDuplicatePermission | Создание дубликатов |
| univerAPI.Enum.WorkbookPermissionPoint.Comment | WorkbookCommentPermission | Комментирование |
| univerAPI.Enum.WorkbookPermissionPoint.ManageCollaborator | WorkbookManageCollaboratorPermission | Управление участниками |
| univerAPI.Enum.WorkbookPermissionPoint.CreateSheet | WorkbookCreateSheetPermission | Создание листов |
| univerAPI.Enum.WorkbookPermissionPoint.DeleteSheet | WorkbookDeleteSheetPermission | Удаление листов |
| univerAPI.Enum.WorkbookPermissionPoint.RenameSheet | WorkbookRenameSheetPermission | Переименование листов |
| univerAPI.Enum.WorkbookPermissionPoint.MoveSheet | WorkbookMoveSheetPermission | Перемещение листов |
| univerAPI.Enum.WorkbookPermissionPoint.HideSheet | WorkbookHideSheetPermission | Скрытие листов |
| univerAPI.Enum.WorkbookPermissionPoint.CopySheet | WorkbookCopySheetPermission | Копирование листов |
| univerAPI.Enum.WorkbookPermissionPoint.ViewHistory | WorkbookViewHistoryPermission | Просмотр истории |
| univerAPI.Enum.WorkbookPermissionPoint.RecoverHistory | WorkbookRecoverHistoryPermission | Восстановление из истории |
| univerAPI.Enum.WorkbookPermissionPoint.CreateProtection | WorkbookCreateProtectPermission | Создание защиты |
| univerAPI.Enum.WorkbookPermissionPoint.InsertRow | WorkbookInsertRowPermission | Вставка строк |
| univerAPI.Enum.WorkbookPermissionPoint.InsertColumn | WorkbookInsertColumnPermission | Вставка столбцов |
| univerAPI.Enum.WorkbookPermissionPoint.DeleteRow | WorkbookDeleteRowPermission | Удаление строк |
| univerAPI.Enum.WorkbookPermissionPoint.DeleteColumn | WorkbookDeleteColumnPermission | Удаление столбцов |
Разрешения листа
| Перечисление API | Соответствующий класс точки разрешения | Описание |
|---|---|---|
| univerAPI.Enum.WorksheetPermissionPoint.Edit | WorksheetEditPermission | Редактирование |
| univerAPI.Enum.WorksheetPermissionPoint.View | WorksheetViewPermission | Просмотр |
| univerAPI.Enum.WorksheetPermissionPoint.Copy | WorksheetCopyPermission | Копирование |
| univerAPI.Enum.WorksheetPermissionPoint.SetCellValue | WorksheetSetCellValuePermission | Изменение значений ячеек |
| univerAPI.Enum.WorksheetPermissionPoint.SetCellStyle | WorksheetSetCellStylePermission | Изменение стилей ячеек |
| univerAPI.Enum.WorksheetPermissionPoint.SetRowStyle | WorksheetSetRowStylePermission | Настройка стилей строк |
| univerAPI.Enum.WorksheetPermissionPoint.SetColumnStyle | WorksheetSetColumnStylePermission | Настройка стилей столбцов |
| univerAPI.Enum.WorksheetPermissionPoint.InsertRow | WorksheetInsertRowPermission | Вставка строк |
| univerAPI.Enum.WorksheetPermissionPoint.InsertColumn | WorksheetInsertColumnPermission | Вставка столбцов |
| univerAPI.Enum.WorksheetPermissionPoint.DeleteRow | WorksheetDeleteRowPermission | Удаление строк |
| univerAPI.Enum.WorksheetPermissionPoint.DeleteColumn | WorksheetDeleteColumnPermission | Удаление столбцов |
| univerAPI.Enum.WorksheetPermissionPoint.Sort | WorksheetSortPermission | Сортировка |
| univerAPI.Enum.WorksheetPermissionPoint.Filter | WorksheetFilterPermission | Фильтрация |
| univerAPI.Enum.WorksheetPermissionPoint.PivotTable | WorksheetPivotTablePermission | Использование сводных таблиц |
| univerAPI.Enum.WorksheetPermissionPoint.InsertHyperlink | WorksheetInsertHyperlinkPermission | Использование гиперссылок |
| univerAPI.Enum.WorksheetPermissionPoint.ManageCollaborator | WorksheetManageCollaboratorPermission | Управление участниками |
| univerAPI.Enum.WorksheetPermissionPoint.DeleteProtection | WorksheetDeleteProtectionPermission | Удаление защиты |
| univerAPI.Enum.WorksheetPermissionPoint.EditExtraObject | WorksheetEditExtraObjectPermission | Редактирование дополнительных объектов |
| univerAPI.Enum.WorksheetPermissionPoint.SelectProtectedCells | WorksheetSelectProtectedCellsPermission | Выделение защищённых ячеек |
| univerAPI.Enum.WorksheetPermissionPoint.SelectUnProtectedCells | WorksheetSelectUnProtectedCellsPermission | Выделение незащищённых ячеек |
Защита диапазона
| Перечисление API | Соответствующий класс точки разрешения | Описание |
|---|---|---|
| univerAPI.Enum.RangePermissionPoint.Edit | RangeProtectionPermissionEditPoint | Редактирование защищённых диапазонов |
| univerAPI.Enum.RangePermissionPoint.View | RangeProtectionPermissionViewPoint | Просмотр содержимого защищённых диапазонов |
| univerAPI.Enum.RangePermissionPoint.Delete | RangeProtectionPermissionDeleteProtectionPoint | Удаление защищённых диапазонов |
| univerAPI.Enum.RangePermissionPoint.ManageCollaborator | RangeProtectionPermissionManageCollaPoint | Управление участниками для защищённых диапазонов |
Настройка интерфейса прав
Стратегия затенения защищённого диапазона
Чтобы различать защищённые области, которые текущий пользователь может и не может редактировать, используйте non-editable. Затенение скрывается для доступных для редактирования защищённых областей и сохраняется там, где право редактирования отключено. Защищённые диапазоны, недоступные для просмотра, остаются замаскированными.
Эта настройка управляет отображением защиты диапазонов и листов. Она не создаёт правила защиты, не меняет права редактирования или просмотра и не добавляет затенение к незащищённым областям. Сначала настройте правила и права текущего пользователя, как показано выше.
| Стратегия | Отображение |
|---|---|
true / 'always' | Показывать затенение всех защищённых областей (по умолчанию). |
'non-editable' | Скрывать затенение редактируемых защищённых областей и сохранять его для нередактируемых. |
'non-viewable' | Показывать затенение только для защищённых областей, недоступных для просмотра. |
false / 'none' | Скрывать всё затенение защиты; проверки прав продолжают действовать. |
Предпросмотр затенения защиты
Сравните отображение одних и тех же областей для текущего пользователя при разных стратегиях.
Без защиты
Без затенения
Защищено · редактирование
Без затенения
Защищено · только чтение
С затенением
Защищено · просмотр запрещён
С затенением
Это иллюстрация: изменение затенения не меняет права. Недоступное содержимое остаётся скрытым даже при выборе none.
Задайте стратегию при инициализации:
univer.registerPlugin(UniverSheetsUIPlugin, { protectedRangeShadow: 'non-editable',})createUniver({ presets: [ UniverSheetsCorePreset({ sheets: { protectedRangeShadow: 'non-editable', }, }), ],})Также эту настройку можно изменять динамически через API:
Приведённый ниже Facade API обновляет существующие книги в текущем экземпляре Univer. В режиме плагинов сначала импортируйте @univerjs/sheets-ui/facade; пресет Sheets Core уже включает этот импорт.
// Set to only show shadows for non-editable rangesuniverAPI.setProtectedRangeShadowStrategy('non-editable')// Get the current protected range shadow display strategyconsole.log(univerAPI.getProtectedRangeShadowStrategy())// Subscribe to changes in the protected range shadow strategyconst subscription = univerAPI.getProtectedRangeShadowStrategy$().subscribe((strategy) => { console.log('Global strategy changed to:', strategy) // Update UI or perform other actions})// Later, unsubscribe to clean upsubscription.unsubscribe()Пользовательский компонент выбора пользователей
Встроенный в Univer компонент выбора пользователей имеет ограниченные возможности настройки. Для более сложных сценариев можно предоставить собственный компонент, как показано ниже.
Инструкции по созданию собственных компонентов см. в разделе Пользовательские компоненты.
univer.registerPlugin(UniverSheetsUIPlugin, { protectedRangeUserSelector: { /** * Custom component; must implement the `IPermissionDetailUserPartProps` interface. */ component: CustomPermissionDetailUserPart, /** * The framework of the component. Must be passed correctly. */ framework: 'react', },})const { univer } = createUniver({ presets: [ UniverSheetsCorePreset({ sheets: { protectedRangeUserSelector: { /** * Custom component; must implement the `IPermissionDetailUserPartProps` interface. */ component: CustomPermissionDetailUserPart, /** * The framework of the component. Must be passed correctly. */ framework: 'react', }, }, }), ],})Вызывайте setSelectUserList() из обработчика изменения выбора. Этот минимальный пример React очищает выбор: useDependency вызывается внутри компонента, а сервис обновляется только после нажатия. Остальную часть выбора реализуйте по IPermissionDetailUserPartProps.
import type { IPermissionDetailUserPartProps } from '@univerjs/sheets-ui'import type { FC } from 'react'import { SheetPermissionUserManagerService } from '@univerjs/sheets-ui'import { useDependency } from '@univerjs/ui'export const CustomPermissionDetailUserPart: FC<IPermissionDetailUserPartProps> = () => { const service = useDependency(SheetPermissionUserManagerService) const clearSelection = () => service.setSelectUserList([]) return <button type="button" onClick={clearSelection}>Очистить выбранных пользователей</button>}import type { IPermissionDetailUserPartProps } from '@univerjs/preset-sheets-core'import type { FC } from 'react'import { SheetPermissionUserManagerService, useDependency } from '@univerjs/preset-sheets-core'export const CustomPermissionDetailUserPart: FC<IPermissionDetailUserPartProps> = () => { const service = useDependency(SheetPermissionUserManagerService) const clearSelection = () => service.setSelectUserList([]) return <button type="button" onClick={clearSelection}>Очистить выбранных пользователей</button>}Скрытие диалогового окна разрешений
univerAPI.setPermissionDialogVisible(false)Интеграция сервиса авторизации
Расширенное использование
Если в собственном плагине требуется проверять разрешения, можно работать с точками разрешений напрямую.
В следующем примере на основе WorkbookEditablePermission показано, как проверять разрешения в собственном плагине. Другие точки разрешений работают аналогично.
import { IPermissionService } from '@univerjs/core'import { WorkbookEditablePermission } from '@univerjs/sheets'class YourService { constructor(@IPermissionService private _permissionService: IPermissionService) { } setWorkbookNotEditable() { this._permissionService.updatePermissionPoint(new WorkbookEditablePermission('unitId').id, false) } setWorkbookEditable() { this._permissionService.updatePermissionPoint(new WorkbookEditablePermission('unitId').id, true) }}Расширение точек разрешений
Чтобы настроить собственную точку разрешения, реализуйте IPermissionPoint и зарегистрируйте её в службе разрешений:
import type { IPermissionPoint } from '@univerjs/core'import { IPermissionService, PermissionStatus } from '@univerjs/core'import { UnitAction, UnitObject } from '@univerjs/protocol'export class CustomPermissionPoint implements IPermissionPoint { type = UnitObject.Unkonwn // your type subType = UnitAction.View // your subType status = PermissionStatus.INIT value = true // Default value id: string constructor(unitId: string, subUnitId: string, customId: string) { // The id must be unique within `IPermissionService`. this.id = `${unitId}.${subUnitId}.${customId}` }}class YourService { constructor(@IPermissionService private _permissionService: IPermissionService) { this._init() } _init() { this._permissionService.addPermissionPoint(new CustomPermissionPoint('unitId', 'subUnitId', 'my-id')) }}// How to use it elsewhereclass ConsumeService { constructor(@IPermissionService private _permissionService: IPermissionService) { } doSomething() { const point = this._permissionService.getPermissionPoint(new CustomPermissionPoint('unitId', 'subUnitId', 'my-id').id) console.log(point?.value) } bindEvent() { // This returns an RxJS observable that lets you listen for permission changes const point$ = this._permissionService.getPermissionPoint$(new CustomPermissionPoint('unitId', 'subUnitId', 'my-id').id) console.log(point$) }}Интеграция со сторонней службой авторизации (для опытных пользователей)
Реализуйте IAuthzIoService в приложении и свяжите методы прав, ролей и участников с сервером. В примере предполагается, что ./authorization-service экспортирует эту реализацию как YourAuthzService. Зарегистрируйте её до создания книг, сохранив остальные параметры и плагины.
import { IAuthzIoService, Univer } from '@univerjs/core'import { YourAuthzService } from './authorization-service'const univer = new Univer({ override: [[IAuthzIoService, { useClass: YourAuthzService }]],})Сервис должен сохранять правила защиты и изменения участников, возвращать права текущего пользователя и передавать ошибки запросов вызывающему коду. Пустые списки в заглушке не обеспечивают сохранение данных. При совместной работе сервер отдельно проверяет чтение, JOIN и изменение; см. Идентификация и авторизация. Защита интерфейса и скрытие затенения не заменяют серверную авторизацию.
Управление участниками
Управление участниками реализуется через пользователей, ACL и сервис прав вашего приложения. Защитите чтение, JOIN и изменения согласно Identity and authorization. Для API ниже требуется соответствующая реализация сервиса прав.
- Получение списка участников
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const workbookPermission = fWorkbook.getWorkbookPermission()const collaborators = await workbookPermission.listCollaborators()console.log(collaborators)- Добавление участников
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const workbookPermission = fWorkbook.getWorkbookPermission()// Add multiple collaborators at onceawait workbookPermission.setCollaborators([ { user: { userID: 'user1', name: 'John Doe', avatar: 'https://...' }, role: univerAPI.Enum.UnitRole.Editor, }, { user: { userID: 'user2', name: 'Jane Smith', avatar: '' }, role: univerAPI.Enum.UnitRole.Reader, },])// Add a single collaboratorawait workbookPermission.addCollaborator( { userID: 'user1', name: 'John Doe', avatar: 'https://...' }, univerAPI.Enum.UnitRole.Editor,)- Изменение роли участника
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const workbookPermission = fWorkbook.getWorkbookPermission()await workbookPermission.updateCollaborator( { userID: 'user1', name: 'John Doe Updated', avatar: 'https://...' }, univerAPI.Enum.UnitRole.Reader,)- Удаление участников
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const workbookPermission = fWorkbook.getWorkbookPermission()// Remove multiple collaboratorsawait workbookPermission.removeCollaborators(['user1', 'user2'])// Remove a single collaboratorawait workbookPermission.removeCollaborator('user1')Reference
Насколько полезно это руководство?