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