2024-02-10 14:25:33 +01:00
|
|
|
use std::net::Ipv6Addr;
|
|
|
|
|
2024-02-10 11:44:31 +01:00
|
|
|
use axum::{
|
|
|
|
extract::Query,
|
2024-02-10 13:23:20 +01:00
|
|
|
http::StatusCode,
|
|
|
|
response::IntoResponse,
|
2024-02-10 11:44:31 +01:00
|
|
|
routing::{get, post},
|
|
|
|
Form, Json, Router,
|
|
|
|
};
|
2024-02-10 12:39:34 +01:00
|
|
|
use secrecy::ExposeSecret;
|
2024-02-10 11:44:31 +01:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use tracing::{event, instrument, Level};
|
|
|
|
|
2024-02-10 12:40:00 +01:00
|
|
|
use crate::auth::{AuthenticationError, UserServerKeyGenerator};
|
|
|
|
use crate::secrets::{Password, ServerHash, UserToken};
|
2024-02-10 11:13:11 +01:00
|
|
|
|
|
|
|
#[instrument]
|
2024-02-10 14:25:33 +01:00
|
|
|
pub async fn run(port: u16) -> color_eyre::Result<()> {
|
2024-02-10 11:44:31 +01:00
|
|
|
let app = Router::new()
|
|
|
|
.route("/tls-check/success", get(|| async { "OK" }))
|
2024-02-10 12:40:00 +01:00
|
|
|
.route("/api-login", post(api_login))
|
|
|
|
.route(
|
|
|
|
"/generate-user-server-key-2",
|
|
|
|
post(generate_user_server_key_2),
|
|
|
|
);
|
2024-02-10 14:25:33 +01:00
|
|
|
let listener = tokio::net::TcpListener::bind((Ipv6Addr::UNSPECIFIED, port)).await?;
|
2024-02-10 11:13:11 +01:00
|
|
|
axum::serve(listener, app).await?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2024-02-10 11:44:31 +01:00
|
|
|
|
2024-02-10 11:49:36 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
|
|
|
struct ApiError {
|
2024-02-10 13:23:20 +01:00
|
|
|
#[serde(skip_serializing)]
|
|
|
|
status: StatusCode,
|
2024-02-10 11:49:36 +01:00
|
|
|
error: String,
|
|
|
|
message: String,
|
|
|
|
}
|
|
|
|
|
2024-02-10 13:23:20 +01:00
|
|
|
impl From<AuthenticationError> for ApiError {
|
|
|
|
fn from(err: AuthenticationError) -> Self {
|
|
|
|
Self {
|
|
|
|
status: StatusCode::UNAUTHORIZED,
|
|
|
|
error: "authentication-failed".to_owned(),
|
|
|
|
message: err.to_string(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoResponse for ApiError {
|
|
|
|
fn into_response(self) -> axum::response::Response {
|
|
|
|
(self.status, Json(self)).into_response()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type ApiResult<T> = Result<T, ApiError>;
|
2024-02-10 11:49:36 +01:00
|
|
|
|
2024-02-10 11:44:31 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
|
|
|
struct ApiVersion {
|
|
|
|
api_version: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
|
|
struct LoginRequest {
|
|
|
|
username: String,
|
|
|
|
password: Password,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
|
|
struct LoginResponse {
|
|
|
|
username: String,
|
|
|
|
token: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[instrument]
|
|
|
|
async fn api_login(
|
|
|
|
Query(ApiVersion { api_version }): Query<ApiVersion>,
|
|
|
|
Form(LoginRequest { username, password }): Form<LoginRequest>,
|
2024-02-10 11:49:36 +01:00
|
|
|
) -> ApiResult<Json<LoginResponse>> {
|
2024-02-10 11:44:31 +01:00
|
|
|
event!(Level::WARN, "Creating dummy token");
|
2024-02-10 12:39:34 +01:00
|
|
|
let user_token = UserToken("invalid".to_owned().into());
|
2024-02-10 11:44:31 +01:00
|
|
|
|
|
|
|
Ok(Json(LoginResponse {
|
|
|
|
username,
|
2024-02-10 12:39:34 +01:00
|
|
|
token: user_token.0.expose_secret().to_owned(),
|
2024-02-10 11:44:31 +01:00
|
|
|
}))
|
|
|
|
}
|
2024-02-10 12:40:00 +01:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
|
|
struct UserServerKeyRequest {
|
|
|
|
username: String,
|
|
|
|
token: UserToken,
|
|
|
|
server_hash: ServerHash,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
|
|
struct UserServerKeyResponse {
|
|
|
|
server_key: String,
|
|
|
|
server_key_timestamp: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[instrument]
|
|
|
|
async fn generate_user_server_key_2(
|
|
|
|
Query(ApiVersion { api_version }): Query<ApiVersion>,
|
|
|
|
Form(UserServerKeyRequest {
|
|
|
|
username,
|
|
|
|
token,
|
|
|
|
server_hash,
|
|
|
|
}): Form<UserServerKeyRequest>,
|
|
|
|
) -> ApiResult<Json<UserServerKeyResponse>> {
|
|
|
|
event!(Level::WARN, "Creating dummy user_server_key");
|
|
|
|
|
|
|
|
let generator: UserServerKeyGenerator = todo!();
|
|
|
|
let (server_key, server_key_timestamp) = generator
|
|
|
|
.generate_user_server_key(&username, &token, &server_hash)
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
Ok(Json(UserServerKeyResponse {
|
|
|
|
server_key: server_key.0.expose_secret().to_owned(),
|
|
|
|
server_key_timestamp,
|
|
|
|
}))
|
|
|
|
}
|