Univer
Univer Sheet
Features
Permission

Permission

📊 Univer Sheet

Univer provides the ability to control permissions, which can typically be used to restrict users' operations on workbooks, worksheets, and selections. When a user performs an operation without permission, the code execution can be terminated and the user can be prompted for missing permissions. For example, you can set protection in a selected area to determine whether other collaborators can use editing, reading, copying, filtering, and more within that protected area.

Basic example

workbook permission

Currently, the overall permissions of a workbook are modified directly through the API. We provide the Facade API. You can set the edit permissions of a workbook by calling this API.

import { FUniver } from "@univerjs/facade";
 
const univerAPI = FUniver.newAPI(univer);

Then you can use Univer by calling the univerAPI method and set the entire workbook to be uneditable:

univerAPI.getActiveWorkbook().setEditable(false);

The essence is to control the switch of permissions by setting the value of the permission point. The command corresponding to the permission point will read the value of the point before execution. If the permission value is false, the execution of the command will be terminated.

Worksheet permission code example

The permissions for worksheets and selections are set in command mode.

const accessor = univer.__getInjector();
const commandService = accessor.get(ICommandService);
// import { getSheetCommandTarget } from '@univerjs/sheets';
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,
  },
});

This demo is to add protection to the worksheet. permissionId is a randomly generated unique ID for storing permissions. You need to generate it yourself. unitType is the type of the worksheet. You can use the UnitObject enumeration in the warehouse to replace the magic number above. unitId is the id of the workbook, and subUnitId is the id of the worksheet.

To delete, you can use DeleteWorksheetProtectionMutation, the parameters are unitId and subUnitId.

DeleteWorksheetProtectionMutationParams {
  unitId: string;
  subUnitId: string;
}

Custom selection permission code example

const accessor = univer.__getInjector();
const commandService = accessor.get(ICommandService);
const sheetSelectionManagerService = accessor.get(SheetsSelectionsService);
// import { getSheetCommandTarget } from '@univerjs/sheets';
const target = getSheetCommandTarget(univerInstanceService);
if (!target) {
  return;
}
const { unitId, subUnitId } = target;
const ranges = sheetSelectionManagerService.getCurrentSelections().map(selection => selection.range);
commandService.executeCommand(AddRangeProtectionMutation.id, {
  unitId,
  subUnitId,
  rules: [{
    permissionId: "3xtfxG1",
    name: "sheet1",
    unitType: 3,
    unitId,
    subUnitId,
    ranges,
    id: 'rule1'
  }],
});

This demo adds permission protection to a custom selection. The parameters here are the same as above, with the addition of a ranges parameter, which is the area you selected, and an id parameter, which is the unique id used to identify this rule and is used to delete this rule.

In typical workflows, the creator of a permissioned area will have the highest level of access, which means they can always edit the area they created. To implement a scenario where no one, including the creator, can edit the area, you can add the following code to the demo provided above.

const permissionService = accessor.get(IPermissionService);
// The third parameter of RangeProtectionPermissionEditPoint is the permissionId generated above. Setting it to false indicates that editing is not allowed.
permissionService.updatePermissionPoint(new RangeProtectionPermissionEditPoint(unitId, subUnitId, "3xtfxG1").id, false);

To delete, you can use DeleteRangeProtectionMutation, the parameters are unitId and subUnitId and the ruleIds you want to delete in batches.

DeleteRangeProtectionMutationParams {
  unitId: string;
  subUnitId: string;
  ruleIds: string[];
}

Extended usage

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

import { WorkbookEditablePermission } from '@univerjs/sheets';
import { IPermissionService } from '@univerjs/core';
 
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 { IPermissionService, IPermissionPoint } 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

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 (opens in a new tab) 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 (opens in a new tab) interface for runtime replacement.

Here's how you can replace it:

import { IAuthzIoService, Injector, Univer } from '@univerjs/core';
 
class YourAuthzService implements IAuthzIoService { }
 
export class YourPlugin extends Plugin {
  override onStarting(injector: Injector): void {
    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 point bits

To access the specific code related to permission point at the given URL, you can refer to the code (opens in a new tab).

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

PermissionDescription
WorkbookEditablePermissionWhether or not editing is allowed.
WorkbookPrintPermissionWhether or not printing is allowed.
WorkbookCommentPermissionWhether or not commenting is allowed.
WorkbookViewPermissionWhether or not viewing is allowed.
WorkbookCopyPermissionWhether or not copying is allowed.
WorkbookExportPermissionWhether or not exporting is allowed.
WorkbookManageCollaboratorPermissionWhether or not managing collaborators is allowed.

Worksheet Permissions

PermissionDescription
WorksheetCopyPermissionWhether or not copying is allowed.
WorksheetDeleteColumnPermissionWhether or not delete columns is allowed.
WorksheetDeleteRowPermissionWhether or not delete row is allowed.
WorksheetFilterPermissionWhether or not sort is allowed.
WorksheetInsertColumnPermissionWhether or not insert columns is allowed.
WorksheetInsertHyperlinkPermissionWhether or not use hyperlinks is allowed.
WorksheetInsertRowPermissionWhether or not insert row is allowed.
WorksheetPivotTablePermissionWhether or not use pivot tables is allowed.
WorksheetSetCellStylePermissionWhether or not set cell style is allowed.
WorksheetSetCellValuePermissionWhether or not set cell value is allowed.
WorksheetSetColumnStylePermissionWhether or not set column style is allowed.
WorksheetSetRowStylePermissionWhether or not set row style is allowed.
WorksheetSortPermissionWhether or not use sort is allowed.
WorksheetViewPermissionWhether or not viewing is allowed.
WorksheetEditPermissionWhether or not editing is allowed.

Range Permissions

PermissionDescription
RangeProtectionPermissionViewPointWhether or not view the contents of a protected area.
RangeProtectionPermissionEditPointWhether or not edit the contents of a protected area.

Copyright © 2021-2024 DreamNum Co,Ltd. All Rights Reserved.