Login endpoint #20
@@ -3,6 +3,8 @@ pub mod request {
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
pub struct Request {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,13 +31,50 @@ pub mod endpoint {
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
Json(payload): Json<request::Request>,
|
||||
) -> (StatusCode, Json<response::Response>) {
|
||||
let mut usr = icarus_models::user::User::default();
|
||||
let usr = icarus_models::user::User {
|
||||
username: payload.username,
|
||||
password: payload.password,
|
||||
..Default::default()
|
||||
};
|
||||
// usr.username = payload.username;
|
||||
// usr.password = payload.password;
|
||||
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(response::Response {
|
||||
message: String::from("Not implemented"),
|
||||
}),
|
||||
)
|
||||
// Check if user exists
|
||||
let user_exists = repo::user::exists(&pool, &usr.username).await.unwrap();
|
||||
if !user_exists {
|
||||
// End
|
||||
}
|
||||
let user = repo::user::get(&pool, &usr.username).await.unwrap();
|
||||
let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap();
|
||||
let salt_literal = salt.salt.clone();
|
||||
let salt_str = hashing::get_salt(&salt_literal).unwrap();
|
||||
|
||||
// Check if password is correct
|
||||
let hash_password = hashing::hash_password(&usr.password, &salt_str).unwrap();
|
||||
if hashing::verify_password(&usr.password, hash_password.clone()).unwrap() {
|
||||
println!("Do work");
|
||||
}
|
||||
|
||||
// Create token
|
||||
let key = token_stuff::get_key().unwrap();
|
||||
let token_literal = token_stuff::create_token(&key).unwrap();
|
||||
|
||||
let result = token_stuff::verify_token(&key, &token_literal);
|
||||
|
||||
if result {
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(response::Response {
|
||||
message: String::from("Not implemented"),
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(response::Response {
|
||||
message: String::from("Not implemented"),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,10 @@ pub fn generate_salt() -> Result<SaltString, argon2::Error> {
|
||||
Ok(salt)
|
||||
}
|
||||
|
||||
pub fn get_salt(s: &str) -> Result<SaltString, argon2::password_hash::Error> {
|
||||
SaltString::from_b64(s)
|
||||
}
|
||||
|
||||
pub fn hash_password(
|
||||
password: &String,
|
||||
salt: &SaltString,
|
||||
|
13
src/lib.rs
13
src/lib.rs
@@ -41,7 +41,6 @@ pub mod db_pool {
|
||||
}
|
||||
|
||||
mod token_stuff {
|
||||
use dotenvy;
|
||||
use josekit::{
|
||||
self,
|
||||
jws::{JwsHeader, alg::hmac::HmacJwsAlgorithm::Hs256},
|
||||
@@ -49,7 +48,6 @@ mod token_stuff {
|
||||
};
|
||||
|
||||
pub const TOKENTYPE: &str = "JWT";
|
||||
pub const TESTKEY: &str = "dfsdferferf";
|
||||
pub const KEY_ENV: &str = "SECRET_KEY";
|
||||
|
||||
pub fn get_key() -> Result<String, dotenvy::Error> {
|
||||
@@ -65,12 +63,11 @@ mod token_stuff {
|
||||
let mut payload = JwtPayload::new();
|
||||
payload.set_subject("Something random");
|
||||
|
||||
let mut key: String = String::new();
|
||||
if provided_key.is_empty() {
|
||||
key = get_key().unwrap();
|
||||
let key: String = if provided_key.is_empty() {
|
||||
get_key().unwrap()
|
||||
} else {
|
||||
key = provided_key.clone();
|
||||
}
|
||||
provided_key.to_owned()
|
||||
};
|
||||
|
||||
let signer = Hs256.signer_from_bytes(key.as_bytes()).unwrap();
|
||||
let jwt = josekit::jwt::encode_with_signer(&payload, &header, &signer).unwrap();
|
||||
@@ -80,7 +77,7 @@ mod token_stuff {
|
||||
|
||||
pub fn verify_token(key: &String, token: &String) -> bool {
|
||||
let ver = Hs256.verifier_from_bytes(key.as_bytes()).unwrap();
|
||||
let (payload, _header) = jwt::decode_with_verifier(&token, &ver).unwrap();
|
||||
let (payload, _header) = jwt::decode_with_verifier(token, &ver).unwrap();
|
||||
match payload.subject() {
|
||||
Some(_sub) => true,
|
||||
None => false,
|
||||
|
@@ -7,6 +7,41 @@ pub mod user {
|
||||
pub date_created: Option<time::OffsetDateTime>,
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
pool: &sqlx::PgPool,
|
||||
username: &String,
|
||||
) -> Result<icarus_models::user::User, sqlx::Error> {
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
SELECT * FROM "user" WHERE username = $1
|
||||
"#,
|
||||
)
|
||||
.bind(username)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(r) => match r {
|
||||
Some(r) => Ok(icarus_models::user::User {
|
||||
id: r.try_get("id")?,
|
||||
username: r.try_get("username")?,
|
||||
password: r.try_get("password")?,
|
||||
email: r.try_get("email")?,
|
||||
email_verified: r.try_get("email_verified")?,
|
||||
phone: r.try_get("phone")?,
|
||||
salt_id: r.try_get("salt_id")?,
|
||||
firstname: r.try_get("firstname")?,
|
||||
lastname: r.try_get("lastname")?,
|
||||
date_created: r.try_get("date_created")?,
|
||||
last_login: r.try_get("last_login")?,
|
||||
status: r.try_get("status")?,
|
||||
}),
|
||||
None => Err(sqlx::Error::RowNotFound),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn exists(pool: &sqlx::PgPool, username: &String) -> Result<bool, sqlx::Error> {
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
@@ -72,6 +107,31 @@ pub mod salt {
|
||||
pub id: uuid::Uuid,
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
pool: &sqlx::PgPool,
|
||||
id: &uuid::Uuid,
|
||||
) -> Result<icarus_models::user::salt::Salt, sqlx::Error> {
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
SELECT * FROM "salt" WHERE id = $1
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(r) => match r {
|
||||
Some(r) => Ok(icarus_models::user::salt::Salt {
|
||||
id: r.try_get("id")?,
|
||||
salt: r.try_get("salt")?,
|
||||
}),
|
||||
None => Err(sqlx::Error::RowNotFound),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn insert(
|
||||
pool: &sqlx::PgPool,
|
||||
salt: &icarus_models::user::salt::Salt,
|
||||
|
Reference in New Issue
Block a user