Mercurial > lbo > hg > analyrics
view src/configdb.rs @ 76:a58e1922e173
Fix some redirects and date calculations
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Fri, 09 Sep 2022 07:08:20 +0200 |
parents | b9d9b4508898 |
children | fd0237049be0 |
line wrap: on
line source
use crate::db::{DBType, PoolType}; use anyhow::Error; use log::{debug, error, info, warn, Level}; use rand::distributions::{Alphanumeric, DistString}; use rocket::futures::StreamExt; use rocket_db_pools::sqlx::{Executor, Row, Sqlite, SqlitePool}; use rocket_db_pools::{Connection, Database, Pool}; use sqlx::prelude::FromRow; fn generate_salt() -> String { Alphanumeric.sample_string(&mut rand::thread_rng(), 16) } // TO DO: use other databases? #[derive(Database)] #[database("sqlite_main")] pub struct ConfigDB(pub PoolType); #[derive(Default, Clone, Debug, FromRow)] pub struct UserRecord { pub name: String, pub tz_offset: i64, } pub struct ConfigDBSession<'p, DB: sqlx::Database>(pub &'p mut sqlx::pool::PoolConnection<DB>); impl<'p> ConfigDBSession<'p, Sqlite> { pub async fn check_user_password<S0: AsRef<str>, S1: AsRef<str>>( &mut self, user: S0, password: S1, ) -> Result<bool, Error> { // TODO: salt passwords. let salt: String = match sqlx::query("SELECT salt FROM users WHERE username = ? LIMIT 1;") .bind(user.as_ref()) .fetch_one(&mut *self.0) .await { Ok(r) => r.get(0), Err(e) => { warn!("Error querying salt: {}", e); return Ok(false); } }; let pwdhash = sha256::digest(format!("{}{}", salt, password.as_ref())); let q = sqlx::query("SELECT username FROM users WHERE username = ? AND password_hash = ?;") .bind(user.as_ref()) .bind(pwdhash); let result = self.0.fetch_all(q).await?; Ok(result.len() == 1) } pub async fn get_user_details(&mut self, user: &str) -> Result<UserRecord, Error> { let entry = sqlx::query("SELECT name, tz_offset FROM users WHERE username = ? LIMIT 1") .bind(user) .fetch_one(&mut *self.0) .await?; Ok(UserRecord::from_row(&entry)?) } pub async fn update_user_password<S0: AsRef<str>, S1: AsRef<str>, S2: AsRef<str>>( &mut self, user: S0, oldpass: S1, newpass: S2, ) -> Result<(), Error> { if !self.check_user_password(user, oldpass).await? { anyhow::bail!("User not authorized (wrong password?)") } // Old password is ok. let salt = generate_salt(); let newpass_hash = sha256::digest(format!("{}{}", salt, newpass.as_ref())); sqlx::query("UPDATE users SET salt = ?, password_hash = ?;") .bind(salt) .bind(newpass_hash) .execute(&mut *self.0) .await?; Ok(()) } pub async fn update_user_tz<S0: AsRef<str>>( &mut self, user: S0, tz_offset: i64, ) -> Result<(), Error> { if sqlx::query("SELECT username FROM users WHERE username = ?") .bind(user.as_ref()) .fetch_all(&mut *self.0) .await? .len() != 1 { anyhow::bail!("User not found, or duplicate user {}", user.as_ref()) } sqlx::query("UPDATE users SET tz_offset = ? WHERE username = ?") .bind(tz_offset) .bind(user.as_ref()) .execute(&mut *self.0) .await?; Ok(()) } pub async fn is_admin<S0: AsRef<str>>(&mut self, user: S0) -> Result<bool, Error> { Ok(sqlx::query("SELECT is_admin FROM users JOIN permissions ON (users.id = permissions.user_id) WHERE username = ?") .bind(user.as_ref()) .fetch_one(&mut *self.0) .await? .get(0)) } }