open_lark/service/cloud_docs/permission/public_v2/
patch.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/// 更新云文档权限设置请求 (v2)
15#[derive(Debug, Serialize, Default, Clone)]
16pub struct PatchPermissionPublicV2Request {
17    #[serde(skip)]
18    api_request: ApiRequest,
19    /// 文档token
20    #[serde(skip)]
21    token: String,
22    /// 文档类型
23    #[serde(skip)]
24    obj_type: String,
25    /// 链接分享设置
26    #[serde(skip_serializing_if = "Option::is_none")]
27    link_share_setting: Option<String>,
28    /// 是否允许复制
29    #[serde(skip_serializing_if = "Option::is_none")]
30    allow_copy: Option<bool>,
31    /// 是否允许评论
32    #[serde(skip_serializing_if = "Option::is_none")]
33    allow_comment: Option<bool>,
34    /// 是否允许保存副本
35    #[serde(skip_serializing_if = "Option::is_none")]
36    allow_save_copy: Option<bool>,
37    /// 水印设置
38    #[serde(skip_serializing_if = "Option::is_none")]
39    watermark_setting: Option<String>,
40    /// 是否允许分享到组织外
41    #[serde(skip_serializing_if = "Option::is_none")]
42    allow_share_partner_tenant: Option<bool>,
43    /// 访问权限设置
44    #[serde(skip_serializing_if = "Option::is_none")]
45    access_setting: Option<String>,
46    /// 分享范围设置
47    #[serde(skip_serializing_if = "Option::is_none")]
48    share_scope: Option<String>,
49    /// 过期时间 (Unix时间戳)
50    #[serde(skip_serializing_if = "Option::is_none")]
51    expire_time: Option<i64>,
52}
53
54impl PatchPermissionPublicV2Request {
55    pub fn builder() -> PatchPermissionPublicV2RequestBuilder {
56        PatchPermissionPublicV2RequestBuilder::default()
57    }
58
59    pub fn new(token: impl ToString, obj_type: impl ToString) -> Self {
60        Self {
61            token: token.to_string(),
62            obj_type: obj_type.to_string(),
63            ..Default::default()
64        }
65    }
66
67    /// 更新文档权限设置
68    pub fn for_doc(token: impl ToString) -> Self {
69        Self::new(token, "doc")
70    }
71
72    /// 更新电子表格权限设置
73    pub fn for_sheet(token: impl ToString) -> Self {
74        Self::new(token, "sheet")
75    }
76
77    /// 更新多维表格权限设置
78    pub fn for_bitable(token: impl ToString) -> Self {
79        Self::new(token, "bitable")
80    }
81
82    /// 更新知识库权限设置
83    pub fn for_wiki(token: impl ToString) -> Self {
84        Self::new(token, "wiki")
85    }
86}
87
88#[derive(Default)]
89pub struct PatchPermissionPublicV2RequestBuilder {
90    request: PatchPermissionPublicV2Request,
91}
92
93impl PatchPermissionPublicV2RequestBuilder {
94    /// 文档token
95    pub fn token(mut self, token: impl ToString) -> Self {
96        self.request.token = token.to_string();
97        self
98    }
99
100    /// 文档类型
101    pub fn obj_type(mut self, obj_type: impl ToString) -> Self {
102        self.request.obj_type = obj_type.to_string();
103        self
104    }
105
106    /// 设置为文档类型
107    pub fn as_doc(mut self) -> Self {
108        self.request.obj_type = "doc".to_string();
109        self
110    }
111
112    /// 设置为电子表格类型
113    pub fn as_sheet(mut self) -> Self {
114        self.request.obj_type = "sheet".to_string();
115        self
116    }
117
118    /// 设置为多维表格类型
119    pub fn as_bitable(mut self) -> Self {
120        self.request.obj_type = "bitable".to_string();
121        self
122    }
123
124    /// 设置为知识库类型
125    pub fn as_wiki(mut self) -> Self {
126        self.request.obj_type = "wiki".to_string();
127        self
128    }
129
130    /// 设置链接分享设置
131    pub fn link_share_setting(mut self, setting: impl ToString) -> Self {
132        self.request.link_share_setting = Some(setting.to_string());
133        self
134    }
135
136    /// 关闭分享
137    pub fn close_sharing(mut self) -> Self {
138        self.request.link_share_setting = Some("closed".to_string());
139        self
140    }
141
142    /// 组织内可读
143    pub fn tenant_readable(mut self) -> Self {
144        self.request.link_share_setting = Some("tenant_readable".to_string());
145        self
146    }
147
148    /// 组织内可编辑
149    pub fn tenant_editable(mut self) -> Self {
150        self.request.link_share_setting = Some("tenant_editable".to_string());
151        self
152    }
153
154    /// 任何人可读
155    pub fn anyone_readable(mut self) -> Self {
156        self.request.link_share_setting = Some("anyone_readable".to_string());
157        self
158    }
159
160    /// 任何人可编辑
161    pub fn anyone_editable(mut self) -> Self {
162        self.request.link_share_setting = Some("anyone_editable".to_string());
163        self
164    }
165
166    /// 是否允许复制
167    pub fn allow_copy(mut self, allow: bool) -> Self {
168        self.request.allow_copy = Some(allow);
169        self
170    }
171
172    /// 允许复制
173    pub fn enable_copy(mut self) -> Self {
174        self.request.allow_copy = Some(true);
175        self
176    }
177
178    /// 禁止复制
179    pub fn disable_copy(mut self) -> Self {
180        self.request.allow_copy = Some(false);
181        self
182    }
183
184    /// 是否允许评论
185    pub fn allow_comment(mut self, allow: bool) -> Self {
186        self.request.allow_comment = Some(allow);
187        self
188    }
189
190    /// 允许评论
191    pub fn enable_comment(mut self) -> Self {
192        self.request.allow_comment = Some(true);
193        self
194    }
195
196    /// 禁止评论
197    pub fn disable_comment(mut self) -> Self {
198        self.request.allow_comment = Some(false);
199        self
200    }
201
202    /// 是否允许保存副本
203    pub fn allow_save_copy(mut self, allow: bool) -> Self {
204        self.request.allow_save_copy = Some(allow);
205        self
206    }
207
208    /// 允许保存副本
209    pub fn enable_save_copy(mut self) -> Self {
210        self.request.allow_save_copy = Some(true);
211        self
212    }
213
214    /// 禁止保存副本
215    pub fn disable_save_copy(mut self) -> Self {
216        self.request.allow_save_copy = Some(false);
217        self
218    }
219
220    /// 水印设置
221    pub fn watermark_setting(mut self, setting: impl ToString) -> Self {
222        self.request.watermark_setting = Some(setting.to_string());
223        self
224    }
225
226    /// 开启水印
227    pub fn enable_watermark(mut self) -> Self {
228        self.request.watermark_setting = Some("visible".to_string());
229        self
230    }
231
232    /// 关闭水印
233    pub fn disable_watermark(mut self) -> Self {
234        self.request.watermark_setting = Some("none".to_string());
235        self
236    }
237
238    /// 是否允许分享到组织外
239    pub fn allow_share_partner_tenant(mut self, allow: bool) -> Self {
240        self.request.allow_share_partner_tenant = Some(allow);
241        self
242    }
243
244    /// 允许组织外分享
245    pub fn enable_external_share(mut self) -> Self {
246        self.request.allow_share_partner_tenant = Some(true);
247        self
248    }
249
250    /// 禁止组织外分享
251    pub fn disable_external_share(mut self) -> Self {
252        self.request.allow_share_partner_tenant = Some(false);
253        self
254    }
255
256    /// 访问权限设置
257    pub fn access_setting(mut self, setting: impl ToString) -> Self {
258        self.request.access_setting = Some(setting.to_string());
259        self
260    }
261
262    /// 分享范围设置
263    pub fn share_scope(mut self, scope: impl ToString) -> Self {
264        self.request.share_scope = Some(scope.to_string());
265        self
266    }
267
268    /// 设置过期时间 (Unix时间戳)
269    pub fn expire_time(mut self, timestamp: i64) -> Self {
270        self.request.expire_time = Some(timestamp);
271        self
272    }
273
274    /// 设置过期时间 (从现在开始的秒数)
275    pub fn expire_after_seconds(mut self, seconds: i64) -> Self {
276        let expire_time = chrono::Utc::now().timestamp() + seconds;
277        self.request.expire_time = Some(expire_time);
278        self
279    }
280
281    /// 设置过期时间 (从现在开始的小时数)
282    pub fn expire_after_hours(self, hours: i64) -> Self {
283        self.expire_after_seconds(hours * 3600)
284    }
285
286    /// 设置过期时间 (从现在开始的天数)
287    pub fn expire_after_days(self, days: i64) -> Self {
288        self.expire_after_seconds(days * 86400)
289    }
290
291    /// 移除过期时间 (永久有效)
292    pub fn never_expire(mut self) -> Self {
293        self.request.expire_time = Some(0); // 0表示永久有效
294        self
295    }
296
297    /// 设置为企业级安全模式
298    pub fn enterprise_secure_mode(mut self) -> Self {
299        self.request.link_share_setting = Some("tenant_readable".to_string());
300        self.request.allow_copy = Some(false);
301        self.request.allow_comment = Some(false);
302        self.request.allow_save_copy = Some(false);
303        self.request.watermark_setting = Some("visible".to_string());
304        self.request.allow_share_partner_tenant = Some(false);
305        self
306    }
307
308    /// 设置为协作模式
309    pub fn collaboration_mode(mut self) -> Self {
310        self.request.link_share_setting = Some("tenant_editable".to_string());
311        self.request.allow_copy = Some(true);
312        self.request.allow_comment = Some(true);
313        self.request.allow_save_copy = Some(true);
314        self.request.watermark_setting = Some("none".to_string());
315        self.request.allow_share_partner_tenant = Some(false);
316        self
317    }
318
319    /// 设置为公开分享模式
320    pub fn public_share_mode(mut self) -> Self {
321        self.request.link_share_setting = Some("anyone_readable".to_string());
322        self.request.allow_copy = Some(false);
323        self.request.allow_comment = Some(true);
324        self.request.allow_save_copy = Some(false);
325        self.request.watermark_setting = Some("visible".to_string());
326        self.request.allow_share_partner_tenant = Some(true);
327        self
328    }
329
330    /// 设置为开放编辑模式
331    pub fn open_edit_mode(mut self) -> Self {
332        self.request.link_share_setting = Some("anyone_editable".to_string());
333        self.request.allow_copy = Some(true);
334        self.request.allow_comment = Some(true);
335        self.request.allow_save_copy = Some(true);
336        self.request.watermark_setting = Some("none".to_string());
337        self.request.allow_share_partner_tenant = Some(true);
338        self
339    }
340
341    pub fn build(mut self) -> PatchPermissionPublicV2Request {
342        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
343        self.request
344    }
345}
346
347crate::impl_executable_builder_owned!(
348    PatchPermissionPublicV2RequestBuilder,
349    crate::service::cloud_docs::permission::PermissionService,
350    PatchPermissionPublicV2Request,
351    BaseResponse<PatchPermissionPublicV2Response>,
352    patch_permission_public_v2
353);
354
355/// 权限更新结果 (v2)
356#[derive(Debug, Deserialize)]
357pub struct PermissionUpdateResultV2 {
358    /// 链接分享设置
359    pub link_share_setting: Option<String>,
360    /// 是否允许复制
361    pub allow_copy: Option<bool>,
362    /// 是否允许评论
363    pub allow_comment: Option<bool>,
364    /// 是否允许保存副本
365    pub allow_save_copy: Option<bool>,
366    /// 水印设置
367    pub watermark_setting: Option<String>,
368    /// 是否允许分享到组织外
369    pub allow_share_partner_tenant: Option<bool>,
370    /// 访问权限设置
371    pub access_setting: Option<String>,
372    /// 分享范围设置
373    pub share_scope: Option<String>,
374    /// 过期时间
375    pub expire_time: Option<i64>,
376    /// 更新时间
377    pub update_time: Option<i64>,
378}
379
380/// 更新云文档权限设置响应 (v2)
381#[derive(Debug, Deserialize)]
382pub struct PatchPermissionPublicV2Response {
383    /// 更新后的权限设置
384    pub permission_public: PermissionUpdateResultV2,
385}
386
387impl ApiResponseTrait for PatchPermissionPublicV2Response {
388    fn data_format() -> ResponseFormat {
389        ResponseFormat::Data
390    }
391}
392
393/// 更新云文档权限设置 (v2)
394pub async fn patch_permission_public_v2(
395    request: PatchPermissionPublicV2Request,
396    config: &Config,
397    option: Option<RequestOption>,
398) -> SDKResult<BaseResponse<PatchPermissionPublicV2Response>> {
399    let mut api_req = request.api_request;
400    api_req.http_method = Method::PATCH;
401    api_req.api_path = format!(
402        "/open-apis/drive/v2/permissions/{}/public?type={}",
403        request.token, request.obj_type
404    );
405
406    api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
407
408    let api_resp = Transport::request(api_req, config, option).await?;
409    Ok(api_resp)
410}
411
412impl PermissionUpdateResultV2 {
413    /// 获取分享级别描述
414    pub fn share_level_description(&self) -> Option<&'static str> {
415        self.link_share_setting
416            .as_ref()
417            .map(|setting| match setting.as_str() {
418                "closed" => "关闭分享",
419                "tenant_readable" => "组织内可读",
420                "tenant_editable" => "组织内可编辑",
421                "anyone_readable" => "任何人可读",
422                "anyone_editable" => "任何人可编辑",
423                _ => "未知设置",
424            })
425    }
426
427    /// 是否有更新时间
428    pub fn has_update_time(&self) -> bool {
429        self.update_time.is_some()
430    }
431
432    /// 是否有过期时间
433    pub fn has_expire_time(&self) -> bool {
434        self.expire_time.is_some()
435    }
436
437    /// 获取更新时间格式化字符串
438    pub fn update_time_formatted(&self) -> Option<String> {
439        self.update_time
440            .map(|timestamp| format!("更新时间: {timestamp}"))
441    }
442
443    /// 获取过期时间格式化字符串
444    pub fn expire_time_formatted(&self) -> Option<String> {
445        self.expire_time.map(|timestamp| {
446            if timestamp == 0 {
447                "永久有效".to_string()
448            } else {
449                let datetime =
450                    chrono::DateTime::from_timestamp(timestamp, 0).unwrap_or_else(chrono::Utc::now);
451                format!("过期时间: {}", datetime.format("%Y-%m-%d %H:%M:%S"))
452            }
453        })
454    }
455
456    /// 获取权限变更摘要
457    pub fn changes_summary(&self) -> Vec<String> {
458        let mut changes = Vec::new();
459
460        if let Some(ref setting) = self.link_share_setting {
461            changes.push(format!(
462                "分享设置: {}",
463                match setting.as_str() {
464                    "closed" => "关闭分享",
465                    "tenant_readable" => "组织内可读",
466                    "tenant_editable" => "组织内可编辑",
467                    "anyone_readable" => "任何人可读",
468                    "anyone_editable" => "任何人可编辑",
469                    _ => setting,
470                }
471            ));
472        }
473
474        if let Some(allow_copy) = self.allow_copy {
475            changes.push(format!(
476                "复制权限: {}",
477                if allow_copy { "允许" } else { "禁止" }
478            ));
479        }
480
481        if let Some(allow_comment) = self.allow_comment {
482            changes.push(format!(
483                "评论权限: {}",
484                if allow_comment { "允许" } else { "禁止" }
485            ));
486        }
487
488        if let Some(allow_save_copy) = self.allow_save_copy {
489            changes.push(format!(
490                "保存副本: {}",
491                if allow_save_copy { "允许" } else { "禁止" }
492            ));
493        }
494
495        if let Some(ref watermark) = self.watermark_setting {
496            changes.push(format!(
497                "水印设置: {}",
498                match watermark.as_str() {
499                    "visible" => "显示水印",
500                    "none" => "无水印",
501                    _ => watermark,
502                }
503            ));
504        }
505
506        if let Some(allow_external) = self.allow_share_partner_tenant {
507            changes.push(format!(
508                "组织外分享: {}",
509                if allow_external { "允许" } else { "禁止" }
510            ));
511        }
512
513        if let Some(ref access) = self.access_setting {
514            changes.push(format!("访问设置: {access}"));
515        }
516
517        if let Some(ref scope) = self.share_scope {
518            changes.push(format!("分享范围: {scope}"));
519        }
520
521        if let Some(expire_time) = self.expire_time {
522            if expire_time == 0 {
523                changes.push("过期设置: 永久有效".to_string());
524            } else {
525                let datetime = chrono::DateTime::from_timestamp(expire_time, 0)
526                    .unwrap_or_else(chrono::Utc::now);
527                changes.push(format!(
528                    "过期设置: {}",
529                    datetime.format("%Y-%m-%d %H:%M:%S")
530                ));
531            }
532        }
533
534        changes
535    }
536
537    /// 计算安全级别
538    pub fn security_level(&self) -> &'static str {
539        if let Some(ref setting) = self.link_share_setting {
540            match setting.as_str() {
541                "closed" => "最安全",
542                "tenant_readable" => {
543                    if self.allow_share_partner_tenant == Some(false) {
544                        "较安全"
545                    } else {
546                        "中等安全"
547                    }
548                }
549                "tenant_editable" => "中等安全",
550                "anyone_readable" => "较低安全",
551                "anyone_editable" => "低安全",
552                _ => "未知",
553            }
554        } else {
555            "未变更"
556        }
557    }
558
559    /// 获取高级功能变更
560    pub fn advanced_changes(&self) -> Vec<String> {
561        let mut changes = Vec::new();
562
563        if self.access_setting.is_some() {
564            changes.push("访问权限配置已更新".to_string());
565        }
566
567        if self.share_scope.is_some() {
568            changes.push("分享范围已调整".to_string());
569        }
570
571        if self.allow_share_partner_tenant.is_some() {
572            changes.push("组织外分享权限已变更".to_string());
573        }
574
575        if self.expire_time.is_some() {
576            changes.push("过期时间已设置".to_string());
577        }
578
579        changes
580    }
581}
582
583impl PatchPermissionPublicV2Response {
584    /// 获取更新结果
585    pub fn update_result(&self) -> &PermissionUpdateResultV2 {
586        &self.permission_public
587    }
588
589    /// 是否更新成功
590    pub fn is_updated(&self) -> bool {
591        // 如果有任何字段有值,说明更新成功
592        self.permission_public.link_share_setting.is_some()
593            || self.permission_public.allow_copy.is_some()
594            || self.permission_public.allow_comment.is_some()
595            || self.permission_public.allow_save_copy.is_some()
596            || self.permission_public.watermark_setting.is_some()
597            || self.permission_public.allow_share_partner_tenant.is_some()
598            || self.permission_public.access_setting.is_some()
599            || self.permission_public.share_scope.is_some()
600            || self.permission_public.expire_time.is_some()
601    }
602
603    /// 获取更新摘要
604    pub fn update_summary(&self) -> String {
605        let changes = self.permission_public.changes_summary();
606        if changes.is_empty() {
607            "权限设置无变更".to_string()
608        } else {
609            format!("权限设置已更新: {}", changes.join(", "))
610        }
611    }
612
613    /// 获取安全性评估
614    pub fn security_assessment(&self) -> String {
615        format!(
616            "安全级别: {} - {}",
617            self.permission_public.security_level(),
618            self.get_security_tips()
619        )
620    }
621
622    /// 获取安全建议
623    fn get_security_tips(&self) -> &'static str {
624        if let Some(ref setting) = self.permission_public.link_share_setting {
625            match setting.as_str() {
626                "closed" => "文档仅限邀请用户访问,安全性最高",
627                "tenant_readable" => {
628                    if self.permission_public.allow_share_partner_tenant == Some(false) {
629                        "组织内用户可查看,适合内部分享"
630                    } else {
631                        "允许组织外分享,注意内容安全"
632                    }
633                }
634                "tenant_editable" => "组织内用户可编辑,注意权限管控",
635                "anyone_readable" => "任何人可查看,建议开启密码保护",
636                "anyone_editable" => "任何人可编辑,存在较高安全风险",
637                _ => "权限设置需要进一步确认",
638            }
639        } else {
640            "权限设置保持原有配置"
641        }
642    }
643
644    /// 获取操作建议
645    pub fn operation_recommendations(&self) -> Vec<String> {
646        let mut recommendations = Vec::new();
647
648        if let Some(ref setting) = self.permission_public.link_share_setting {
649            if setting == "anyone_editable" || setting == "anyone_readable" {
650                recommendations.push("建议设置密码保护".to_string());
651
652                if self.permission_public.allow_copy == Some(true) {
653                    recommendations.push("建议禁止复制以防止内容泄露".to_string());
654                }
655
656                if self.permission_public.watermark_setting != Some("visible".to_string()) {
657                    recommendations.push("建议开启水印以标识来源".to_string());
658                }
659            }
660        }
661
662        if self.permission_public.allow_share_partner_tenant == Some(true) {
663            recommendations.push("已开启组织外分享,请确保内容合规".to_string());
664        }
665
666        if let Some(expire_time) = self.permission_public.expire_time {
667            if expire_time > 0 {
668                let remaining = expire_time - chrono::Utc::now().timestamp();
669                if remaining < 86400 {
670                    recommendations.push("分享即将过期,请注意及时续期".to_string());
671                }
672            }
673        }
674
675        let advanced_changes = self.permission_public.advanced_changes();
676        if !advanced_changes.is_empty() {
677            recommendations.push("已应用高级配置,请验证功能是否符合预期".to_string());
678        }
679
680        if recommendations.is_empty() {
681            recommendations.push("当前权限配置合理".to_string());
682        }
683
684        recommendations
685    }
686
687    /// 获取高级功能报告
688    pub fn advanced_features_report(&self) -> String {
689        let changes = self.permission_public.advanced_changes();
690        if changes.is_empty() {
691            "未更新高级功能".to_string()
692        } else {
693            format!("高级功能更新: {}", changes.join(", "))
694        }
695    }
696
697    /// 获取过期状态报告
698    pub fn expiration_report(&self) -> Option<String> {
699        self.permission_public.expire_time_formatted()
700    }
701}
702
703#[cfg(test)]
704mod tests {
705    use super::*;
706
707    #[test]
708    fn test_patch_permission_public_v2_request_builder() {
709        let request = PatchPermissionPublicV2Request::builder()
710            .token("doccnxxxxxx")
711            .as_doc()
712            .tenant_readable()
713            .disable_copy()
714            .enable_comment()
715            .enable_watermark()
716            .disable_external_share()
717            .build();
718
719        assert_eq!(request.token, "doccnxxxxxx");
720        assert_eq!(request.obj_type, "doc");
721        assert_eq!(
722            request.link_share_setting,
723            Some("tenant_readable".to_string())
724        );
725        assert_eq!(request.allow_copy, Some(false));
726        assert_eq!(request.allow_comment, Some(true));
727        assert_eq!(request.watermark_setting, Some("visible".to_string()));
728        assert_eq!(request.allow_share_partner_tenant, Some(false));
729    }
730
731    #[test]
732    fn test_convenience_modes() {
733        let enterprise_request = PatchPermissionPublicV2Request::builder()
734            .token("doccnxxxxxx")
735            .as_doc()
736            .enterprise_secure_mode()
737            .build();
738
739        assert_eq!(
740            enterprise_request.link_share_setting,
741            Some("tenant_readable".to_string())
742        );
743        assert_eq!(enterprise_request.allow_copy, Some(false));
744        assert_eq!(enterprise_request.allow_comment, Some(false));
745        assert_eq!(enterprise_request.allow_save_copy, Some(false));
746        assert_eq!(
747            enterprise_request.watermark_setting,
748            Some("visible".to_string())
749        );
750        assert_eq!(enterprise_request.allow_share_partner_tenant, Some(false));
751
752        let public_request = PatchPermissionPublicV2Request::builder()
753            .token("doccnxxxxxx")
754            .as_doc()
755            .public_share_mode()
756            .build();
757
758        assert_eq!(
759            public_request.link_share_setting,
760            Some("anyone_readable".to_string())
761        );
762        assert_eq!(public_request.allow_copy, Some(false));
763        assert_eq!(public_request.allow_comment, Some(true));
764        assert_eq!(public_request.allow_save_copy, Some(false));
765        assert_eq!(
766            public_request.watermark_setting,
767            Some("visible".to_string())
768        );
769        assert_eq!(public_request.allow_share_partner_tenant, Some(true));
770    }
771
772    #[test]
773    fn test_expiration_settings() {
774        let request = PatchPermissionPublicV2Request::builder()
775            .token("doccnxxxxxx")
776            .as_doc()
777            .expire_after_days(7)
778            .build();
779
780        assert!(request.expire_time.is_some());
781        assert!(request.expire_time.unwrap() > chrono::Utc::now().timestamp());
782
783        let permanent_request = PatchPermissionPublicV2Request::builder()
784            .token("doccnxxxxxx")
785            .as_doc()
786            .never_expire()
787            .build();
788
789        assert_eq!(permanent_request.expire_time, Some(0));
790    }
791
792    #[test]
793    fn test_permission_update_result_v2_methods() {
794        let result = PermissionUpdateResultV2 {
795            link_share_setting: Some("tenant_editable".to_string()),
796            allow_copy: Some(false),
797            allow_comment: Some(true),
798            allow_save_copy: Some(false),
799            watermark_setting: Some("visible".to_string()),
800            allow_share_partner_tenant: Some(false),
801            access_setting: Some("advanced".to_string()),
802            share_scope: Some("limited".to_string()),
803            expire_time: Some(chrono::Utc::now().timestamp() + 86400),
804            update_time: Some(chrono::Utc::now().timestamp()),
805        };
806
807        assert_eq!(result.share_level_description(), Some("组织内可编辑"));
808        assert!(result.has_update_time());
809        assert!(result.has_expire_time());
810        assert_eq!(result.security_level(), "中等安全");
811
812        let changes = result.changes_summary();
813        assert!(!changes.is_empty());
814        assert!(changes.iter().any(|c| c.contains("组织内可编辑")));
815        assert!(changes.iter().any(|c| c.contains("复制权限: 禁止")));
816        assert!(changes.iter().any(|c| c.contains("评论权限: 允许")));
817
818        let advanced_changes = result.advanced_changes();
819        assert!(!advanced_changes.is_empty());
820        assert!(advanced_changes
821            .iter()
822            .any(|c| c.contains("访问权限配置已更新")));
823    }
824}