hive-c0re: annotate remaining dashboard routes with utoipa
This commit is contained in:
parent
8ebefeb0d5
commit
582ebe5eee
21 changed files with 738 additions and 45 deletions
|
|
@ -22,16 +22,17 @@ use std::path::Path;
|
|||
use axum::extract::{Form, Query};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
use super::{Ident, error_response};
|
||||
use crate::coordinator::Coordinator;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, IntoParams)]
|
||||
pub(super) struct MatrixAccountsQuery {
|
||||
agent: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, ToSchema)]
|
||||
struct MatrixAccount {
|
||||
name: String,
|
||||
/// Effective homeserver, backfilled from the daemon snapshot; `None` when
|
||||
|
|
@ -46,7 +47,7 @@ struct MatrixAccount {
|
|||
user_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, ToSchema)]
|
||||
struct MatrixAccountsResponse {
|
||||
accounts: Vec<MatrixAccount>,
|
||||
/// Unix mtime of the daemon's `matrix-accounts.json` snapshot (when the
|
||||
|
|
@ -102,6 +103,19 @@ fn account_name_from_filename(fname: &str) -> Option<String> {
|
|||
Some(suffix.to_owned())
|
||||
}
|
||||
|
||||
/// `GET /api/matrix-accounts?agent=<name>` — matrix accounts provisioned
|
||||
/// for `agent`, backfilled with homeserver/live/user_id from the daemon's
|
||||
/// snapshot.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/matrix-accounts",
|
||||
params(MatrixAccountsQuery),
|
||||
responses(
|
||||
(status = 200, description = "provisioned matrix accounts for the agent", body = MatrixAccountsResponse),
|
||||
(status = 500, description = "invalid agent name, or a state-dir read failed"),
|
||||
),
|
||||
tag = "matrix_accounts"
|
||||
)]
|
||||
pub(super) async fn get_matrix_accounts(Query(q): Query<MatrixAccountsQuery>) -> Response {
|
||||
let agent = q.agent.trim();
|
||||
// Validate through the single `Ident` type so a crafted `agent` can't
|
||||
|
|
@ -156,7 +170,7 @@ pub(super) async fn get_matrix_accounts(Query(q): Query<MatrixAccountsQuery>) ->
|
|||
/// mutation convention). `mode` is `"password"` (needs `user_id` +
|
||||
/// `password`) or `"token"` (needs `token`; `user_id` is recovered via
|
||||
/// whoami).
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub(super) struct MatrixLoginForm {
|
||||
agent: String,
|
||||
account: String,
|
||||
|
|
@ -167,7 +181,7 @@ pub(super) struct MatrixLoginForm {
|
|||
token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, ToSchema)]
|
||||
struct MatrixLoginResult {
|
||||
ok: bool,
|
||||
user_id: String,
|
||||
|
|
@ -178,6 +192,16 @@ struct MatrixLoginResult {
|
|||
/// On success writes the token to `matrix-token-<account>` via hive-priv and
|
||||
/// kicks the daemon. Operator-authenticated (dashboard). Never echoes the
|
||||
/// token back — only `{ ok, user_id }`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/matrix-account-login",
|
||||
request_body(content = MatrixLoginForm, content_type = "application/x-www-form-urlencoded"),
|
||||
responses(
|
||||
(status = 200, description = "account provisioned", body = MatrixLoginResult),
|
||||
(status = 500, description = "invalid input, or the homeserver login/whoami failed"),
|
||||
),
|
||||
tag = "matrix_accounts"
|
||||
)]
|
||||
pub(super) async fn post_matrix_account_login(Form(f): Form<MatrixLoginForm>) -> Response {
|
||||
let agent = f.agent.trim();
|
||||
let account = f.account.trim();
|
||||
|
|
@ -257,13 +281,13 @@ pub(super) async fn post_matrix_account_login(Form(f): Form<MatrixLoginForm>) ->
|
|||
/// `github-token` file. The GitHub counterpart of the matrix login form, but
|
||||
/// far simpler: no account creation, no homeserver, no login modes — the
|
||||
/// operator pastes a PAT for an existing account.
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub(super) struct GithubAccountForm {
|
||||
agent: String,
|
||||
token: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, ToSchema)]
|
||||
struct GithubAccountResult {
|
||||
ok: bool,
|
||||
}
|
||||
|
|
@ -275,6 +299,16 @@ struct GithubAccountResult {
|
|||
/// helper read the file live, so the new token takes effect immediately.
|
||||
/// Operator-authenticated (dashboard). Never echoes the token back — only
|
||||
/// `{ ok: true }`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/github-account",
|
||||
request_body(content = GithubAccountForm, content_type = "application/x-www-form-urlencoded"),
|
||||
responses(
|
||||
(status = 200, description = "PAT provisioned", body = GithubAccountResult),
|
||||
(status = 500, description = "invalid agent name, empty token, or the write failed"),
|
||||
),
|
||||
tag = "matrix_accounts"
|
||||
)]
|
||||
pub(super) async fn post_github_account(Form(f): Form<GithubAccountForm>) -> Response {
|
||||
let agent = f.agent.trim();
|
||||
let token = f.token.trim();
|
||||
|
|
@ -291,12 +325,12 @@ pub(super) async fn post_github_account(Form(f): Form<GithubAccountForm>) -> Res
|
|||
axum::Json(GithubAccountResult { ok: true }).into_response()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, IntoParams)]
|
||||
pub(super) struct GithubAccountQuery {
|
||||
agent: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, ToSchema)]
|
||||
struct GithubAccountStatus {
|
||||
/// A `github-token` file exists in the agent's state dir (a PAT has been
|
||||
/// provisioned). A static PAT has no live/heartbeat concept, so this is
|
||||
|
|
@ -308,6 +342,16 @@ struct GithubAccountStatus {
|
|||
/// PAT provisioned (its `github-token` file exists). Lets the credentials tab
|
||||
/// show "token stored" vs "not set" instead of a black-hole paste field.
|
||||
/// Never returns the token itself.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/github-account",
|
||||
params(GithubAccountQuery),
|
||||
responses(
|
||||
(status = 200, description = "whether a github PAT is provisioned", body = GithubAccountStatus),
|
||||
(status = 500, description = "invalid agent name"),
|
||||
),
|
||||
tag = "matrix_accounts"
|
||||
)]
|
||||
pub(super) async fn get_github_account(Query(q): Query<GithubAccountQuery>) -> Response {
|
||||
let agent = q.agent.trim();
|
||||
let Ok(agent) = Ident::parse(agent) else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue