feat: define and implement RequestAccessToken for Forgejo
This commit is contained in:
parent
6a40fcdf50
commit
e1ae648c8b
80
src/auth/adapter/out/forge/forgejo/request_access_token.rs
Normal file
80
src/auth/adapter/out/forge/forgejo/request_access_token.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use super::Forgejo;
|
||||
use crate::auth::application::port::out::forge::{
|
||||
errors::OutForgePortResult, request_access_token::RequestAccessToken,
|
||||
};
|
||||
use crate::auth::domain::OAuthAccessToken;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
struct ForgejoAccessTokenResponse {
|
||||
refresh_token: String,
|
||||
access_token: String,
|
||||
token_type: String,
|
||||
expires_in: u64,
|
||||
}
|
||||
|
||||
impl From<ForgejoAccessTokenResponse> for OAuthAccessToken {
|
||||
fn from(v: ForgejoAccessTokenResponse) -> Self {
|
||||
let expires_at = Duration::from_secs(v.expires_in);
|
||||
Self {
|
||||
refresh_token: v.refresh_token,
|
||||
access_token: v.access_token,
|
||||
token_type: v.token_type,
|
||||
expires_at, // unix epoch of the instant
|
||||
expires_in: v.expires_in,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
struct ForgejoAccessTokenRequest {
|
||||
code: String,
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
grant_type: String,
|
||||
redirect_uri: Url,
|
||||
}
|
||||
|
||||
impl ForgejoAccessTokenRequest {
|
||||
pub fn new(code: String, redirect_uri: Url, forgejo: &Forgejo) -> Self {
|
||||
Self {
|
||||
code,
|
||||
client_id: forgejo.client_id.clone(),
|
||||
client_secret: forgejo.client_secret.clone(),
|
||||
grant_type: "authorization_code".into(),
|
||||
redirect_uri,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl RequestAccessToken for Forgejo {
|
||||
async fn request_access_token(
|
||||
&self,
|
||||
code: String,
|
||||
redirect_uri: Url,
|
||||
) -> OutForgePortResult<OAuthAccessToken> {
|
||||
let u = {
|
||||
let mut u = self.url().to_owned();
|
||||
u.set_path("/login/oauth/access_token");
|
||||
u
|
||||
};
|
||||
|
||||
let payload = ForgejoAccessTokenRequest::new(code, redirect_uri, self);
|
||||
let res: ForgejoAccessTokenResponse = self
|
||||
.http_client
|
||||
.post(u)
|
||||
.json(&payload)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
Ok(res.into())
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
use mockall::predicate::*;
|
||||
use mockall::*;
|
||||
use url::Url;
|
||||
|
||||
use super::errors::*;
|
||||
use crate::auth::domain::OAuthAccessToken;
|
||||
|
@ -7,7 +8,11 @@ use crate::auth::domain::OAuthAccessToken;
|
|||
#[automock]
|
||||
#[async_trait::async_trait]
|
||||
pub trait RequestAccessToken: Send + Sync {
|
||||
async fn request_access_token(&self, code: &str) -> OutForgePortResult<OAuthAccessToken>;
|
||||
async fn request_access_token(
|
||||
&self,
|
||||
code: String,
|
||||
redirect_uri: Url,
|
||||
) -> OutForgePortResult<OAuthAccessToken>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -21,10 +26,10 @@ pub mod tests {
|
|||
if let Some(times) = times {
|
||||
m.expect_request_access_token()
|
||||
.times(times)
|
||||
.returning(|_| Ok(OAuthAccessToken::default()));
|
||||
.returning(|_, _| Ok(OAuthAccessToken::default()));
|
||||
} else {
|
||||
m.expect_request_access_token()
|
||||
.returning(|_| Ok(OAuthAccessToken::default()));
|
||||
.returning(|_, _| Ok(OAuthAccessToken::default()));
|
||||
}
|
||||
|
||||
Arc::new(m)
|
||||
|
|
Loading…
Reference in a new issue