pub async fn run() -> Result<(), String> {
let url = match std::env::var("DATABASE_URL") {
Ok(u) => u,
Err(_) => {
println!("✗ DATABASE_URL is not set. Add it to .env or your shell environment.");
return Err("DATABASE_URL missing".into());
}
};
println!("✓ DATABASE_URL = {}", crate::redact_password(&url));
let step = crate::progress::Step::start("Connecting to PostgreSQL");
let db = match rustio_admin::Db::connect(&url).await {
Ok(d) => {
step.done_with("Connected to PostgreSQL");
d
}
Err(e) => {
step.failed_with(format!("Could not connect: {e}"));
return Err("connect failed".into());
}
};
let exists: bool = sqlx::query_scalar(
"SELECT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_name = 'rustio_users'
)",
)
.fetch_one(db.pool())
.await
.map_err(|e| format!("table check: {e}"))?;
if exists {
println!("✓ Auth tables present");
} else {
println!(
"· Auth tables missing -- boot the app once or run `rustio user create` to seed them."
);
}
let admin_count: i64 = if exists {
sqlx::query_scalar(
"SELECT COUNT(*) FROM rustio_users \
WHERE role IN ('administrator', 'developer') AND is_active = TRUE",
)
.fetch_one(db.pool())
.await
.unwrap_or(0)
} else {
0
};
if admin_count > 0 {
println!("✓ {admin_count} active administrator(s)");
} else {
println!(
"· No active administrator. Run `rustio user create --email … --role administrator`."
);
}
match std::env::var("RUSTIO_SECRET_KEY") {
Ok(v) if v.len() >= 43 => {
println!("✓ RUSTIO_SECRET_KEY set ({} chars)", v.len());
}
Ok(v) if v.is_empty() => {
println!(
"· RUSTIO_SECRET_KEY is empty. Required for R3 MFA + R4 export \
signing. Generate with: \
`openssl rand 32 | base64 | tr '+/' '-_' | tr -d '='`"
);
}
Ok(v) => {
println!(
"✗ RUSTIO_SECRET_KEY is too short ({} chars; need ≥ 43 URL-safe-base64 \
chars = 32 raw bytes). MFA enrol + emergency-access URL signing \
will refuse. Regenerate with: \
`openssl rand 32 | base64 | tr '+/' '-_' | tr -d '='`",
v.len()
);
}
Err(_) => {
println!(
"· RUSTIO_SECRET_KEY is not set. Required for R3 MFA + R4 export \
signing. Add to `.env`: \
`RUSTIO_SECRET_KEY=$(openssl rand 32 | base64 | tr '+/' '-_' | tr -d '=')`"
);
}
}
if exists {
let mfa_count: Option<i64> =
sqlx::query_scalar("SELECT COUNT(*) FROM rustio_users WHERE mfa_enabled = TRUE")
.fetch_optional(db.pool())
.await
.unwrap_or(None);
if let Some(n) = mfa_count {
if n > 0 {
println!("✓ {n} user(s) enrolled in MFA");
} else {
println!("· No users enrolled in MFA yet (visit /admin/account/mfa/enroll while logged in)");
}
}
}
if exists {
let emerg_count: Option<i64> = sqlx::query_scalar(
"SELECT COUNT(*) FROM rustio_admin_actions \
WHERE action_type = 'emergency_recovery'",
)
.fetch_optional(db.pool())
.await
.unwrap_or(None);
if let Some(n) = emerg_count {
if n > 0 {
println!(
"· {n} emergency-recovery audit row(s) on file (see /admin/history?action=emergency_recovery)"
);
}
}
}
if exists {
let legacy_count: Option<i64> = sqlx::query_scalar(
"SELECT COUNT(*) FROM rustio_admin_actions \
WHERE model_name IN \
('User','user','rustio_users','Group','group','rustio_groups')",
)
.fetch_optional(db.pool())
.await
.unwrap_or(None);
if let Some(n) = legacy_count {
if n > 0 {
println!(
"✗ {n} audit row(s) still carry legacy model_name slugs (`User` / \
`user` / `rustio_users` / `Group` / `group` / `rustio_groups`). \
The History page links to `/admin/{{slug}}/…` and these slugs 404. \
Boot against rustio-admin ≥ 0.8.1 to apply the backfill, OR \
fix any project-side audit emitter that writes these strings."
);
} else {
println!("✓ Audit model_name slugs all canonical (0.8.1 backfill clean)");
}
}
}
Ok(())
}