forked from Roflin/gamenight
Splits database into a separate crate
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
pub mod request;
|
||||
pub mod schema;
|
||||
pub mod util;
|
||||
|
||||
use actix_cors::Cors;
|
||||
use actix_web::middleware::Logger;
|
||||
@@ -8,31 +6,15 @@ use actix_web::HttpServer;
|
||||
use actix_web::App;
|
||||
use actix_web::http;
|
||||
use actix_web::web;
|
||||
use diesel::PgConnection;
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||
use request::{login, register, gamenights, gamenight_post, gamenight_get};
|
||||
use util::GetConnection;
|
||||
use tracing_actix_web::TracingLogger;
|
||||
|
||||
pub(crate) type DbPool = Pool<ConnectionManager<PgConnection>>;
|
||||
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
||||
|
||||
fn run_migration(conn: &mut PgConnection) {
|
||||
conn.run_pending_migrations(MIGRATIONS).unwrap();
|
||||
}
|
||||
use gamenight_database::*;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let url = "postgres://root:root@127.0.0.1/gamenight";
|
||||
let manager = ConnectionManager::<PgConnection>::new(url);
|
||||
// Refer to the `r2d2` documentation for more methods to use
|
||||
// when building a connection pool
|
||||
let pool = Pool::builder()
|
||||
.test_on_check_out(true)
|
||||
.build(manager)
|
||||
.expect("Could not build connection pool");
|
||||
|
||||
let pool = get_connection_pool(url);
|
||||
|
||||
let mut conn = pool.get_conn();
|
||||
run_migration(&mut conn);
|
||||
|
||||
@@ -6,7 +6,7 @@ use jsonwebtoken::{encode, Header, EncodingKey, decode, DecodingKey, Validation}
|
||||
use serde::{Serialize, Deserialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{schema::user::{User, get_user}, DbPool};
|
||||
use gamenight_database::{user::{get_user, Role, User}, DbPool};
|
||||
|
||||
use super::error::ApiError;
|
||||
|
||||
@@ -16,6 +16,24 @@ pub struct Claims {
|
||||
uid: Uuid
|
||||
}
|
||||
|
||||
pub struct AuthUser {
|
||||
pub id: Uuid,
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub role: Role,
|
||||
}
|
||||
|
||||
impl From<User> for AuthUser {
|
||||
fn from(value: User) -> Self {
|
||||
Self{
|
||||
id: value.id,
|
||||
username: value.username,
|
||||
email: value.email,
|
||||
role: value.role,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_claims(req: &HttpRequest) -> Result<Claims, ApiError> {
|
||||
let token = req.headers()
|
||||
.get(http::header::AUTHORIZATION)
|
||||
@@ -43,18 +61,19 @@ pub fn get_token(user: &User) -> Result<String, ApiError> {
|
||||
&EncodingKey::from_secret(secret.as_bytes()))?)
|
||||
}
|
||||
|
||||
impl FromRequest for User {
|
||||
impl FromRequest for AuthUser {
|
||||
type Error = ApiError;
|
||||
type Future = Ready<Result<Self, Self::Error>>;
|
||||
|
||||
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
|
||||
ready(
|
||||
(|| -> Result<User, ApiError>{
|
||||
(|| -> Result<AuthUser, ApiError>{
|
||||
let pool = req.app_data::<Data<DbPool>>().expect("No database configured");
|
||||
let mut conn = pool.get().expect("couldn't get db connection from pool");
|
||||
let uid = get_claims(req)?.uid;
|
||||
let user = get_user(&mut conn, uid)?;
|
||||
|
||||
Ok(get_user(&mut conn, uid)?)
|
||||
Ok(user.into())
|
||||
})()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use actix_web::{ResponseError, error::BlockingError, HttpResponse, http::{header
|
||||
use serde::{Serialize, Deserialize};
|
||||
use validator::ValidationErrors;
|
||||
|
||||
use crate::schema::error::DatabaseError;
|
||||
use gamenight_database::error::DatabaseError;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ApiError {
|
||||
|
||||
@@ -2,18 +2,18 @@ use actix_web::{get, web, Responder, http::header::ContentType, HttpResponse, po
|
||||
use chrono::{DateTime, ParseError};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::schema::{self};
|
||||
use crate::schema::user::User;
|
||||
use gamenight_database::{gamenight::Gamenight, DbPool, GetConnection};
|
||||
|
||||
use crate::request::authorization::AuthUser;
|
||||
use crate::request::requests::GamenightGet;
|
||||
use crate::request::requests::GamenightPost;
|
||||
use crate::request::responses::GameNightsResponse;
|
||||
use crate::request::error::ApiError;
|
||||
use crate::DbPool;
|
||||
use crate::util::GetConnection;
|
||||
|
||||
|
||||
impl GamenightPost {
|
||||
pub fn into_with_user(&self, user: User) -> Result<schema::gamenight::Gamenight, ParseError> {
|
||||
Ok(schema::gamenight::Gamenight {
|
||||
pub fn into_with_user(&self, user: AuthUser) -> Result<Gamenight, ParseError> {
|
||||
Ok(Gamenight {
|
||||
datetime: DateTime::parse_from_rfc3339(&self.datetime)?.with_timezone(&chrono::Utc),
|
||||
id: Uuid::new_v4(),
|
||||
name: self.name.clone(),
|
||||
@@ -29,9 +29,9 @@ impl From<GamenightGet> for Uuid {
|
||||
}
|
||||
|
||||
#[get("/gamenights")]
|
||||
pub async fn gamenights(pool: web::Data<DbPool>, _user: User) -> Result<impl Responder, ApiError> {
|
||||
pub async fn gamenights(pool: web::Data<DbPool>, _user: AuthUser) -> Result<impl Responder, ApiError> {
|
||||
let mut conn = pool.get_conn();
|
||||
let gamenights: GameNightsResponse = schema::gamenights(&mut conn)?;
|
||||
let gamenights: GameNightsResponse = gamenight_database::gamenights(&mut conn)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(ContentType::json())
|
||||
@@ -40,19 +40,19 @@ pub async fn gamenights(pool: web::Data<DbPool>, _user: User) -> Result<impl Res
|
||||
}
|
||||
|
||||
#[post("/gamenight")]
|
||||
pub async fn gamenight_post(pool: web::Data<DbPool>, user: User, gamenight_data: web::Json<GamenightPost>) -> Result<impl Responder, ApiError> {
|
||||
pub async fn gamenight_post(pool: web::Data<DbPool>, user: AuthUser, gamenight_data: web::Json<GamenightPost>) -> Result<impl Responder, ApiError> {
|
||||
let mut conn = pool.get_conn();
|
||||
|
||||
schema::gamenight::add_gamenight(&mut conn, gamenight_data.into_with_user(user)?)?;
|
||||
gamenight_database::gamenight::add_gamenight(&mut conn, gamenight_data.into_with_user(user)?)?;
|
||||
|
||||
Ok(HttpResponse::Ok())
|
||||
}
|
||||
|
||||
#[get("/gamenight")]
|
||||
pub async fn gamenight_get(pool: web::Data<DbPool>, _user: User, gamenight_data: web::Json<GamenightGet>) -> Result<impl Responder, ApiError> {
|
||||
pub async fn gamenight_get(pool: web::Data<DbPool>, _user: AuthUser, gamenight_data: web::Json<GamenightGet>) -> Result<impl Responder, ApiError> {
|
||||
let mut conn = pool.get_conn();
|
||||
|
||||
let gamenight = schema::gamenight::get_gamenight(&mut conn, gamenight_data.into_inner().into())?;
|
||||
let gamenight = gamenight_database::gamenight::get_gamenight(&mut conn, gamenight_data.into_inner().into())?;
|
||||
//let participants = schema::user::get_participants(&mut conn, gamenight_id);
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
use gamenight_database::{DbPool, GetConnection, user::count_users_with_username, user::count_users_with_email};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use validator::Validate;
|
||||
use diesel::PgConnection;
|
||||
use diesel::r2d2::ConnectionManager;
|
||||
use diesel::r2d2::Pool;
|
||||
|
||||
use crate::schema::user::{unique_email, unique_username};
|
||||
use validator::{Validate, ValidationError};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Login {
|
||||
@@ -13,7 +9,29 @@ pub struct Login {
|
||||
}
|
||||
|
||||
pub struct RegisterContext<'v_a> {
|
||||
pub pool: &'v_a Pool<ConnectionManager<PgConnection>>
|
||||
pub pool: &'v_a DbPool
|
||||
}
|
||||
|
||||
pub fn unique_username(username: &String, context: &RegisterContext) -> Result<(), ValidationError> {
|
||||
let mut conn = context.pool.get_conn();
|
||||
|
||||
match count_users_with_username(&mut conn, username)
|
||||
{
|
||||
Ok(0) => Ok(()),
|
||||
Ok(_) => Err(ValidationError::new("User already exists")),
|
||||
Err(_) => Err(ValidationError::new("Database error while validating user")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unique_email(email: &String, context: &RegisterContext) -> Result<(), ValidationError> {
|
||||
let mut conn = context.pool.get_conn();
|
||||
|
||||
match count_users_with_email(&mut conn, email)
|
||||
{
|
||||
Ok(0) => Ok(()),
|
||||
Ok(_) => Err(ValidationError::new("email already exists")),
|
||||
Err(_) => Err(ValidationError::new("Database error while validating email"))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate)]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::schema::gamenight::Gamenight;
|
||||
use gamenight_database::gamenight::Gamenight;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct LoginResponse {
|
||||
|
||||
@@ -2,27 +2,25 @@
|
||||
use actix_web::http::header::ContentType;
|
||||
use actix_web::{web, get, post, HttpResponse, Responder};
|
||||
use validator::ValidateArgs;
|
||||
use crate::DbPool;
|
||||
use crate::request::requests::{Login, Register, RegisterContext};
|
||||
use crate::request::error::ApiError;
|
||||
use crate::request::responses::LoginResponse;
|
||||
use crate::request::authorization::get_token;
|
||||
use crate::util::GetConnection;
|
||||
use crate::schema::{self};
|
||||
use serde_json;
|
||||
use gamenight_database::{DbPool, GetConnection};
|
||||
|
||||
impl From<Login> for schema::user::LoginUser {
|
||||
impl From<Login> for gamenight_database::user::LoginUser {
|
||||
fn from(val: Login) -> Self {
|
||||
schema::user::LoginUser {
|
||||
gamenight_database::user::LoginUser {
|
||||
username: val.username,
|
||||
password: val.password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Register> for schema::user::Register {
|
||||
impl From<Register> for gamenight_database::user::Register {
|
||||
fn from(val: Register) -> Self {
|
||||
schema::user::Register {
|
||||
gamenight_database::user::Register {
|
||||
email: val.email,
|
||||
username: val.username,
|
||||
password: val.password
|
||||
@@ -36,7 +34,7 @@ pub async fn login(pool: web::Data<DbPool>, login_data: web::Json<Login>) -> Res
|
||||
|
||||
if let Ok(Some(user)) = web::block(move || {
|
||||
let mut conn = pool.get_conn();
|
||||
schema::login(&mut conn, data.into())
|
||||
gamenight_database::login(&mut conn, data.into())
|
||||
})
|
||||
.await?
|
||||
{
|
||||
@@ -58,7 +56,7 @@ pub async fn register(pool: web::Data<DbPool>, register_data: web::Json<Register
|
||||
register_data.validate_with_args(&RegisterContext{pool: &pool})?;
|
||||
let register_request = register_data.into_inner().into();
|
||||
let mut conn = pool.get_conn();
|
||||
schema::register(&mut conn, register_request)?;
|
||||
gamenight_database::register(&mut conn, register_request)?;
|
||||
Ok(())
|
||||
}).await??;
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
pub struct DatabaseError(pub String);
|
||||
|
||||
impl From<diesel::result::Error> for DatabaseError {
|
||||
fn from(value: diesel::result::Error) -> Self {
|
||||
DatabaseError(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<argon2::password_hash::Error> for DatabaseError {
|
||||
fn from(value: argon2::password_hash::Error) -> Self {
|
||||
DatabaseError(value.to_string())
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{Insertable, Queryable, PgConnection, RunQueryDsl, insert_into, QueryDsl};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use uuid::Uuid;
|
||||
use crate::schema::schema::gamenight;
|
||||
|
||||
use super::error::DatabaseError;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Insertable, Queryable)]
|
||||
#[diesel(table_name = gamenight)]
|
||||
pub struct Gamenight {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub datetime: DateTime<Utc>,
|
||||
pub owner_id: Uuid,
|
||||
}
|
||||
|
||||
pub fn gamenights(conn: &mut PgConnection) -> Result<Vec::<Gamenight>, DatabaseError> {
|
||||
Ok(gamenight::table.load::<Gamenight>(conn)?)
|
||||
}
|
||||
|
||||
pub fn add_gamenight(conn: &mut PgConnection, gamenight: Gamenight) -> Result<usize, DatabaseError> {
|
||||
Ok(insert_into(gamenight::table).values(&gamenight).execute(conn)?)
|
||||
}
|
||||
|
||||
pub(crate) fn get_gamenight(conn: &mut PgConnection, id: Uuid) -> Result<Gamenight, DatabaseError> {
|
||||
Ok(gamenight::table.find(id).first(conn)?)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
use diesel::{ExpressionMethods, Insertable, PgConnection, QueryDsl, Queryable, RunQueryDsl};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use uuid::Uuid;
|
||||
use crate::schema::schema::gamenight_participants;
|
||||
|
||||
use super::error::DatabaseError;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Insertable, Queryable)]
|
||||
#[diesel(belongs_to(Gamenight))]
|
||||
#[diesel(belongs_to(User))]
|
||||
#[diesel(table_name = gamenight_participants)]
|
||||
pub struct GamenightParticipants {
|
||||
pub gamenight_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
}
|
||||
|
||||
pub fn gamenight_participants(conn: &mut PgConnection, id: Uuid) -> Result<Vec<GamenightParticipants>, DatabaseError> {
|
||||
Ok(gamenight_participants::table
|
||||
.filter(gamenight_participants::gamenight_id.eq(id))
|
||||
.get_results(conn)?)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
pub mod user;
|
||||
pub mod error;
|
||||
pub mod schema;
|
||||
pub mod gamenight;
|
||||
pub mod gamenight_participants;
|
||||
|
||||
pub use user::login;
|
||||
pub use user::register;
|
||||
pub use gamenight::gamenights;
|
||||
pub use gamenight_participants::gamenight_participants;
|
||||
@@ -1,83 +0,0 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
pub mod sql_types {
|
||||
#[derive(diesel::sql_types::SqlType)]
|
||||
#[diesel(postgres_type(name = "role"))]
|
||||
pub struct Role;
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
gamenight (id) {
|
||||
id -> Uuid,
|
||||
name -> Varchar,
|
||||
datetime -> Timestamptz,
|
||||
owner_id -> Uuid,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
gamenight_gamelist (gamenight_id, game_id) {
|
||||
gamenight_id -> Uuid,
|
||||
game_id -> Uuid,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
gamenight_participants (gamenight_id, user_id) {
|
||||
gamenight_id -> Uuid,
|
||||
user_id -> Uuid,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
known_games (id) {
|
||||
id -> Uuid,
|
||||
name -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
pwd (user_id) {
|
||||
user_id -> Uuid,
|
||||
password -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
registration_tokens (id) {
|
||||
id -> Uuid,
|
||||
#[max_length = 32]
|
||||
token -> Bpchar,
|
||||
single_use -> Bool,
|
||||
expires -> Nullable<Timestamptz>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
use diesel::sql_types::*;
|
||||
use super::sql_types::Role;
|
||||
|
||||
users (id) {
|
||||
id -> Uuid,
|
||||
username -> Varchar,
|
||||
email -> Varchar,
|
||||
role -> Role,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(gamenight -> users (owner_id));
|
||||
diesel::joinable!(gamenight_gamelist -> gamenight (gamenight_id));
|
||||
diesel::joinable!(gamenight_gamelist -> known_games (game_id));
|
||||
diesel::joinable!(gamenight_participants -> gamenight (gamenight_id));
|
||||
diesel::joinable!(gamenight_participants -> users (user_id));
|
||||
diesel::joinable!(pwd -> users (user_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
gamenight,
|
||||
gamenight_gamelist,
|
||||
gamenight_participants,
|
||||
known_games,
|
||||
pwd,
|
||||
registration_tokens,
|
||||
users,
|
||||
);
|
||||
@@ -1,154 +0,0 @@
|
||||
use argon2::password_hash::Salt;
|
||||
use diesel::Connection;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use uuid::Uuid;
|
||||
use diesel::{PgConnection, ExpressionMethods, QueryDsl, RunQueryDsl, Insertable, Queryable};
|
||||
use diesel_derive_enum::DbEnum;
|
||||
use argon2::password_hash::SaltString;
|
||||
use argon2::PasswordHash;
|
||||
use argon2::PasswordVerifier;
|
||||
use argon2::Argon2;
|
||||
use argon2::password_hash::PasswordHasher;
|
||||
use validator::ValidationError;
|
||||
use crate::util::GetConnection;
|
||||
use super::schema::{pwd, users};
|
||||
pub use super::error::DatabaseError;
|
||||
use ::rand_core::{OsRng,TryRngCore};
|
||||
use crate::request::requests::RegisterContext;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Insertable, Queryable)]
|
||||
#[diesel(table_name = pwd)]
|
||||
struct Pwd {
|
||||
user_id: Uuid,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Insertable, Queryable)]
|
||||
#[diesel(table_name = users)]
|
||||
pub struct User {
|
||||
pub id: Uuid,
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub role: Role,
|
||||
}
|
||||
|
||||
#[derive(DbEnum, Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
|
||||
#[ExistingTypePath = "crate::schema::schema::sql_types::Role"]
|
||||
pub enum Role {
|
||||
Admin,
|
||||
User
|
||||
}
|
||||
|
||||
pub struct LoginUser {
|
||||
pub username: String,
|
||||
pub password: String
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct LoginResult {
|
||||
pub result: bool,
|
||||
pub user: Option<User>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct RegisterResult {
|
||||
pub result: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Register {
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub password: String
|
||||
}
|
||||
|
||||
pub fn login(conn: &mut PgConnection, user: LoginUser) -> Result<Option<User>, DatabaseError> {
|
||||
let id: Uuid = users::table
|
||||
.filter(users::username.eq(&user.username))
|
||||
.or_filter(users::email.eq(&user.username))
|
||||
.select(users::id)
|
||||
.first(conn)?;
|
||||
|
||||
let pwd: String = pwd::table
|
||||
.filter(pwd::user_id.eq(id))
|
||||
.select(pwd::password)
|
||||
.first(conn)?;
|
||||
|
||||
let parsed_hash = PasswordHash::new(&pwd)?;
|
||||
|
||||
if Argon2::default()
|
||||
.verify_password(user.password.as_bytes(), &parsed_hash)
|
||||
.is_ok()
|
||||
{
|
||||
Ok(Some(users::table.find(id).first(conn)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_user(conn: &mut PgConnection, id: Uuid) -> Result<User, DatabaseError> {
|
||||
Ok(users::table.find(id).first(conn)?)
|
||||
}
|
||||
|
||||
pub fn unique_username(username: &String, context: &RegisterContext) -> Result<(), ValidationError> {
|
||||
let mut conn = context.pool.get().expect("Couldn't get db connection from pool");
|
||||
|
||||
match users::table
|
||||
.count()
|
||||
.filter(users::username.eq(username))
|
||||
.get_result(&mut conn)
|
||||
{
|
||||
Ok(0) => Ok(()),
|
||||
Ok(_) => Err(ValidationError::new("User already exists")),
|
||||
Err(_) => Err(ValidationError::new("Database error while validating user")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unique_email(email: &String, context: &RegisterContext) -> Result<(), ValidationError> {
|
||||
let mut conn = context.pool.get_conn();
|
||||
|
||||
match users::table
|
||||
.count()
|
||||
.filter(users::email.eq(email))
|
||||
.get_result(&mut conn)
|
||||
{
|
||||
Ok(0) => Ok(()),
|
||||
Ok(_) => Err(ValidationError::new("email already exists")),
|
||||
Err(_) => Err(ValidationError::new(
|
||||
"Database error while validating email",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(conn: &mut PgConnection, register: Register) -> Result<(), DatabaseError> {
|
||||
let mut bytes = [0u8; Salt::RECOMMENDED_LENGTH];
|
||||
OsRng.try_fill_bytes(&mut bytes).unwrap();
|
||||
let salt = SaltString::encode_b64(&bytes).unwrap();
|
||||
let argon2 = Argon2::default();
|
||||
|
||||
let password_hash = argon2
|
||||
.hash_password(register.password.as_bytes(), &salt)?
|
||||
.to_string();
|
||||
|
||||
conn.transaction(|c| {
|
||||
let id = Uuid::new_v4();
|
||||
|
||||
diesel::insert_into(users::table)
|
||||
.values(User {
|
||||
id,
|
||||
username: register.username,
|
||||
email: register.email,
|
||||
role: Role::User,
|
||||
})
|
||||
.execute(c)?;
|
||||
|
||||
diesel::insert_into(pwd::table)
|
||||
.values(Pwd {
|
||||
user_id: id,
|
||||
password: password_hash,
|
||||
})
|
||||
.execute(c)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use diesel::{r2d2::{PooledConnection, ManageConnection, Pool}};
|
||||
|
||||
pub trait GetConnection<T> where T: ManageConnection {
|
||||
fn get_conn(&self) -> PooledConnection<T>;
|
||||
}
|
||||
|
||||
impl<T: ManageConnection> GetConnection<T> for Pool<T> {
|
||||
fn get_conn(&self) -> PooledConnection<T> {
|
||||
self.get().expect("Couldn't get db connection from pool")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user