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 ListPermissionMembersRequest {
#[serde(skip)]
api_request: ApiRequest,
#[serde(skip)]
token: String,
#[serde(skip)]
obj_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
page_token: Option<String>,
}
impl ListPermissionMembersRequest {
pub fn builder() -> ListPermissionMembersRequestBuilder {
ListPermissionMembersRequestBuilder::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()
}
}
}
#[derive(Default)]
pub struct ListPermissionMembersRequestBuilder {
request: ListPermissionMembersRequest,
}
impl ListPermissionMembersRequestBuilder {
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 page_size(mut self, page_size: i32) -> Self {
self.request.page_size = Some(page_size);
self
}
pub fn page_token(mut self, page_token: impl ToString) -> Self {
self.request.page_token = Some(page_token.to_string());
self
}
pub fn build(mut self) -> ListPermissionMembersRequest {
self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
self.request
}
}
crate::impl_executable_builder_owned!(
ListPermissionMembersRequestBuilder,
crate::service::cloud_docs::permission::PermissionService,
ListPermissionMembersRequest,
BaseResponse<ListPermissionMembersResponse>,
list_members
);
#[derive(Debug, Deserialize)]
pub struct PermissionMember {
pub member_type: String,
pub member_id: String,
pub perm: Permission,
pub name: Option<String>,
pub avatar: Option<String>,
pub type_str: Option<String>,
pub is_inherited: Option<bool>,
pub inherit_info: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct ListPermissionMembersResponse {
pub members: Vec<PermissionMember>,
pub has_more: bool,
pub page_token: Option<String>,
}
impl ApiResponseTrait for ListPermissionMembersResponse {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
pub async fn list_permission_members(
request: ListPermissionMembersRequest,
config: &Config,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<ListPermissionMembersResponse>> {
let mut api_req = request.api_request;
api_req.http_method = Method::GET;
api_req.api_path = format!(
"{}?type={}",
EndpointBuilder::replace_param(DRIVE_V1_PERMISSIONS_MEMBERS, "token", &request.token),
request.obj_type
);
let mut query_params = Vec::new();
if let Some(page_size) = request.page_size {
query_params.push(format!("page_size={page_size}"));
}
if let Some(page_token) = request.page_token {
query_params.push(format!("page_token={page_token}"));
}
if !query_params.is_empty() {
api_req.api_path = format!("{}&{}", api_req.api_path, query_params.join("&"));
}
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 PermissionMember {
pub fn display_name(&self) -> String {
self.name
.as_ref()
.cloned()
.unwrap_or_else(|| self.member_id.clone())
}
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 can_edit(&self) -> bool {
self.perm.can_edit()
}
pub fn is_owner(&self) -> bool {
self.perm.is_owner()
}
pub fn has_inherited_permission(&self) -> bool {
self.is_inherited.unwrap_or(false)
}
pub fn permission_description(&self) -> String {
let mut desc = self.perm.description().to_string();
if self.has_inherited_permission() {
desc.push_str(" (继承)");
if let Some(inherit_info) = &self.inherit_info {
desc.push_str(&format!(" 来源: {inherit_info}"));
}
}
desc
}
pub fn member_type_description(&self) -> String {
self.type_str
.as_ref()
.cloned()
.unwrap_or_else(|| match self.member_type.as_str() {
"user" => "用户".to_string(),
"chat" => "群组".to_string(),
"department" => "部门".to_string(),
_ => "未知".to_string(),
})
}
pub fn summary(&self) -> String {
format!(
"{} ({}) - {} - {}",
self.display_name(),
self.member_id,
self.member_type_description(),
self.permission_description()
)
}
}
impl ListPermissionMembersResponse {
pub fn count(&self) -> usize {
self.members.len()
}
pub fn is_empty(&self) -> bool {
self.members.is_empty()
}
pub fn owners(&self) -> Vec<&PermissionMember> {
self.members
.iter()
.filter(|member| member.is_owner())
.collect()
}
pub fn editors(&self) -> Vec<&PermissionMember> {
self.members
.iter()
.filter(|member| matches!(member.perm, Permission::Edit))
.collect()
}
pub fn commenters(&self) -> Vec<&PermissionMember> {
self.members
.iter()
.filter(|member| matches!(member.perm, Permission::Comment))
.collect()
}
pub fn viewers(&self) -> Vec<&PermissionMember> {
self.members
.iter()
.filter(|member| matches!(member.perm, Permission::View))
.collect()
}
pub fn group_by_permission(&self) -> std::collections::HashMap<String, Vec<&PermissionMember>> {
let mut groups = std::collections::HashMap::new();
for member in &self.members {
let perm_key = member.perm.description().to_string();
groups.entry(perm_key).or_insert_with(Vec::new).push(member);
}
groups
}
pub fn group_by_member_type(
&self,
) -> std::collections::HashMap<String, Vec<&PermissionMember>> {
let mut groups = std::collections::HashMap::new();
for member in &self.members {
groups
.entry(member.member_type.clone())
.or_insert_with(Vec::new)
.push(member);
}
groups
}
pub fn inherited_members(&self) -> Vec<&PermissionMember> {
self.members
.iter()
.filter(|member| member.has_inherited_permission())
.collect()
}
pub fn direct_members(&self) -> Vec<&PermissionMember> {
self.members
.iter()
.filter(|member| !member.has_inherited_permission())
.collect()
}
pub fn permission_summary(&self) -> String {
let owners = self.owners().len();
let editors = self.editors().len();
let commenters = self.commenters().len();
let viewers = self.viewers().len();
format!(
"协作者总数: {}, 所有者: {}, 编辑者: {}, 评论者: {}, 阅读者: {}",
self.count(),
owners,
editors,
commenters,
viewers
)
}
}
#[cfg(test)]
#[allow(unused_variables, unused_unsafe)]
mod tests {
use super::*;
#[test]
fn test_list_permission_members_request_builder() {
let request = ListPermissionMembersRequest::builder()
.token("doccnxxxxxx")
.as_doc()
.page_size(20)
.page_token("token123")
.build();
assert_eq!(request.token, "doccnxxxxxx");
assert_eq!(request.obj_type, "doc");
assert_eq!(request.page_size, Some(20));
assert_eq!(request.page_token, Some("token123".to_string()));
}
#[test]
fn test_list_permission_members_new() {
let request = ListPermissionMembersRequest::new("doccnxxxxxx", "doc");
assert_eq!(request.token, "doccnxxxxxx");
assert_eq!(request.obj_type, "doc");
}
}