use crate::common::{
api_utils::serialize_params, constants::endpoints::SPARK_V1_DIRECTORY_USER_ID_CONVERT,
};
use openlark_core::{
SDKResult,
api::{ApiRequest, ApiResponseTrait, ResponseFormat},
config::Config,
http::Transport,
req_option::RequestOption,
};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
#[repr(i32)]
pub enum UserIdConvertType {
ForceUserIdToFeishuOpenId = 10,
ForceUserIdToFeishuUnionId = 11,
FeishuOpenIdToForceUserId = 20,
FeishuUnionIdToForceUserId = 21,
}
#[derive(Debug, Clone)]
pub struct DirectoryUserIdConvertRequestBuilder {
config: Config,
id_convert_type: UserIdConvertType,
ids: Vec<String>,
}
impl DirectoryUserIdConvertRequestBuilder {
pub fn new(config: Config, id_convert_type: UserIdConvertType) -> Self {
Self {
config,
id_convert_type,
ids: Vec::new(),
}
}
pub fn id_convert_type(mut self, id_convert_type: UserIdConvertType) -> Self {
self.id_convert_type = id_convert_type;
self
}
pub fn id(mut self, id: impl Into<String>) -> Self {
self.ids.push(id.into());
self
}
pub fn ids(mut self, ids: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.ids = ids.into_iter().map(Into::into).collect();
self
}
pub async fn execute(self) -> SDKResult<DirectoryUserIdConvertResponse> {
self.execute_with_options(RequestOption::default()).await
}
pub async fn execute_with_options(
self,
option: RequestOption,
) -> SDKResult<DirectoryUserIdConvertResponse> {
let request = DirectoryUserIdConvertRequest {
id_convert_type: self.id_convert_type,
ids: self.ids,
};
let req: ApiRequest<DirectoryUserIdConvertResponse> =
ApiRequest::post(SPARK_V1_DIRECTORY_USER_ID_CONVERT)
.body(serialize_params(&request, "转换妙搭和飞书用户 ID")?);
Transport::request_typed(req, &self.config, Some(option), "转换妙搭和飞书用户 ID").await
}
}
#[derive(Debug, Clone, Serialize)]
struct DirectoryUserIdConvertRequest {
#[serde(rename = "id_convert_type")]
id_convert_type: UserIdConvertType,
#[serde(rename = "ids", skip_serializing_if = "Vec::is_empty")]
ids: Vec<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct DirectoryUserIdMapItem {
#[serde(rename = "source_id")]
pub source_id: String,
#[serde(rename = "target_id")]
pub target_id: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct DirectoryUserIdConvertResponse {
#[serde(default, rename = "items")]
pub items: Vec<DirectoryUserIdMapItem>,
}
impl ApiResponseTrait for DirectoryUserIdConvertResponse {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[deprecated(
note = "renamed to DirectoryUserIdConvertRequestBuilder, will be removed in v1.0 (#271)"
)]
pub type DirectoryUserIdConvertBuilder = DirectoryUserIdConvertRequestBuilder;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_basic() {
let config = Config::builder()
.app_id("test_app")
.app_secret("test_secret")
.build();
let request = DirectoryUserIdConvertRequestBuilder::new(
config,
UserIdConvertType::ForceUserIdToFeishuOpenId,
)
.id("123456789837364")
.id("223456789837364");
assert_eq!(request.ids.len(), 2);
assert_eq!(
request.id_convert_type,
UserIdConvertType::ForceUserIdToFeishuOpenId
);
}
#[test]
fn test_request_serialization() {
let request = DirectoryUserIdConvertRequest {
id_convert_type: UserIdConvertType::FeishuUnionIdToForceUserId,
ids: vec!["ou_xxx".to_string()],
};
let value = serde_json::to_value(&request).unwrap();
assert_eq!(value["id_convert_type"], 21);
assert_eq!(value["ids"][0], "ou_xxx");
}
#[test]
fn test_response_deserialization() {
let json = r#"{
"items": [
{
"source_id": "123445678933432",
"target_id": "ou_1234cdjhjfedgfhgdhy3884"
}
]
}"#;
let response: DirectoryUserIdConvertResponse =
serde_json::from_str(json).expect("JSON 反序列化失败");
assert_eq!(response.items.len(), 1);
assert_eq!(response.items[0].source_id, "123445678933432");
assert_eq!(response.items[0].target_id, "ou_1234cdjhjfedgfhgdhy3884");
}
}