151 lines
4.4 KiB
Rust
151 lines
4.4 KiB
Rust
use axum::{
|
|
extract::{Path, Query, State},
|
|
http::StatusCode,
|
|
Json,
|
|
};
|
|
use utoipa::OpenApi;
|
|
use uuid::Uuid;
|
|
|
|
use crate::{
|
|
auth::{passkeys::PasskeySummary, TenantScopedConn},
|
|
error::AppResult,
|
|
http::responders::JsonResponse,
|
|
services::profile::{
|
|
ApiTokenCreatedResponse, ApiTokenResponse, CreateApiTokenRequest, ProfileService,
|
|
RevokePasskeyQuery,
|
|
},
|
|
state::AppState,
|
|
};
|
|
|
|
#[utoipa::path(
|
|
get,
|
|
path = "/api/profile/passkeys",
|
|
responses((status = 200, description = "List registered passkeys", body = [PasskeySummary])),
|
|
tag = "Profile"
|
|
)]
|
|
pub async fn list_passkeys(
|
|
State(state): State<AppState>,
|
|
TenantScopedConn {
|
|
mut conn, user_id, ..
|
|
}: TenantScopedConn,
|
|
) -> AppResult<JsonResponse<Vec<PasskeySummary>>> {
|
|
ProfileService::new(&state).list_passkeys(&mut conn, user_id)
|
|
}
|
|
|
|
#[utoipa::path(
|
|
get,
|
|
path = "/api/profile/api-tokens",
|
|
responses((status = 200, description = "List API tokens", body = [ApiTokenResponse])),
|
|
tag = "Profile"
|
|
)]
|
|
pub async fn list_api_tokens(
|
|
State(state): State<AppState>,
|
|
TenantScopedConn {
|
|
mut conn,
|
|
tenant_id,
|
|
user_id,
|
|
..
|
|
}: TenantScopedConn,
|
|
) -> AppResult<JsonResponse<Vec<ApiTokenResponse>>> {
|
|
ProfileService::new(&state).list_api_tokens(&mut conn, tenant_id, user_id)
|
|
}
|
|
|
|
#[utoipa::path(
|
|
post,
|
|
path = "/api/profile/api-tokens",
|
|
request_body = CreateApiTokenRequest,
|
|
responses((status = 201, description = "API token created", body = ApiTokenCreatedResponse)),
|
|
tag = "Profile"
|
|
)]
|
|
pub async fn create_api_token(
|
|
State(state): State<AppState>,
|
|
TenantScopedConn {
|
|
mut conn,
|
|
tenant_id,
|
|
user_id,
|
|
..
|
|
}: TenantScopedConn,
|
|
Json(payload): Json<CreateApiTokenRequest>,
|
|
) -> AppResult<JsonResponse<ApiTokenCreatedResponse>> {
|
|
ProfileService::new(&state).create_api_token(&mut conn, tenant_id, user_id, payload)
|
|
}
|
|
|
|
#[utoipa::path(
|
|
post,
|
|
path = "/api/profile/api-tokens/{id}/regenerate",
|
|
params(("id" = Uuid, Path, description = "API token ID")),
|
|
responses((status = 200, description = "API token regenerated", body = ApiTokenCreatedResponse)),
|
|
tag = "Profile"
|
|
)]
|
|
pub async fn regenerate_api_token(
|
|
State(state): State<AppState>,
|
|
TenantScopedConn {
|
|
mut conn,
|
|
tenant_id,
|
|
user_id,
|
|
..
|
|
}: TenantScopedConn,
|
|
Path(token_id): Path<Uuid>,
|
|
) -> AppResult<JsonResponse<ApiTokenCreatedResponse>> {
|
|
ProfileService::new(&state).regenerate_api_token(&mut conn, tenant_id, user_id, token_id)
|
|
}
|
|
|
|
#[utoipa::path(
|
|
delete,
|
|
path = "/api/profile/api-tokens/{id}",
|
|
params(("id" = Uuid, Path, description = "API token ID")),
|
|
responses((status = 204, description = "API token revoked")),
|
|
tag = "Profile"
|
|
)]
|
|
pub async fn delete_api_token(
|
|
State(state): State<AppState>,
|
|
TenantScopedConn {
|
|
mut conn, user_id, ..
|
|
}: TenantScopedConn,
|
|
Path(token_id): Path<Uuid>,
|
|
) -> AppResult<StatusCode> {
|
|
ProfileService::new(&state).delete_api_token(&mut conn, user_id, token_id)
|
|
}
|
|
|
|
#[utoipa::path(
|
|
delete,
|
|
path = "/api/profile/passkeys/{id}",
|
|
params(
|
|
("id" = Uuid, Path, description = "Passkey ID"),
|
|
("reason" = Option<String>, Query, description = "Optional reason for revoking the passkey")
|
|
),
|
|
responses((status = 204, description = "Passkey revoked")),
|
|
tag = "Profile"
|
|
)]
|
|
pub async fn delete_passkey(
|
|
State(state): State<AppState>,
|
|
TenantScopedConn {
|
|
mut conn, user_id, ..
|
|
}: TenantScopedConn,
|
|
Path(passkey_id): Path<Uuid>,
|
|
Query(query): Query<RevokePasskeyQuery>,
|
|
) -> AppResult<StatusCode> {
|
|
ProfileService::new(&state).delete_passkey(&mut conn, user_id, passkey_id, query.reason)
|
|
}
|
|
|
|
#[derive(OpenApi)]
|
|
#[openapi(
|
|
paths(
|
|
crate::routes::profile::list_api_tokens,
|
|
crate::routes::profile::create_api_token,
|
|
crate::routes::profile::regenerate_api_token,
|
|
crate::routes::profile::delete_api_token,
|
|
crate::routes::profile::list_passkeys,
|
|
crate::routes::profile::delete_passkey
|
|
),
|
|
components(schemas(
|
|
crate::models::ApiCapability,
|
|
crate::services::profile::ApiTokenResponse,
|
|
crate::services::profile::ApiTokenCreatedResponse,
|
|
crate::services::profile::CreateApiTokenRequest,
|
|
crate::services::profile::RevokePasskeyQuery,
|
|
crate::auth::passkeys::PasskeySummary
|
|
))
|
|
)]
|
|
pub struct ProfileApiDoc;
|