open_lark/service/cloud_docs/drive/v1/
permissions.rs

1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    core::{
6        api_req::ApiRequest,
7        api_resp::{ApiResponseTrait, BaseResponse},
8        config::Config,
9        constants::AccessTokenType,
10        endpoints::cloud_docs::*,
11        http::Transport,
12        req_option::RequestOption,
13        SDKResult,
14    },
15    impl_executable_builder_owned,
16};
17
18pub struct PermissionsService {
19    config: Config,
20}
21
22impl PermissionsService {
23    pub fn new(config: Config) -> Self {
24        Self { config }
25    }
26
27    /// 获取云文档权限设置
28    pub async fn get(
29        &self,
30        request: GetPermissionRequest,
31        option: Option<RequestOption>,
32    ) -> SDKResult<BaseResponse<GetPermissionResponse>> {
33        let mut api_req = request.api_request;
34        api_req.http_method = Method::GET;
35        api_req.api_path = DRIVE_V2_PERMISSIONS_PUBLIC.replace("{}", &request.token);
36        api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
37
38        let api_resp = Transport::request(api_req, &self.config, option).await?;
39
40        Ok(api_resp)
41    }
42
43    /// 更新云文档权限设置
44    pub async fn patch(
45        &self,
46        request: PatchPermissionRequest,
47        option: Option<RequestOption>,
48    ) -> SDKResult<BaseResponse<GetPermissionResponse>> {
49        let mut api_req = request.api_request;
50        api_req.http_method = Method::PATCH;
51        api_req.api_path = DRIVE_V2_PERMISSIONS_PUBLIC.replace("{}", &request.token);
52        api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
53
54        let api_resp = Transport::request(api_req, &self.config, option).await?;
55
56        Ok(api_resp)
57    }
58}
59
60/// 获取云文档权限设置
61#[derive(Debug, Default)]
62pub struct GetPermissionRequest {
63    api_request: ApiRequest,
64    /// 文件的 token
65    token: String,
66    /// 文件类型,需要与文件的 token 相匹配
67    ///
68    /// 示例值:"doc"
69    ///
70    /// 可选值有:
71    ///
72    /// - doc:旧版文档
73    /// - sheet:电子表格
74    /// - file:云空间文件
75    /// - wiki:知识库节点
76    /// - bitable:多维表格
77    /// - docx:新版文档
78    /// - mindnote:思维笔记
79    /// - minutes:妙记
80    /// - slides:幻灯片
81    r#type: String,
82}
83
84impl GetPermissionRequest {
85    pub fn builder() -> GetPermissionRequestBuilder {
86        GetPermissionRequestBuilder::default()
87    }
88}
89
90#[derive(Default)]
91pub struct GetPermissionRequestBuilder {
92    request: GetPermissionRequest,
93}
94
95impl GetPermissionRequestBuilder {
96    /// 文件的 token
97    pub fn token(mut self, token: impl ToString) -> Self {
98        self.request.token = token.to_string();
99        self
100    }
101
102    /// 文件类型,需要与文件的 token 相匹配
103    ///
104    /// 示例值:"doc"
105    ///
106    /// 可选值有:
107    ///
108    /// - doc:旧版文档
109    /// - sheet:电子表格
110    /// - file:云空间文件
111    /// - wiki:知识库节点
112    /// - bitable:多维表格
113    /// - docx:新版文档
114    /// - mindnote:思维笔记
115    /// - minutes:妙记
116    /// - slides:幻灯片
117    pub fn r#type(mut self, r#type: impl ToString) -> Self {
118        self.request.r#type = r#type.to_string();
119        self.request
120            .api_request
121            .query_params
122            .insert("type", r#type.to_string());
123        self
124    }
125
126    pub fn build(self) -> GetPermissionRequest {
127        self.request
128    }
129}
130
131/// 返回的文档公共设置
132#[derive(Debug, Deserialize)]
133pub struct GetPermissionResponse {
134    /// 返回的文档公共设置
135    pub permission_public: PermissionPublic,
136}
137
138impl ApiResponseTrait for GetPermissionResponse {
139    fn data_format() -> crate::core::api_resp::ResponseFormat {
140        crate::core::api_resp::ResponseFormat::Data
141    }
142}
143
144#[derive(Debug, Deserialize)]
145/// 返回的文档公共设置
146pub struct PermissionPublic {
147    /// 允许内容被分享到组织外
148    ///
149    /// 可选值有:
150    ///
151    /// - open:打开
152    /// - closed:关闭
153    /// - allow_share_partner_tenant:允许分享给关联组织
154    pub external_access_entity: Option<String>,
155    /// 谁可以创建副本、打印、下载
156    ///
157    /// 可选值有:
158    ///
159    /// - anyone_can_view:拥有可阅读权限的用户
160    /// - anyone_can_edit:拥有可编辑权限的用户
161    /// - only_full_access:拥有可管理权限(包括我)的用户
162    pub security_entity: Option<String>,
163    /// 谁可以评论
164    ///
165    /// 可选值有:
166    ///
167    /// - anyone_can_view:拥有可阅读权限的用户
168    /// - anyone_can_edit:拥有可编辑权限的用户
169    pub comment_entity: Option<String>,
170    /// 谁可以添加和管理协作者-组织维度
171    ///
172    /// 可选值有:
173    ///
174    /// - anyone:所有可阅读或编辑此文档的用户
175    /// - same_tenant:组织内所有可阅读或编辑此文档的用户
176    pub share_entity: Option<String>,
177    /// 谁可以添加和管理协作者-协作者维度
178    ///
179    /// 可选值有:
180    ///
181    /// - collaborator_can_view:拥有可阅读权限的协作者
182    /// - collaborator_can_edit:拥有可编辑权限的协作者
183    /// - collaborator_full_access:拥有可管理权限(包括我)的协作者
184    pub manage_collaborator_entity: Option<String>,
185    /// 链接分享设置
186    ///
187    /// 可选值有:
188    ///
189    /// - tenant_readable:组织内获得链接的人可阅读
190    /// - tenant_editable:组织内获得链接的人可编辑
191    /// - partner_tenant_readable:关联组织的人可阅读
192    /// - partner_tenant_editable:关联组织的人可编辑
193    /// - anyone_readable:互联网上获得链接的任何人可阅读(仅external_access=“open”时有效)
194    /// - anyone_editable:互联网上获得链接的任何人可编辑(仅external_access=“open”时有效)
195    /// - closed:关闭链接分享
196    pub link_share_entity: Option<String>,
197    /// 谁可以复制内容
198    ///
199    /// 可选值有:
200    ///
201    /// - anyone_can_view:拥有可阅读权限的用户
202    /// - anyone_can_edit:拥有可编辑权限的用户
203    /// - only_full_access:拥有可管理权限(包括我)的协作者
204    pub copy_entity: Option<String>,
205    /// 节点是否已加锁,加锁之后不再继承父级页面的权限
206    pub lock_switch: Option<bool>,
207}
208
209#[derive(Debug, Default, Serialize)]
210pub struct PatchPermissionRequest {
211    #[serde(skip)]
212    api_request: ApiRequest,
213    /// 文件的 token
214    #[serde(skip)]
215    token: String,
216    /// 允许内容被分享到组织外
217    ///
218    /// 示例值:"open"
219    ///
220    /// 可选值有:
221    ///
222    /// - open:打开
223    /// - closed:关闭
224    /// - allow_share_partner_tenant:允许分享给关联组织(只有租户后台设置仅允许关联组织分享,
225    ///   才能设置为该值)
226    #[serde(skip_serializing_if = "Option::is_none")]
227    external_access_entity: Option<String>,
228    /// 谁可以创建副本、打印、下载
229    ///
230    /// 示例值:"anyone_can_view"
231    ///
232    /// 可选值有:
233    ///
234    /// - anyone_can_view:拥有可阅读权限的用户
235    /// - anyone_can_edit:拥有可编辑权限的用户
236    /// - only_full_access:拥有可管理权限(包括我)的用户
237    #[serde(skip_serializing_if = "Option::is_none")]
238    security_entity: Option<String>,
239    /// 谁可以评论
240    ///
241    /// 示例值:"anyone_can_view"
242    ///
243    /// 可选值有:
244    ///
245    /// - anyone_can_view:拥有可阅读权限的用户
246    /// - anyone_can_edit:拥有可编辑权限的用户
247    #[serde(skip_serializing_if = "Option::is_none")]
248    comment_entity: Option<String>,
249    /// 谁可以添加和管理协作者-组织维度
250    ///
251    /// 示例值:"anyone"
252    ///
253    /// 可选值有:
254    ///
255    /// - anyone:所有可阅读或编辑此文档的用户
256    /// - same_tenant:组织内所有可阅读或编辑此文档的用户
257    #[serde(skip_serializing_if = "Option::is_none")]
258    share_entity: Option<String>,
259    /// 谁可以添加和管理协作者-协作者维度
260    ///
261    /// 示例值:"collaborator_can_view"
262    ///
263    /// 可选值有:
264    ///
265    /// - collaborator_can_view:拥有可阅读权限的协作者
266    /// - collaborator_can_edit:拥有可编辑权限的协作者
267    /// - collaborator_full_access:拥有可管理权限(包括我)的协作者
268    #[serde(skip_serializing_if = "Option::is_none")]
269    manage_collaborator_entity: Option<String>,
270    /// 链接分享设置
271    ///
272    /// 示例值:"tenant_readable"
273    ///
274    /// 可选值有:
275    ///
276    /// tenant_readable:组织内获得链接的人可阅读
277    /// tenant_editable:组织内获得链接的人可编辑
278    /// partner_tenant_readable:关联组织的人可阅读(只有租户后台设置仅允许关联组织分享,
279    /// 才能设置为该值) partner_tenant_editable:
280    /// 关联组织的人可编辑(只有租户后台设置仅允许关联组织分享,才能设置为该值)
281    /// anyone_readable:互联网上获得链接的任何人可阅读(仅external_access_entity=“open”时有效)
282    /// anyone_editable:互联网上获得链接的任何人可编辑(仅external_access_entity=“open”时有效)
283    /// closed:关闭链接分享
284    #[serde(skip_serializing_if = "Option::is_none")]
285    link_share_entity: Option<String>,
286    #[serde(skip_serializing_if = "Option::is_none")]
287    copy_entity: Option<String>,
288}
289
290impl PatchPermissionRequest {
291    pub fn builder() -> PatchPermissionRequestBuilder {
292        PatchPermissionRequestBuilder::default()
293    }
294}
295
296#[derive(Default)]
297pub struct PatchPermissionRequestBuilder {
298    request: PatchPermissionRequest,
299}
300
301impl PatchPermissionRequestBuilder {
302    /// 文件的 token
303    pub fn token(mut self, token: impl ToString) -> Self {
304        self.request.token = token.to_string();
305        self
306    }
307
308    /// 文件类型,需要与文件的 token 相匹配
309    ///
310    /// 示例值:"doc"
311    ///
312    /// 可选值有:
313    ///
314    /// - doc:旧版文档
315    /// - sheet:电子表格
316    /// - file:云空间文件
317    /// - wiki:知识库节点
318    /// - bitable:多维表格
319    /// - docx:新版文档
320    /// - mindnote:思维笔记
321    /// - minutes:妙记
322    /// - slides:幻灯片
323    pub fn r#type(mut self, r#type: impl ToString) -> Self {
324        self.request
325            .api_request
326            .query_params
327            .insert("type", r#type.to_string());
328        self
329    }
330
331    /// 允许内容被分享到组织外
332    ///
333    /// 示例值:"open"
334    ///
335    /// 可选值有:
336    ///
337    /// - open:打开
338    /// - closed:关闭
339    /// - allow_share_partner_tenant:允许分享给关联组织(只有租户后台设置仅允许关联组织分享,
340    ///   才能设置为该值)
341    pub fn external_access_entity(mut self, external_access_entity: impl ToString) -> Self {
342        self.request.external_access_entity = Some(external_access_entity.to_string());
343        self
344    }
345
346    /// 谁可以创建副本、打印、下载
347    ///
348    /// 示例值:"anyone_can_view"
349    ///
350    /// 可选值有:
351    ///
352    /// - anyone_can_view:拥有可阅读权限的用户
353    /// - anyone_can_edit:拥有可编辑权限的用户
354    /// - only_full_access:拥有可管理权限(包括我)的用户
355    pub fn security_entity(mut self, security_entity: impl ToString) -> Self {
356        self.request.security_entity = Some(security_entity.to_string());
357        self
358    }
359
360    /// 谁可以评论
361    ///
362    /// 示例值:"anyone_can_view"
363    ///
364    /// 可选值有:
365    ///
366    /// - anyone_can_view:拥有可阅读权限的用户
367    /// - anyone_can_edit:拥有可编辑权限的用户
368    pub fn comment_entity(mut self, comment_entity: impl ToString) -> Self {
369        self.request.comment_entity = Some(comment_entity.to_string());
370        self
371    }
372
373    /// 谁可以添加和管理协作者-组织维度
374    ///
375    /// 示例值:"anyone"
376    ///
377    /// 可选值有:
378    ///
379    /// - anyone:所有可阅读或编辑此文档的用户
380    /// - same_tenant:组织内所有可阅读或编辑此文档的用户
381    pub fn share_entity(mut self, share_entity: impl ToString) -> Self {
382        self.request.share_entity = Some(share_entity.to_string());
383        self
384    }
385
386    /// 谁可以添加和管理协作者-协作者维度
387    ///
388    /// 示例值:"collaborator_can_view"
389    ///
390    /// 可选值有:
391    ///
392    /// - collaborator_can_view:拥有可阅读权限的协作者
393    /// - collaborator_can_edit:拥有可编辑权限的协作者
394    /// - collaborator_full_access:拥有可管理权限(包括我)的协作者
395    pub fn manage_collaborator_entity(mut self, manage_collaborator_entity: impl ToString) -> Self {
396        self.request.manage_collaborator_entity = Some(manage_collaborator_entity.to_string());
397        self
398    }
399
400    /// 链接分享设置
401    ///
402    /// 示例值:"tenant_readable"
403    ///
404    /// 可选值有:
405    ///
406    /// tenant_readable:组织内获得链接的人可阅读
407    /// tenant_editable:组织内获得链接的人可编辑
408    /// partner_tenant_readable:关联组织的人可阅读(只有租户后台设置仅允许关联组织分享,
409    /// 才能设置为该值) partner_tenant_editable:
410    /// 关联组织的人可编辑(只有租户后台设置仅允许关联组织分享,才能设置为该值)
411    /// anyone_readable:互联网上获得链接的任何人可阅读(仅external_access_entity=“open”时有效)
412    /// anyone_editable:互联网上获得链接的任何人可编辑(仅external_access_entity=“open”时有效)
413    /// closed:关闭链接分享
414    pub fn link_share_entity(mut self, link_share_entity: impl ToString) -> Self {
415        self.request.link_share_entity = Some(link_share_entity.to_string());
416        self
417    }
418
419    /// 谁可以复制内容
420    ///
421    /// 可选值有:
422    ///
423    /// - anyone_can_view:拥有可阅读权限的用户
424    /// - anyone_can_edit:拥有可编辑权限的用户
425    /// - only_full_access:拥有可管理权限(包括我)的协作者
426    pub fn copy_entity(mut self, copy_entity: impl ToString) -> Self {
427        self.request.copy_entity = Some(copy_entity.to_string());
428        self
429    }
430
431    pub fn build(mut self) -> PatchPermissionRequest {
432        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
433        self.request
434    }
435}
436
437impl_executable_builder_owned!(
438    GetPermissionRequestBuilder,
439    PermissionsService,
440    GetPermissionRequest,
441    BaseResponse<GetPermissionResponse>,
442    get
443);
444
445impl_executable_builder_owned!(
446    PatchPermissionRequestBuilder,
447    PermissionsService,
448    PatchPermissionRequest,
449    BaseResponse<GetPermissionResponse>,
450    patch
451);
452
453#[cfg(test)]
454mod tests {
455    use super::*;
456    use crate::core::api_resp::ResponseFormat;
457    use rstest::rstest;
458
459    // === Helper Functions ===
460
461    fn create_test_config() -> Config {
462        Config::builder()
463            .app_id("test_app_id")
464            .app_secret("test_app_secret")
465            .build()
466    }
467
468    fn create_test_permission_public() -> PermissionPublic {
469        PermissionPublic {
470            external_access_entity: Some("open".to_string()),
471            security_entity: Some("anyone_can_view".to_string()),
472            comment_entity: Some("anyone_can_view".to_string()),
473            share_entity: Some("anyone".to_string()),
474            manage_collaborator_entity: Some("collaborator_can_view".to_string()),
475            link_share_entity: Some("tenant_readable".to_string()),
476            copy_entity: Some("anyone_can_view".to_string()),
477            lock_switch: Some(false),
478        }
479    }
480
481    // === Service Tests ===
482
483    #[test]
484    fn test_permissions_service_new() {
485        let config = create_test_config();
486        let service = PermissionsService::new(config);
487
488        // Service should be created successfully
489        assert!(std::ptr::addr_of!(service).is_aligned());
490    }
491
492    // === GetPermissionRequest Tests ===
493
494    #[test]
495    fn test_get_permission_request_builder_basic() {
496        let request = GetPermissionRequest::builder()
497            .token("test_token_123")
498            .r#type("doc")
499            .build();
500
501        assert_eq!(request.token, "test_token_123");
502        assert_eq!(request.r#type, "doc");
503        assert!(request.api_request.query_params.contains_key("type"));
504        assert_eq!(request.api_request.query_params.get("type").unwrap(), "doc");
505    }
506
507    #[rstest]
508    #[case("doc", "旧版文档")]
509    #[case("sheet", "电子表格")]
510    #[case("file", "云空间文件")]
511    #[case("wiki", "知识库节点")]
512    #[case("bitable", "多维表格")]
513    #[case("docx", "新版文档")]
514    #[case("mindnote", "思维笔记")]
515    #[case("minutes", "妙记")]
516    #[case("slides", "幻灯片")]
517    fn test_get_permission_request_all_file_types(
518        #[case] file_type: &str,
519        #[case] _description: &str,
520    ) {
521        let request = GetPermissionRequest::builder()
522            .token("test_token")
523            .r#type(file_type)
524            .build();
525
526        assert_eq!(request.r#type, file_type);
527        assert_eq!(
528            request.api_request.query_params.get("type").unwrap(),
529            file_type
530        );
531    }
532
533    #[test]
534    fn test_get_permission_request_builder_method_chaining() {
535        let request = GetPermissionRequest::builder()
536            .token("chain_token")
537            .r#type("sheet")
538            .build();
539
540        assert_eq!(request.token, "chain_token");
541        assert_eq!(request.r#type, "sheet");
542    }
543
544    #[test]
545    fn test_get_permission_request_default() {
546        let request = GetPermissionRequest::default();
547
548        assert_eq!(request.token, "");
549        assert_eq!(request.r#type, "");
550        assert!(request.api_request.query_params.is_empty());
551    }
552
553    #[test]
554    fn test_get_permission_request_builder_overwrite() {
555        let request = GetPermissionRequest::builder()
556            .token("first_token")
557            .r#type("doc")
558            .token("second_token") // overwrite
559            .r#type("sheet") // overwrite
560            .build();
561
562        assert_eq!(request.token, "second_token");
563        assert_eq!(request.r#type, "sheet");
564        assert_eq!(
565            request.api_request.query_params.get("type").unwrap(),
566            "sheet"
567        );
568    }
569
570    // === PatchPermissionRequest Tests ===
571
572    #[test]
573    fn test_patch_permission_request_builder_basic() {
574        let request = PatchPermissionRequest::builder()
575            .token("patch_token")
576            .r#type("docx")
577            .external_access_entity("open")
578            .build();
579
580        assert_eq!(request.token, "patch_token");
581        assert_eq!(request.external_access_entity, Some("open".to_string()));
582        assert!(request.api_request.query_params.contains_key("type"));
583        assert_eq!(
584            request.api_request.query_params.get("type").unwrap(),
585            "docx"
586        );
587    }
588
589    #[test]
590    fn test_patch_permission_request_all_entities() {
591        let request = PatchPermissionRequest::builder()
592            .token("full_patch_token")
593            .r#type("doc")
594            .external_access_entity("open")
595            .security_entity("anyone_can_view")
596            .comment_entity("anyone_can_edit")
597            .share_entity("same_tenant")
598            .manage_collaborator_entity("collaborator_can_edit")
599            .link_share_entity("tenant_editable")
600            .copy_entity("only_full_access")
601            .build();
602
603        assert_eq!(request.token, "full_patch_token");
604        assert_eq!(request.external_access_entity, Some("open".to_string()));
605        assert_eq!(request.security_entity, Some("anyone_can_view".to_string()));
606        assert_eq!(request.comment_entity, Some("anyone_can_edit".to_string()));
607        assert_eq!(request.share_entity, Some("same_tenant".to_string()));
608        assert_eq!(
609            request.manage_collaborator_entity,
610            Some("collaborator_can_edit".to_string())
611        );
612        assert_eq!(
613            request.link_share_entity,
614            Some("tenant_editable".to_string())
615        );
616        assert_eq!(request.copy_entity, Some("only_full_access".to_string()));
617    }
618
619    #[rstest]
620    #[case("open", "打开")]
621    #[case("closed", "关闭")]
622    #[case("allow_share_partner_tenant", "允许分享给关联组织")]
623    fn test_patch_external_access_entity_values(#[case] value: &str, #[case] _description: &str) {
624        let request = PatchPermissionRequest::builder()
625            .token("test")
626            .external_access_entity(value)
627            .build();
628
629        assert_eq!(request.external_access_entity, Some(value.to_string()));
630    }
631
632    #[rstest]
633    #[case("anyone_can_view", "拥有可阅读权限的用户")]
634    #[case("anyone_can_edit", "拥有可编辑权限的用户")]
635    #[case("only_full_access", "拥有可管理权限的用户")]
636    fn test_patch_security_entity_values(#[case] value: &str, #[case] _description: &str) {
637        let request = PatchPermissionRequest::builder()
638            .token("test")
639            .security_entity(value)
640            .build();
641
642        assert_eq!(request.security_entity, Some(value.to_string()));
643    }
644
645    #[rstest]
646    #[case("anyone_can_view", "拥有可阅读权限的用户")]
647    #[case("anyone_can_edit", "拥有可编辑权限的用户")]
648    fn test_patch_comment_entity_values(#[case] value: &str, #[case] _description: &str) {
649        let request = PatchPermissionRequest::builder()
650            .token("test")
651            .comment_entity(value)
652            .build();
653
654        assert_eq!(request.comment_entity, Some(value.to_string()));
655    }
656
657    #[rstest]
658    #[case("anyone", "所有可阅读或编辑此文档的用户")]
659    #[case("same_tenant", "组织内所有可阅读或编辑此文档的用户")]
660    fn test_patch_share_entity_values(#[case] value: &str, #[case] _description: &str) {
661        let request = PatchPermissionRequest::builder()
662            .token("test")
663            .share_entity(value)
664            .build();
665
666        assert_eq!(request.share_entity, Some(value.to_string()));
667    }
668
669    #[rstest]
670    #[case("collaborator_can_view", "拥有可阅读权限的协作者")]
671    #[case("collaborator_can_edit", "拥有可编辑权限的协作者")]
672    #[case("collaborator_full_access", "拥有可管理权限的协作者")]
673    fn test_patch_manage_collaborator_entity_values(
674        #[case] value: &str,
675        #[case] _description: &str,
676    ) {
677        let request = PatchPermissionRequest::builder()
678            .token("test")
679            .manage_collaborator_entity(value)
680            .build();
681
682        assert_eq!(request.manage_collaborator_entity, Some(value.to_string()));
683    }
684
685    #[rstest]
686    #[case("tenant_readable", "组织内获得链接的人可阅读")]
687    #[case("tenant_editable", "组织内获得链接的人可编辑")]
688    #[case("partner_tenant_readable", "关联组织的人可阅读")]
689    #[case("partner_tenant_editable", "关联组织的人可编辑")]
690    #[case("anyone_readable", "互联网上获得链接的任何人可阅读")]
691    #[case("anyone_editable", "互联网上获得链接的任何人可编辑")]
692    #[case("closed", "关闭链接分享")]
693    fn test_patch_link_share_entity_values(#[case] value: &str, #[case] _description: &str) {
694        let request = PatchPermissionRequest::builder()
695            .token("test")
696            .link_share_entity(value)
697            .build();
698
699        assert_eq!(request.link_share_entity, Some(value.to_string()));
700    }
701
702    #[test]
703    fn test_patch_permission_request_default() {
704        let request = PatchPermissionRequest::default();
705
706        assert_eq!(request.token, "");
707        assert_eq!(request.external_access_entity, None);
708        assert_eq!(request.security_entity, None);
709        assert_eq!(request.comment_entity, None);
710        assert_eq!(request.share_entity, None);
711        assert_eq!(request.manage_collaborator_entity, None);
712        assert_eq!(request.link_share_entity, None);
713        assert_eq!(request.copy_entity, None);
714    }
715
716    #[test]
717    fn test_patch_permission_request_partial_update() {
718        let request = PatchPermissionRequest::builder()
719            .token("partial_token")
720            .external_access_entity("closed")
721            .security_entity("only_full_access")
722            // Intentionally skip other fields
723            .build();
724
725        assert_eq!(request.token, "partial_token");
726        assert_eq!(request.external_access_entity, Some("closed".to_string()));
727        assert_eq!(
728            request.security_entity,
729            Some("only_full_access".to_string())
730        );
731        assert_eq!(request.comment_entity, None);
732        assert_eq!(request.share_entity, None);
733        assert_eq!(request.manage_collaborator_entity, None);
734        assert_eq!(request.link_share_entity, None);
735        assert_eq!(request.copy_entity, None);
736    }
737
738    // === Response Structure Tests ===
739
740    #[test]
741    fn test_get_permission_response_api_trait() {
742        let format = GetPermissionResponse::data_format();
743        assert_eq!(format, ResponseFormat::Data);
744    }
745
746    #[test]
747    fn test_permission_public_creation() {
748        let permission = create_test_permission_public();
749
750        assert_eq!(permission.external_access_entity, Some("open".to_string()));
751        assert_eq!(
752            permission.security_entity,
753            Some("anyone_can_view".to_string())
754        );
755        assert_eq!(
756            permission.comment_entity,
757            Some("anyone_can_view".to_string())
758        );
759        assert_eq!(permission.share_entity, Some("anyone".to_string()));
760        assert_eq!(
761            permission.manage_collaborator_entity,
762            Some("collaborator_can_view".to_string())
763        );
764        assert_eq!(
765            permission.link_share_entity,
766            Some("tenant_readable".to_string())
767        );
768        assert_eq!(permission.copy_entity, Some("anyone_can_view".to_string()));
769        assert_eq!(permission.lock_switch, Some(false));
770    }
771
772    #[test]
773    fn test_permission_public_optional_fields() {
774        let permission = PermissionPublic {
775            external_access_entity: None,
776            security_entity: None,
777            comment_entity: None,
778            share_entity: None,
779            manage_collaborator_entity: None,
780            link_share_entity: None,
781            copy_entity: None,
782            lock_switch: None,
783        };
784
785        assert_eq!(permission.external_access_entity, None);
786        assert_eq!(permission.security_entity, None);
787        assert_eq!(permission.comment_entity, None);
788        assert_eq!(permission.share_entity, None);
789        assert_eq!(permission.manage_collaborator_entity, None);
790        assert_eq!(permission.link_share_entity, None);
791        assert_eq!(permission.copy_entity, None);
792        assert_eq!(permission.lock_switch, None);
793    }
794
795    #[test]
796    fn test_get_permission_response_creation() {
797        let permission_public = create_test_permission_public();
798        let response = GetPermissionResponse { permission_public };
799
800        assert_eq!(
801            response.permission_public.external_access_entity,
802            Some("open".to_string())
803        );
804        assert_eq!(response.permission_public.lock_switch, Some(false));
805    }
806
807    // === Serialization Tests ===
808
809    #[test]
810    fn test_patch_permission_request_serialization() {
811        let request = PatchPermissionRequest::builder()
812            .token("ser_token")
813            .external_access_entity("open")
814            .security_entity("anyone_can_view")
815            .build();
816
817        let json = serde_json::to_string(&request).unwrap();
818        assert!(json.contains("\"external_access_entity\":\"open\""));
819        assert!(json.contains("\"security_entity\":\"anyone_can_view\""));
820        // Should not contain token (it's skipped)
821        assert!(!json.contains("ser_token"));
822    }
823
824    #[test]
825    fn test_patch_permission_request_serialization_skip_none() {
826        let request = PatchPermissionRequest::builder()
827            .token("skip_token")
828            .external_access_entity("closed")
829            // Other fields are None and should be skipped
830            .build();
831
832        let json = serde_json::to_string(&request).unwrap();
833        assert!(json.contains("\"external_access_entity\":\"closed\""));
834        assert!(!json.contains("security_entity"));
835        assert!(!json.contains("comment_entity"));
836        assert!(!json.contains("share_entity"));
837    }
838
839    #[test]
840    fn test_get_permission_response_deserialization() {
841        let json = r#"{
842            "permission_public": {
843                "external_access_entity": "open",
844                "security_entity": "anyone_can_view",
845                "comment_entity": "anyone_can_edit",
846                "share_entity": "same_tenant",
847                "manage_collaborator_entity": "collaborator_can_view",
848                "link_share_entity": "tenant_readable",
849                "copy_entity": "only_full_access",
850                "lock_switch": true
851            }
852        }"#;
853
854        let response: GetPermissionResponse = serde_json::from_str(json).unwrap();
855
856        assert_eq!(
857            response.permission_public.external_access_entity,
858            Some("open".to_string())
859        );
860        assert_eq!(
861            response.permission_public.security_entity,
862            Some("anyone_can_view".to_string())
863        );
864        assert_eq!(
865            response.permission_public.comment_entity,
866            Some("anyone_can_edit".to_string())
867        );
868        assert_eq!(
869            response.permission_public.share_entity,
870            Some("same_tenant".to_string())
871        );
872        assert_eq!(
873            response.permission_public.manage_collaborator_entity,
874            Some("collaborator_can_view".to_string())
875        );
876        assert_eq!(
877            response.permission_public.link_share_entity,
878            Some("tenant_readable".to_string())
879        );
880        assert_eq!(
881            response.permission_public.copy_entity,
882            Some("only_full_access".to_string())
883        );
884        assert_eq!(response.permission_public.lock_switch, Some(true));
885    }
886
887    #[test]
888    fn test_permission_public_deserialization_partial() {
889        let json = r#"{
890            "external_access_entity": "closed",
891            "lock_switch": false
892        }"#;
893
894        let permission: PermissionPublic = serde_json::from_str(json).unwrap();
895
896        assert_eq!(
897            permission.external_access_entity,
898            Some("closed".to_string())
899        );
900        assert_eq!(permission.lock_switch, Some(false));
901        assert_eq!(permission.security_entity, None);
902        assert_eq!(permission.comment_entity, None);
903        assert_eq!(permission.share_entity, None);
904    }
905
906    // === Edge Case Tests ===
907
908    #[test]
909    fn test_get_permission_request_unicode_token() {
910        let unicode_token = "测试令牌_🔑_token";
911        let request = GetPermissionRequest::builder()
912            .token(unicode_token)
913            .r#type("doc")
914            .build();
915
916        assert_eq!(request.token, unicode_token);
917    }
918
919    #[test]
920    fn test_patch_permission_request_unicode_values() {
921        let request = PatchPermissionRequest::builder()
922            .token("unicode_test")
923            .external_access_entity("测试值")
924            .security_entity("权限值")
925            .build();
926
927        assert_eq!(request.external_access_entity, Some("测试值".to_string()));
928        assert_eq!(request.security_entity, Some("权限值".to_string()));
929    }
930
931    #[test]
932    fn test_get_permission_request_empty_values() {
933        let request = GetPermissionRequest::builder().token("").r#type("").build();
934
935        assert_eq!(request.token, "");
936        assert_eq!(request.r#type, "");
937        assert_eq!(request.api_request.query_params.get("type").unwrap(), "");
938    }
939
940    #[test]
941    fn test_patch_permission_request_empty_values() {
942        let request = PatchPermissionRequest::builder()
943            .token("")
944            .external_access_entity("")
945            .security_entity("")
946            .build();
947
948        assert_eq!(request.token, "");
949        assert_eq!(request.external_access_entity, Some("".to_string()));
950        assert_eq!(request.security_entity, Some("".to_string()));
951    }
952
953    #[test]
954    fn test_long_token_handling() {
955        let long_token = "a".repeat(1000);
956        let request = GetPermissionRequest::builder()
957            .token(&long_token)
958            .r#type("doc")
959            .build();
960
961        assert_eq!(request.token, long_token);
962    }
963
964    #[test]
965    fn test_special_characters_in_token() {
966        let special_token = "token-with_special.chars@123#";
967        let request = PatchPermissionRequest::builder()
968            .token(special_token)
969            .external_access_entity("open")
970            .build();
971
972        assert_eq!(request.token, special_token);
973    }
974
975    // === Debug Tests ===
976
977    #[test]
978    fn test_debug_implementations() {
979        let get_request = GetPermissionRequest::builder()
980            .token("debug_test")
981            .r#type("doc")
982            .build();
983
984        let patch_request = PatchPermissionRequest::builder()
985            .token("debug_patch")
986            .external_access_entity("open")
987            .build();
988
989        let permission = create_test_permission_public();
990        let response = GetPermissionResponse {
991            permission_public: permission,
992        };
993
994        // Should not panic
995        let _debug_get = format!("{:?}", get_request);
996        let _debug_patch = format!("{:?}", patch_request);
997        let _debug_response = format!("{:?}", response);
998        let _debug_permission = format!("{:?}", response.permission_public);
999    }
1000
1001    // === Builder Pattern Tests ===
1002
1003    #[test]
1004    fn test_get_permission_builder_reuse() {
1005        let builder = GetPermissionRequest::builder()
1006            .token("reuse_test")
1007            .r#type("sheet");
1008
1009        // Build multiple requests from same builder state
1010        let request1 = builder.build();
1011
1012        assert_eq!(request1.token, "reuse_test");
1013        assert_eq!(request1.r#type, "sheet");
1014    }
1015
1016    #[test]
1017    fn test_patch_permission_builder_complex_chaining() {
1018        let request = PatchPermissionRequest::builder()
1019            .token("complex_chain")
1020            .r#type("bitable")
1021            .external_access_entity("open")
1022            .security_entity("anyone_can_view")
1023            .comment_entity("anyone_can_edit")
1024            .share_entity("anyone")
1025            .manage_collaborator_entity("collaborator_can_edit")
1026            .link_share_entity("anyone_editable")
1027            .copy_entity("anyone_can_view")
1028            .build();
1029
1030        // Verify all chained values
1031        assert_eq!(request.token, "complex_chain");
1032        assert_eq!(request.external_access_entity, Some("open".to_string()));
1033        assert_eq!(request.security_entity, Some("anyone_can_view".to_string()));
1034        assert_eq!(request.comment_entity, Some("anyone_can_edit".to_string()));
1035        assert_eq!(request.share_entity, Some("anyone".to_string()));
1036        assert_eq!(
1037            request.manage_collaborator_entity,
1038            Some("collaborator_can_edit".to_string())
1039        );
1040        assert_eq!(
1041            request.link_share_entity,
1042            Some("anyone_editable".to_string())
1043        );
1044        assert_eq!(request.copy_entity, Some("anyone_can_view".to_string()));
1045
1046        // Verify query param was set
1047        assert_eq!(
1048            request.api_request.query_params.get("type").unwrap(),
1049            "bitable"
1050        );
1051    }
1052
1053    // === Request Body Tests ===
1054
1055    #[test]
1056    fn test_patch_permission_request_body_generation() {
1057        let request = PatchPermissionRequest::builder()
1058            .token("body_test")
1059            .external_access_entity("closed")
1060            .security_entity("only_full_access")
1061            .build();
1062
1063        // Body should be populated after build()
1064        assert!(!request.api_request.body.is_empty());
1065
1066        // Parse body to verify content
1067        let body_str = String::from_utf8(request.api_request.body).unwrap();
1068        let parsed: serde_json::Value = serde_json::from_str(&body_str).unwrap();
1069
1070        assert_eq!(parsed["external_access_entity"], "closed");
1071        assert_eq!(parsed["security_entity"], "only_full_access");
1072        // Token should not be in body (serde skip)
1073        assert!(parsed.get("token").is_none());
1074    }
1075}