caveman/gatherer/src/http_server/token_collect.rs

77 lines
2.1 KiB
Rust

use axum::{
Extension,
extract,
http::StatusCode,
response::{Html, IntoResponse},
};
use cave::db::Database;
use crate::{
http_server::ServerState,
oauth,
};
async fn collect_token(
db: Database,
http_client: &reqwest::Client,
host: &str,
code: String,
) -> Result<(), String> {
// try a few registered apps until one works
for (client_id, client_secret) in db.get_apps(host).await
.map_err(|e| format!("{e}"))?
{
let app = oauth::Application {
client_id,
client_secret,
};
match app.obtain_token(http_client, host, code.clone()).await {
Ok(token) => {
db.add_token(host, &app.client_id, &token).await
.expect("db.add_token");
// success, done!
return Ok(());
}
Err(e) => {
tracing::error!("obtain_token for {}: {}", host, e);
// app seems blocked, remove
let _ = db.delete_app(host, &app.client_id).await;
}
}
}
Err(format!("No registered app found for instance {host}"))
}
#[derive(serde::Deserialize)]
pub struct OAuthCode {
code: String,
}
pub async fn get_token_collect(
Extension(ServerState { db, http_client, mut store, .. }): Extension<ServerState>,
extract::Path(host): extract::Path<String>,
extract::Query(OAuthCode { code }): extract::Query<OAuthCode>,
) -> impl IntoResponse {
match collect_token(db, &http_client, &host, code.clone()).await {
Ok(()) => {
let _ = store.save_host(&host).await;
(
StatusCode::SEE_OTHER,
[("location", "/token/thanks")]
).into_response()
}
Err(e) => {
tracing::error!("{}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
[("content-type", "text/plain")],
e
).into_response()
}
}
}
pub async fn get_token_thanks() -> impl IntoResponse {
Html(&include_bytes!("../../templates/token_thanks.html")[..])
}