Permission Control

GitHubEdit on GitHub

Univer provides permission control capabilities, typically used to restrict user operations on workbooks, sheets, and ranges. When a user performs an operation without permission, the code execution can be halted and the user will be prompted about the missing permissions. For example, you can set area protection within a range, which allows setting whether other collaborators can edit, read, copy, filter, etc., within the protected range.

Note: Univer provides extendable foundational capabilities, not customized features. If you have more extensive and tailored requirements such as persistence or organizational structures, you need to implement the storage of permission rules and integrate organizational structures yourself. In this case, you need to write custom plugins to achieve this. Therefore, after setting permissions, you might find the permission list empty when viewing it, or user information returns empty when you check it. This is because this information needs to be fetched via API requests; it's custom logic that requires additional implementation on your part. You can refer to the third-party integration below.

Basic Example

Workbook Permissions Code Example

Currently, workbook-level permissions are directly modified through the API. We provide the Facade API, and you can use this API to set permissions for different functions of the workbook.

Taking edit permission as an example (other functions require replacing the permission points, see the list of permission points - Workbook for details), you can use the following code to set the entire workbook to be non-editable:

const fWorkbook = univerAPI.getActiveWorkbook()
const permission = fWorkbook.getWorkbookPermission()

// Set the workbook to be non-editable
await permission.setPoint(univerAPI.Enum.WorkbookPermissionPoint.Edit, false)

Worksheet Permissions Code Example

Worksheet and range-related permissions can be set via both the Facade API and command. Here, we'll use worksheet edit permissions as an example. Other worksheet functions require replacing the permission points, see the list of permission points - Worksheet for details.

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// Create worksheet protection, allow specified users to edit
const permissionId = await permission.protect({
  allowedUsers: ['user1', 'user2'],
  name: 'My Worksheet Protection',
})

// If you need to set permission points, you must first create worksheet protection
await permission.setPoint(univerAPI.Enum.WorksheetPermissionPoint.Edit, false)
import { ICommandService, IPermissionService, IUniverInstanceService } from '@univerjs/core'
import { AddWorksheetProtectionMutation, getSheetCommandTarget, WorksheetEditPermission } from '@univerjs/sheets'

const accessor = univer.__getInjector()
const commandService = accessor.get(ICommandService)
const univerInstanceService = accessor.get(IUniverInstanceService)

const target = getSheetCommandTarget(univerInstanceService)
if (!target) {
  return
}

const { unitId, subUnitId } = target

commandService.executeCommand(AddWorksheetProtectionMutation.id, {
  unitId,
  subUnitId,
  rule: {
    permissionId: '2sxcza1',
    name: 'sheet',
    unitType: 2,
    unitId,
    subUnitId,
  },
})

const permissionService = accessor.get(IPermissionService)
permissionService.updatePermissionPoint(new WorksheetEditPermission(unitId, subUnitId).id, false)

Parameters in this command: permissionId is a unique ID you generate to store the permission, unitType is the sheet type (you can use the UnitObject enum from the repository), unitId is the workbook id, and subUnitId is the sheet id.

Delete Worksheet Permissions

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// Remove worksheet protection
await permission.unprotect()
import { DeleteWorksheetProtectionMutation } from '@univerjs/sheets'

commandService.executeCommand(DeleteWorksheetProtectionMutation.id, {
  unitId,
  subUnitId,
})

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()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

// Set range protection permission, allow specified users to edit but not allow others to view
const rule = await permission.protect({
  name: 'My protected range',
  allowEdit: true,
  allowViewByOthers: false,
  allowedUsers: ['user1', 'user2'],
})
console.log(rule)

// If you need to set permission points, you must first create range protection
await permission.setPoint(univerAPI.Enum.RangePermissionPoint.Edit, false)
await permission.setPoint(univerAPI.Enum.RangePermissionPoint.View, true)
import { ICommandService, IPermissionService, IUniverInstanceService } from '@univerjs/core'
import { AddRangeProtectionMutation, getSheetCommandTarget, RangeProtectionPermissionEditPoint } from '@univerjs/sheets'

const accessor = univer.__getInjector()
const commandService = accessor.get(ICommandService)
const univerInstanceService = accessor.get(IUniverInstanceService)

const target = getSheetCommandTarget(univerInstanceService)
if (!target) {
  return
}

const { unitId, subUnitId } = target
const ranges = [
  {
    startRow: 0,
    startColumn: 0,
    endRow: 2,
    endColumn: 1,
  },
  {
    startRow: 3,
    startColumn: 2,
    endRow: 4,
    endColumn: 3,
  },
]

commandService.executeCommand(AddRangeProtectionMutation.id, {
  unitId,
  subUnitId,
  rules: [{
    permissionId: '3xtfxG1',
    name: 'sheet1',
    unitType: 3,
    unitId,
    subUnitId,
    ranges,
    id: 'rule1',
  }],
})

const permissionService = accessor.get(IPermissionService)
// Here, RangeProtectionPermissionEditPoint's third parameter is the generated permissionId, false means not editable
permissionService.updatePermissionPoint(new RangeProtectionPermissionEditPoint(unitId, subUnitId, '3xtfxG1').id, false)

Here, the parameters are similar to those above, with additional ranges parameter for selected areas, and id parameter for uniquely identifying the rule, used for deletion.

Delete Range Protection Permissions

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

// Remove range protection
await permission.unprotect()
import { DeleteRangeProtectionMutation } from '@univerjs/sheets'

commandService.executeCommand(DeleteRangeProtectionMutation.id, {
  unitId,
  subUnitId,
  ruleIds: ['rule1'],
})

Extended usage

Here we take WorkbookEditablePermission as an example and add permission verification in your own plug-in. Other points are similar.

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)
  }
}

You can also extend and modify other permission points to achieve permission control for different functions. For a specific list of points, please refer to the bottom of the article.

How to extend the permission point

import type { IPermissionPoint } from '@univerjs/core'
import { IPermissionService } from '@univerjs/core'

export class CustomPermissionPoint implements IPermissionPoint {
  type = UnitObject.Unkonwn // your type
  subType = UnitAction.View // your subType
  status = PermissionStatus.INIT
  value = true // Initial values
  id: string
  constructor(unitId: string, subUnitId: string, customId: string) {
    // The id attribute needs to be guaranteed to be unique throughout `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 elsewhere
class 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 will get an RX object, allowing you to listen for changes to the current permissions and make a list of changes
    const pount$ = this._permissionService.getPermissionPoint$(new CustomPermissionPoint('unitId', 'subUnitId', 'my-id').id)
    console.log(pount$)
  }
}

Integration of Third-Party Authorization Service(Advanced Usage)

Caution

It is recommended to avoid mixing custom permission access with the Permission Facade API, as it allows for more granular control over permission points.

The logic for determining permissions is typically handled by an external service, which involves a communication process. In the frontend SDK implementation, we use the AuthzIoLocalService to handle this logic.

In a production environment, we need to replace this implementation with a backend service. The frontend needs to implement the corresponding request functions based on the IAuthzIoService interface for runtime replacement.

Permission

Here is a simple example demonstrating the addition and deletion of protected range permissions for two predefined roles (Owner/Reader). The Owner has editing/viewing permissions for protected ranges, while the Reader cannot edit or view the contents of cells within protected ranges.

import type { Injector } from '@univerjs/core'
import type { IActionInfo, IAllowedRequest, IBatchAllowedResponse, ICollaborator, ICreateRequest, ICreateRequest_SelectRangeObject, IListPermPointRequest, IPermissionPoint, IPutCollaboratorsRequest, IUnitRoleKV, IUpdatePermPointRequest } from '@univerjs/protocol'
import { createDefaultUser, generateRandomId, IAuthzIoService, Inject, IResourceManagerService, isDevRole, Univer, UserManagerService } from '@univerjs/core'
import { ObjectScope, UnitAction, UnitObject, UnitRole, UniverType } from '@univerjs/protocol'

class YourAuthzService implements IAuthzIoService {
  private _permissionMap: Map<string, ICreateRequest_SelectRangeObject & { objectType: UnitObject }> = new Map([])

  constructor(
    @IResourceManagerService private _resourceManagerService: IResourceManagerService,
    @Inject(UserManagerService) private _userManagerService: UserManagerService,
  ) {
    this._initSnapshot()
    this._initDefaultUser()
  }

  private _initDefaultUser() {
    const currentUser = this._userManagerService.getCurrentUser()
    const currentUserIsValid = currentUser && currentUser.userID
    if (!currentUserIsValid) {
      this._userManagerService.setCurrentUser(createDefaultUser(UnitRole.Owner))
    }
  }

  private _getRole(type: UnitRole) {
    const user = this._userManagerService.getCurrentUser()
    if (!user) {
      return false
    }
    return isDevRole(user.userID, type)
  }

  private _initSnapshot() {
    this._resourceManagerService.registerPluginResource({
      toJson: (_unitId: string) => {
        const obj = [...this._permissionMap.keys()].reduce((r, k) => {
          const v = this._permissionMap.get(k)
          r[k] = v!
          return r
        }, {} as Record<string, ICreateRequest_SelectRangeObject & { objectType: UnitObject }>)
        return JSON.stringify(obj)
      },
      parseJson: (json: string) => {
        return JSON.parse(json)
      },
      pluginName: 'SHEET_AuthzIoMockService_PLUGIN',
      businesses: [UniverType.UNIVER_SHEET, UniverType.UNIVER_DOC, UniverType.UNIVER_SLIDE],
      onLoad: (_unitId, resource) => {
        for (const key in resource) {
          this._permissionMap.set(key, resource[key])
        }
      },
      onUnLoad: () => {
        this._permissionMap.clear()
      },
    })
  }

  async create(config: ICreateRequest): Promise<string> {
    const permissionId = generateRandomId(8)
    if (config.objectType === UnitObject.SelectRange && config.selectRangeObject) {
      this._permissionMap.set(permissionId, { ...config.selectRangeObject, objectType: config.objectType })
    }
    return permissionId
  }

  async batchAllowed(config: IAllowedRequest[]): Promise<IBatchAllowedResponse['objectActions']> {
    const selectionRangeConfig = config.filter(c => c.objectType === UnitObject.SelectRange)
    if (selectionRangeConfig.length) {
      const currentUser = this._userManagerService.getCurrentUser()
      const res = [] as IBatchAllowedResponse['objectActions']
      selectionRangeConfig.forEach((c) => {
        res.push({
          unitID: c.unitID,
          objectID: c.objectID,
          actions: c.actions.map((action) => {
            if (isDevRole(currentUser.userID, UnitRole.Owner)) {
              return { action, allowed: true }
            }
            return { action, allowed: false }
          }),
        })
      })
      return res
    }
    return Promise.resolve([])
  }

  async list(config: IListPermPointRequest): Promise <IPermissionPoint[]> {
    const result: IPermissionPoint[] = []
    config.objectIDs.forEach((objectID) => {
      const rule = this._permissionMap.get(objectID)
      if (rule) {
        const item = {
          objectID,
          unitID: config.unitID,
          objectType: rule!.objectType,
          name: rule!.name,
          shareOn: false,
          shareRole: UnitRole.Owner,
          shareScope: -1,
          scope: {
            read: ObjectScope.AllCollaborator,
            edit: ObjectScope.AllCollaborator,
          },
          creator: createDefaultUser(UnitRole.Owner),
          strategies: [
            {
              action: UnitAction.View,
              role: UnitRole.Owner,
            },
            {
              action: UnitAction.Edit,
              role: UnitRole.Owner,
            },
          ],
          actions: config.actions.map((a) => {
            return { action: a, allowed: this._getRole(UnitRole.Owner) }
          }),
        }
        result.push(item)
      }
    })
    return result
  }

  async listCollaborators(): Promise<ICollaborator[]> {
    // List the existing collaborators
    return []
  }

  async allowed(_config: IAllowedRequest): Promise<IActionInfo[]> {
    // Because this is a mockService for handling permissions, we will not write real logic in it. We will only return an empty array to ensure that the permissions originally set by the user are not modified.
    // If you want to achieve persistence of permissions, you can modify the logic here.
    return Promise.resolve([])
  }

  async listRoles(): Promise<{ roles: IUnitRoleKV[], actions: UnitAction[] }> {
    return {
      roles: [],
      actions: [],
    }
  }

  async update(config: IUpdatePermPointRequest): Promise<void> {
    // Update bit information
  }

  async updateCollaborator(): Promise<void> {
    // Update collaborator information
    return undefined
  }

  async createCollaborator(): Promise<void> {
    // Create new collaborator information
    return undefined
  }

  async deleteCollaborator(): Promise<void> {
    return undefined
  }

  async putCollaborators(config: IPutCollaboratorsRequest): Promise<void> {
    return undefined
  }
}

export class YourPlugin extends Plugin {
  constructor(
    _config: unknown,
    @Inject(Injector) protected override _injector: Injector,
  ) {
  }

  override onStarting(): void {
    this._injector.add([IAuthzIoService, { useClass: YourAuthzService }])
  }
}

// By setting the override option to [[IAuthzIoService, null]], you can instruct Univer not to register the built-in IAuthzIoService.
// This way, Univer will use the service provided by YourAuthzService as the implementation of the authorization service.
const univer = new Univer({
  override: [[IAuthzIoService, null]],
})

univer.registerPlugin(YourPlugin)

List of permission points

To access the specific code related to permission point at the given URL, you can refer to the code.

In the case where the permission control of the workbook intersects with the worksheet/range, all permissions must be set to true in order to use them.

Workbook Permissions

API EnumCorresponding Permission Point ClassDescription
univerAPI.Enum.WorkbookPermissionPoint.EditWorkbookEditablePermissionCan edit
univerAPI.Enum.WorkbookPermissionPoint.ViewWorkbookViewPermissionCan view
univerAPI.Enum.WorkbookPermissionPoint.PrintWorkbookPrintPermissionCan print
univerAPI.Enum.WorkbookPermissionPoint.ExportWorkbookExportPermissionCan export
univerAPI.Enum.WorkbookPermissionPoint.ShareWorkbookSharePermissionCan share
univerAPI.Enum.WorkbookPermissionPoint.CopyContentWorkbookCopyPermissionCan copy
univerAPI.Enum.WorkbookPermissionPoint.DuplicateFileWorkbookDuplicatePermissionCan duplicate
univerAPI.Enum.WorkbookPermissionPoint.CommentWorkbookCommentPermissionCan comment
univerAPI.Enum.WorkbookPermissionPoint.ManageCollaboratorWorkbookManageCollaboratorPermissionCan manage collaborators
univerAPI.Enum.WorkbookPermissionPoint.CreateSheetWorkbookCreateSheetPermissionCan create worksheets
univerAPI.Enum.WorkbookPermissionPoint.DeleteSheetWorkbookDeleteSheetPermissionCan delete worksheets
univerAPI.Enum.WorkbookPermissionPoint.RenameSheetWorkbookRenameSheetPermissionCan rename worksheets
univerAPI.Enum.WorkbookPermissionPoint.MoveSheetWorkbookMoveSheetPermissionCan move worksheets
univerAPI.Enum.WorkbookPermissionPoint.HideSheetWorkbookHideSheetPermissionCan hide worksheets
univerAPI.Enum.WorkbookPermissionPoint.CopySheetWorkbookCopySheetPermissionCan copy worksheets
univerAPI.Enum.WorkbookPermissionPoint.ViewHistoryWorksheetViewHistoryPermissionCan view history
univerAPI.Enum.WorkbookPermissionPoint.ManageHistoryWorkbookHistoryPermissionCan manage history
univerAPI.Enum.WorkbookPermissionPoint.RecoverHistoryWorksheetRecoverHistoryPermissionCan recover history
univerAPI.Enum.WorkbookPermissionPoint.CreateProtectionWorkbookCreateProtectPermissionCan create protection
univerAPI.Enum.WorkbookPermissionPoint.InsertRowWorkbookInsertRowPermissionCan insert rows
univerAPI.Enum.WorkbookPermissionPoint.InsertColumnWorkbookInsertColumnPermissionCan insert columns
univerAPI.Enum.WorkbookPermissionPoint.DeleteRowWorkbookDeleteRowPermissionCan delete rows
univerAPI.Enum.WorkbookPermissionPoint.DeleteColumnWorkbookDeleteColumnPermissionCan delete columns

Worksheet Permissions

API EnumCorresponding Permission Point ClassDescription
univerAPI.Enum.WorksheetPermissionPoint.EditWorksheetEditPermissionCan edit
univerAPI.Enum.WorksheetPermissionPoint.ViewWorksheetViewPermissionCan view
univerAPI.Enum.WorksheetPermissionPoint.CopyWorksheetCopyPermissionCan copy
univerAPI.Enum.WorksheetPermissionPoint.SetCellValueWorksheetSetCellValuePermissionCan edit cell values
univerAPI.Enum.WorksheetPermissionPoint.SetCellStyleWorksheetSetCellStylePermissionCan edit cell styles
univerAPI.Enum.WorksheetPermissionPoint.SetRowStyleWorksheetSetRowStylePermissionCan set row styles
univerAPI.Enum.WorksheetPermissionPoint.SetColumnStyleWorksheetSetColumnStylePermissionCan set column styles
univerAPI.Enum.WorksheetPermissionPoint.InsertRowWorksheetInsertRowPermissionCan insert rows
univerAPI.Enum.WorksheetPermissionPoint.InsertColumnWorksheetInsertColumnPermissionCan insert columns
univerAPI.Enum.WorksheetPermissionPoint.DeleteRowWorksheetDeleteRowPermissionCan delete rows
univerAPI.Enum.WorksheetPermissionPoint.DeleteColumnWorksheetDeleteColumnPermissionCan delete columns
univerAPI.Enum.WorksheetPermissionPoint.SortWorksheetSortPermissionCan sort
univerAPI.Enum.WorksheetPermissionPoint.FilterWorksheetFilterPermissionCan filter
univerAPI.Enum.WorksheetPermissionPoint.PivotTableWorksheetPivotTablePermissionCan use pivot tables
univerAPI.Enum.WorksheetPermissionPoint.InsertHyperlinkWorksheetInsertHyperlinkPermissionCan use hyperlinks
univerAPI.Enum.WorksheetPermissionPoint.ManageCollaboratorWorksheetManageCollaboratorPermissionCan manage collaborators
univerAPI.Enum.WorksheetPermissionPoint.DeleteProtectionWorksheetDeleteProtectionPermissionCan delete protection

Range Protection

API EnumCorresponding Permission Point ClassDescription
univerAPI.Enum.RangePermissionPoint.EditRangeProtectionPermissionEditPointCan edit protected ranges
univerAPI.Enum.RangePermissionPoint.ViewRangeProtectionPermissionViewPointCan view content of protected ranges
univerAPI.Enum.RangePermissionPoint.DeleteRangeProtectionPermissionDeleteProtectionPointCan delete protected ranges

Configuration

Protection Range Shadow Strategy

The permission background shadow is displayed by default. You can hide it using the following code:

createUniver({
  presets: [
    UniverSheetsCorePreset({
      sheets: {
        /**
         * Strategy for showing the protected range shadow.
         * - true or 'always': Show shadow for all protected ranges (default behavior)
         * - 'non-editable': Only show shadow for ranges that cannot be edited (Edit permission is false)
         * - 'non-viewable': Only show shadow for ranges that cannot be viewed (View permission is false)
         * - false or 'none': Never show shadow for protected ranges
         * @default true
         */
        protectedRangeShadow: false,
      },
    }),
  ],
})
univer.registerPlugin(UniverSheetsUIPlugin, {
  /**
   * Strategy for showing the protected range shadow.
   * - true or 'always': Show shadow for all protected ranges (default behavior)
   * - 'non-editable': Only show shadow for ranges that cannot be edited (Edit permission is false)
   * - 'non-viewable': Only show shadow for ranges that cannot be viewed (View permission is false)
   * - false or 'none': Never show shadow for protected ranges
   * @default true
   */
  protectedRangeShadow: false,
})

Also can be modified dynamically through the API:

// Set to only show shadows for non-editable ranges
univerAPI.setProtectedRangeShadowStrategy('non-editable')

// Get the current protected range shadow display strategy
console.log(univerAPI.getProtectedRangeShadowStrategy())

// Subscribe to changes in the protected range shadow strategy
const subscription = univerAPI.getProtectedRangeShadowStrategy$().subscribe((strategy) => {
  console.log('Global strategy changed to:', strategy)
  // Update UI or perform other actions
})

// Later, unsubscribe to clean up
subscription.unsubscribe()

Custom User Component

Univer's built-in custom user components are limited in their adaptability. If you need more complex custom components, you can create them using the following method.

You can refer to Custom Components for how to create custom components.

const { univer } = createUniver({
  presets: [
    UniverSheetsCorePreset({
      sheets: {
        protectedRangeUserSelector: {
        /**
         * custom component, should implement the `IPermissionDetailUserPartProps` interface.
         */
          component: CustomPermissionDetailUserPart,
          /**
           * The framework of the component. Must be passed correctly.
           */
          framework: 'react',
        },
      },
    }),
  ],
})
univer.registerPlugin(UniverSheetsUIPlugin, {
  protectedRangeUserSelector: {
    /**
     * custom component, should implement the `IPermissionDetailUserPartProps` interface.
     */
    component: CustomPermissionDetailUserPart,
    /**
     * The framework of the component. Must be passed correctly.
     */
    framework: 'react',
  },
})

After completing the custom user settings, please synchronize it to the sheetPermissionUserManagerService service's _selectUserList for later use.

import { SheetPermissionUserManagerService, useDependency } from '@univerjs/preset-sheets-core'

const sheetPermissionUserManagerService = useDependency(SheetPermissionUserManagerService)
// For the specific data structure, refer to: https://github.com/dream-num/univer/blob/b4d4cfa063c9e6d5a82d1fc6b05edc206a415252/packages/sheets-ui/src/services/permission/sheet-permission-user-list.service.ts#L57
sheetPermissionUserManagerService.setSelectUserList([])
import { SheetPermissionUserManagerService } from '@univerjs/sheets-ui'
import { useDependency } from '@univerjs/ui'

const sheetPermissionUserManagerService = useDependency(SheetPermissionUserManagerService)
// For the specific data structure, refer to: https://github.com/dream-num/univer/blob/b4d4cfa063c9e6d5a82d1fc6b05edc206a415252/packages/sheets-ui/src/services/permission/sheet-permission-user-list.service.ts#L57
sheetPermissionUserManagerService.setSelectUserList([])

Facade API

Workbook Permissions

Get Workbook Permission Instance

const fWorkbook = univerAPI.getActiveWorkbook()
const permission = fWorkbook.getWorkbookPermission()

Set Workbook Permission Point

WorkbookPermissionPoint enum values list can be found in Workbook Permission Points List.

const fWorkbook = univerAPI.getActiveWorkbook()
const permission = fWorkbook.getWorkbookPermission()

// Set the workbook print permission to unavailable
await permission.setPoint(univerAPI.Enum.WorkbookPermissionPoint.Print, false)

Using predefined modes:

const fWorkbook = univerAPI.getActiveWorkbook()
const permission = fWorkbook.getWorkbookPermission()

// Set to owner mode
await permission.setMode('owner')

// Set to editor mode
await permission.setMode('editor')

// Set to viewer mode
await permission.setMode('viewer')

// Set to commenter mode
await permission.setMode('commenter')

Using shortcut methods:

  • FWorkbookPermission.setReadOnly(): Set to read-only mode, equivalent to setMode('viewer')
  • FWorkbookPermission.setEditable(): Set to editable mode, equivalent to setMode('editor')

Get Workbook Permission Point Status

const fWorkbook = univerAPI.getActiveWorkbook()
const permission = fWorkbook.getWorkbookPermission()

// Get workbook print permission status
const canPrint = permission.getPoint(univerAPI.Enum.WorkbookPermissionPoint.Print)
console.log('Can print:', canPrint)

// Get all workbook permission point statuses
const snapshot = permission.getSnapshot()
console.log('Workbook permission snapshot:', snapshot)

Using shortcut methods:

  • FWorkbookPermission.canEdit(): Check if the workbook is editable

Subscribe to Workbook Permission Point Changes

const fWorkbook = univerAPI.getActiveWorkbook()
const permission = fWorkbook.getWorkbookPermission()

// Subscribe to workbook permission point changes
const unsubscribe = permission.subscribe((snapshot) => {
  console.log('Permission changed:', snapshot)
})

// Remove subscription
unsubscribe()

Collaborator Management

Caution

Collaborator management related APIs are only available when using the collaborative editing feature and integrating with the USIP service. When using a custom permission service, please refer to the "Integration of Third-Party Authorization Service" section above to implement the collaborator management logic yourself.

  • Get Collaborators List
const fWorkbook = univerAPI.getActiveWorkbook()
const permission = workbook.getWorkbookPermission()

const collaborators = await permission.listCollaborators()
console.log(collaborators)
  • Add Collaborators
const fWorkbook = univerAPI.getActiveWorkbook()
const permission = workbook.getWorkbookPermission()

// Add multiple collaborators at once
await permission.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 single Collaborator
await permission.addCollaborator(
  { userID: 'user1', name: 'John Doe', avatar: 'https://...' },
  univerAPI.Enum.UnitRole.Editor,
)
  • Update Collaborator Role
const fWorkbook = univerAPI.getActiveWorkbook()
const permission = workbook.getWorkbookPermission()

await permission.updateCollaborator(
  { userID: 'user1', name: 'John Doe Updated', avatar: 'https://...' },
  univerAPI.Enum.UnitRole.Reader,
)
  • Remove Collaborators
const fWorkbook = univerAPI.getActiveWorkbook()
const permission = workbook.getWorkbookPermission()

// Remove multiple collaborators
await permission.removeCollaborators(['user1', 'user2'])

// Remove single collaborator
await permission.removeCollaborator('user1')

Worksheet Permissions

Get Worksheet Permission Instance

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

Worksheet Protection

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// Set worksheet protection, allowing specified users to edit
const permissionId = await permission.protect({
  allowedUsers: ['user1', 'user2'],
  name: 'My Worksheet Protection',
})

// Check if the worksheet is protected
const isProtected = permission.isProtected()
console.log('Is worksheet protected:', isProtected)

if (isProtected) {
  // Remove worksheet protection
  await permission.unprotect()
}

Range Protection

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// Set multiple protected ranges, A1:B2 is not editable but viewable by others, C3:D4 is editable by specified users but not viewable by others
const rules = await permission.protectRanges([
  {
    ranges: [fWorksheet.getRange('A1:B2')],
    options: { name: 'Protected Area 1', allowEdit: false, allowViewByOthers: true },
  },
  {
    ranges: [fWorksheet.getRange('C3:D4')],
    options: { name: 'Protected Area 2', allowEdit: true, allowViewByOthers: false, allowedUsers: ['user1'] },
  },
])
console.log(rules)

// Get all current protection range rules
const rules = await permission.listRangeProtectionRules()
console.log(rules)

// Remove the first protection range
await permission.unprotectRules([rules[0].id])

Set Worksheet Permission Point

WorksheetPermissionPoint enum values list can be found in Worksheet Permission Points List.

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// If you need to set permission points, you must first create worksheet protection
await permission.protect()

// Set the worksheet insert row permission to unavailable
await permission.setPoint(univerAPI.Enum.WorksheetPermissionPoint.InsertRow, false)

Using predefined modes:

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// If you need to set permission points, you must first create worksheet protection
await permission.protect()

// Set to editable mode
await permission.setMode('editable')

// Set to read-only mode
await permission.setMode('readOnly')

// Set to filter/sort only mode
await permission.setMode('filterOnly')

// Set to custom mode
await permission.applyConfig({
  mode: 'readOnly',
  points: {
    [univerAPI.Enum.WorksheetPermissionPoint.InsertRow]: true,
    [univerAPI.Enum.WorksheetPermissionPoint.InsertColumn]: true,
  },
})

Using shortcut methods:

  • FWorksheetPermission.setReadOnly(): Set to read-only mode, equivalent to setMode('readOnly')
  • FWorksheetPermission.setEditable(): Set to editable mode, equivalent to setMode('editable')

Get Worksheet Permission Point Status

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// Get worksheet insert row permission status
const canInsertRow = permission.getPoint(univerAPI.Enum.WorksheetPermissionPoint.InsertRow)

// Get all worksheet permission point statuses
const snapshot = permission.getSnapshot()

Using shortcut methods:

  • FWorksheetPermission.canEdit(): boolean: Check if the worksheet is editable
  • FWorksheetPermission.canEditCell(row: number, col: number): boolean: Check if a specific cell is editable
  • FWorksheetPermission.debugCellPermission(row: number, col: number): ICellPermissionDebugInfo: Get permission debug info for a specific cell

Subscribe to Worksheet Permission Point Changes

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()

// Subscribe to worksheet permission point changes
const unsubscribe = permission.subscribe((snapshot) => {
  console.log('Permission changed:', snapshot)
})

// Remove subscription
unsubscribe()

Range Permissions

Get Range Permission Instance

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

Set Range Protection

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

// Set protection for the range, allowing specified users to edit but not allowing others to view
const rule = await permission.protect({
  name: 'My protected range',
  allowEdit: true,
  allowViewByOthers: false,
  allowedUsers: ['user1', 'user2'],
})
console.log(rule)

// Get current range protection rules
const rules = await permission.listRules()
console.log(rules)

// Remove range protection
await permission.unprotect()

Set Range Permission Point

RangePermissionPoint enum values list can be found in Range Protection Points List.

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

// If you need to set permission points, you must first create range protection
await permission.protect({
  name: 'My protected range',
  allowEdit: true,
  allowViewByOthers: false,
  allowedUsers: ['user1', 'user2'],
})

// Set the edit permission of the A1:B2 selection to unavailable, and the view permission to available
await permission.setPoint(univerAPI.Enum.RangePermissionPoint.Edit, false)
await permission.setPoint(univerAPI.Enum.RangePermissionPoint.View, true)

Get Range Permission Point Status

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

// Get the edit permission status of the selection
const canEdit = permission.getPoint(univerAPI.Enum.RangePermissionPoint.Edit)
console.log(canEdit)

// Get all range permission point statuses
const snapshot = permission.getSnapshot()

Using shortcut methods:

  • FRangePermission.isProtected(): boolean: Check if the range is protected
  • FRangePermission.canEdit(): boolean: Check if the range is editable
  • FRangePermission.canView(): boolean: Check if the range is viewable
  • FRangePermission.canDelete(): boolean: Check if the selection can delete protection

Subscribe to Range Permission Point Changes

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const fRange = fWorksheet.getRange('A1:B2')
const permission = fRange.getRangePermission()

// Subscribe to range permission point changes
const unsubscribe = permission.subscribe((snapshot) => {
  console.log('Permission changed:', snapshot)
})

// Remove subscription
unsubscribe()

Permission Rule API

const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const permission = fWorksheet.getWorksheetPermission()
const rules = await permission.listRangeProtectionRules()
const rule = rules?.[0]

// ID Get the ID of the first protection rule
const ruleId = rule?.id
console.log(ruleId)

// Get the ranges of the first protection rule
const ranges = rule?.ranges
console.log(ranges)

// A1:C3 Update the ranges of the first protection rule to A1:C3
await rule?.updateRanges([fWorksheet.getRange('A1:C3')])

// Remove the first protection rule
await rule?.remove()

Remove permission dialog

univerAPI.setPermissionDialogVisible(false)

How is this guide?