feat: ✨ admin routing part 3
This commit is contained in:
parent
bf2b0a439c
commit
8fb39f27ca
14 changed files with 305 additions and 139 deletions
|
@ -1,7 +1,7 @@
|
|||
-- Add up migration script here
|
||||
CREATE TABLE IF NOT EXISTS "login" (
|
||||
user_id BIGSERIAL NOT NULL REFERENCES "user" (user_id),
|
||||
token VARCHAR(1024) NOT NULL,
|
||||
authorization_token VARCHAR(1024) NOT NULL,
|
||||
token_creation_time TIMESTAMPTZ NOT NULL DEFAULT NOW (),
|
||||
PRIMARY KEY (user_id, token)
|
||||
PRIMARY KEY (user_id, authorization_token)
|
||||
);
|
||||
|
|
|
@ -2,43 +2,43 @@ use crate::feature::login::Login;
|
|||
|
||||
use super::DATABASE_CONNECTIONS;
|
||||
|
||||
pub async fn create(user_id: &i64, token: &String) -> Result<Login, sqlx::Error> {
|
||||
pub async fn create(user_id: &i64, authorization_token: &String) -> Result<Login, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Login,
|
||||
r#"
|
||||
INSERT INTO "login"(user_id, token)
|
||||
INSERT INTO "login"(user_id, authorization_token)
|
||||
VALUES ($1, $2)
|
||||
RETURNING *
|
||||
"#,
|
||||
user_id,
|
||||
token,
|
||||
authorization_token,
|
||||
)
|
||||
.fetch_one(&*DATABASE_CONNECTIONS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn read(user_id: &i64, token: &String) -> Result<Login, sqlx::Error> {
|
||||
pub async fn read(user_id: &i64, authorization_token: &String) -> Result<Login, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Login,
|
||||
r#"
|
||||
SELECT * FROM "login" WHERE "user_id" = $1 AND "token" = $2
|
||||
SELECT * FROM "login" WHERE "user_id" = $1 AND "authorization_token" = $2
|
||||
"#,
|
||||
user_id,
|
||||
token
|
||||
authorization_token
|
||||
)
|
||||
.fetch_one(&*DATABASE_CONNECTIONS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete(user_id: &i64, token: &String) -> Result<Login, sqlx::Error> {
|
||||
pub async fn delete(user_id: &i64, authorization_token: &String) -> Result<Login, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Login,
|
||||
r#"
|
||||
DELETE FROM "login" WHERE "user_id" = $1 AND "token" = $2
|
||||
DELETE FROM "login" WHERE "user_id" = $1 AND "authorization_token" = $2
|
||||
RETURNING *
|
||||
"#,
|
||||
user_id,
|
||||
token,
|
||||
authorization_token,
|
||||
)
|
||||
.fetch_one(&*DATABASE_CONNECTIONS)
|
||||
.await
|
||||
|
|
|
@ -67,6 +67,22 @@ pub async fn delete(user_id: &i64, contact_id: &i64) -> Result<UserContact, sqlx
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn read_for_value(
|
||||
contact_id: &i64,
|
||||
contact_value: &String,
|
||||
) -> Result<UserContact, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
UserContact,
|
||||
r#"
|
||||
SELECT * FROM "user_contact" WHERE "contact_id" = $1 AND "contact_value" = $2
|
||||
"#,
|
||||
contact_id,
|
||||
contact_value,
|
||||
)
|
||||
.fetch_one(&*DATABASE_CONNECTIONS)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn read_all_for_user(user_id: &i64) -> Result<Vec<UserContact>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
UserContact,
|
||||
|
|
|
@ -15,7 +15,7 @@ static ONE_TIME_PASSWORDS: LazyLock<RwLock<Vec<OneTimePassword>>> =
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct OneTimePassword {
|
||||
pub user_id: i64,
|
||||
user_id: i64,
|
||||
pub one_time_password: String,
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,13 @@ impl OneTimePassword {
|
|||
RwLock::new(vec![])
|
||||
}
|
||||
|
||||
pub async fn from_string(user: &User, one_time_password: &String) -> Self {
|
||||
OneTimePassword {
|
||||
user_id: user.user_id,
|
||||
one_time_password: one_time_password.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn new(user: &User, user_email: &String) -> Result<(), ForumMailError> {
|
||||
let one_time_password = "123".to_owned();
|
||||
let new_self = Self {
|
||||
|
|
|
@ -12,23 +12,23 @@ use crate::{database::login, error::ForumAuthError, SERVER_CONFIG};
|
|||
|
||||
use super::user::User;
|
||||
|
||||
static TOKEN_META: LazyLock<TokenMeta> = LazyLock::new(TokenMeta::init);
|
||||
static TOKEN_META: LazyLock<AuthorizationTokenMeta> = LazyLock::new(AuthorizationTokenMeta::init);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CustomClaim {
|
||||
pub user_id: i64,
|
||||
}
|
||||
|
||||
pub struct TokenMeta {
|
||||
token_key: HS256Key,
|
||||
token_verification_options: Option<VerificationOptions>,
|
||||
pub struct AuthorizationTokenMeta {
|
||||
authorization_token: HS256Key,
|
||||
authorization_token_verification_options: Option<VerificationOptions>,
|
||||
}
|
||||
|
||||
impl TokenMeta {
|
||||
impl AuthorizationTokenMeta {
|
||||
fn init() -> Self {
|
||||
Self {
|
||||
token_key: HS256Key::generate(),
|
||||
token_verification_options: {
|
||||
authorization_token: HS256Key::generate(),
|
||||
authorization_token_verification_options: {
|
||||
let mut verification_options = VerificationOptions::default();
|
||||
verification_options.time_tolerance = Some(jwt_simple::prelude::Duration::from(0));
|
||||
Some(verification_options)
|
||||
|
@ -37,7 +37,7 @@ impl TokenMeta {
|
|||
}
|
||||
|
||||
async fn create_token(user_id: &i64) -> Option<String> {
|
||||
let key = &TOKEN_META.token_key;
|
||||
let key = &TOKEN_META.authorization_token;
|
||||
let custom_claim = CustomClaim { user_id: *user_id };
|
||||
let claims = Claims::with_custom_claims(
|
||||
custom_claim,
|
||||
|
@ -47,23 +47,24 @@ impl TokenMeta {
|
|||
);
|
||||
|
||||
let token = key.authenticate(claims).unwrap();
|
||||
match TokenMeta::verify_token(&token).await {
|
||||
match AuthorizationTokenMeta::verify_token(&token).await {
|
||||
Ok(_) => Some(token),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn verify_token(token: &String) -> Result<JWTClaims<CustomClaim>, jwt_simple::Error> {
|
||||
TOKEN_META
|
||||
.token_key
|
||||
.verify_token::<CustomClaim>(token, TOKEN_META.token_verification_options.clone())
|
||||
TOKEN_META.authorization_token.verify_token::<CustomClaim>(
|
||||
token,
|
||||
TOKEN_META.authorization_token_verification_options.clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Login {
|
||||
pub user_id: i64,
|
||||
pub token: String,
|
||||
pub authorization_token: String,
|
||||
pub token_creation_time: DateTime<Utc>,
|
||||
}
|
||||
|
||||
|
@ -71,24 +72,24 @@ impl Login {
|
|||
pub async fn create(user_id: &i64) -> Result<Login, sqlx::Error> {
|
||||
User::read(user_id).await?;
|
||||
|
||||
let token = TokenMeta::create_token(user_id)
|
||||
let token = AuthorizationTokenMeta::create_token(user_id)
|
||||
.await
|
||||
.expect("Should not panic if it isn't configured wrong");
|
||||
login::create(user_id, &token).await
|
||||
}
|
||||
|
||||
pub async fn read(user_id: &i64, token: &String) -> Result<Login, sqlx::Error> {
|
||||
pub async fn read(user_id: &i64, authorization_token: &String) -> Result<Login, sqlx::Error> {
|
||||
User::read(user_id).await?;
|
||||
|
||||
login::read(user_id, token).await
|
||||
login::read(user_id, authorization_token).await
|
||||
}
|
||||
|
||||
pub async fn update(
|
||||
user_id: &i64,
|
||||
token: &String,
|
||||
authorization_token: &String,
|
||||
) -> Result<Login, Box<dyn std::error::Error>> {
|
||||
let login = Login::read(user_id, token).await?;
|
||||
match TokenMeta::verify_token(token).await {
|
||||
let login = Login::read(user_id, authorization_token).await?;
|
||||
match AuthorizationTokenMeta::verify_token(authorization_token).await {
|
||||
Ok(_) => Ok(login),
|
||||
Err(_) => {
|
||||
if DateTime::<Utc>::default()
|
||||
|
@ -96,7 +97,7 @@ impl Login {
|
|||
.num_minutes()
|
||||
<= SERVER_CONFIG.login_token_refresh_time_limit as i64
|
||||
{
|
||||
Login::delete(user_id, token).await?;
|
||||
Login::delete(user_id, authorization_token).await?;
|
||||
let login = Login::create(user_id).await?;
|
||||
Ok(login)
|
||||
} else {
|
||||
|
@ -105,8 +106,8 @@ impl Login {
|
|||
}
|
||||
}
|
||||
}
|
||||
pub async fn delete(user_id: &i64, token: &String) -> Result<Login, sqlx::Error> {
|
||||
login::delete(user_id, token).await
|
||||
pub async fn delete(user_id: &i64, authorization_token: &String) -> Result<Login, sqlx::Error> {
|
||||
login::delete(user_id, authorization_token).await
|
||||
}
|
||||
|
||||
pub async fn read_all_for_user(user_id: &i64) -> Result<Vec<Login>, sqlx::Error> {
|
||||
|
|
|
@ -24,6 +24,13 @@ impl UserContact {
|
|||
user_contact::read(&user.user_id, contact_id).await
|
||||
}
|
||||
|
||||
pub async fn read_for_value(
|
||||
contact_id: &i64,
|
||||
contact_value: &String,
|
||||
) -> Result<UserContact, sqlx::Error> {
|
||||
user_contact::read_for_value(contact_id, contact_value).await
|
||||
}
|
||||
|
||||
pub async fn update(
|
||||
user: &User,
|
||||
contact_id: &i64,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
pub mod contact;
|
||||
pub mod interaction;
|
||||
pub mod login;
|
||||
pub mod role;
|
||||
pub mod user;
|
||||
pub mod user_contact;
|
||||
|
@ -9,10 +11,12 @@ use super::middleware::builder_or_admin_by_authorization_token;
|
|||
|
||||
pub fn route() -> Router {
|
||||
Router::new()
|
||||
.nest("/logins", login::route())
|
||||
.nest("/users", user::route())
|
||||
.nest("/roles", role::route())
|
||||
.nest("/contacts", contact::route())
|
||||
.nest("/user_contacts", user_contact::route())
|
||||
.nest("/interactions", interaction::route())
|
||||
.route_layer(axum::middleware::from_fn(
|
||||
builder_or_admin_by_authorization_token,
|
||||
))
|
||||
|
|
58
src/routing/admin/interaction.rs
Normal file
58
src/routing/admin/interaction.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use axum::{
|
||||
extract::Path,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{delete, patch, post},
|
||||
Json, Router,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::feature::interaction::Interaction;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CreateInteraction {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct UpdateInteraction {
|
||||
id: i64,
|
||||
name: String,
|
||||
}
|
||||
|
||||
pub fn route() -> Router {
|
||||
Router::new()
|
||||
.route("/", post(create))
|
||||
.route("/", patch(update))
|
||||
.route("/{id}", delete(delete_))
|
||||
}
|
||||
|
||||
async fn create(Json(create_interaction): Json<CreateInteraction>) -> impl IntoResponse {
|
||||
match Interaction::create(&create_interaction.name).await {
|
||||
Ok(interaction) => (StatusCode::CREATED, Json(serde_json::json!(interaction))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn update(Json(update_interaction): Json<UpdateInteraction>) -> impl IntoResponse {
|
||||
match Interaction::update(&update_interaction.id, &update_interaction.name).await {
|
||||
Ok(interaction) => (StatusCode::ACCEPTED, Json(serde_json::json!(interaction))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
||||
match Interaction::delete(&id).await {
|
||||
Ok(interaction) => (StatusCode::NO_CONTENT, Json(serde_json::json!(interaction))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
45
src/routing/admin/login.rs
Normal file
45
src/routing/admin/login.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{delete, get},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
feature::{login::Login, user::User},
|
||||
routing::middleware::by_uri_then_insert,
|
||||
};
|
||||
|
||||
pub fn route() -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
"/users/{user_id}",
|
||||
delete(delete_all_for_user).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||
)
|
||||
.route(
|
||||
"/count/users/{user_id}",
|
||||
get(count_all_for_user).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||
)
|
||||
}
|
||||
|
||||
async fn delete_all_for_user(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||
match Login::delete_all_for_user(&user.user_id).await {
|
||||
Ok(logins) => (StatusCode::OK, Json(serde_json::json!(logins))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn count_all_for_user(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||
match Login::count_all_for_user(&user.user_id).await {
|
||||
Ok(login_count) => (StatusCode::OK, Json(serde_json::json!(login_count))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
|
@ -90,21 +90,25 @@ async fn update(
|
|||
Extension(target_user): Extension<Arc<User>>,
|
||||
Json(update_user): Json<UpdateUser>,
|
||||
) -> impl IntoResponse {
|
||||
match User::update(
|
||||
&target_user.user_id,
|
||||
&update_user.name,
|
||||
&update_user.surname,
|
||||
&update_user.gender,
|
||||
&update_user.birth_date,
|
||||
&update_user.role_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(user) => (StatusCode::ACCEPTED, Json(serde_json::json!(user))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
if update_user.role_id == 0 {
|
||||
(StatusCode::FORBIDDEN, Json(serde_json::json!({})))
|
||||
} else {
|
||||
match User::update(
|
||||
&target_user.user_id,
|
||||
&update_user.name,
|
||||
&update_user.surname,
|
||||
&update_user.gender,
|
||||
&update_user.birth_date,
|
||||
&update_user.role_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(user) => (StatusCode::ACCEPTED, Json(serde_json::json!(user))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
use axum::{
|
||||
extract::Path,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, patch, post},
|
||||
Json, Router,
|
||||
};
|
||||
use axum::{extract::Path, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::feature::interaction::Interaction;
|
||||
|
@ -22,23 +16,10 @@ struct UpdateInteraction {
|
|||
|
||||
pub fn route() -> Router {
|
||||
Router::new()
|
||||
.route("/", post(create))
|
||||
.route("/{id}", get(read))
|
||||
.route("/", patch(update))
|
||||
.route("/{id}", delete(delete_))
|
||||
.route("/", get(read_all))
|
||||
}
|
||||
|
||||
async fn create(Json(create_interaction): Json<CreateInteraction>) -> impl IntoResponse {
|
||||
match Interaction::create(&create_interaction.name).await {
|
||||
Ok(interaction) => (StatusCode::CREATED, Json(serde_json::json!(interaction))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
||||
match Interaction::read(&id).await {
|
||||
Ok(interaction) => (StatusCode::OK, Json(serde_json::json!(interaction))),
|
||||
|
@ -49,26 +30,6 @@ async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
|||
}
|
||||
}
|
||||
|
||||
async fn update(Json(update_interaction): Json<UpdateInteraction>) -> impl IntoResponse {
|
||||
match Interaction::update(&update_interaction.id, &update_interaction.name).await {
|
||||
Ok(interaction) => (StatusCode::ACCEPTED, Json(serde_json::json!(interaction))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
||||
match Interaction::delete(&id).await {
|
||||
Ok(interaction) => (StatusCode::NO_CONTENT, Json(serde_json::json!(interaction))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_all() -> impl IntoResponse {
|
||||
match Interaction::read_all().await {
|
||||
Ok(interactions) => (StatusCode::OK, Json(serde_json::json!(interactions))),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
extract::Path,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, patch, post},
|
||||
|
@ -11,18 +10,20 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::feature::{auth::OneTimePassword, login::Login, user::User, user_contact::UserContact};
|
||||
|
||||
use super::middleware::{user_and_token_then_insert, UserAndAuthorizationToken};
|
||||
use super::middleware::{
|
||||
by_authorization_token_then_insert, user_and_token_then_insert, UserAndAuthorizationToken,
|
||||
};
|
||||
|
||||
const CONTACT_EMAIL_DEFAULT_ID: i64 = 0;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CreateOneTimePassword {
|
||||
pub user_id: i64,
|
||||
pub user_email: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CreateLogin {
|
||||
user_id: i64,
|
||||
user_email: String,
|
||||
one_time_password: String,
|
||||
}
|
||||
|
||||
|
@ -30,26 +31,48 @@ pub fn route() -> Router {
|
|||
Router::new()
|
||||
.route("/one_time_password", post(create_one_time_password))
|
||||
.route("/", post(create))
|
||||
.route("/users/{user_id}/tokens/{token}", get(read))
|
||||
.route(
|
||||
"/",
|
||||
get(read).route_layer(axum::middleware::from_fn(user_and_token_then_insert)),
|
||||
)
|
||||
.route(
|
||||
"/",
|
||||
patch(update).route_layer(axum::middleware::from_fn(user_and_token_then_insert)),
|
||||
)
|
||||
.route("/users/{user_id}/tokens/{token}", delete(delete_))
|
||||
.route("/users/{user_id}", get(read_all_for_user))
|
||||
.route("/users/{user_id}", delete(delete_all_for_user))
|
||||
.route("/count/users/{user_id}", get(count_all_for_user))
|
||||
.route(
|
||||
"/",
|
||||
delete(delete_).route_layer(axum::middleware::from_fn(user_and_token_then_insert)),
|
||||
)
|
||||
.route(
|
||||
"/users",
|
||||
delete(delete_all_for_user).route_layer(axum::middleware::from_fn(
|
||||
by_authorization_token_then_insert,
|
||||
)),
|
||||
)
|
||||
.route("/count/users", get(count_all_for_user))
|
||||
}
|
||||
async fn create_one_time_password(
|
||||
Json(create_one_time_password): Json<CreateOneTimePassword>,
|
||||
) -> impl IntoResponse {
|
||||
//todo get user from middleware or something
|
||||
let user = User::read(&create_one_time_password.user_id).await.unwrap();
|
||||
match UserContact::read(&user, &CONTACT_EMAIL_DEFAULT_ID).await {
|
||||
Ok(user_email) => match OneTimePassword::new(&user, &user_email.contact_value).await {
|
||||
Ok(_) => (StatusCode::CREATED, Json(serde_json::json!(""))),
|
||||
match UserContact::read_for_value(
|
||||
&CONTACT_EMAIL_DEFAULT_ID,
|
||||
&create_one_time_password.user_email,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(user_contact) => match User::read(&user_contact.user_id).await {
|
||||
Ok(user) => {
|
||||
match OneTimePassword::new(&user, &create_one_time_password.user_email).await {
|
||||
Ok(_) => (StatusCode::CREATED, Json(serde_json::json!({}))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
// this must be impossible that's why I send 500
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
},
|
||||
|
@ -60,30 +83,50 @@ async fn create_one_time_password(
|
|||
}
|
||||
}
|
||||
async fn create(Json(create_login): Json<CreateLogin>) -> impl IntoResponse {
|
||||
let one_time_password = OneTimePassword {
|
||||
user_id: create_login.user_id,
|
||||
one_time_password: create_login.one_time_password,
|
||||
};
|
||||
match UserContact::read_for_value(&CONTACT_EMAIL_DEFAULT_ID, &create_login.user_email).await {
|
||||
Ok(user_contact) => match User::read(&user_contact.user_id).await {
|
||||
Ok(user) => {
|
||||
let one_time_password =
|
||||
OneTimePassword::from_string(&user, &create_login.one_time_password).await;
|
||||
|
||||
match OneTimePassword::verify(&one_time_password).await {
|
||||
true => match Login::create(&one_time_password.user_id).await {
|
||||
Ok(login) => (StatusCode::CREATED, Json(serde_json::json!(login))),
|
||||
match OneTimePassword::verify(&one_time_password).await {
|
||||
true => match Login::create(&user.user_id).await {
|
||||
Ok(login) => (StatusCode::CREATED, Json(serde_json::json!(login))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
},
|
||||
false => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(
|
||||
"One Time Password Authentication Failed".to_string()
|
||||
)),
|
||||
),
|
||||
}
|
||||
}
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
// this must be impossible that's why I send 500
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
},
|
||||
false => (
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(
|
||||
"One Time Password Authentication Failed".to_string()
|
||||
)),
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read(Path((user_id, token)): Path<(i64, String)>) -> impl IntoResponse {
|
||||
match Login::read(&user_id, &token).await {
|
||||
async fn read(
|
||||
Extension(user_and_authorization_token): Extension<Arc<UserAndAuthorizationToken>>,
|
||||
) -> impl IntoResponse {
|
||||
match Login::read(
|
||||
&user_and_authorization_token.user.user_id,
|
||||
&user_and_authorization_token.authorization_token,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(login) => (StatusCode::OK, Json(serde_json::json!(login))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
@ -109,8 +152,15 @@ async fn update(
|
|||
}
|
||||
}
|
||||
|
||||
async fn delete_(Path((user_id, token)): Path<(i64, String)>) -> impl IntoResponse {
|
||||
match Login::delete(&user_id, &token).await {
|
||||
async fn delete_(
|
||||
Extension(user_and_authorization_token): Extension<Arc<UserAndAuthorizationToken>>,
|
||||
) -> impl IntoResponse {
|
||||
match Login::delete(
|
||||
&user_and_authorization_token.user.user_id,
|
||||
&user_and_authorization_token.authorization_token,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(login) => (StatusCode::NO_CONTENT, Json(serde_json::json!(login))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
@ -119,8 +169,8 @@ async fn delete_(Path((user_id, token)): Path<(i64, String)>) -> impl IntoRespon
|
|||
}
|
||||
}
|
||||
|
||||
async fn read_all_for_user(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
match Login::read_all_for_user(&user_id).await {
|
||||
async fn delete_all_for_user(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||
match Login::delete_all_for_user(&user.user_id).await {
|
||||
Ok(logins) => (StatusCode::OK, Json(serde_json::json!(logins))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
@ -129,18 +179,8 @@ async fn read_all_for_user(Path(user_id): Path<i64>) -> impl IntoResponse {
|
|||
}
|
||||
}
|
||||
|
||||
async fn delete_all_for_user(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
match Login::delete_all_for_user(&user_id).await {
|
||||
Ok(logins) => (StatusCode::OK, Json(serde_json::json!(logins))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn count_all_for_user(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
match Login::count_all_for_user(&user_id).await {
|
||||
async fn count_all_for_user(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||
match Login::count_all_for_user(&user.user_id).await {
|
||||
Ok(login_count) => (StatusCode::OK, Json(serde_json::json!(login_count))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
|
|
@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::{
|
||||
error::ForumAuthError,
|
||||
feature::{login::TokenMeta, user::User},
|
||||
feature::{login::AuthorizationTokenMeta, user::User},
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -43,7 +43,7 @@ async fn authorization_token_extraction(
|
|||
async fn user_extraction_from_authorization_token(
|
||||
authorization_token: &String,
|
||||
) -> Result<User, ForumAuthError> {
|
||||
match TokenMeta::verify_token(&authorization_token.to_string()).await {
|
||||
match AuthorizationTokenMeta::verify_token(&authorization_token.to_string()).await {
|
||||
Ok(claims) => User::read(&claims.custom.user_id)
|
||||
.await
|
||||
.map_err(|err_val| ForumAuthError::AuthenticationFailed(err_val.to_string())),
|
||||
|
|
|
@ -1,12 +1,35 @@
|
|||
use axum::{extract::Path, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
extract::Path, http::StatusCode, response::IntoResponse, routing::get, Extension, Json, Router,
|
||||
};
|
||||
|
||||
use crate::feature::user::User;
|
||||
|
||||
use super::middleware::by_authorization_token_then_insert;
|
||||
|
||||
pub fn route() -> Router {
|
||||
Router::new().route("/{user_id}", get(read))
|
||||
Router::new()
|
||||
.route(
|
||||
"/",
|
||||
get(read).route_layer(axum::middleware::from_fn(
|
||||
by_authorization_token_then_insert,
|
||||
)),
|
||||
)
|
||||
.route("/{user_id}", get(read_anybody))
|
||||
}
|
||||
|
||||
async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
async fn read(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||
match User::read(&user.user_id).await {
|
||||
Ok(user) => (StatusCode::OK, Json(serde_json::json!(user))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!(err_val.to_string())),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_anybody(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
match User::read(&user_id).await {
|
||||
Ok(user) => (StatusCode::OK, Json(serde_json::json!(user))),
|
||||
Err(err_val) => (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue