use reqwest::Method;
use serde::{Deserialize, Serialize};
use crate::core::{
api_req::ApiRequest,
api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
config::Config,
constants::AccessTokenType,
endpoints::{cloud_docs::*, EndpointBuilder},
http::Transport,
query_params::QueryParams,
req_option::RequestOption,
SDKResult,
};
#[derive(Debug, Serialize, Default, Clone)]
pub struct PatchPermissionPublicRequest {
#[serde(skip)]
api_request: ApiRequest,
#[serde(skip)]
token: String,
#[serde(skip)]
obj_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
link_share_setting: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
allow_copy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
allow_comment: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
allow_save_copy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
watermark_setting: Option<String>,
}
impl PatchPermissionPublicRequest {
pub fn builder() -> PatchPermissionPublicRequestBuilder {
PatchPermissionPublicRequestBuilder::default()
}
pub fn new(token: impl ToString, obj_type: impl ToString) -> Self {
Self {
token: token.to_string(),
obj_type: obj_type.to_string(),
..Default::default()
}
}
pub fn for_doc(token: impl ToString) -> Self {
Self::new(token, "doc")
}
pub fn for_sheet(token: impl ToString) -> Self {
Self::new(token, "sheet")
}
pub fn for_bitable(token: impl ToString) -> Self {
Self::new(token, "bitable")
}
pub fn for_wiki(token: impl ToString) -> Self {
Self::new(token, "wiki")
}
}
#[derive(Default)]
pub struct PatchPermissionPublicRequestBuilder {
request: PatchPermissionPublicRequest,
}
impl PatchPermissionPublicRequestBuilder {
pub fn token(mut self, token: impl ToString) -> Self {
self.request.token = token.to_string();
self
}
pub fn obj_type(mut self, obj_type: impl ToString) -> Self {
self.request.obj_type = obj_type.to_string();
self
}
pub fn as_doc(mut self) -> Self {
self.request.obj_type = "doc".to_string();
self
}
pub fn as_sheet(mut self) -> Self {
self.request.obj_type = "sheet".to_string();
self
}
pub fn as_bitable(mut self) -> Self {
self.request.obj_type = "bitable".to_string();
self
}
pub fn as_wiki(mut self) -> Self {
self.request.obj_type = "wiki".to_string();
self
}
pub fn link_share_setting(mut self, setting: impl ToString) -> Self {
self.request.link_share_setting = Some(setting.to_string());
self
}
pub fn close_sharing(mut self) -> Self {
self.request.link_share_setting = Some("closed".to_string());
self
}
pub fn tenant_readable(mut self) -> Self {
self.request.link_share_setting = Some("tenant_readable".to_string());
self
}
pub fn tenant_editable(mut self) -> Self {
self.request.link_share_setting = Some("tenant_editable".to_string());
self
}
pub fn anyone_readable(mut self) -> Self {
self.request.link_share_setting = Some("anyone_readable".to_string());
self
}
pub fn anyone_editable(mut self) -> Self {
self.request.link_share_setting = Some("anyone_editable".to_string());
self
}
pub fn allow_copy(mut self, allow: bool) -> Self {
self.request.allow_copy = Some(allow);
self
}
pub fn enable_copy(mut self) -> Self {
self.request.allow_copy = Some(true);
self
}
pub fn disable_copy(mut self) -> Self {
self.request.allow_copy = Some(false);
self
}
pub fn allow_comment(mut self, allow: bool) -> Self {
self.request.allow_comment = Some(allow);
self
}
pub fn enable_comment(mut self) -> Self {
self.request.allow_comment = Some(true);
self
}
pub fn disable_comment(mut self) -> Self {
self.request.allow_comment = Some(false);
self
}
pub fn allow_save_copy(mut self, allow: bool) -> Self {
self.request.allow_save_copy = Some(allow);
self
}
pub fn enable_save_copy(mut self) -> Self {
self.request.allow_save_copy = Some(true);
self
}
pub fn disable_save_copy(mut self) -> Self {
self.request.allow_save_copy = Some(false);
self
}
pub fn watermark_setting(mut self, setting: impl ToString) -> Self {
self.request.watermark_setting = Some(setting.to_string());
self
}
pub fn enable_watermark(mut self) -> Self {
self.request.watermark_setting = Some("visible".to_string());
self
}
pub fn disable_watermark(mut self) -> Self {
self.request.watermark_setting = Some("none".to_string());
self
}
pub fn secure_mode(mut self) -> Self {
self.request.link_share_setting = Some("tenant_readable".to_string());
self.request.allow_copy = Some(false);
self.request.allow_comment = Some(false);
self.request.allow_save_copy = Some(false);
self.request.watermark_setting = Some("visible".to_string());
self
}
pub fn open_mode(mut self) -> Self {
self.request.link_share_setting = Some("anyone_editable".to_string());
self.request.allow_copy = Some(true);
self.request.allow_comment = Some(true);
self.request.allow_save_copy = Some(true);
self.request.watermark_setting = Some("none".to_string());
self
}
pub fn build(mut self) -> PatchPermissionPublicRequest {
self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
self.request
}
}
#[derive(Debug, Deserialize)]
pub struct PermissionUpdateResult {
pub link_share_setting: Option<String>,
pub allow_copy: Option<bool>,
pub allow_comment: Option<bool>,
pub allow_save_copy: Option<bool>,
pub watermark_setting: Option<String>,
pub update_time: Option<i64>,
}
#[derive(Debug, Deserialize)]
pub struct PatchPermissionPublicResponse {
pub permission_public: PermissionUpdateResult,
}
impl ApiResponseTrait for PatchPermissionPublicResponse {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
pub async fn patch_permission_public(
request: PatchPermissionPublicRequest,
config: &Config,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<PatchPermissionPublicResponse>> {
let mut api_req = request.api_request;
api_req.http_method = Method::PATCH;
api_req.api_path =
EndpointBuilder::replace_param(DRIVE_V1_PERMISSIONS_PUBLIC, "token", &request.token);
api_req
.query_params
.insert(QueryParams::TYPE, request.obj_type);
api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
let api_resp = Transport::request(api_req, config, option).await?;
Ok(api_resp)
}
impl PermissionUpdateResult {
pub fn share_level_description(&self) -> Option<&'static str> {
self.link_share_setting
.as_ref()
.map(|setting| match setting.as_str() {
"closed" => "关闭分享",
"tenant_readable" => "组织内可读",
"tenant_editable" => "组织内可编辑",
"anyone_readable" => "任何人可读",
"anyone_editable" => "任何人可编辑",
_ => "未知设置",
})
}
pub fn has_update_time(&self) -> bool {
self.update_time.is_some()
}
pub fn update_time_formatted(&self) -> Option<String> {
self.update_time
.map(|timestamp| format!("更新时间: {timestamp}"))
}
pub fn changes_summary(&self) -> Vec<String> {
let mut changes = Vec::new();
if let Some(ref setting) = self.link_share_setting {
changes.push(format!(
"分享设置: {}",
match setting.as_str() {
"closed" => "关闭分享",
"tenant_readable" => "组织内可读",
"tenant_editable" => "组织内可编辑",
"anyone_readable" => "任何人可读",
"anyone_editable" => "任何人可编辑",
_ => setting,
}
));
}
if let Some(allow_copy) = self.allow_copy {
changes.push(format!(
"复制权限: {}",
if allow_copy { "允许" } else { "禁止" }
));
}
if let Some(allow_comment) = self.allow_comment {
changes.push(format!(
"评论权限: {}",
if allow_comment { "允许" } else { "禁止" }
));
}
if let Some(allow_save_copy) = self.allow_save_copy {
changes.push(format!(
"保存副本: {}",
if allow_save_copy { "允许" } else { "禁止" }
));
}
if let Some(ref watermark) = self.watermark_setting {
changes.push(format!(
"水印设置: {}",
match watermark.as_str() {
"visible" => "显示水印",
"none" => "无水印",
_ => watermark,
}
));
}
changes
}
pub fn security_level(&self) -> &'static str {
if let Some(ref setting) = self.link_share_setting {
match setting.as_str() {
"closed" => "最安全",
"tenant_readable" => "较安全",
"tenant_editable" => "中等安全",
"anyone_readable" => "较低安全",
"anyone_editable" => "低安全",
_ => "未知",
}
} else {
"未变更"
}
}
}
impl PatchPermissionPublicResponse {
pub fn update_result(&self) -> &PermissionUpdateResult {
&self.permission_public
}
pub fn is_updated(&self) -> bool {
self.permission_public.link_share_setting.is_some()
|| self.permission_public.allow_copy.is_some()
|| self.permission_public.allow_comment.is_some()
|| self.permission_public.allow_save_copy.is_some()
|| self.permission_public.watermark_setting.is_some()
}
pub fn update_summary(&self) -> String {
let changes = self.permission_public.changes_summary();
if changes.is_empty() {
"权限设置无变更".to_string()
} else {
format!("权限设置已更新: {}", changes.join(", "))
}
}
pub fn security_assessment(&self) -> String {
format!(
"安全级别: {} - {}",
self.permission_public.security_level(),
self.get_security_tips()
)
}
fn get_security_tips(&self) -> &'static str {
if let Some(ref setting) = self.permission_public.link_share_setting {
match setting.as_str() {
"closed" => "文档仅限邀请用户访问,安全性最高",
"tenant_readable" => "组织内用户可查看,适合内部分享",
"tenant_editable" => "组织内用户可编辑,注意权限管控",
"anyone_readable" => "任何人可查看,建议开启密码保护",
"anyone_editable" => "任何人可编辑,存在安全风险",
_ => "权限设置需要进一步确认",
}
} else {
"权限设置保持原有配置"
}
}
pub fn operation_recommendations(&self) -> Vec<String> {
let mut recommendations = Vec::new();
if let Some(ref setting) = self.permission_public.link_share_setting {
if setting == "anyone_editable" || setting == "anyone_readable" {
recommendations.push("建议设置密码保护".to_string());
if self.permission_public.allow_copy == Some(true) {
recommendations.push("建议禁止复制以防止内容泄露".to_string());
}
if self.permission_public.watermark_setting != Some("visible".to_string()) {
recommendations.push("建议开启水印以标识来源".to_string());
}
}
}
if recommendations.is_empty() {
recommendations.push("当前权限配置合理".to_string());
}
recommendations
}
}
#[cfg(test)]
#[allow(unused_variables, unused_unsafe)]
mod tests {
use super::*;
#[test]
fn test_patch_permission_public_request_builder() {
let request = PatchPermissionPublicRequest::builder()
.token("doccnxxxxxx")
.as_doc()
.tenant_readable()
.disable_copy()
.enable_comment()
.enable_watermark()
.build();
assert_eq!(request.token, "doccnxxxxxx");
assert_eq!(request.obj_type, "doc");
assert_eq!(
request.link_share_setting,
Some("tenant_readable".to_string())
);
assert_eq!(request.allow_copy, Some(false));
assert_eq!(request.allow_comment, Some(true));
assert_eq!(request.watermark_setting, Some("visible".to_string()));
}
#[test]
fn test_convenience_modes() {
let secure_request = PatchPermissionPublicRequest::builder()
.token("doccnxxxxxx")
.as_doc()
.secure_mode()
.build();
assert_eq!(
secure_request.link_share_setting,
Some("tenant_readable".to_string())
);
assert_eq!(secure_request.allow_copy, Some(false));
assert_eq!(secure_request.allow_comment, Some(false));
assert_eq!(secure_request.allow_save_copy, Some(false));
assert_eq!(
secure_request.watermark_setting,
Some("visible".to_string())
);
let open_request = PatchPermissionPublicRequest::builder()
.token("doccnxxxxxx")
.as_doc()
.open_mode()
.build();
assert_eq!(
open_request.link_share_setting,
Some("anyone_editable".to_string())
);
assert_eq!(open_request.allow_copy, Some(true));
assert_eq!(open_request.allow_comment, Some(true));
assert_eq!(open_request.allow_save_copy, Some(true));
assert_eq!(open_request.watermark_setting, Some("none".to_string()));
}
#[test]
fn test_permission_update_result_methods() {
let result = PermissionUpdateResult {
link_share_setting: Some("tenant_editable".to_string()),
allow_copy: Some(false),
allow_comment: Some(true),
allow_save_copy: Some(false),
watermark_setting: Some("visible".to_string()),
update_time: Some(1234567890),
};
assert_eq!(result.share_level_description(), Some("组织内可编辑"));
assert!(result.has_update_time());
assert_eq!(result.security_level(), "中等安全");
let changes = result.changes_summary();
assert_eq!(changes.len(), 5);
assert!(changes.iter().any(|c| c.contains("组织内可编辑")));
assert!(changes.iter().any(|c| c.contains("复制权限: 禁止")));
assert!(changes.iter().any(|c| c.contains("评论权限: 允许")));
}
}