From 46ce0e969fd620dbec0400f2ef4ff475ae7841c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Foxy=20=E5=B0=8F=E7=8B=90?= Date: Sun, 21 Jun 2026 15:07:11 +0800 Subject: [PATCH] feat: implement Permission API wrappers & publishFile method - Add PermissionModel with updatePermissions() and setPassword() methods - Add LarkApp.publishFile(URI, enablePassword, editable) for document publishing - Export Permission module from module index Closes #35 --- src/Lark.ts | 45 ++++++++++++++++++++++++++++ src/module/Permission/index.ts | 47 +++++++++++++++++++++++++++++ src/module/Permission/type.ts | 55 ++++++++++++++++++++++++++++++++++ src/module/index.ts | 1 + 4 files changed, 148 insertions(+) create mode 100644 src/module/Permission/index.ts create mode 100644 src/module/Permission/type.ts diff --git a/src/Lark.ts b/src/Lark.ts index 4014fdb..d0639c2 100644 --- a/src/Lark.ts +++ b/src/Lark.ts @@ -9,6 +9,7 @@ import { DocumentAIModel, DocumentModel, DriveFileModel, + PermissionModel, TableFormView, UserIdType, WikiNode, @@ -53,6 +54,7 @@ export class LarkApp implements LarkAppOption { wikiNodeStore: WikiNodeModel; documentStore: DocumentModel; documentAIStore: DocumentAIModel; + permissionStore: PermissionModel; constructor(option: LarkAppServerOption | LarkAppClientOption) { Object.assign(this, option); @@ -79,6 +81,9 @@ export class LarkApp implements LarkAppOption { this.documentAIStore = new (class extends DocumentAIModel { client = client; })(); + this.permissionStore = new (class extends PermissionModel { + client = client; + })(); } private boot() { @@ -315,4 +320,44 @@ export class LarkApp implements LarkAppOption { ); return { appId, tables, tableIdMap, forms, formLinkMap }; } + + /** + * Publish a document with public access settings & optional password protection + * + * @param URI - Document URI (e.g. `docx/xxx` or `wiki/xxx`) + * @param enablePassword - Whether to enable password protection + * @param editable - Whether anyone with the link can edit + * + * @see {@link PermissionModel#updatePermissions} + * @see {@link PermissionModel#setPassword} + */ + async publishFile( + URI: string, + enablePassword = false, + editable = false + ): Promise<{ password?: string }> { + await this.getAccessToken(); + + let [[type, token]] = DriveFileModel.parseURI(URI); + + if (type === 'wiki') { + ({ obj_type: type, obj_token: token } = await this.wiki2drive(token)); + } else { + type = getLarkDocumentType(type as LarkDocumentPathType); + } + await this.permissionStore.updatePermissions(token, type, { + external_access_entity: 'open', + link_share_entity: editable ? 'anyone_editable' : 'anyone_readable', + security_entity: editable ? 'anyone_can_edit' : 'anyone_can_view', + comment_entity: 'anyone_can_view', + share_entity: 'anyone', + manage_collaborator_entity: 'collaborator_can_edit', + copy_entity: 'anyone_can_view' + }); + if (!enablePassword) return {}; + + const password = await this.permissionStore.setPassword(token, type); + + return { password }; + } } diff --git a/src/module/Permission/index.ts b/src/module/Permission/index.ts new file mode 100644 index 0000000..5e2f3b6 --- /dev/null +++ b/src/module/Permission/index.ts @@ -0,0 +1,47 @@ +import { RESTClient, toggle } from 'mobx-restful'; +import { buildURLData } from 'web-utility'; + +import { LarkData } from '../../type'; +import { + PasswordResponse, + PermissionFileType, + PermissionPublic, + PermissionPublicResponse +} from './type'; + +export * from './type'; + +export abstract class PermissionModel { + abstract client: RESTClient; + + /** + * Update common settings of a document + * + * @see {@link https://open.feishu.cn/document/server-docs/docs/permission/permission-public/patch-2} + */ + @toggle('uploading') + async updatePermissions( + token: string, + type: PermissionFileType, + data: PermissionPublic + ) { + const { body } = await this.client.patch>( + `drive/v2/permissions/${token}/public?${buildURLData({ type })}`, + data + ); + return body!.data!.permission_public; + } + + /** + * Enable password for a document + * + * @see {@link https://open.feishu.cn/document/server-docs/docs/permission/permission-public/permission-public-password/create} + */ + @toggle('uploading') + async setPassword(token: string, type: PermissionFileType) { + const { body } = await this.client.post>( + `drive/v1/permissions/${token}/public/password?${buildURLData({ type })}` + ); + return body!.data!.password; + } +} diff --git a/src/module/Permission/type.ts b/src/module/Permission/type.ts new file mode 100644 index 0000000..a8459eb --- /dev/null +++ b/src/module/Permission/type.ts @@ -0,0 +1,55 @@ +import { LarkDocumentType } from '../../type'; + +export type PermissionFileType = LarkDocumentType | 'wiki' | 'minutes'; + +export type ExternalAccessEntity = 'open' | 'closed' | 'allow_share_partner_tenant'; + +export type SecurityEntity = 'anyone_can_view' | 'anyone_can_edit' | 'only_full_access'; + +export type CommentEntity = 'anyone_can_view' | 'anyone_can_edit'; + +export type ShareEntity = 'anyone' | 'same_tenant'; + +export type ManageCollaboratorEntity = + | 'collaborator_can_view' + | 'collaborator_can_edit' + | 'collaborator_full_access'; + +export type LinkShareEntity = + | 'tenant_readable' + | 'tenant_editable' + | 'partner_tenant_readable' + | 'partner_tenant_editable' + | 'anyone_readable' + | 'anyone_editable' + | 'closed'; + +export type CopyEntity = 'anyone_can_view' | 'anyone_can_edit' | 'only_full_access'; + +export interface PermissionPublic { + external_access_entity?: ExternalAccessEntity; + security_entity?: SecurityEntity; + comment_entity?: CommentEntity; + share_entity?: ShareEntity; + manage_collaborator_entity?: ManageCollaboratorEntity; + link_share_entity?: LinkShareEntity; + copy_entity?: CopyEntity; +} + +export interface PermissionPublicResponse { + permission_public: Record< + | 'external_access_entity' + | 'security_entity' + | 'comment_entity' + | 'share_entity' + | 'manage_collaborator_entity' + | 'link_share_entity' + | 'copy_entity' + | 'lock_switch', + string + >; +} + +export interface PasswordResponse { + password: string; +} diff --git a/src/module/index.ts b/src/module/index.ts index dfe010f..c2a5534 100644 --- a/src/module/index.ts +++ b/src/module/index.ts @@ -9,3 +9,4 @@ export * from './BITable'; export * from './Drive'; export * from './Wiki'; export * from './DocumentAI'; +export * from './Permission';