view src/configdb.rs @ 26:b1850e6f4d9a

Split up source code
author Lewin Bormann <lbo@spheniscida.de>
date Thu, 14 Jul 2022 20:35:14 -0700
parents
children 792eb8ac3d93
line wrap: on
line source


use crate::db::{PoolType, DBType};

use anyhow::Error;
use log::{debug, error, info, warn, Level};

use rocket::futures::StreamExt;
use rocket_db_pools::sqlx::{Executor, Row, Sqlite, SqlitePool};
use rocket_db_pools::{Connection, Database, Pool};
use sqlx::prelude::FromRow;

// 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<S: AsRef<str>>(
        &mut self,
        user: S,
        password: S,
    ) -> 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)?)
    }
}