cleanup
This commit is contained in:
+135
-1
@@ -13,7 +13,7 @@ use diesel::{pg::PgConnection, prelude::*};
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use utoipa::ToSchema;
|
||||
use utoipa::{OpenApi, ToSchema};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
@@ -104,12 +104,71 @@ pub enum LoginResponseVariants {
|
||||
Selection(TenantSelectionResponse),
|
||||
}
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
paths(
|
||||
login,
|
||||
signup_start,
|
||||
signup_finish,
|
||||
refresh,
|
||||
logout,
|
||||
me,
|
||||
list_tenants,
|
||||
select_tenant,
|
||||
passkey_register_start,
|
||||
passkey_register_finish,
|
||||
passkey_login_start,
|
||||
passkey_login_finish,
|
||||
),
|
||||
components(schemas(
|
||||
LoginRequest,
|
||||
SignupStartRequest,
|
||||
SignupStartResponse,
|
||||
SignupFinishRequest,
|
||||
LoginResponse,
|
||||
LoginResponseVariants,
|
||||
TenantSnippet,
|
||||
TenantSelectionResponse,
|
||||
TenantSelectionRequest,
|
||||
TenantListResponse,
|
||||
crate::auth::AuthenticatedUser,
|
||||
crate::auth::passkeys::RegistrationChallengeResponse,
|
||||
crate::auth::passkeys::AuthenticationChallengeResponse,
|
||||
crate::auth::passkeys::PasskeySummary,
|
||||
crate::auth::passkeys::PasskeyRegistrationFinishPayload,
|
||||
crate::auth::passkeys::PasskeyLoginStartPayload,
|
||||
crate::auth::passkeys::PasskeyLoginFinishPayload,
|
||||
))
|
||||
)]
|
||||
pub struct AuthApiDoc;
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/login",
|
||||
request_body = LoginRequest,
|
||||
responses(
|
||||
(status = 200, description = "Login succeeded", body = LoginResponseVariants),
|
||||
(status = 401, description = "Invalid credentials")
|
||||
),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn login(_state: State<AppState>, _payload: Json<LoginRequest>) -> AppResult<Response> {
|
||||
Err(AppError::bad_request(
|
||||
"password authentication is no longer supported",
|
||||
))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/signup/start",
|
||||
request_body = SignupStartRequest,
|
||||
responses(
|
||||
(status = 200, description = "Signup challenge created", body = SignupStartResponse),
|
||||
(status = 400, description = "Invalid signup request"),
|
||||
(status = 409, description = "Username already exists")
|
||||
),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn signup_start(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<SignupStartRequest>,
|
||||
@@ -147,6 +206,17 @@ pub async fn signup_start(
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/signup/finish",
|
||||
request_body = SignupFinishRequest,
|
||||
responses(
|
||||
(status = 200, description = "Signup completed", body = LoginResponseVariants),
|
||||
(status = 400, description = "Invalid signup completion"),
|
||||
(status = 409, description = "Username already exists")
|
||||
),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn signup_finish(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<SignupFinishRequest>,
|
||||
@@ -204,6 +274,15 @@ pub async fn signup_finish(
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/refresh",
|
||||
responses(
|
||||
(status = 200, description = "Refreshed access token", body = LoginResponse),
|
||||
(status = 401, description = "Missing or invalid refresh token")
|
||||
),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn refresh(
|
||||
State(state): State<AppState>,
|
||||
jar: Option<TypedHeader<Cookie>>,
|
||||
@@ -257,6 +336,13 @@ fn insert_user(conn: &mut PgConnection, id: Uuid, username: &str) -> AppResult<(
|
||||
.map_err(AppError::from)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/select-tenant",
|
||||
request_body = TenantSelectionRequest,
|
||||
responses((status = 200, description = "Tenant selected", body = LoginResponse)),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn select_tenant(
|
||||
State(state): State<AppState>,
|
||||
TypedHeader(Authorization(bearer)): TypedHeader<Authorization<Bearer>>,
|
||||
@@ -293,6 +379,12 @@ pub async fn select_tenant(
|
||||
issue_session(&state, &mut conn, &user, payload.tenant_id)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/logout",
|
||||
responses((status = 204, description = "Session revoked")),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn logout(
|
||||
State(state): State<AppState>,
|
||||
user: AuthenticatedUser,
|
||||
@@ -338,10 +430,22 @@ pub async fn logout(
|
||||
Ok((headers, StatusCode::NO_CONTENT))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/auth/me",
|
||||
responses((status = 200, description = "Authenticated principal", body = AuthenticatedUser)),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn me(user: AuthenticatedUser) -> Json<AuthenticatedUser> {
|
||||
Json(user)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/auth/tenants",
|
||||
responses((status = 200, description = "Available tenants", body = TenantListResponse)),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn list_tenants(
|
||||
State(state): State<AppState>,
|
||||
auth: Option<TypedHeader<Authorization<Bearer>>>,
|
||||
@@ -374,6 +478,12 @@ pub async fn list_tenants(
|
||||
Ok(Json(TenantListResponse { tenants }))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/passkeys/register/start",
|
||||
responses((status = 200, description = "Passkey registration challenge", body = RegistrationChallengeResponse)),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn passkey_register_start(
|
||||
State(state): State<AppState>,
|
||||
user: AuthenticatedUser,
|
||||
@@ -389,6 +499,13 @@ pub async fn passkey_register_start(
|
||||
Ok(Json(challenge))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/passkeys/register/finish",
|
||||
request_body = PasskeyRegistrationFinishPayload,
|
||||
responses((status = 200, description = "Passkey registered", body = PasskeySummary)),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn passkey_register_finish(
|
||||
State(state): State<AppState>,
|
||||
user: AuthenticatedUser,
|
||||
@@ -419,6 +536,13 @@ pub async fn passkey_register_finish(
|
||||
Ok(Json(PasskeySummary::from(passkey)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/passkeys/login/start",
|
||||
request_body = PasskeyLoginStartPayload,
|
||||
responses((status = 200, description = "Passkey authentication challenge", body = AuthenticationChallengeResponse)),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn passkey_login_start(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<PasskeyLoginStartPayload>,
|
||||
@@ -442,6 +566,16 @@ pub async fn passkey_login_start(
|
||||
Ok(Json(challenge))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/auth/passkeys/login/finish",
|
||||
request_body = PasskeyLoginFinishPayload,
|
||||
responses(
|
||||
(status = 200, description = "Passkey login successful", body = LoginResponseVariants),
|
||||
(status = 401, description = "Authentication failed")
|
||||
),
|
||||
tag = "Auth"
|
||||
)]
|
||||
pub async fn passkey_login_finish(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<PasskeyLoginFinishPayload>,
|
||||
|
||||
Reference in New Issue
Block a user