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,
req_option::RequestOption,
SDKResult,
};
use super::batch_create::Permission;
#[derive(Debug, Serialize, Default, Clone)]
pub struct DeletePermissionMemberRequest {
#[serde(skip)]
api_request: ApiRequest,
#[serde(skip)]
token: String,
#[serde(skip)]
obj_type: String,
#[serde(skip)]
member_type: String,
#[serde(skip)]
member_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
need_notification: Option<bool>,
}
impl DeletePermissionMemberRequest {
pub fn builder() -> DeletePermissionMemberRequestBuilder {
DeletePermissionMemberRequestBuilder::default()
}
pub fn new(
token: impl ToString,
obj_type: impl ToString,
member_type: impl ToString,
member_id: impl ToString,
) -> Self {
Self {
token: token.to_string(),
obj_type: obj_type.to_string(),
member_type: member_type.to_string(),
member_id: member_id.to_string(),
..Default::default()
}
}
pub fn for_user(token: impl ToString, obj_type: impl ToString, user_id: impl ToString) -> Self {
Self::new(token, obj_type, "user", user_id)
}
pub fn for_chat(token: impl ToString, obj_type: impl ToString, chat_id: impl ToString) -> Self {
Self::new(token, obj_type, "chat", chat_id)
}
pub fn for_department(
token: impl ToString,
obj_type: impl ToString,
department_id: impl ToString,
) -> Self {
Self::new(token, obj_type, "department", department_id)
}
}
#[derive(Default)]
pub struct DeletePermissionMemberRequestBuilder {
request: DeletePermissionMemberRequest,
}
impl DeletePermissionMemberRequestBuilder {
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 member(mut self, member_type: impl ToString, member_id: impl ToString) -> Self {
self.request.member_type = member_type.to_string();
self.request.member_id = member_id.to_string();
self
}
pub fn user(mut self, user_id: impl ToString) -> Self {
self.request.member_type = "user".to_string();
self.request.member_id = user_id.to_string();
self
}
pub fn chat(mut self, chat_id: impl ToString) -> Self {
self.request.member_type = "chat".to_string();
self.request.member_id = chat_id.to_string();
self
}
pub fn department(mut self, department_id: impl ToString) -> Self {
self.request.member_type = "department".to_string();
self.request.member_id = department_id.to_string();
self
}
pub fn need_notification(mut self, need: bool) -> Self {
self.request.need_notification = Some(need);
self
}
pub fn with_notification(mut self) -> Self {
self.request.need_notification = Some(true);
self
}
pub fn without_notification(mut self) -> Self {
self.request.need_notification = Some(false);
self
}
pub fn build(mut self) -> DeletePermissionMemberRequest {
self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
self.request
}
}
#[derive(Debug, Deserialize)]
pub struct PermissionMemberDeleted {
pub member_type: String,
pub member_id: String,
pub delete_time: Option<i64>,
pub old_perm: Option<Permission>,
pub notified: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub struct DeletePermissionMemberResponse {
pub member: PermissionMemberDeleted,
}
impl ApiResponseTrait for DeletePermissionMemberResponse {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
pub async fn delete_permission_member(
request: DeletePermissionMemberRequest,
config: &Config,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<DeletePermissionMemberResponse>> {
let mut api_req = request.api_request;
api_req.http_method = Method::DELETE;
api_req.api_path = format!(
"{}?type={}&member_type={}",
EndpointBuilder::replace_params_from_array(
DRIVE_V1_PERMISSIONS_MEMBER_GET,
&[("token", &request.token), ("member_id", &request.member_id)]
),
request.obj_type,
request.member_type
);
if let Some(need_notification) = request.need_notification {
api_req.api_path = format!(
"{}&need_notification={}",
api_req.api_path, need_notification
);
}
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 PermissionMemberDeleted {
pub fn member_id(&self) -> &str {
&self.member_id
}
pub fn member_type(&self) -> &str {
&self.member_type
}
pub fn old_permission(&self) -> Option<&Permission> {
self.old_perm.as_ref()
}
pub fn is_user(&self) -> bool {
self.member_type == "user"
}
pub fn is_chat(&self) -> bool {
self.member_type == "chat"
}
pub fn is_department(&self) -> bool {
self.member_type == "department"
}
pub fn was_notified(&self) -> bool {
self.notified.unwrap_or(false)
}
pub fn has_delete_time(&self) -> bool {
self.delete_time.is_some()
}
pub fn has_old_permission(&self) -> bool {
self.old_perm.is_some()
}
pub fn was_owner(&self) -> bool {
if let Some(old_perm) = &self.old_perm {
old_perm.is_owner()
} else {
false
}
}
pub fn could_edit(&self) -> bool {
if let Some(old_perm) = &self.old_perm {
old_perm.can_edit()
} else {
false
}
}
pub fn delete_time_formatted(&self) -> Option<String> {
self.delete_time
.map(|timestamp| format!("删除时间: {timestamp}"))
}
pub fn member_type_description(&self) -> String {
match self.member_type.as_str() {
"user" => "用户".to_string(),
"chat" => "群组".to_string(),
"department" => "部门".to_string(),
_ => "未知".to_string(),
}
}
pub fn old_permission_description(&self) -> Option<String> {
self.old_perm
.as_ref()
.map(|perm| perm.description().to_string())
}
pub fn summary(&self) -> String {
let mut parts = vec![format!(
"{} ({})",
self.member_id,
self.member_type_description()
)];
if let Some(old_perm_desc) = self.old_permission_description() {
parts.push(format!("原权限: {old_perm_desc}"));
}
if let Some(time) = self.delete_time_formatted() {
parts.push(time);
}
if self.was_notified() {
parts.push("已通知".to_string());
}
parts.join(", ")
}
}
impl DeletePermissionMemberResponse {
pub fn member_id(&self) -> &str {
self.member.member_id()
}
pub fn member_type(&self) -> &str {
self.member.member_type()
}
pub fn old_permission(&self) -> Option<&Permission> {
self.member.old_permission()
}
pub fn is_deleted(&self) -> bool {
!self.member.member_id.is_empty()
}
pub fn success_summary(&self) -> String {
format!("协作者权限移除成功: {}", self.member.summary())
}
pub fn was_notified(&self) -> bool {
self.member.was_notified()
}
pub fn deleted_owner(&self) -> bool {
self.member.was_owner()
}
pub fn deleted_editor(&self) -> bool {
self.member.could_edit()
}
pub fn delete_time(&self) -> Option<i64> {
self.member.delete_time
}
pub fn risk_level(&self) -> &'static str {
if self.deleted_owner() {
"高风险" } else if self.deleted_editor() {
"中风险" } else {
"低风险" }
}
}
#[cfg(test)]
#[allow(unused_variables, unused_unsafe)]
mod tests {
use super::*;
#[test]
fn test_delete_permission_member_request_builder() {
let request = DeletePermissionMemberRequest::builder()
.token("doccnxxxxxx")
.as_doc()
.user("user123")
.with_notification()
.build();
assert_eq!(request.token, "doccnxxxxxx");
assert_eq!(request.obj_type, "doc");
assert_eq!(request.member_type, "user");
assert_eq!(request.member_id, "user123");
assert_eq!(request.need_notification, Some(true));
}
#[test]
fn test_delete_permission_member_convenience_methods() {
let request = DeletePermissionMemberRequest::for_user("doccnxxxxxx", "doc", "user123");
assert_eq!(request.member_type, "user");
assert_eq!(request.member_id, "user123");
let request = DeletePermissionMemberRequest::for_chat("doccnxxxxxx", "doc", "chat456");
assert_eq!(request.member_type, "chat");
assert_eq!(request.member_id, "chat456");
let request =
DeletePermissionMemberRequest::for_department("doccnxxxxxx", "doc", "dept789");
assert_eq!(request.member_type, "department");
assert_eq!(request.member_id, "dept789");
}
#[test]
fn test_permission_member_deleted_methods() {
let member = PermissionMemberDeleted {
member_type: "user".to_string(),
member_id: "user123".to_string(),
delete_time: Some(1234567890),
old_perm: Some(Permission::Edit),
notified: Some(true),
};
assert!(member.is_user());
assert!(!member.is_chat());
assert!(!member.is_department());
assert!(member.was_notified());
assert!(member.has_delete_time());
assert!(member.has_old_permission());
assert!(!member.was_owner());
assert!(member.could_edit());
assert_eq!(member.member_type_description(), "用户");
assert_eq!(
member.old_permission_description(),
Some("编辑者".to_string())
);
}
#[test]
fn test_delete_permission_member_response_risk_level() {
let response_owner = DeletePermissionMemberResponse {
member: PermissionMemberDeleted {
member_type: "user".to_string(),
member_id: "user123".to_string(),
delete_time: Some(1234567890),
old_perm: Some(Permission::FullAccess),
notified: Some(true),
},
};
assert_eq!(response_owner.risk_level(), "高风险");
let response_editor = DeletePermissionMemberResponse {
member: PermissionMemberDeleted {
member_type: "user".to_string(),
member_id: "user123".to_string(),
delete_time: Some(1234567890),
old_perm: Some(Permission::Edit),
notified: Some(true),
},
};
assert_eq!(response_editor.risk_level(), "中风险");
let response_viewer = DeletePermissionMemberResponse {
member: PermissionMemberDeleted {
member_type: "user".to_string(),
member_id: "user123".to_string(),
delete_time: Some(1234567890),
old_perm: Some(Permission::View),
notified: Some(true),
},
};
assert_eq!(response_viewer.risk_level(), "低风险");
}
}