feat(server): create-user CLI + session-store migration on startup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 15:07:58 +02:00
parent 642f709bbe
commit dbff95c2a9
6 changed files with 159 additions and 8 deletions
+10 -1
View File
@@ -1,10 +1,11 @@
use clap::Parser;
use server::Config;
const CLEARED: [(&str, Option<&str>); 3] = [
const CLEARED: [(&str, Option<&str>); 4] = [
("DATABASE_URL", None),
("BIND_ADDR", None),
("APP_NAME", None),
("SESSION_COOKIE_SECURE", None),
];
#[test]
@@ -25,3 +26,11 @@ fn database_url_is_required() {
assert!(Config::try_parse_from(["server"]).is_err());
});
}
#[test]
fn cookie_secure_defaults_to_true() {
temp_env::with_vars(CLEARED, || {
let config = Config::try_parse_from(["server", "--database-url", "postgres://x"]).unwrap();
assert!(config.cookie_secure);
});
}
+40
View File
@@ -0,0 +1,40 @@
use db::Db;
use domain::Role;
use sqlx::PgPool;
// Note: `server::create_user` opens its own DB connection by URL, but `#[sqlx::test]`
// provisions a temporary database whose URL is not directly exposed. The test below
// exercises the same building blocks that `server::create_user` composes —
// `auth::hash_password` + `db::users::create_user` + `db::users::credentials_by_email` —
// against the test pool, which fully validates the end-to-end bootstrap logic.
#[sqlx::test(migrations = "../db/migrations")]
async fn create_user_persists_and_password_verifies(pool: PgPool) {
let db = Db::from_pool(pool.clone());
let hash = auth::hash_password("bootstrap-pw-123").unwrap();
let mut tx = db.pool().begin().await.unwrap();
db::users::create_user(
&mut tx,
domain::AuditActor::System,
&domain::NewUser {
email: domain::Email::parse("boss@example.com").unwrap(),
password_hash: hash,
role: Role::Admin,
},
)
.await
.unwrap();
tx.commit().await.unwrap();
let (user, stored_hash) = db::users::credentials_by_email(db.pool(), "boss@example.com")
.await
.unwrap()
.unwrap();
assert_eq!(user.role, Role::Admin);
assert!(auth::verify_password("bootstrap-pw-123", &stored_hash));
}