feat(gateway): hivectl gateway user management + fix htpasswdFile assertion

Add `hivectl gateway {create-user,delete-user,list-users}` subcommands for
managing htpasswd files used by gateway Basic auth. Pure Rust bcrypt
(cost 12, $2y$ prefix nginx accepts). No external htpasswd binary required.

Also fix the NixOS module assertion: `cfg.auth ? htpasswdFile` is always
true in the module system (declared options always exist as keys); switch
to `nullOr path; default = null` + `!= null` check so the assertion
actually fires with a useful error when enable=true but no file is set.
Guard bind-mount and nginx config against null to prevent eval errors.

Update docs/gateway.md to show hivectl commands instead of raw htpasswd.
This commit is contained in:
atlas 2026-06-01 23:00:38 +02:00
commit 4bff450343
61 changed files with 1084 additions and 547 deletions

View file

@ -217,7 +217,14 @@ async fn ensure_user_exists(name: &str, admin: bool, password: Option<&str>) ->
/// from the operator's point of view: same password input → same final
/// account state.
async fn change_user_password(name: &str, password: &str) -> Result<()> {
let args = ["user", "change-password", "--username", name, "--password", password];
let args = [
"user",
"change-password",
"--username",
name,
"--password",
password,
];
forge_admin(&args)
.await
.with_context(|| format!("forgejo admin user change-password {name}"))?;
@ -551,9 +558,8 @@ pub async fn ensure_shared_docs_repo(core_token: &str) -> Result<()> {
/// Mirrors `meta_read_access` so agents can clone the shared docs repo
/// without authentication hassle.
pub async fn shared_docs_access(name: &str, core_token: &str) -> Result<()> {
let url = format!(
"{FORGE_HTTP}/api/v1/repos/{SHARED_ORG}/{SHARED_DOCS_REPO}/collaborators/{name}"
);
let url =
format!("{FORGE_HTTP}/api/v1/repos/{SHARED_ORG}/{SHARED_DOCS_REPO}/collaborators/{name}");
let body = r#"{"permission":"read"}"#;
let out = Command::new("curl")
.args([