Permission Control
Univer provides permission control capabilities to restrict user operations on workbooks, worksheets, and ranges. When a user attempts an operation without the required permission, execution is halted and the user is notified. For example, you can protect a range to control whether collaborators can edit, view, copy, or filter within that range.
Your service must persist protection rules and collaborator changes, return the current user’s permissions, and propagate request failures. Empty mock lists are not a persistence implementation. In collaboration, the backend must independently check read, JOIN, and mutation permissions; see Identity and authorization. UI protection and hiding shadows do not replace server authorization.
Choose a task below. Basic operations, advanced examples, configuration, and troubleshooting stay on this page; full API contracts are maintained in Reference.
Core Concepts
- Scope: Permissions apply at three levels—workbook, worksheet, and range.
- Permission Points: Each feature corresponds to a permission point. Modifying a point controls whether that feature is available.
- Protection Rules: Before setting permission points for worksheets and ranges, you must create a protection rule.
Local, non-persistent permissions can be changed through permission points. For persistence, see Permission Service Integration
In a collaborative editing scenario, updating a permission point synchronizes the server state:
false: The permission point requires at least theownerroletrue: The permission point requires at least thereaderrole
Basic Example
Replace user1 and user2 with real collaborator IDs returned by your authorization service before using the allowedUsers examples.
The most common permission setting methods are shown below at three levels: workbook, worksheet, and range.
Workbook Permissions Code Example
Workbook-level permissions can be set directly via the Facade API.
The following example disables editing for the entire workbook. For other functions, replace the permission point accordingly (see the workbook permission points list):
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)Key points:
- Workbook permission points can be set directly without creating protection rules.
Worksheet Permissions Code Example
Worksheet and range permissions can be set via the Facade API or commands. The following example demonstrates how to set worksheet edit permissions. For other features, replace the permission point accordingly (see the worksheet permission points list):
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)Delete Worksheet Permissions
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()Custom Range Permissions Code Example
Range permissions can also be set via API and command modes. Here, we'll use range edit permissions as an example. Other range functions require replacing the permission points, see the list of permission points - Range for details.
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)Delete Range Protection Permissions
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()}Common tasks
Set a workbook to read-only
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const permission = fWorkbook.getWorkbookPermission()await permission.setMode('viewer')console.log(permission.getSnapshot())Manage protected ranges
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')])}Diagnose cell permissions
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const permission = fWorkbook.getActiveSheet().getWorksheetPermission()console.log(permission.debugCellPermission(0, 0))List of permission points
You can view the source code for all permission points here.
When workbook permissions overlap with worksheet or range permissions, all relevant permissions must be set to true for the feature to be usable.
Workbook Permissions
| API Enum | Corresponding Permission Point Class | Description |
|---|---|---|
| univerAPI.Enum.WorkbookPermissionPoint.Edit | WorkbookEditablePermission | Can edit |
| univerAPI.Enum.WorkbookPermissionPoint.View | WorkbookViewPermission | Can view |
| univerAPI.Enum.WorkbookPermissionPoint.Print | WorkbookPrintPermission | Can print |
| univerAPI.Enum.WorkbookPermissionPoint.Export | WorkbookExportPermission | Can export |
| univerAPI.Enum.WorkbookPermissionPoint.Share | WorkbookSharePermission | Can share |
| univerAPI.Enum.WorkbookPermissionPoint.CopyContent | WorkbookCopyPermission | Can copy |
| univerAPI.Enum.WorkbookPermissionPoint.DuplicateFile | WorkbookDuplicatePermission | Can duplicate |
| univerAPI.Enum.WorkbookPermissionPoint.Comment | WorkbookCommentPermission | Can comment |
| univerAPI.Enum.WorkbookPermissionPoint.ManageCollaborator | WorkbookManageCollaboratorPermission | Can manage collaborators |
| univerAPI.Enum.WorkbookPermissionPoint.CreateSheet | WorkbookCreateSheetPermission | Can create worksheets |
| univerAPI.Enum.WorkbookPermissionPoint.DeleteSheet | WorkbookDeleteSheetPermission | Can delete worksheets |
| univerAPI.Enum.WorkbookPermissionPoint.RenameSheet | WorkbookRenameSheetPermission | Can rename worksheets |
| univerAPI.Enum.WorkbookPermissionPoint.MoveSheet | WorkbookMoveSheetPermission | Can move worksheets |
| univerAPI.Enum.WorkbookPermissionPoint.HideSheet | WorkbookHideSheetPermission | Can hide worksheets |
| univerAPI.Enum.WorkbookPermissionPoint.CopySheet | WorkbookCopySheetPermission | Can copy worksheets |
| univerAPI.Enum.WorkbookPermissionPoint.ViewHistory | WorkbookViewHistoryPermission | Can view history |
| univerAPI.Enum.WorkbookPermissionPoint.RecoverHistory | WorkbookRecoverHistoryPermission | Can recover history |
| univerAPI.Enum.WorkbookPermissionPoint.CreateProtection | WorkbookCreateProtectPermission | Can create protection |
| univerAPI.Enum.WorkbookPermissionPoint.InsertRow | WorkbookInsertRowPermission | Can insert rows |
| univerAPI.Enum.WorkbookPermissionPoint.InsertColumn | WorkbookInsertColumnPermission | Can insert columns |
| univerAPI.Enum.WorkbookPermissionPoint.DeleteRow | WorkbookDeleteRowPermission | Can delete rows |
| univerAPI.Enum.WorkbookPermissionPoint.DeleteColumn | WorkbookDeleteColumnPermission | Can delete columns |
Worksheet Permissions
| API Enum | Corresponding Permission Point Class | Description |
|---|---|---|
| univerAPI.Enum.WorksheetPermissionPoint.Edit | WorksheetEditPermission | Can edit |
| univerAPI.Enum.WorksheetPermissionPoint.View | WorksheetViewPermission | Can view |
| univerAPI.Enum.WorksheetPermissionPoint.Copy | WorksheetCopyPermission | Can copy |
| univerAPI.Enum.WorksheetPermissionPoint.SetCellValue | WorksheetSetCellValuePermission | Can edit cell values |
| univerAPI.Enum.WorksheetPermissionPoint.SetCellStyle | WorksheetSetCellStylePermission | Can edit cell styles |
| univerAPI.Enum.WorksheetPermissionPoint.SetRowStyle | WorksheetSetRowStylePermission | Can set row styles |
| univerAPI.Enum.WorksheetPermissionPoint.SetColumnStyle | WorksheetSetColumnStylePermission | Can set column styles |
| univerAPI.Enum.WorksheetPermissionPoint.InsertRow | WorksheetInsertRowPermission | Can insert rows |
| univerAPI.Enum.WorksheetPermissionPoint.InsertColumn | WorksheetInsertColumnPermission | Can insert columns |
| univerAPI.Enum.WorksheetPermissionPoint.DeleteRow | WorksheetDeleteRowPermission | Can delete rows |
| univerAPI.Enum.WorksheetPermissionPoint.DeleteColumn | WorksheetDeleteColumnPermission | Can delete columns |
| univerAPI.Enum.WorksheetPermissionPoint.Sort | WorksheetSortPermission | Can sort |
| univerAPI.Enum.WorksheetPermissionPoint.Filter | WorksheetFilterPermission | Can filter |
| univerAPI.Enum.WorksheetPermissionPoint.PivotTable | WorksheetPivotTablePermission | Can use pivot tables |
| univerAPI.Enum.WorksheetPermissionPoint.InsertHyperlink | WorksheetInsertHyperlinkPermission | Can use hyperlinks |
| univerAPI.Enum.WorksheetPermissionPoint.ManageCollaborator | WorksheetManageCollaboratorPermission | Can manage collaborators |
| univerAPI.Enum.WorksheetPermissionPoint.DeleteProtection | WorksheetDeleteProtectionPermission | Can delete protection |
| univerAPI.Enum.WorksheetPermissionPoint.EditExtraObject | WorksheetEditExtraObjectPermission | Can edit extra objects |
| univerAPI.Enum.WorksheetPermissionPoint.SelectProtectedCells | WorksheetSelectProtectedCellsPermission | Can select protected cells |
| univerAPI.Enum.WorksheetPermissionPoint.SelectUnProtectedCells | WorksheetSelectUnProtectedCellsPermission | Can select unprotected cells |
Range Protection
| API Enum | Corresponding Permission Point Class | Description |
|---|---|---|
| univerAPI.Enum.RangePermissionPoint.Edit | RangeProtectionPermissionEditPoint | Can edit protected ranges |
| univerAPI.Enum.RangePermissionPoint.View | RangeProtectionPermissionViewPoint | Can view content of protected ranges |
| univerAPI.Enum.RangePermissionPoint.Delete | RangeProtectionPermissionDeleteProtectionPoint | Can delete protected ranges |
| univerAPI.Enum.RangePermissionPoint.ManageCollaborator | RangeProtectionPermissionManageCollaPoint | Can manage collaborators for protected ranges |
Permission UI Configuration
Protected Range Shadow Strategy
To distinguish protected areas that the current user can edit from those they cannot, use non-editable. Editable protected areas have no shadow; protected areas with editing disabled keep their shadow. Non-viewable protected ranges remain masked.
This setting controls the display of range and worksheet protection. It does not create protection rules or change edit/view permissions, and it does not add shadows to unprotected areas. Configure the protection rules and the current user's permissions first, as shown above.
| Strategy | Display behavior |
|---|---|
true / 'always' | Show shadows for all protected areas (default). |
'non-editable' | Hide shadows on editable protected areas; keep them on non-editable areas. |
'non-viewable' | Show shadows only on non-viewable protected areas. |
false / 'none' | Hide all protection shadows; permission checks still apply. |
Protection shadow preview
Compare the same areas under different strategies for the current user.
Unprotected
No shadow
Protected · editable
No shadow
Protected · read-only
Shadow shown
Protected · not viewable
Shadow shown
Illustration only: changing the shadow does not change permissions. Hidden content stays hidden, even with none.
Set the strategy during initialization:
univer.registerPlugin(UniverSheetsUIPlugin, { protectedRangeShadow: 'non-editable',})createUniver({ presets: [ UniverSheetsCorePreset({ sheets: { protectedRangeShadow: 'non-editable', }, }), ],})You can also modify it dynamically via the API:
The Facade API below updates existing workbooks in the current Univer instance. In plugin mode, first import @univerjs/sheets-ui/facade; the Sheets Core preset already includes it.
// 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()Custom User Component
Univer's built-in user selector has limited flexibility. For more complex scenarios, you can provide a custom component as shown below.
You can refer to Custom Components for how to create custom components.
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', }, }, }), ],})Call setSelectUserList() from your picker’s change handler. This minimal React example clears the selection; useDependency runs inside the component and the service update runs only after a click. Implement the rest of your picker using 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}>Clear selected users</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}>Clear selected users</button>}Hide the Permission Dialog
univerAPI.setPermissionDialogVisible(false)Permission Service Integration
Extended usage
When you need to check permissions in your own plugin, you can manipulate the permission points directly.
The following example uses WorkbookEditablePermission to demonstrate how to check permissions in your own plugin. Other permission points work similarly.
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) }}How to Extend Permission Points
To customize permission points, implement IPermissionPoint and register it with the permission service:
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$) }}Integrating a Third-Party Authorization Service (Advanced)
Implement IAuthzIoService in your application and connect its permission, role, and collaborator methods to your backend. The example assumes that ./authorization-service exports this implementation as YourAuthzService. Register it before creating workbooks; keep the other initialization options and plugin registrations.
import { IAuthzIoService, Univer } from '@univerjs/core'import { YourAuthzService } from './authorization-service'const univer = new Univer({ override: [[IAuthzIoService, { useClass: YourAuthzService }]],})Your service must persist protection rules and collaborator changes, return the current user’s permissions, and propagate request failures. Empty mock lists are not a persistence implementation. In collaboration, the backend must independently check read, JOIN, and mutation permissions; see Identity and authorization. UI protection and hiding shadows do not replace server authorization.
Collaborator Management
Collaborator management belongs to your application and permission service. Connect your user/ACL model and enforce server-side read, JOIN, and edit policies; see identity and authorization. The frontend APIs below require a matching permission-service implementation and do not automatically configure server authorization.
- Get Collaborators List
const fWorkbook = univerAPI.getActiveWorkbook()if (!fWorkbook) throw new Error('No active workbook')const workbookPermission = fWorkbook.getWorkbookPermission()const collaborators = await workbookPermission.listCollaborators()console.log(collaborators)- Add 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,)- Update collaborator role
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,)- Remove collaborators
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
How is this guide?