bda1ef251a
calling this v0.4.0
97 lines
2.9 KiB
Rust
97 lines
2.9 KiB
Rust
use clap::{Parser, Subcommand};
|
|
use sqlx::postgres::PgPoolOptions;
|
|
use std::time::Duration;
|
|
use std::sync::Arc;
|
|
use crate::repo::user_repo::UserRepository;
|
|
use crate::repo::space_repo::SpaceRepository;
|
|
use crate::repo::channel_repo::ChannelRepository;
|
|
use crate::repo::{UserRepo, SpaceRepo, ChannelRepo};
|
|
use argon2::{
|
|
password_hash::{PasswordHasher, SaltString},
|
|
Argon2,
|
|
};
|
|
use rand::rngs::OsRng;
|
|
|
|
#[derive(Parser)]
|
|
#[command(author, version, about, long_about = None)]
|
|
pub struct Cli {
|
|
#[command(subcommand)]
|
|
pub command: Option<Commands>,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum Commands {
|
|
/// First-time setup for the server
|
|
Setup {
|
|
/// Admin username
|
|
#[arg(short, long)]
|
|
username: String,
|
|
|
|
/// Admin password
|
|
#[arg(short, long)]
|
|
password: String,
|
|
|
|
/// Default space name
|
|
#[arg(short, long, default_value = "Default Space")]
|
|
space: String,
|
|
|
|
/// Default channel name
|
|
#[arg(short, long, default_value = "general")]
|
|
channel: String,
|
|
},
|
|
}
|
|
|
|
pub async fn handle_cli() -> bool {
|
|
let cli = Cli::parse();
|
|
|
|
match cli.command {
|
|
Some(Commands::Setup { username, password, space, channel }) => {
|
|
if let Err(e) = run_setup(username, password, space, channel).await {
|
|
eprintln!("Setup failed: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
println!("Setup completed successfully!");
|
|
true
|
|
}
|
|
None => false,
|
|
}
|
|
}
|
|
|
|
async fn run_setup(username: String, password: String, space_name: String, channel_name: String) -> Result<(), Box<dyn std::error::Error>> {
|
|
dotenv::dotenv().ok();
|
|
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
|
|
|
let pool = PgPoolOptions::new()
|
|
.max_connections(1)
|
|
.acquire_timeout(Duration::from_secs(5))
|
|
.connect(&db_url)
|
|
.await?;
|
|
|
|
let user_repo = UserRepository::new(pool.clone());
|
|
let space_repo = SpaceRepository::new(pool.clone());
|
|
let channel_repo = ChannelRepository::new(pool.clone());
|
|
|
|
// 1. Create admin user
|
|
println!("Creating admin user: {}...", username);
|
|
|
|
let argon2 = Argon2::default();
|
|
let salt = SaltString::generate(&mut OsRng);
|
|
let passhash = argon2
|
|
.hash_password(password.as_bytes(), &salt)
|
|
.map_err(|e| e.to_string())?
|
|
.to_string();
|
|
|
|
let user_id = user_repo.new_user("admin@localhost", &username, &passhash).await?;
|
|
user_repo.set_role(user_id, "admin").await?;
|
|
|
|
// 2. Create default space
|
|
println!("Creating default space: {}...", space_name);
|
|
let space_id = space_repo.create(&space_name, Some("Default space created during setup"), user_id).await?;
|
|
|
|
// 3. Create default channel
|
|
println!("Creating default channel: {}...", channel_name);
|
|
channel_repo.create(&channel_name, Some("Default channel"), space_id).await?;
|
|
|
|
Ok(())
|
|
}
|