feat(#2302): fold is_plain_ident into PlainIdent newtype

This commit is contained in:
damocles 2026-07-19 17:56:55 +02:00 committed by mara
commit d4e91bfeeb
3 changed files with 112 additions and 86 deletions

View file

@ -23,20 +23,9 @@ use axum::extract::{Form, Query};
use axum::response::{IntoResponse, Response};
use serde::{Deserialize, Serialize};
use super::error_response;
use super::{error_response, idents::PlainIdent};
use crate::coordinator::Coordinator;
/// Plain-identifier check matching hive-priv's `validate_name_chars`
/// (lowercase ascii + digits + hyphens) — same guard used by
/// `matrix_accounts::is_plain_ident`. Duplicated locally (private, not
/// worth a shared-util churn for one predicate) rather than exported from
/// that module, since both call sites are dashboard-only.
fn is_plain_ident(s: &str) -> bool {
!s.is_empty()
&& s.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
}
#[derive(Deserialize)]
struct ForgeSidecar {
base_url: String,
@ -75,10 +64,10 @@ pub(super) struct ExtraForgesQuery {
/// sidecar when present. Never returns a token.
pub(super) async fn get_extra_forges(Query(q): Query<ExtraForgesQuery>) -> Response {
let agent = q.agent.trim();
if !is_plain_ident(agent) {
let Ok(agent) = PlainIdent::parse(agent) else {
return error_response(&format!("extra-forges: invalid agent {agent:?}"));
}
let dir = Coordinator::agent_notes_dir(agent);
};
let dir = Coordinator::agent_notes_dir(agent.as_str());
let mut forges = Vec::new();
match std::fs::read_dir(&dir) {
Ok(entries) => {
@ -141,12 +130,12 @@ struct ExtraForgeAccountResult {
pub(super) async fn post_extra_forge_account(Form(f): Form<ExtraForgeAccountForm>) -> Response {
let agent = f.agent.trim();
let label = f.label.trim();
if !is_plain_ident(agent) {
let Ok(agent) = PlainIdent::parse(agent) else {
return error_response(&format!("extra-forge-account: invalid agent {agent:?}"));
}
if !is_plain_ident(label) {
};
let Ok(label) = PlainIdent::parse(label) else {
return error_response(&format!("extra-forge-account: invalid label {label:?}"));
}
};
match f.action.as_str() {
"add" => {
@ -160,9 +149,13 @@ pub(super) async fn post_extra_forge_account(Form(f): Form<ExtraForgeAccountForm
let Some(token) = f.token.as_deref().filter(|t| !t.is_empty()) else {
return error_response("extra-forge-account: token is required");
};
if let Err(e) =
crate::priv_client::write_agent_extra_forge_account(agent, label, base_url, token)
.await
if let Err(e) = crate::priv_client::write_agent_extra_forge_account(
agent.as_str(),
label.as_str(),
base_url,
token,
)
.await
{
return error_response(&format!(
"extra-forge-account: write account failed: {e:#}"
@ -171,7 +164,9 @@ pub(super) async fn post_extra_forge_account(Form(f): Form<ExtraForgeAccountForm
tracing::info!(%agent, %label, "extra-forge-account: provisioned");
}
"remove" => {
if let Err(e) = crate::priv_client::delete_agent_extra_forge_account(agent, label).await
if let Err(e) =
crate::priv_client::delete_agent_extra_forge_account(agent.as_str(), label.as_str())
.await
{
return error_response(&format!(
"extra-forge-account: delete account failed: {e:#}"
@ -187,19 +182,3 @@ pub(super) async fn post_extra_forge_account(Form(f): Form<ExtraForgeAccountForm
}
axum::Json(ExtraForgeAccountResult { ok: true }).into_response()
}
#[cfg(test)]
mod tests {
use super::is_plain_ident;
#[test]
fn is_plain_ident_matches_validate_name_chars() {
assert!(is_plain_ident("codeberg"));
assert!(is_plain_ident("my-forge-1"));
assert!(!is_plain_ident(""));
assert!(!is_plain_ident("MyForge"));
assert!(!is_plain_ident("my_forge"));
assert!(!is_plain_ident("../escape"));
assert!(!is_plain_ident("a/b"));
}
}