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