mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-08 00:01:07 +00:00
96 lines
2.9 KiB
Rust
96 lines
2.9 KiB
Rust
use std::sync::Arc;
|
|
|
|
use anyhow::{anyhow, Context};
|
|
use axum::{extract::Query, response::Redirect, routing::get, Extension, Router};
|
|
use axum_oauth2::github::{GithubOauthClient, GithubOauthExtension};
|
|
use helpers::handle_anyhow_error;
|
|
use mungos::{doc, Deserialize};
|
|
use types::{monitor_timestamp, CoreConfig, User};
|
|
|
|
use crate::{response, state::StateExtension};
|
|
|
|
use super::JwtExtension;
|
|
|
|
pub fn router(config: &CoreConfig) -> Router {
|
|
let client = GithubOauthClient::new(
|
|
config.github_oauth.id.clone(),
|
|
config.github_oauth.secret.clone(),
|
|
format!("{}/auth/github/callback", config.host),
|
|
&[],
|
|
"monitor".to_string(),
|
|
);
|
|
Router::new()
|
|
.route(
|
|
"/login",
|
|
get(|Extension(client): GithubOauthExtension| async move {
|
|
Redirect::to(&client.get_login_redirect_url())
|
|
}),
|
|
)
|
|
.route(
|
|
"/callback",
|
|
get(|client, jwt, state, query| async {
|
|
let redirect = callback(client, jwt, state, query)
|
|
.await
|
|
.map_err(handle_anyhow_error)?;
|
|
response!(redirect)
|
|
}),
|
|
)
|
|
.layer(Extension(Arc::new(client)))
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct CallbackQuery {
|
|
state: String,
|
|
code: String,
|
|
}
|
|
|
|
async fn callback(
|
|
Extension(client): GithubOauthExtension,
|
|
Extension(jwt_client): JwtExtension,
|
|
Extension(state): StateExtension,
|
|
Query(query): Query<CallbackQuery>,
|
|
) -> anyhow::Result<Redirect> {
|
|
if !client.check_state(&query.state) {
|
|
return Err(anyhow!("state mismatch"));
|
|
}
|
|
let token = client.get_access_token(&query.code).await?;
|
|
let github_user = client.get_github_user(&token.access_token).await?;
|
|
let github_id = github_user.id.to_string();
|
|
let user = state
|
|
.db
|
|
.users
|
|
.find_one(doc! { "github_id": &github_id }, None)
|
|
.await
|
|
.context("failed at find user query from mongo")?;
|
|
let jwt = match user {
|
|
Some(user) => jwt_client
|
|
.generate(user.id)
|
|
.context("failed to generate jwt")?,
|
|
None => {
|
|
let ts = monitor_timestamp();
|
|
let user = User {
|
|
username: github_user.login,
|
|
avatar: github_user.avatar_url.into(),
|
|
github_id: github_id.into(),
|
|
created_at: ts.clone(),
|
|
updated_at: ts,
|
|
..Default::default()
|
|
};
|
|
let user_id = state
|
|
.db
|
|
.users
|
|
.create_one(user)
|
|
.await
|
|
.context("failed to create user on mongo")?;
|
|
jwt_client
|
|
.generate(user_id)
|
|
.context("failed to generate jwt")?
|
|
}
|
|
};
|
|
let exchange_token = jwt_client.create_exchange_token(jwt);
|
|
Ok(Redirect::to(&format!(
|
|
"{}?token={exchange_token}",
|
|
state.config.host
|
|
)))
|
|
}
|