Moved all database code to db module

develop
Jef Roosens 2021-09-01 12:50:33 +02:00
parent 2cc4d53961
commit fb2a6126fe
Signed by untrusted user: Jef Roosens
GPG Key ID: B580B976584B5F30
8 changed files with 67 additions and 33 deletions

4
.dockerignore 100644
View File

@ -0,0 +1,4 @@
.vim/
out/
vendor/
target/

3
.gitignore vendored
View File

@ -16,3 +16,6 @@ out/
# Added by cargo
/target
.vim/
vendor/

View File

@ -1,4 +1,4 @@
use diesel::{insert_into, prelude::*, PgConnection};
use diesel::PgConnection;
use rocket::serde::json::Json;
use uuid::Uuid;
@ -7,7 +7,6 @@ use crate::{
db,
errors::{RbError, RbResult},
guards::Admin,
schema::users::dsl as users,
RbDbConn,
};
@ -49,12 +48,7 @@ pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) ->
admin: true,
};
insert_into(users::users)
.values(&new_user)
.on_conflict(users::username)
.do_update()
.set(&new_user)
.execute(conn)
db::users::create_or_update(conn, &new_user)
.map_err(|_| RbError::Custom("Couldn't create admin."))?;
Ok(true)

View File

@ -1,5 +1,5 @@
use chrono::Utc;
use diesel::{prelude::*, PgConnection};
use diesel::PgConnection;
use hmac::{Hmac, NewMac};
use jwt::SignWithKey;
use rand::{thread_rng, Rng};
@ -8,9 +8,7 @@ use sha2::Sha256;
use crate::{
db,
db::{tokens::NewRefreshToken, users::User},
errors::{RbError, RbResult},
schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users},
RbJwtConf,
};
@ -34,7 +32,7 @@ pub struct Claims
pub fn generate_jwt_token(
conn: &PgConnection,
jwt: &RbJwtConf,
user: &User,
user: &db::User,
) -> RbResult<JWTResponse>
{
let key: Hmac<Sha256> = Hmac::new_from_slice(jwt.key.as_bytes())
@ -65,7 +63,7 @@ pub fn generate_jwt_token(
// Store refresh token in database
db::tokens::create(
conn,
&NewRefreshToken {
&db::NewRefreshToken {
token: refresh_token.to_vec(),
user_id: user.id,
expires_at: refresh_expire,
@ -93,11 +91,10 @@ pub fn refresh_token(
// If we see that the token has already been used before, we block the user.
if token_entry.last_used_at.is_some() {
let target = users::users.filter(users::id.eq(token_entry.user_id));
diesel::update(target)
.set(users::blocked.eq(true))
.execute(conn)
.map_err(|_| RbError::Custom("Couldn't block user."))?;
// If we fail to block the user, the end user must know
if let Err(err) = db::users::block(conn, token_entry.user_id) {
return Err(err);
}
return Err(RbError::AuthDuplicateRefreshToken);
}
@ -110,11 +107,7 @@ pub fn refresh_token(
}
// We update the last_used_at value for the refresh token
let target = refresh_tokens::refresh_tokens.filter(refresh_tokens::token.eq(token_entry.token));
diesel::update(target)
.set(refresh_tokens::last_used_at.eq(cur_time))
.execute(conn)
.map_err(|_| RbError::Custom("Couldn't update last used time."))?;
db::tokens::update_last_used_at(conn, &token_entry.token, cur_time)?;
generate_jwt_token(conn, jwt, &user)
}

View File

@ -5,7 +5,7 @@ use self::{
jwt::{generate_jwt_token, JWTResponse},
pass::verify_user,
};
use crate::{errors::RbResult, guards::User, RbConfig, RbDbConn, RbJwtConf};
use crate::{errors::RbResult, guards::User, RbConfig, RbDbConn};
pub mod jwt;
pub mod pass;

View File

@ -1,20 +1,16 @@
use argon2::verify_encoded;
use diesel::{prelude::*, PgConnection};
use diesel::PgConnection;
use rand::{thread_rng, Rng};
use crate::{
db::users::User,
db,
errors::{RbError, RbResult},
schema::users::dsl as users,
};
pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> RbResult<User>
pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> RbResult<db::User>
{
// TODO handle non-"NotFound" Diesel errors accordingely
let user = users::users
.filter(users::username.eq(username))
.first::<User>(conn)
.map_err(|_| RbError::AuthUnknownUser)?;
let user = db::users::find_by_username(conn, username).map_err(|_| RbError::AuthUnknownUser)?;
// Check if a user is blocked
if user.blocked {

View File

@ -56,3 +56,17 @@ pub fn find_with_user(
.map_err(|_| RbError::Custom("Couldn't get refresh token & user."))
.ok()
}
pub fn update_last_used_at(
conn: &PgConnection,
token_: &[u8],
last_used_at_: chrono::NaiveDateTime,
) -> RbResult<()>
{
diesel::update(refresh_tokens.filter(token.eq(token_)))
.set(last_used_at.eq(last_used_at_))
.execute(conn)
.map_err(|_| RbError::DbError("Couldn't update last_used_at."))?;
Ok(())
}

View File

@ -14,7 +14,6 @@ pub struct User
pub username: String,
#[serde(skip_serializing)]
pub password: String,
#[serde(skip_serializing)]
pub blocked: bool,
pub admin: bool,
}
@ -40,6 +39,14 @@ pub fn find(conn: &PgConnection, user_id: Uuid) -> Option<User>
users.find(user_id).first::<User>(conn).ok()
}
pub fn find_by_username(conn: &PgConnection, username_: &str) -> RbResult<User>
{
Ok(users
.filter(username.eq(username_))
.first::<User>(conn)
.map_err(|_| RbError::DbError("Couldn't find users by username."))?)
}
pub fn create(conn: &PgConnection, new_user: &NewUser) -> RbResult<()>
{
let count = diesel::insert_into(users)
@ -54,6 +61,19 @@ pub fn create(conn: &PgConnection, new_user: &NewUser) -> RbResult<()>
Ok(())
}
pub fn create_or_update(conn: &PgConnection, new_user: &NewUser) -> RbResult<()>
{
diesel::insert_into(users)
.values(new_user)
.on_conflict(username)
.do_update()
.set(new_user)
.execute(conn)
.map_err(|_| RbError::DbError("Couldn't create or update user."))?;
Ok(())
}
pub fn delete(conn: &PgConnection, user_id: Uuid) -> RbResult<()>
{
diesel::delete(users.filter(id.eq(user_id)))
@ -62,3 +82,13 @@ pub fn delete(conn: &PgConnection, user_id: Uuid) -> RbResult<()>
Ok(())
}
pub fn block(conn: &PgConnection, user_id: Uuid) -> RbResult<()>
{
diesel::update(users.filter(id.eq(user_id)))
.set(blocked.eq(true))
.execute(conn)
.map_err(|_| RbError::DbError("Couldn't block user."))?;
Ok(())
}