Moved all database code to db module
parent
2cc4d53961
commit
fb2a6126fe
|
@ -0,0 +1,4 @@
|
||||||
|
.vim/
|
||||||
|
out/
|
||||||
|
vendor/
|
||||||
|
target/
|
|
@ -16,3 +16,6 @@ out/
|
||||||
# Added by cargo
|
# Added by cargo
|
||||||
|
|
||||||
/target
|
/target
|
||||||
|
|
||||||
|
.vim/
|
||||||
|
vendor/
|
||||||
|
|
10
src/admin.rs
10
src/admin.rs
|
@ -1,4 +1,4 @@
|
||||||
use diesel::{insert_into, prelude::*, PgConnection};
|
use diesel::PgConnection;
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ use crate::{
|
||||||
db,
|
db,
|
||||||
errors::{RbError, RbResult},
|
errors::{RbError, RbResult},
|
||||||
guards::Admin,
|
guards::Admin,
|
||||||
schema::users::dsl as users,
|
|
||||||
RbDbConn,
|
RbDbConn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,12 +48,7 @@ pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) ->
|
||||||
admin: true,
|
admin: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
insert_into(users::users)
|
db::users::create_or_update(conn, &new_user)
|
||||||
.values(&new_user)
|
|
||||||
.on_conflict(users::username)
|
|
||||||
.do_update()
|
|
||||||
.set(&new_user)
|
|
||||||
.execute(conn)
|
|
||||||
.map_err(|_| RbError::Custom("Couldn't create admin."))?;
|
.map_err(|_| RbError::Custom("Couldn't create admin."))?;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use diesel::{prelude::*, PgConnection};
|
use diesel::PgConnection;
|
||||||
use hmac::{Hmac, NewMac};
|
use hmac::{Hmac, NewMac};
|
||||||
use jwt::SignWithKey;
|
use jwt::SignWithKey;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
@ -8,9 +8,7 @@ use sha2::Sha256;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db,
|
db,
|
||||||
db::{tokens::NewRefreshToken, users::User},
|
|
||||||
errors::{RbError, RbResult},
|
errors::{RbError, RbResult},
|
||||||
schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users},
|
|
||||||
RbJwtConf,
|
RbJwtConf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,7 +32,7 @@ pub struct Claims
|
||||||
pub fn generate_jwt_token(
|
pub fn generate_jwt_token(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
jwt: &RbJwtConf,
|
jwt: &RbJwtConf,
|
||||||
user: &User,
|
user: &db::User,
|
||||||
) -> RbResult<JWTResponse>
|
) -> RbResult<JWTResponse>
|
||||||
{
|
{
|
||||||
let key: Hmac<Sha256> = Hmac::new_from_slice(jwt.key.as_bytes())
|
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
|
// Store refresh token in database
|
||||||
db::tokens::create(
|
db::tokens::create(
|
||||||
conn,
|
conn,
|
||||||
&NewRefreshToken {
|
&db::NewRefreshToken {
|
||||||
token: refresh_token.to_vec(),
|
token: refresh_token.to_vec(),
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
expires_at: refresh_expire,
|
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 we see that the token has already been used before, we block the user.
|
||||||
if token_entry.last_used_at.is_some() {
|
if token_entry.last_used_at.is_some() {
|
||||||
let target = users::users.filter(users::id.eq(token_entry.user_id));
|
// If we fail to block the user, the end user must know
|
||||||
diesel::update(target)
|
if let Err(err) = db::users::block(conn, token_entry.user_id) {
|
||||||
.set(users::blocked.eq(true))
|
return Err(err);
|
||||||
.execute(conn)
|
}
|
||||||
.map_err(|_| RbError::Custom("Couldn't block user."))?;
|
|
||||||
|
|
||||||
return Err(RbError::AuthDuplicateRefreshToken);
|
return Err(RbError::AuthDuplicateRefreshToken);
|
||||||
}
|
}
|
||||||
|
@ -110,11 +107,7 @@ pub fn refresh_token(
|
||||||
}
|
}
|
||||||
|
|
||||||
// We update the last_used_at value for the 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));
|
db::tokens::update_last_used_at(conn, &token_entry.token, cur_time)?;
|
||||||
diesel::update(target)
|
|
||||||
.set(refresh_tokens::last_used_at.eq(cur_time))
|
|
||||||
.execute(conn)
|
|
||||||
.map_err(|_| RbError::Custom("Couldn't update last used time."))?;
|
|
||||||
|
|
||||||
generate_jwt_token(conn, jwt, &user)
|
generate_jwt_token(conn, jwt, &user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use self::{
|
||||||
jwt::{generate_jwt_token, JWTResponse},
|
jwt::{generate_jwt_token, JWTResponse},
|
||||||
pass::verify_user,
|
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 jwt;
|
||||||
pub mod pass;
|
pub mod pass;
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
use argon2::verify_encoded;
|
use argon2::verify_encoded;
|
||||||
use diesel::{prelude::*, PgConnection};
|
use diesel::PgConnection;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::users::User,
|
db,
|
||||||
errors::{RbError, RbResult},
|
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
|
// TODO handle non-"NotFound" Diesel errors accordingely
|
||||||
let user = users::users
|
let user = db::users::find_by_username(conn, username).map_err(|_| RbError::AuthUnknownUser)?;
|
||||||
.filter(users::username.eq(username))
|
|
||||||
.first::<User>(conn)
|
|
||||||
.map_err(|_| RbError::AuthUnknownUser)?;
|
|
||||||
|
|
||||||
// Check if a user is blocked
|
// Check if a user is blocked
|
||||||
if user.blocked {
|
if user.blocked {
|
||||||
|
|
|
@ -56,3 +56,17 @@ pub fn find_with_user(
|
||||||
.map_err(|_| RbError::Custom("Couldn't get refresh token & user."))
|
.map_err(|_| RbError::Custom("Couldn't get refresh token & user."))
|
||||||
.ok()
|
.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(())
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ pub struct User
|
||||||
pub username: String,
|
pub username: String,
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub password: String,
|
pub password: String,
|
||||||
#[serde(skip_serializing)]
|
|
||||||
pub blocked: bool,
|
pub blocked: bool,
|
||||||
pub admin: 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()
|
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<()>
|
pub fn create(conn: &PgConnection, new_user: &NewUser) -> RbResult<()>
|
||||||
{
|
{
|
||||||
let count = diesel::insert_into(users)
|
let count = diesel::insert_into(users)
|
||||||
|
@ -54,6 +61,19 @@ pub fn create(conn: &PgConnection, new_user: &NewUser) -> RbResult<()>
|
||||||
Ok(())
|
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<()>
|
pub fn delete(conn: &PgConnection, user_id: Uuid) -> RbResult<()>
|
||||||
{
|
{
|
||||||
diesel::delete(users.filter(id.eq(user_id)))
|
diesel::delete(users.filter(id.eq(user_id)))
|
||||||
|
@ -62,3 +82,13 @@ pub fn delete(conn: &PgConnection, user_id: Uuid) -> RbResult<()>
|
||||||
|
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
|
|
Reference in New Issue