open_lark/service/cloud_docs/permission/member/
batch_create.rs

1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3
4use crate::core::{
5    api_req::ApiRequest,
6    api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
7    config::Config,
8    constants::AccessTokenType,
9    endpoints::{cloud_docs::*, EndpointBuilder},
10    http::Transport,
11    req_option::RequestOption,
12    SDKResult,
13};
14
15/// 协作者权限
16#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
17#[serde(rename_all = "snake_case")]
18#[derive(Default)]
19pub enum Permission {
20    /// 所有者
21    FullAccess,
22    /// 编辑者
23    Edit,
24    /// 阅读者
25    #[default]
26    View,
27    /// 评论者
28    Comment,
29}
30
31/// 协作者信息
32#[derive(Debug, Serialize, Deserialize, Clone)]
33pub struct Collaborator {
34    /// 协作者ID类型
35    pub member_type: String,
36    /// 协作者ID
37    pub member_id: String,
38    /// 权限
39    pub perm: Permission,
40}
41
42/// 批量增加协作者权限请求
43#[derive(Debug, Serialize, Default, Clone)]
44pub struct BatchCreatePermissionMemberRequest {
45    #[serde(skip)]
46    api_request: ApiRequest,
47    /// 文档token
48    #[serde(skip)]
49    token: String,
50    /// 文档类型
51    #[serde(skip)]
52    obj_type: String,
53    /// 协作者列表
54    members: Vec<Collaborator>,
55    /// 是否通知
56    #[serde(skip_serializing_if = "Option::is_none")]
57    need_notification: Option<bool>,
58}
59
60impl BatchCreatePermissionMemberRequest {
61    pub fn builder() -> BatchCreatePermissionMemberRequestBuilder {
62        BatchCreatePermissionMemberRequestBuilder::default()
63    }
64
65    pub fn new(token: impl ToString, obj_type: impl ToString, members: Vec<Collaborator>) -> Self {
66        Self {
67            token: token.to_string(),
68            obj_type: obj_type.to_string(),
69            members,
70            ..Default::default()
71        }
72    }
73}
74
75#[derive(Default)]
76pub struct BatchCreatePermissionMemberRequestBuilder {
77    request: BatchCreatePermissionMemberRequest,
78}
79
80impl BatchCreatePermissionMemberRequestBuilder {
81    /// 文档token
82    pub fn token(mut self, token: impl ToString) -> Self {
83        self.request.token = token.to_string();
84        self
85    }
86
87    /// 文档类型
88    pub fn obj_type(mut self, obj_type: impl ToString) -> Self {
89        self.request.obj_type = obj_type.to_string();
90        self
91    }
92
93    /// 设置为文档类型
94    pub fn as_doc(mut self) -> Self {
95        self.request.obj_type = "doc".to_string();
96        self
97    }
98
99    /// 设置为电子表格类型
100    pub fn as_sheet(mut self) -> Self {
101        self.request.obj_type = "sheet".to_string();
102        self
103    }
104
105    /// 设置为多维表格类型
106    pub fn as_bitable(mut self) -> Self {
107        self.request.obj_type = "bitable".to_string();
108        self
109    }
110
111    /// 设置为知识库类型
112    pub fn as_wiki(mut self) -> Self {
113        self.request.obj_type = "wiki".to_string();
114        self
115    }
116
117    /// 协作者列表
118    pub fn members(mut self, members: Vec<Collaborator>) -> Self {
119        self.request.members = members;
120        self
121    }
122
123    /// 添加协作者
124    pub fn add_member(mut self, member: Collaborator) -> Self {
125        self.request.members.push(member);
126        self
127    }
128
129    /// 添加用户协作者
130    pub fn add_user(mut self, user_id: impl ToString, permission: Permission) -> Self {
131        self.request.members.push(Collaborator {
132            member_type: "user".to_string(),
133            member_id: user_id.to_string(),
134            perm: permission,
135        });
136        self
137    }
138
139    /// 添加群组协作者
140    pub fn add_chat(mut self, chat_id: impl ToString, permission: Permission) -> Self {
141        self.request.members.push(Collaborator {
142            member_type: "chat".to_string(),
143            member_id: chat_id.to_string(),
144            perm: permission,
145        });
146        self
147    }
148
149    /// 添加部门协作者
150    pub fn add_department(mut self, department_id: impl ToString, permission: Permission) -> Self {
151        self.request.members.push(Collaborator {
152            member_type: "department".to_string(),
153            member_id: department_id.to_string(),
154            perm: permission,
155        });
156        self
157    }
158
159    /// 是否通知
160    pub fn need_notification(mut self, need: bool) -> Self {
161        self.request.need_notification = Some(need);
162        self
163    }
164
165    /// 启用通知
166    pub fn with_notification(mut self) -> Self {
167        self.request.need_notification = Some(true);
168        self
169    }
170
171    /// 禁用通知
172    pub fn without_notification(mut self) -> Self {
173        self.request.need_notification = Some(false);
174        self
175    }
176
177    pub fn build(mut self) -> BatchCreatePermissionMemberRequest {
178        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
179        self.request
180    }
181}
182
183crate::impl_executable_builder_owned!(
184    BatchCreatePermissionMemberRequestBuilder,
185    crate::service::cloud_docs::permission::PermissionService,
186    BatchCreatePermissionMemberRequest,
187    BaseResponse<BatchCreatePermissionMemberResponse>,
188    batch_create_member
189);
190
191/// 成员操作结果
192#[derive(Debug, Deserialize)]
193pub struct MemberResult {
194    /// 协作者ID类型
195    pub member_type: String,
196    /// 协作者ID
197    pub member_id: String,
198    /// 权限
199    pub perm: Permission,
200    /// 操作结果
201    pub result: String,
202    /// 错误码(如果有)
203    pub code: Option<i32>,
204    /// 错误信息(如果有)
205    pub msg: Option<String>,
206}
207
208/// 批量增加协作者权限响应
209#[derive(Debug, Deserialize)]
210pub struct BatchCreatePermissionMemberResponse {
211    /// 操作结果列表
212    pub members: Vec<MemberResult>,
213}
214
215impl ApiResponseTrait for BatchCreatePermissionMemberResponse {
216    fn data_format() -> ResponseFormat {
217        ResponseFormat::Data
218    }
219}
220
221/// 批量增加协作者权限
222pub async fn batch_create_permission_member(
223    request: BatchCreatePermissionMemberRequest,
224    config: &Config,
225    option: Option<RequestOption>,
226) -> SDKResult<BaseResponse<BatchCreatePermissionMemberResponse>> {
227    let mut api_req = request.api_request;
228    api_req.http_method = Method::POST;
229    api_req.api_path = format!(
230        "{}?type={}",
231        EndpointBuilder::replace_param(
232            DRIVE_V1_PERMISSIONS_MEMBERS_BATCH_CREATE,
233            "token",
234            &request.token
235        ),
236        request.obj_type
237    );
238
239    // 添加通知参数
240    if let Some(need_notification) = request.need_notification {
241        api_req.api_path = format!(
242            "{}&need_notification={}",
243            api_req.api_path, need_notification
244        );
245    }
246
247    api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
248
249    let api_resp = Transport::request(api_req, config, option).await?;
250    Ok(api_resp)
251}
252
253impl Permission {
254    /// 权限级别(数值越大权限越高)
255    pub fn level(&self) -> u8 {
256        match self {
257            Permission::View => 1,
258            Permission::Comment => 2,
259            Permission::Edit => 3,
260            Permission::FullAccess => 4,
261        }
262    }
263
264    /// 是否有编辑权限
265    pub fn can_edit(&self) -> bool {
266        matches!(self, Permission::Edit | Permission::FullAccess)
267    }
268
269    /// 是否有评论权限
270    pub fn can_comment(&self) -> bool {
271        !matches!(self, Permission::View)
272    }
273
274    /// 是否是所有者
275    pub fn is_owner(&self) -> bool {
276        matches!(self, Permission::FullAccess)
277    }
278
279    /// 权限描述
280    pub fn description(&self) -> &'static str {
281        match self {
282            Permission::FullAccess => "所有者",
283            Permission::Edit => "编辑者",
284            Permission::Comment => "评论者",
285            Permission::View => "阅读者",
286        }
287    }
288}
289
290impl MemberResult {
291    /// 操作是否成功
292    pub fn is_success(&self) -> bool {
293        self.result == "success"
294    }
295
296    /// 是否有错误
297    pub fn has_error(&self) -> bool {
298        self.code.is_some() || self.msg.is_some()
299    }
300
301    /// 获取错误信息
302    pub fn error_message(&self) -> Option<String> {
303        if let (Some(code), Some(msg)) = (self.code, &self.msg) {
304            Some(format!("错误码: {code}, 错误信息: {msg}"))
305        } else if let Some(msg) = &self.msg {
306            Some(msg.clone())
307        } else {
308            self.code.map(|code| format!("错误码: {code}"))
309        }
310    }
311}
312
313impl BatchCreatePermissionMemberResponse {
314    /// 获取成功的操作数量
315    pub fn success_count(&self) -> usize {
316        self.members
317            .iter()
318            .filter(|member| member.is_success())
319            .count()
320    }
321
322    /// 获取失败的操作数量
323    pub fn failed_count(&self) -> usize {
324        self.members
325            .iter()
326            .filter(|member| !member.is_success())
327            .count()
328    }
329
330    /// 获取成功的操作
331    pub fn successful_members(&self) -> Vec<&MemberResult> {
332        self.members
333            .iter()
334            .filter(|member| member.is_success())
335            .collect()
336    }
337
338    /// 获取失败的操作
339    pub fn failed_members(&self) -> Vec<&MemberResult> {
340        self.members
341            .iter()
342            .filter(|member| !member.is_success())
343            .collect()
344    }
345
346    /// 操作摘要
347    pub fn summary(&self) -> String {
348        format!(
349            "总计: {}, 成功: {}, 失败: {}",
350            self.members.len(),
351            self.success_count(),
352            self.failed_count()
353        )
354    }
355}
356
357#[cfg(test)]
358#[allow(unused_variables, unused_unsafe)]
359mod tests {
360    use super::*;
361
362    #[test]
363    fn test_batch_create_permission_member_request_builder() {
364        let request = BatchCreatePermissionMemberRequest::builder()
365            .token("doccnxxxxxx")
366            .as_doc()
367            .add_user("user123", Permission::Edit)
368            .add_chat("chat456", Permission::View)
369            .with_notification()
370            .build();
371
372        assert_eq!(request.token, "doccnxxxxxx");
373        assert_eq!(request.obj_type, "doc");
374        assert_eq!(request.members.len(), 2);
375        assert_eq!(request.need_notification, Some(true));
376    }
377
378    #[test]
379    fn test_permission_methods() {
380        assert!(Permission::Edit.can_edit());
381        assert!(Permission::FullAccess.can_edit());
382        assert!(!Permission::View.can_edit());
383
384        assert!(Permission::Edit.can_comment());
385        assert!(!Permission::View.can_comment());
386
387        assert!(Permission::FullAccess.is_owner());
388        assert!(!Permission::Edit.is_owner());
389
390        assert_eq!(Permission::FullAccess.level(), 4);
391        assert_eq!(Permission::View.level(), 1);
392    }
393}