open_lark/service/cloud_docs/permission/member/
transfer_owner.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, Default, Clone)]
17pub struct TransferOwnerRequest {
18    #[serde(skip)]
19    api_request: ApiRequest,
20    /// 文档token
21    #[serde(skip)]
22    token: String,
23    /// 文档类型
24    #[serde(skip)]
25    obj_type: String,
26    /// 新所有者ID类型
27    member_type: String,
28    /// 新所有者ID
29    member_id: String,
30    /// 是否移除当前所有者的权限
31    #[serde(skip_serializing_if = "Option::is_none")]
32    remove_old_owner: Option<bool>,
33    /// 是否通知
34    #[serde(skip_serializing_if = "Option::is_none")]
35    need_notification: Option<bool>,
36}
37
38impl TransferOwnerRequest {
39    pub fn builder() -> TransferOwnerRequestBuilder {
40        TransferOwnerRequestBuilder::default()
41    }
42
43    pub fn new(
44        token: impl ToString,
45        obj_type: impl ToString,
46        member_type: impl ToString,
47        member_id: impl ToString,
48    ) -> Self {
49        Self {
50            token: token.to_string(),
51            obj_type: obj_type.to_string(),
52            member_type: member_type.to_string(),
53            member_id: member_id.to_string(),
54            ..Default::default()
55        }
56    }
57
58    /// 转移给用户
59    pub fn to_user(token: impl ToString, obj_type: impl ToString, user_id: impl ToString) -> Self {
60        Self::new(token, obj_type, "user", user_id)
61    }
62}
63
64#[derive(Default)]
65pub struct TransferOwnerRequestBuilder {
66    request: TransferOwnerRequest,
67}
68
69impl TransferOwnerRequestBuilder {
70    /// 文档token
71    pub fn token(mut self, token: impl ToString) -> Self {
72        self.request.token = token.to_string();
73        self
74    }
75
76    /// 文档类型
77    pub fn obj_type(mut self, obj_type: impl ToString) -> Self {
78        self.request.obj_type = obj_type.to_string();
79        self
80    }
81
82    /// 设置为文档类型
83    pub fn as_doc(mut self) -> Self {
84        self.request.obj_type = "doc".to_string();
85        self
86    }
87
88    /// 设置为电子表格类型
89    pub fn as_sheet(mut self) -> Self {
90        self.request.obj_type = "sheet".to_string();
91        self
92    }
93
94    /// 设置为多维表格类型
95    pub fn as_bitable(mut self) -> Self {
96        self.request.obj_type = "bitable".to_string();
97        self
98    }
99
100    /// 设置为知识库类型
101    pub fn as_wiki(mut self) -> Self {
102        self.request.obj_type = "wiki".to_string();
103        self
104    }
105
106    /// 新所有者类型和ID
107    pub fn new_owner(mut self, member_type: impl ToString, member_id: impl ToString) -> Self {
108        self.request.member_type = member_type.to_string();
109        self.request.member_id = member_id.to_string();
110        self
111    }
112
113    /// 转移给用户
114    pub fn to_user(mut self, user_id: impl ToString) -> Self {
115        self.request.member_type = "user".to_string();
116        self.request.member_id = user_id.to_string();
117        self
118    }
119
120    /// 转移给群组
121    pub fn to_chat(mut self, chat_id: impl ToString) -> Self {
122        self.request.member_type = "chat".to_string();
123        self.request.member_id = chat_id.to_string();
124        self
125    }
126
127    /// 转移给部门
128    pub fn to_department(mut self, department_id: impl ToString) -> Self {
129        self.request.member_type = "department".to_string();
130        self.request.member_id = department_id.to_string();
131        self
132    }
133
134    /// 是否移除当前所有者的权限
135    pub fn remove_old_owner(mut self, remove: bool) -> Self {
136        self.request.remove_old_owner = Some(remove);
137        self
138    }
139
140    /// 移除当前所有者权限
141    pub fn remove_current_owner(mut self) -> Self {
142        self.request.remove_old_owner = Some(true);
143        self
144    }
145
146    /// 保留当前所有者权限
147    pub fn keep_current_owner(mut self) -> Self {
148        self.request.remove_old_owner = Some(false);
149        self
150    }
151
152    /// 是否通知
153    pub fn need_notification(mut self, need: bool) -> Self {
154        self.request.need_notification = Some(need);
155        self
156    }
157
158    /// 启用通知
159    pub fn with_notification(mut self) -> Self {
160        self.request.need_notification = Some(true);
161        self
162    }
163
164    /// 禁用通知
165    pub fn without_notification(mut self) -> Self {
166        self.request.need_notification = Some(false);
167        self
168    }
169
170    pub fn build(mut self) -> TransferOwnerRequest {
171        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
172        self.request
173    }
174}
175
176/// 转移结果
177#[derive(Debug, Deserialize)]
178pub struct TransferResult {
179    /// 新所有者ID类型
180    pub member_type: String,
181    /// 新所有者ID
182    pub member_id: String,
183    /// 转移时间(毫秒时间戳)
184    pub transfer_time: Option<i64>,
185    /// 原所有者ID类型
186    pub old_owner_type: Option<String>,
187    /// 原所有者ID
188    pub old_owner_id: Option<String>,
189}
190
191/// 转移所有者响应
192#[derive(Debug, Deserialize)]
193pub struct TransferOwnerResponse {
194    /// 转移结果
195    pub member: TransferResult,
196}
197
198impl ApiResponseTrait for TransferOwnerResponse {
199    fn data_format() -> ResponseFormat {
200        ResponseFormat::Data
201    }
202}
203
204/// 转移所有者
205pub async fn transfer_owner(
206    request: TransferOwnerRequest,
207    config: &Config,
208    option: Option<RequestOption>,
209) -> SDKResult<BaseResponse<TransferOwnerResponse>> {
210    let mut api_req = request.api_request;
211    api_req.http_method = Method::POST;
212    api_req.api_path = format!(
213        "{}?type={}",
214        EndpointBuilder::replace_param(
215            DRIVE_V1_PERMISSIONS_MEMBERS_TRANSFER_OWNER,
216            "token",
217            &request.token
218        ),
219        request.obj_type
220    );
221
222    // 添加其他查询参数
223    let mut query_params = Vec::new();
224    if let Some(remove_old_owner) = request.remove_old_owner {
225        query_params.push(format!("remove_old_owner={remove_old_owner}"));
226    }
227    if let Some(need_notification) = request.need_notification {
228        query_params.push(format!("need_notification={need_notification}"));
229    }
230
231    if !query_params.is_empty() {
232        api_req.api_path = format!("{}&{}", api_req.api_path, query_params.join("&"));
233    }
234
235    api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
236
237    let api_resp = Transport::request(api_req, config, option).await?;
238    Ok(api_resp)
239}
240
241impl TransferResult {
242    /// 是否有转移时间
243    pub fn has_transfer_time(&self) -> bool {
244        self.transfer_time.is_some()
245    }
246
247    /// 是否有原所有者信息
248    pub fn has_old_owner_info(&self) -> bool {
249        self.old_owner_type.is_some() && self.old_owner_id.is_some()
250    }
251
252    /// 获取转移时间的格式化字符串
253    pub fn transfer_time_formatted(&self) -> Option<String> {
254        self.transfer_time
255            .map(|timestamp| format!("转移时间: {timestamp}"))
256    }
257
258    /// 获取新所有者信息
259    pub fn new_owner_info(&self) -> String {
260        format!("新所有者: {} ({})", self.member_id, self.member_type)
261    }
262
263    /// 获取原所有者信息
264    pub fn old_owner_info(&self) -> Option<String> {
265        if let (Some(old_type), Some(old_id)) = (&self.old_owner_type, &self.old_owner_id) {
266            Some(format!("原所有者: {old_id} ({old_type})"))
267        } else {
268            None
269        }
270    }
271
272    /// 获取转移摘要
273    pub fn summary(&self) -> String {
274        let mut parts = vec![self.new_owner_info()];
275
276        if let Some(old_info) = self.old_owner_info() {
277            parts.push(old_info);
278        }
279
280        if let Some(time_info) = self.transfer_time_formatted() {
281            parts.push(time_info);
282        }
283
284        parts.join(", ")
285    }
286}
287
288impl TransferOwnerResponse {
289    /// 获取新所有者ID
290    pub fn new_owner_id(&self) -> &str {
291        &self.member.member_id
292    }
293
294    /// 获取新所有者类型
295    pub fn new_owner_type(&self) -> &str {
296        &self.member.member_type
297    }
298
299    /// 获取转移时间
300    pub fn transfer_time(&self) -> Option<i64> {
301        self.member.transfer_time
302    }
303
304    /// 是否成功转移
305    pub fn is_transferred(&self) -> bool {
306        !self.member.member_id.is_empty()
307    }
308
309    /// 获取转移成功摘要
310    pub fn success_summary(&self) -> String {
311        format!("所有者转移成功: {}", self.member.summary())
312    }
313}
314
315#[cfg(test)]
316#[allow(unused_variables, unused_unsafe)]
317mod tests {
318    use super::*;
319
320    #[test]
321    fn test_transfer_owner_request_builder() {
322        let request = TransferOwnerRequest::builder()
323            .token("doccnxxxxxx")
324            .as_doc()
325            .to_user("user123")
326            .remove_current_owner()
327            .with_notification()
328            .build();
329
330        assert_eq!(request.token, "doccnxxxxxx");
331        assert_eq!(request.obj_type, "doc");
332        assert_eq!(request.member_type, "user");
333        assert_eq!(request.member_id, "user123");
334        assert_eq!(request.remove_old_owner, Some(true));
335        assert_eq!(request.need_notification, Some(true));
336    }
337
338    #[test]
339    fn test_transfer_owner_convenience_method() {
340        let request = TransferOwnerRequest::to_user("doccnxxxxxx", "doc", "user123");
341        assert_eq!(request.member_type, "user");
342        assert_eq!(request.member_id, "user123");
343    }
344}