use crate::models::oauth::*;
use openlark_core::{SDKResult, config::Config, req_option::RequestOption, validate_required};
use serde::{Deserialize, Serialize};
pub struct AuthorizationBuilder {
app_id: String,
redirect_uri: String,
scope: Option<String>,
state: Option<String>,
response_type: Option<String>,
config: Config,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AuthorizationCodeResponseData {
pub data: AuthorizationUrlResponse,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AuthorizationUrlResponse {
pub authorization_url: String,
pub app_id: String,
pub redirect_uri: String,
pub scope: Option<String>,
pub state: Option<String>,
}
impl AuthorizationBuilder {
pub fn new(config: Config) -> Self {
Self {
app_id: String::new(),
redirect_uri: String::new(),
scope: None,
state: None,
response_type: Some("code".to_string()),
config,
}
}
pub fn app_id(mut self, app_id: impl Into<String>) -> Self {
self.app_id = app_id.into();
self
}
pub fn redirect_uri(mut self, uri: impl Into<String>) -> Self {
self.redirect_uri = uri.into();
self
}
pub fn scope(mut self, scope: impl Into<String>) -> Self {
self.scope = Some(scope.into());
self
}
pub fn state(mut self, state: impl Into<String>) -> Self {
self.state = Some(state.into());
self
}
pub async fn execute(self) -> SDKResult<AuthorizationCodeResponseData> {
self.execute_with_options(RequestOption::default()).await
}
pub async fn execute_with_options(
self,
_option: RequestOption,
) -> SDKResult<AuthorizationCodeResponseData> {
validate_required!(self.app_id, "应用ID不能为空");
validate_required!(self.redirect_uri, "重定向URI不能为空");
let url = self.build_authorization_url();
Ok(AuthorizationCodeResponseData {
data: AuthorizationUrlResponse {
authorization_url: url.clone(),
app_id: self.app_id,
redirect_uri: self.redirect_uri,
scope: self.scope,
state: self.state,
},
})
}
fn build_authorization_url(&self) -> String {
use crate::common::api_endpoints::OAuthApiOld;
let api_endpoint = OAuthApiOld::Index;
let mut url = format!(
"{}{}?app_id={}&redirect_uri={}",
self.config.base_url(),
api_endpoint.path(),
urlencoding::encode(&self.app_id),
urlencoding::encode(&self.redirect_uri)
);
if let Some(scope) = &self.scope {
url.push_str(&format!("&scope={}", urlencoding::encode(scope)));
}
if let Some(state) = &self.state {
url.push_str(&format!("&state={}", urlencoding::encode(state)));
}
url.push_str(&format!(
"&response_type={}",
self.response_type.clone().unwrap_or_default()
));
url
}
pub fn build_url(self) -> String {
self.build_authorization_url()
}
pub async fn send(self) -> SDKResult<AuthorizationCodeResponse> {
Err(openlark_core::error::configuration_error(
"OAuth授权需要重定向流程,请使用 build_url() 获取授权链接",
))
}
}
#[derive(Debug)]
pub struct OAuthServiceOld {
config: Config,
}
impl OAuthServiceOld {
pub fn new(config: Config) -> Self {
Self { config }
}
pub fn authorization(&self) -> AuthorizationBuilder {
AuthorizationBuilder::new(self.config.clone())
}
pub fn index(&self) -> AuthorizationBuilder {
self.authorization()
}
}
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
#[test]
fn test_serialization_roundtrip() {
let json = r#"{"test": "value"}"#;
assert!(serde_json::from_str::<serde_json::Value>(json).is_ok());
}
#[test]
fn test_deserialization_from_json() {
let json = r#"{"field": "data"}"#;
let value: serde_json::Value = serde_json::from_str(json).expect("JSON 反序列化失败");
assert_eq!(value["field"], "data");
}
}