create password reset utility

Co-authored-by: Wout Schellaert <wout.schellaert@gmail.com>
This commit is contained in:
Ilion Beyst 2022-08-09 23:27:22 +02:00
parent 58c1c5f9fb
commit 406c726601
4 changed files with 92 additions and 8 deletions

View file

@ -2,8 +2,16 @@
name = "planetwars-server"
version = "0.0.0"
edition = "2021"
default-run = "planetwars-server"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "planetwars-server"
path = "src/main.rs"
[[bin]]
name = "planetwars-server-cli"
path = "src/cli.rs"
[dependencies]
futures = "0.3"
@ -32,6 +40,7 @@ sha2 = "0.10"
tokio-util = { version="0.7.3", features=["io"] }
prost = "0.10"
tonic = "0.7.2"
clap = { version = "3.2", features = ["derive", "env"]}
# TODO: remove me
shlex = "1.1"

View file

@ -0,0 +1,54 @@
extern crate planetwars_server;
extern crate tokio;
use clap::Parser;
use planetwars_server::db;
use planetwars_server::{create_db_pool, get_config};
#[derive(clap::Parser)]
struct Args {
#[clap(subcommand)]
action: Action,
}
#[derive(clap::Subcommand)]
enum Action {
SetPassword(SetPassword),
}
impl Action {
async fn run(self) {
match self {
Action::SetPassword(set_password) => set_password.run().await,
}
}
}
#[derive(clap::Parser)]
struct SetPassword {
#[clap(value_parser)]
username: String,
#[clap(value_parser)]
new_password: String,
}
impl SetPassword {
async fn run(self) {
let global_config = get_config().unwrap();
let pool = create_db_pool(&global_config).await;
let conn = pool.get().await.expect("could not get database connection");
let credentials = db::users::Credentials {
username: &self.username,
password: &self.new_password,
};
db::users::set_user_password(credentials, &conn).expect("could not set password");
}
}
#[tokio::main]
pub async fn main() {
let args = Args::parse();
args.action.run().await;
}

View file

@ -42,11 +42,17 @@ fn argon2_config() -> argon2::Config<'static> {
}
}
pub fn create_user(credentials: &Credentials, conn: &PgConnection) -> QueryResult<User> {
pub fn hash_password(password: &str) -> (Vec<u8>, [u8; 32]) {
let argon_config = argon2_config();
let salt: [u8; 32] = rand::thread_rng().gen();
let hash = argon2::hash_raw(credentials.password.as_bytes(), &salt, &argon_config).unwrap();
let hash = argon2::hash_raw(password.as_bytes(), &salt, &argon_config).unwrap();
(hash, salt)
}
pub fn create_user(credentials: &Credentials, conn: &PgConnection) -> QueryResult<User> {
let (hash, salt) = hash_password(&credentials.password);
let new_user = NewUser {
username: credentials.username,
password_salt: &salt,
@ -69,6 +75,22 @@ pub fn find_user_by_name(username: &str, db_conn: &PgConnection) -> QueryResult<
.first::<User>(db_conn)
}
pub fn set_user_password(credentials: Credentials, db_conn: &PgConnection) -> QueryResult<()> {
let (hash, salt) = hash_password(&credentials.password);
let n_changes = diesel::update(users::table.filter(users::username.eq(&credentials.username)))
.set((
users::password_salt.eq(salt.as_slice()),
users::password_hash.eq(hash.as_slice()),
))
.execute(db_conn)?;
if n_changes == 0 {
Err(diesel::result::Error::NotFound)
} else {
Ok(())
}
}
pub fn authenticate_user(credentials: &Credentials, db_conn: &PgConnection) -> Option<User> {
find_user_by_name(credentials.username, db_conn)
.optional()

View file

@ -94,11 +94,9 @@ pub async fn seed_simplebot(config: &GlobalConfig, pool: &ConnectionPool) {
pub type DbPool = Pool<DieselConnectionManager<PgConnection>>;
pub async fn prepare_db(config: &GlobalConfig) -> DbPool {
pub async fn create_db_pool(config: &GlobalConfig) -> DbPool {
let manager = DieselConnectionManager::<PgConnection>::new(&config.database_url);
let pool = bb8::Pool::builder().build(manager).await.unwrap();
seed_simplebot(config, &pool).await;
pool
bb8::Pool::builder().build(manager).await.unwrap()
}
// create all directories required for further operation
@ -165,7 +163,8 @@ async fn run_registry(config: Arc<GlobalConfig>, db_pool: DbPool) {
pub async fn run_app() {
let global_config = Arc::new(get_config().unwrap());
let db_pool = prepare_db(&global_config).await;
let db_pool = create_db_pool(&global_config).await;
seed_simplebot(&global_config, &db_pool).await;
init_directories(&global_config).unwrap();
if global_config.ranker_enabled {