Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/Lark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DocumentAIModel,
DocumentModel,
DriveFileModel,
PermissionModel,
TableFormView,
UserIdType,
WikiNode,
Expand Down Expand Up @@ -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);
Expand All @@ -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() {
Expand Down Expand Up @@ -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 };
}
}
47 changes: 47 additions & 0 deletions src/module/Permission/index.ts
Original file line number Diff line number Diff line change
@@ -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<LarkData<PermissionPublicResponse>>(
`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<LarkData<PasswordResponse>>(
`drive/v1/permissions/${token}/public/password?${buildURLData({ type })}`
);
return body!.data!.password;
}
}
55 changes: 55 additions & 0 deletions src/module/Permission/type.ts
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions src/module/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './BITable';
export * from './Drive';
export * from './Wiki';
export * from './DocumentAI';
export * from './Permission';