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,
};
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
#[derive(Default)]
pub enum Permission {
FullAccess,
Edit,
#[default]
View,
Comment,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Collaborator {
pub member_type: String,
pub member_id: String,
pub perm: Permission,
}
#[derive(Debug, Serialize, Default, Clone)]
pub struct BatchCreatePermissionMemberRequest {
#[serde(skip)]
api_request: ApiRequest,
#[serde(skip)]
token: String,
#[serde(skip)]
obj_type: String,
members: Vec<Collaborator>,
#[serde(skip_serializing_if = "Option::is_none")]
need_notification: Option<bool>,
}
impl BatchCreatePermissionMemberRequest {
pub fn builder() -> BatchCreatePermissionMemberRequestBuilder {
BatchCreatePermissionMemberRequestBuilder::default()
}
pub fn new(token: impl ToString, obj_type: impl ToString, members: Vec<Collaborator>) -> Self {
Self {
token: token.to_string(),
obj_type: obj_type.to_string(),
members,
..Default::default()
}
}
}
#[derive(Default)]
pub struct BatchCreatePermissionMemberRequestBuilder {
request: BatchCreatePermissionMemberRequest,
}
impl BatchCreatePermissionMemberRequestBuilder {
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 members(mut self, members: Vec<Collaborator>) -> Self {
self.request.members = members;
self
}
pub fn add_member(mut self, member: Collaborator) -> Self {
self.request.members.push(member);
self
}
pub fn add_user(mut self, user_id: impl ToString, permission: Permission) -> Self {
self.request.members.push(Collaborator {
member_type: "user".to_string(),
member_id: user_id.to_string(),
perm: permission,
});
self
}
pub fn add_chat(mut self, chat_id: impl ToString, permission: Permission) -> Self {
self.request.members.push(Collaborator {
member_type: "chat".to_string(),
member_id: chat_id.to_string(),
perm: permission,
});
self
}
pub fn add_department(mut self, department_id: impl ToString, permission: Permission) -> Self {
self.request.members.push(Collaborator {
member_type: "department".to_string(),
member_id: department_id.to_string(),
perm: permission,
});
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) -> BatchCreatePermissionMemberRequest {
self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
self.request
}
}
crate::impl_executable_builder_owned!(
BatchCreatePermissionMemberRequestBuilder,
crate::service::cloud_docs::permission::PermissionService,
BatchCreatePermissionMemberRequest,
BaseResponse<BatchCreatePermissionMemberResponse>,
batch_create_member
);
#[derive(Debug, Deserialize)]
pub struct MemberResult {
pub member_type: String,
pub member_id: String,
pub perm: Permission,
pub result: String,
pub code: Option<i32>,
pub msg: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct BatchCreatePermissionMemberResponse {
pub members: Vec<MemberResult>,
}
impl ApiResponseTrait for BatchCreatePermissionMemberResponse {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
pub async fn batch_create_permission_member(
request: BatchCreatePermissionMemberRequest,
config: &Config,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<BatchCreatePermissionMemberResponse>> {
let mut api_req = request.api_request;
api_req.http_method = Method::POST;
api_req.api_path = format!(
"{}?type={}",
EndpointBuilder::replace_param(
DRIVE_V1_PERMISSIONS_MEMBERS_BATCH_CREATE,
"token",
&request.token
),
request.obj_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 Permission {
pub fn level(&self) -> u8 {
match self {
Permission::View => 1,
Permission::Comment => 2,
Permission::Edit => 3,
Permission::FullAccess => 4,
}
}
pub fn can_edit(&self) -> bool {
matches!(self, Permission::Edit | Permission::FullAccess)
}
pub fn can_comment(&self) -> bool {
!matches!(self, Permission::View)
}
pub fn is_owner(&self) -> bool {
matches!(self, Permission::FullAccess)
}
pub fn description(&self) -> &'static str {
match self {
Permission::FullAccess => "所有者",
Permission::Edit => "编辑者",
Permission::Comment => "评论者",
Permission::View => "阅读者",
}
}
}
impl MemberResult {
pub fn is_success(&self) -> bool {
self.result == "success"
}
pub fn has_error(&self) -> bool {
self.code.is_some() || self.msg.is_some()
}
pub fn error_message(&self) -> Option<String> {
if let (Some(code), Some(msg)) = (self.code, &self.msg) {
Some(format!("错误码: {code}, 错误信息: {msg}"))
} else if let Some(msg) = &self.msg {
Some(msg.clone())
} else {
self.code.map(|code| format!("错误码: {code}"))
}
}
}
impl BatchCreatePermissionMemberResponse {
pub fn success_count(&self) -> usize {
self.members
.iter()
.filter(|member| member.is_success())
.count()
}
pub fn failed_count(&self) -> usize {
self.members
.iter()
.filter(|member| !member.is_success())
.count()
}
pub fn successful_members(&self) -> Vec<&MemberResult> {
self.members
.iter()
.filter(|member| member.is_success())
.collect()
}
pub fn failed_members(&self) -> Vec<&MemberResult> {
self.members
.iter()
.filter(|member| !member.is_success())
.collect()
}
pub fn summary(&self) -> String {
format!(
"总计: {}, 成功: {}, 失败: {}",
self.members.len(),
self.success_count(),
self.failed_count()
)
}
}
#[cfg(test)]
#[allow(unused_variables, unused_unsafe)]
mod tests {
use super::*;
#[test]
fn test_batch_create_permission_member_request_builder() {
let request = BatchCreatePermissionMemberRequest::builder()
.token("doccnxxxxxx")
.as_doc()
.add_user("user123", Permission::Edit)
.add_chat("chat456", Permission::View)
.with_notification()
.build();
assert_eq!(request.token, "doccnxxxxxx");
assert_eq!(request.obj_type, "doc");
assert_eq!(request.members.len(), 2);
assert_eq!(request.need_notification, Some(true));
}
#[test]
fn test_permission_methods() {
assert!(Permission::Edit.can_edit());
assert!(Permission::FullAccess.can_edit());
assert!(!Permission::View.can_edit());
assert!(Permission::Edit.can_comment());
assert!(!Permission::View.can_comment());
assert!(Permission::FullAccess.is_owner());
assert!(!Permission::Edit.is_owner());
assert_eq!(Permission::FullAccess.level(), 4);
assert_eq!(Permission::View.level(), 1);
}
}