Added login and updated register function
This commit is contained in:
parent
36c785e8f2
commit
35527cbeb7
@ -1,6 +1,6 @@
|
|||||||
CREATE TABLE "users" (
|
CREATE TABLE "users" (
|
||||||
user_id uuid NOT NULL PRIMARY KEY,
|
user_id uuid NOT NULL PRIMARY KEY,
|
||||||
email text UNIQUE,
|
email text NOT NULL UNIQUE,
|
||||||
password text NOT NULL,
|
password text NOT NULL,
|
||||||
admin boolean NOT NULL
|
admin boolean NOT NULL
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ use std::collections::HashSet;
|
|||||||
|
|
||||||
use argon2::{
|
use argon2::{
|
||||||
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
|
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
|
||||||
Argon2,
|
Argon2, PasswordHash, PasswordVerifier,
|
||||||
};
|
};
|
||||||
use axum::{extract::FromRequestParts, http::request::Parts, RequestPartsExt};
|
use axum::{extract::FromRequestParts, http::request::Parts, RequestPartsExt};
|
||||||
use axum_extra::{
|
use axum_extra::{
|
||||||
@ -76,6 +76,16 @@ pub async fn generate_password_hash(
|
|||||||
Ok(password_hash?)
|
Ok(password_hash?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn verify_password_hash(
|
||||||
|
password: &str,
|
||||||
|
hash: &str,
|
||||||
|
) -> Result<(), argon2::password_hash::Error> {
|
||||||
|
let parsed_hash = PasswordHash::new(hash)?;
|
||||||
|
Argon2::default().verify_password(password.as_bytes(), &parsed_hash)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_session_token() -> String {
|
pub fn generate_session_token() -> String {
|
||||||
let session = ChaCha20Rng::from_os_rng()
|
let session = ChaCha20Rng::from_os_rng()
|
||||||
.sample_iter(&Alphanumeric)
|
.sample_iter(&Alphanumeric)
|
||||||
|
@ -5,6 +5,7 @@ pub enum AuthError {
|
|||||||
NoPermssions,
|
NoPermssions,
|
||||||
InvalidToken,
|
InvalidToken,
|
||||||
Unexpected,
|
Unexpected,
|
||||||
|
InvalidPassword,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for AuthError {
|
impl Display for AuthError {
|
||||||
@ -13,6 +14,7 @@ impl Display for AuthError {
|
|||||||
Self::NoPermssions => write!(f, "{}", "No permissions"),
|
Self::NoPermssions => write!(f, "{}", "No permissions"),
|
||||||
Self::InvalidToken => write!(f, "{}", "Invalid token"),
|
Self::InvalidToken => write!(f, "{}", "Invalid token"),
|
||||||
Self::Unexpected => write!(f, "{}", "Unexpected error"),
|
Self::Unexpected => write!(f, "{}", "Unexpected error"),
|
||||||
|
Self::InvalidPassword => write!(f, "{}", "Password is incorrect"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use sqlx::Postgres;
|
use sqlx::{PgPool, Postgres};
|
||||||
|
|
||||||
#[derive(validator::Validate)]
|
#[derive(validator::Validate)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
@ -36,6 +36,14 @@ impl User {
|
|||||||
|
|
||||||
Ok(user_id)
|
Ok(user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_from_email(transaction: &PgPool, email: String) -> Result<Self, sqlx::Error> {
|
||||||
|
let user = sqlx::query_as!(Self, "SELECT * FROM users WHERE email = $1", email)
|
||||||
|
.fetch_one(transaction)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -14,7 +14,7 @@ pub fn routes() -> Router<AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn root(
|
async fn root(
|
||||||
State(state): State<AppState>,
|
State(_state): State<AppState>,
|
||||||
permissions: Permissions<'_>,
|
permissions: Permissions<'_>,
|
||||||
) -> Result<String, (StatusCode, String)> {
|
) -> Result<String, (StatusCode, String)> {
|
||||||
tracing::info!("{:?}", permissions);
|
tracing::info!("{:?}", permissions);
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
use axum::{extract::State, routing::post, Json, Router};
|
use axum::{extract::State, routing::post, Json, Router};
|
||||||
|
|
||||||
|
use crate::auth::verify_password_hash;
|
||||||
use crate::database::model::member::SearchMember;
|
use crate::database::model::member::SearchMember;
|
||||||
use crate::database::model::Member as DbMember;
|
use crate::database::model::Member as DbMember;
|
||||||
use crate::database::model::Session as DbSession;
|
use crate::database::model::Session as DbSession;
|
||||||
use crate::database::model::User as DbUser;
|
use crate::database::model::User as DbUser;
|
||||||
use crate::database::model::UserMember as DbUserMember;
|
use crate::database::model::UserMember as DbUserMember;
|
||||||
use crate::model::session::Session;
|
use crate::model::session::Session;
|
||||||
use crate::{
|
use crate::{auth::generate_password_hash, AppState};
|
||||||
auth::{generate_password_hash, Permissions},
|
|
||||||
AppState,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn routes() -> Router<AppState> {
|
pub fn routes() -> Router<AppState> {
|
||||||
Router::new()
|
Router::new()
|
||||||
@ -17,16 +15,36 @@ pub fn routes() -> Router<AppState> {
|
|||||||
.route("/auth/register", post(register))
|
.route("/auth/register", post(register))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct LoginRequest {
|
||||||
|
email: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn login<'a>(
|
pub async fn login<'a>(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
permissions: Permissions<'a>,
|
Json(login_request): Json<LoginRequest>,
|
||||||
body: String,
|
) -> Result<String, crate::Error> {
|
||||||
) -> Result<(), crate::Error> {
|
let db_user = DbUser::get_from_email(&state.pool, login_request.email).await?;
|
||||||
Ok(())
|
|
||||||
|
match verify_password_hash(&login_request.password, &db_user.password).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(_err) => return Err(crate::Error::Auth(crate::auth::AuthError::InvalidPassword)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create session
|
||||||
|
let mut transaction = state.pool.begin().await?;
|
||||||
|
|
||||||
|
let db_session: DbSession = Session::new(db_user.user_id).into();
|
||||||
|
db_session.insert(&mut transaction).await?;
|
||||||
|
|
||||||
|
transaction.commit().await?;
|
||||||
|
|
||||||
|
Ok(db_session.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct AuthRequest {
|
pub struct RegisterRequest {
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
registration_tokens: Vec<String>,
|
registration_tokens: Vec<String>,
|
||||||
@ -34,8 +52,7 @@ pub struct AuthRequest {
|
|||||||
|
|
||||||
pub async fn register<'a>(
|
pub async fn register<'a>(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
permissions: Permissions<'a>,
|
Json(auth_request): Json<RegisterRequest>,
|
||||||
Json(auth_request): Json<AuthRequest>,
|
|
||||||
) -> Result<String, crate::Error> {
|
) -> Result<String, crate::Error> {
|
||||||
// Get all the members to link with the user
|
// Get all the members to link with the user
|
||||||
let members = DbMember::search(
|
let members = DbMember::search(
|
||||||
|
@ -6,8 +6,8 @@ pub mod migrate;
|
|||||||
|
|
||||||
pub fn routes() -> Router<AppState> {
|
pub fn routes() -> Router<AppState> {
|
||||||
Router::new()
|
Router::new()
|
||||||
// .route("/members/migrate_request", post(migrate::migrate_request))
|
.route("/members/migrate_request", post(migrate::migrate_request))
|
||||||
// .route("/members/migrate_confirm", post(migrate::migrate_confirm))
|
.route("/members/migrate_confirm", post(migrate::migrate_confirm))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_members<'a>(
|
pub async fn get_members<'a>(
|
||||||
|
@ -35,6 +35,10 @@ impl IntoResponse for Error {
|
|||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
String::from("Unexpected error occured"),
|
String::from("Unexpected error occured"),
|
||||||
),
|
),
|
||||||
|
Error::Auth(AuthError::InvalidPassword) => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
String::from("Invalid password"),
|
||||||
|
),
|
||||||
Error::Csv(err) => (StatusCode::BAD_REQUEST, err.to_string()),
|
Error::Csv(err) => (StatusCode::BAD_REQUEST, err.to_string()),
|
||||||
Error::NotFound => (
|
Error::NotFound => (
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user