Skip to content

Commit

Permalink
chore: update sdk permission
Browse files Browse the repository at this point in the history
  • Loading branch information
ybzky committed Jan 24, 2025
1 parent 043aedc commit cb20919
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 107 deletions.
239 changes: 149 additions & 90 deletions packages/core/src/services/authz-io/authz-io-local.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@
* limitations under the License.
*/

import type { IActionInfo, IAllowedRequest, IBatchAllowedResponse, ICollaborator, ICreateRequest, ICreateRequest_SelectRangeObject, IListPermPointRequest, IPermissionPoint, IPutCollaboratorsRequest, IUnitRoleKV, IUpdatePermPointRequest, UnitAction, UnitObject } from '@univerjs/protocol';
import { ObjectScope, UnitRole, UniverType } from '@univerjs/protocol';
import type { IActionInfo, IAllowedRequest, IBatchAllowedResponse, ICollaborator, ICreateRequest, IListPermPointRequest, IPermissionPoint, IPutCollaboratorsRequest, IUnitRoleKV, IUpdatePermPointRequest } from '@univerjs/protocol';
import type { IUser } from '../user-manager/user-manager.service';
import type { IAuthzIoService, ICreateInfo, IPermissionLocalData, IPermissionLocalJson, IPermissionLocalRule } from './type';
import { ObjectScope, UnitAction, UnitObject, UnitRole } from '@univerjs/protocol';
import { Inject } from '../../common/di';
import { UniverInstanceType } from '../../common/unit';
import { generateRandomId } from '../../shared/tools';

import { IResourceManagerService } from '../resource-manager/type';
import { UserManagerService } from '../user-manager/user-manager.service';
import { createDefaultUser, isDevRole } from '../user-manager/const';

import type { IAuthzIoService } from './type';
import { UserManagerService } from '../user-manager/user-manager.service';

/**
* Do not use the mock implementation in a production environment as it is a minimal version.
*/
export class AuthzIoLocalService implements IAuthzIoService {
private _permissionMap: Map<string, ICreateRequest_SelectRangeObject & { objectType: UnitObject }> = new Map([]);

// private _sheetPermissionPointMap: Map<string, { action: UnitAction; allowed: boolean }[]> = new Map();
private _permissionMap: IPermissionLocalData = new Map();

constructor(
@IResourceManagerService private _resourceManagerService: IResourceManagerService,
Expand Down Expand Up @@ -58,120 +58,162 @@ export class AuthzIoLocalService implements IAuthzIoService {

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);
toJson: (unitId: string) => {
const unitMap = this._permissionMap.get(unitId);
const res: IPermissionLocalJson = {};
if (unitMap?.ruleMap) {
res.rules = {};
unitMap.ruleMap.keys().forEach((key) => {
const rule = unitMap.ruleMap.get(key);
if (rule) {
res.rules![key] = rule;
}
});
}
if (unitMap?.createMap) {
res.creates = {};
unitMap.createMap.keys().forEach((key) => {
const create = unitMap.createMap.get(key);
if (create) {
res.creates![key] = create;
}
});
}
return JSON.stringify(res);
},
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]);
}
businesses: [UniverInstanceType.UNIVER_SHEET],
onLoad: (unitId, resource) => {
const { rules, creates } = resource;
const ruleMap = new Map();
Object.keys(rules).forEach((key) => {
ruleMap.set(key, rules[key]);
});
const createMap = new Map();
Object.keys(creates).forEach((key) => {
createMap.set(key, creates[key]);
});
this._permissionMap.set(unitId, {
ruleMap,
createMap,
});
},
onUnLoad: () => {
this._permissionMap.clear();
onUnLoad: (unitId) => {
this._permissionMap.delete(unitId);
},
});
}

async create(config: ICreateRequest): Promise<string> {
return generateRandomId(8);
const permissionId = generateRandomId(8);
let rule;
if (config.objectType === UnitObject.SelectRange) {
rule = config.selectRangeObject;
if (!rule) {
throw new Error('[AuthIoService]: The rule param and type do not match');
}
} else if (config.objectType === UnitObject.Worksheet) {
rule = config.worksheetObject;
if (!rule) {
throw new Error('[AuthIoService]: The rule param and type do not match');
}
} else {
throw new Error('[AuthIoService]: Invalid objectType');
}

const { unitID } = rule;
let ruleWithUnitMap = this._permissionMap.get(unitID);
if (!ruleWithUnitMap) {
ruleWithUnitMap = {
ruleMap: new Map(),
createMap: new Map(),
};
this._permissionMap.set(unitID, ruleWithUnitMap);
}
ruleWithUnitMap.createMap.set(permissionId, {
objectID: permissionId,
objectType: config.objectType,
creator: this._userManagerService.getCurrentUser(),
});
ruleWithUnitMap.ruleMap.set(permissionId, rule);
return permissionId;
}

async allowed(_config: IAllowedRequest): Promise<IActionInfo[]> {
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.

const { unitID, objectID, objectType, actions } = config;
const ruleMap = this._permissionMap.get(unitID)?.ruleMap;
const createMap = this._permissionMap.get(unitID)?.createMap;
const rule = ruleMap?.get(objectID);
const create = createMap?.get(objectID);
const user = this._userManagerService.getCurrentUser();

if (!rule) {
return Promise.resolve([]);
}

if (objectType === UnitObject.Worksheet || objectType === UnitObject.SelectRange) {
return actions.map((point) => this._getActionAllowed(rule, point, user, create));
}

return Promise.resolve([]);
}

async batchAllowed(_config: IAllowedRequest[]): Promise<IBatchAllowedResponse['objectActions']> {
return Promise.resolve([]);
async batchAllowed(configs: IAllowedRequest[]): Promise<IBatchAllowedResponse['objectActions']> {
return configs.filter((config) => config.objectType === UnitObject.Worksheet || config.objectType === UnitObject.SelectRange).reduce((result, config) => {
const { unitID, objectID, actions } = config;
const permissionData = this._permissionMap.get(unitID);
const ruleMap = permissionData?.ruleMap;
const createMap = permissionData?.createMap;
const rule = ruleMap?.get(objectID);
const create = createMap?.get(objectID);
const user = this._userManagerService.getCurrentUser();

if (rule) {
const updatedConfig = {
unitID,
objectID,
actions: actions.map((point) =>
this._getActionAllowed(rule, point, user, create)
),
};

result.push(updatedConfig);
}
return result;
}, [] as IBatchAllowedResponse['objectActions']);
}

// eslint-disable-next-line max-lines-per-function
async list(config: IListPermPointRequest): Promise<IPermissionPoint[]> {
const result: IPermissionPoint[] = [];
const unitMap = this._permissionMap.get(config.unitID);
const ruleMap = unitMap?.ruleMap;
const createMap = unitMap?.createMap;
const user = this._userManagerService.getCurrentUser();
config.objectIDs.forEach((objectID) => {
const rule = this._permissionMap.get(objectID);
if (rule) {
const rule = ruleMap?.get(objectID);
const create = createMap?.get(objectID);
if (rule && create?.creator) {
const item = {
objectID,
unitID: config.unitID,
objectType: rule!.objectType,
name: rule!.name,
objectType: create.objectType,
name: '',
shareOn: false,
shareRole: UnitRole.Owner,
shareRole: UnitRole.UNRECOGNIZED,
shareScope: -1,
scope: {
read: ObjectScope.AllCollaborator,
edit: ObjectScope.AllCollaborator,
},
creator: createDefaultUser(UnitRole.Owner),
strategies: [
{
action: 6,
role: 1,
},
{
action: 16,
role: 1,
},
{
action: 17,
role: 1,
},
{
action: 18,
role: 1,
},
{
action: 19,
role: 1,
},
{
action: 33,
role: 1,
},
{
action: 34,
role: 1,
},
{
action: 35,
role: 1,
},
{
action: 36,
role: 1,
},
{
action: 37,
role: 1,
},
{
action: 38,
role: 1,
},
{
action: 39,
role: 1,
},
{
action: 40,
role: 1,
},
],
actions: config.actions.map((a) => {
return { action: a, allowed: this._getRole(UnitRole.Owner) || this._getRole(UnitRole.Editor) };
}),
creator: create.creator,
strategies: [],
actions: config.actions.map((action) => this._getActionAllowed(rule, action, user, create)),
};
result.push(item);
}
Expand Down Expand Up @@ -216,4 +258,21 @@ export class AuthzIoLocalService implements IAuthzIoService {
async putCollaborators(config: IPutCollaboratorsRequest): Promise<void> {
return undefined;
}

private _getActionAllowed(rule: IPermissionLocalRule, point: UnitAction, user: IUser, create?: ICreateInfo) {
let allowed = false;

if (point === UnitAction.ManageCollaborator || point === UnitAction.Delete) {
allowed = user.userID === create?.creator?.userID;
} else {
allowed = rule?.collaborators.some((collaborator) => {
return collaborator.subject?.userID === user.userID && collaborator.role === UnitRole.Editor;
});
}

return {
action: point,
allowed,
};
}
}
22 changes: 20 additions & 2 deletions packages/core/src/services/authz-io/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
* limitations under the License.
*/

import type { IAllowedRequest, IAllowedResponse, IBatchAllowedResponse, ICreateCollaboratorRequest, ICreateRequest, ICreateResponse, IDeleteCollaboratorRequest, IListCollaboratorRequest, IListCollaboratorResponse, IListPermPointRequest, IListPermPointResponse, IListRolesRequest, IListRolesResponse, IPutCollaboratorsRequest, IUpdateCollaboratorRequest, IUpdatePermPointRequest } from '@univerjs/protocol';
import { createIdentifier } from '../../common/di';
import type { IAllowedRequest, IAllowedResponse, IBatchAllowedResponse, ICreateCollaboratorRequest, ICreateRequest, ICreateRequest_SelectRangeObject, ICreateRequest_WorksheetObject, ICreateResponse, IDeleteCollaboratorRequest, IListCollaboratorRequest, IListCollaboratorResponse, IListPermPointRequest, IListPermPointResponse, IListRolesRequest, IListRolesResponse, IPutCollaboratorsRequest, IUpdateCollaboratorRequest, IUpdatePermPointRequest, UnitObject } from '@univerjs/protocol';
import type { ILogContext } from '../log/context';
import type { IUser } from '../user-manager/user-manager.service';
import { createIdentifier } from '../../common/di';

// FIXME: should not import ILogContext here

Expand All @@ -36,3 +37,20 @@ export interface IAuthzIoService {

export const IAuthzIoService = createIdentifier<IAuthzIoService>('IAuthzIoIoService');

// unitId -> { ruleMap: { permissionId: rule } }
export type IPermissionLocalData = Map<string, {
ruleMap: Map<string, IPermissionLocalRule>;
createMap: Map<string, ICreateInfo>;
}>;

export interface IPermissionLocalJson {
rules?: Record<string, IPermissionLocalRule>;
creates?: Record<string, ICreateInfo>;
}

export type IPermissionLocalRule = ICreateRequest_SelectRangeObject | ICreateRequest_WorksheetObject;
export interface ICreateInfo {
objectID: string;
objectType: UnitObject;
creator: IUser | undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { BehaviorSubject, Subject } from 'rxjs';
import { createDefaultUser } from './const';

export interface IUser {
userID: string; name: string; avatar?: string;
userID: string; name: string; avatar: string;
};

export class UserManagerService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
*/

import type { IRenderContext, IRenderModule, Spreadsheet } from '@univerjs/engine-render';
import type { IUniverSheetsConfig } from '@univerjs/sheets';
import type { MenuConfig } from '@univerjs/ui';
import { connectInjector, Disposable, IConfigService, Inject, Injector, IPermissionService, IUniverInstanceService } from '@univerjs/core';
import { IRenderManagerService } from '@univerjs/engine-render';
import { CheckMarkSingle, DeleteSingle, LockSingle, ProtectSingle, WriteSingle } from '@univerjs/icons';
import { RangeProtectionRuleModel, WorksheetProtectionRuleModel } from '@univerjs/sheets';
import { ComponentManager, IUIPartsService } from '@univerjs/ui';
import { RangeProtectionRuleModel, SHEETS_PLUGIN_CONFIG_KEY, WorksheetProtectionRuleModel } from '@univerjs/sheets';
import { ComponentManager, IMenuManagerService, IUIPartsService } from '@univerjs/ui';
import { merge, throttleTime } from 'rxjs';
import { AddRangeProtectionFromSheetBarCommand, AddRangeProtectionFromToolbarCommand, ViewSheetPermissionFromSheetBarCommand } from '../../commands/commands/range-protection.command';
import { ChangeSheetProtectionFromSheetBarCommand, DeleteWorksheetProtectionFormSheetBarCommand } from '../../commands/commands/worksheet-protection.command';
import { permissionCheckIconKey, permissionDeleteIconKey, permissionEditIconKey, permissionLockIconKey, permissionMenuIconKey, UNIVER_SHEET_PERMISSION_BACKGROUND, UNIVER_SHEET_PERMISSION_DIALOG, UNIVER_SHEET_PERMISSION_PANEL, UNIVER_SHEET_PERMISSION_USER_DIALOG, UNIVER_SHEET_PERMISSION_USER_PART } from '../../consts/permission';
import { SheetSkeletonManagerService } from '../../services/sheet-skeleton-manager.service';
import { SheetPermissionDialog, SheetPermissionPanel, SheetPermissionUserDialog } from '../../views/permission';
Expand All @@ -31,6 +34,7 @@ import { RANGE_PROTECTION_CAN_NOT_VIEW_RENDER_EXTENSION_KEY, RANGE_PROTECTION_CA
import { worksheetProtectionKey, WorksheetProtectionRenderExtension } from '../../views/permission/extensions/worksheet-permission.render';
import { PermissionDetailUserPart } from '../../views/permission/panel-detail/PermissionDetailUserPart';
import { type IUniverSheetsUIConfig, SHEETS_UI_PLUGIN_CONFIG_KEY } from '../config.schema';
import { SHEET_PERMISSION_CONTEXT_MENU_ID } from '../menu/permission.menu';

export interface IUniverSheetsPermissionMenuConfig {
menu: MenuConfig;
Expand All @@ -40,13 +44,27 @@ export class SheetPermissionRenderManagerController extends Disposable {
constructor(
@Inject(Injector) private _injector: Injector,
@Inject(ComponentManager) private _componentManager: ComponentManager,
@Inject(IUIPartsService) private _uiPartsService: IUIPartsService
@Inject(IUIPartsService) private _uiPartsService: IUIPartsService,
@Inject(IConfigService) private _configService: IConfigService,
@Inject(IMenuManagerService) private _menuManagerService: IMenuManagerService
) {
super();
this._init();
}

private _init(): void {
const config = this._configService.getConfig<IUniverSheetsConfig>(SHEETS_PLUGIN_CONFIG_KEY);
if (config?.permissionConfig?.customImplement) {
this._menuManagerService.removeMenuByKeys([
AddRangeProtectionFromToolbarCommand.id,
SHEET_PERMISSION_CONTEXT_MENU_ID,
AddRangeProtectionFromSheetBarCommand.id,
DeleteWorksheetProtectionFormSheetBarCommand.id,
ChangeSheetProtectionFromSheetBarCommand.id,
ViewSheetPermissionFromSheetBarCommand.id,
]);
return;
}
this._initComponents();
this._initUiPartComponents();
}
Expand Down
Loading

0 comments on commit cb20919

Please sign in to comment.