feat: ✨ admin routing part 1
This commit is contained in:
parent
f4765630ee
commit
a462d3a82d
11 changed files with 520 additions and 506 deletions
|
@ -8,3 +8,12 @@ CREATE TABLE IF NOT EXISTS "user"(
|
||||||
role_id BIGINT NOT NULL REFERENCES "role" DEFAULT 10,
|
role_id BIGINT NOT NULL REFERENCES "role" DEFAULT 10,
|
||||||
creation_time TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
creation_time TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
INSERT INTO "user"(user_id, name, surname, gender, birth_date, role_id)
|
||||||
|
VALUES (0, 'Builder', 'Builder', true, NOW(), 0)
|
||||||
|
ON CONFLICT(user_id) DO UPDATE SET
|
||||||
|
"name" = 'Builder',
|
||||||
|
"surname" = 'Builder',
|
||||||
|
"gender" = true,
|
||||||
|
"birth_date" = NOW(),
|
||||||
|
"role_id" = 0;
|
||||||
|
|
|
@ -3,5 +3,6 @@ CREATE TABLE IF NOT EXISTS "user_contact"(
|
||||||
user_id BIGSERIAL NOT NULL REFERENCES "user"(user_id),
|
user_id BIGSERIAL NOT NULL REFERENCES "user"(user_id),
|
||||||
contact_id BIGSERIAL NOT NULL REFERENCES "contact"(id),
|
contact_id BIGSERIAL NOT NULL REFERENCES "contact"(id),
|
||||||
contact_value VARCHAR(256) NOT NULL,
|
contact_value VARCHAR(256) NOT NULL,
|
||||||
PRIMARY KEY (user_id, contact_id)
|
PRIMARY KEY (user_id, contact_id),
|
||||||
|
UNIQUE (contact_id, contact_value)
|
||||||
);
|
);
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl std::fmt::Display for ForumMailError {
|
||||||
ForumMailError::TemplateLackOfParameter => {
|
ForumMailError::TemplateLackOfParameter => {
|
||||||
write!(f, "Template Parameters Are Not Enough")
|
write!(f, "Template Parameters Are Not Enough")
|
||||||
}
|
}
|
||||||
ForumMailError::Send(error) => write!(f, "Sending | {}", error),
|
ForumMailError::Send(err_val) => write!(f, "Sending | {}", err_val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,12 +54,16 @@ impl std::error::Error for ForumMailError {
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum ForumAuthError {
|
pub enum ForumAuthError {
|
||||||
|
AuthenticationFailed(String),
|
||||||
TokenRefreshTimeOver,
|
TokenRefreshTimeOver,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for ForumAuthError {
|
impl std::fmt::Display for ForumAuthError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
ForumAuthError::AuthenticationFailed(err_val) => {
|
||||||
|
write!(f, "Authentication Failed | {}", err_val)
|
||||||
|
}
|
||||||
ForumAuthError::TokenRefreshTimeOver => write!(f, "Token Refresh Time is Over"),
|
ForumAuthError::TokenRefreshTimeOver => write!(f, "Token Refresh Time is Over"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod admin;
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod comment_interaction;
|
pub mod comment_interaction;
|
||||||
pub mod contact;
|
pub mod contact;
|
||||||
|
@ -29,6 +30,7 @@ pub async fn route(concurrency_limit: &usize) -> Router {
|
||||||
.nest("/comment_interactions", comment_interaction::route())
|
.nest("/comment_interactions", comment_interaction::route())
|
||||||
.nest("/contacts", contact::route())
|
.nest("/contacts", contact::route())
|
||||||
.nest("/user_contacts", user_contact::route())
|
.nest("/user_contacts", user_contact::route())
|
||||||
|
.nest("/admin", admin::route())
|
||||||
.layer(CorsLayer::permissive())
|
.layer(CorsLayer::permissive())
|
||||||
.layer(ConcurrencyLimitLayer::new(*concurrency_limit))
|
.layer(ConcurrencyLimitLayer::new(*concurrency_limit))
|
||||||
.layer(TraceLayer::new_for_http())
|
.layer(TraceLayer::new_for_http())
|
||||||
|
|
15
src/routing/admin.rs
Normal file
15
src/routing/admin.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
pub mod role;
|
||||||
|
pub mod user;
|
||||||
|
|
||||||
|
use axum::Router;
|
||||||
|
|
||||||
|
use super::middleware::pass_builder_or_admin_by_authorization_token;
|
||||||
|
|
||||||
|
pub fn route() -> Router {
|
||||||
|
Router::new()
|
||||||
|
.nest("/users", user::route())
|
||||||
|
.nest("/roles", role::route())
|
||||||
|
.route_layer(axum::middleware::from_fn(
|
||||||
|
pass_builder_or_admin_by_authorization_token,
|
||||||
|
))
|
||||||
|
}
|
58
src/routing/admin/role.rs
Normal file
58
src/routing/admin/role.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::role::Role;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct CreateRole {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct UpdateRole {
|
||||||
|
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_role): Json<CreateRole>) -> impl IntoResponse {
|
||||||
|
match Role::create(&create_role.name).await {
|
||||||
|
Ok(role) => (StatusCode::CREATED, Json(serde_json::json!(role))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(Json(update_role): Json<UpdateRole>) -> impl IntoResponse {
|
||||||
|
match Role::update(&update_role.id, &update_role.name).await {
|
||||||
|
Ok(role) => (StatusCode::ACCEPTED, Json(serde_json::json!(role))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
||||||
|
match Role::delete(&id).await {
|
||||||
|
Ok(role) => (StatusCode::NO_CONTENT, Json(serde_json::json!(role))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
299
src/routing/admin/user.rs
Normal file
299
src/routing/admin/user.rs
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::Path,
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
routing::{delete, get, patch, post},
|
||||||
|
Extension, Json, Router,
|
||||||
|
};
|
||||||
|
use chrono::NaiveDate;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{feature::user::User, routing::middleware::pass_by_uri_user_extraction};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct CreateUser {
|
||||||
|
name: String,
|
||||||
|
surname: String,
|
||||||
|
gender: bool,
|
||||||
|
birth_date: NaiveDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct UpdateUser {
|
||||||
|
name: String,
|
||||||
|
surname: String,
|
||||||
|
gender: bool,
|
||||||
|
birth_date: NaiveDate,
|
||||||
|
role_id: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn route() -> Router {
|
||||||
|
Router::new()
|
||||||
|
.route("/", post(create))
|
||||||
|
.route(
|
||||||
|
"/{user_id}",
|
||||||
|
patch(update).route_layer(axum::middleware::from_fn(pass_by_uri_user_extraction)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/{user_id}",
|
||||||
|
delete(delete_).route_layer(axum::middleware::from_fn(pass_by_uri_user_extraction)),
|
||||||
|
)
|
||||||
|
.route("/", get(read_all))
|
||||||
|
.route("/names/{name}", get(read_all_for_name))
|
||||||
|
.route("/surnames/{surname}", get(read_all_for_surname))
|
||||||
|
.route("/birth_dates/{birth_date}", get(read_all_for_birth_date))
|
||||||
|
.route("/roles/{role}", get(read_all_for_role))
|
||||||
|
.route("/genders/{gender}", get(read_all_for_gender))
|
||||||
|
.route("/users_ids", get(read_all_id))
|
||||||
|
.route("/users_ids/names/{name}", get(read_all_id_for_name))
|
||||||
|
.route(
|
||||||
|
"/users_ids/surnames/{surname}",
|
||||||
|
get(read_all_id_for_surname),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users_ids/birth_dates/{birth_date}",
|
||||||
|
get(read_all_id_for_birth_date),
|
||||||
|
)
|
||||||
|
.route("/users_ids/roles/{role}", get(read_all_id_for_role))
|
||||||
|
.route("/users_ids/genders/{gender}", get(read_all_id_for_gender))
|
||||||
|
.route("/count", get(count_all))
|
||||||
|
.route("/count/names/{name}", get(count_all_for_name))
|
||||||
|
.route("/count/surnames/{surname}", get(count_all_for_surname))
|
||||||
|
.route(
|
||||||
|
"/count/birth_dates/{birth_date}",
|
||||||
|
get(count_all_for_birth_date),
|
||||||
|
)
|
||||||
|
.route("/count/roles/{role}", get(count_all_for_role))
|
||||||
|
.route("/count/genders/{gender}", get(count_all_for_gender))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create(Json(create_user): Json<CreateUser>) -> impl IntoResponse {
|
||||||
|
match User::create(
|
||||||
|
&create_user.name,
|
||||||
|
&create_user.surname,
|
||||||
|
&create_user.gender,
|
||||||
|
&create_user.birth_date,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(user) => (StatusCode::CREATED, Json(serde_json::json!(user))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_(Extension(target_user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||||
|
match User::delete(&target_user.user_id).await {
|
||||||
|
Ok(user) => (StatusCode::NO_CONTENT, Json(serde_json::json!(user))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all() -> impl IntoResponse {
|
||||||
|
match User::read_all().await {
|
||||||
|
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_for_name(Path(name): Path<String>) -> impl IntoResponse {
|
||||||
|
match User::read_all_for_name(&name).await {
|
||||||
|
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_for_surname(Path(surname): Path<String>) -> impl IntoResponse {
|
||||||
|
match User::read_all_for_surname(&surname).await {
|
||||||
|
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_for_birth_date(Path(birth_date): Path<NaiveDate>) -> impl IntoResponse {
|
||||||
|
match User::read_all_for_birth_date(&birth_date).await {
|
||||||
|
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_for_role(Path(role_id): Path<i64>) -> impl IntoResponse {
|
||||||
|
match User::read_all_for_role(&role_id).await {
|
||||||
|
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_for_gender(Path(gender): Path<bool>) -> impl IntoResponse {
|
||||||
|
match User::read_all_for_gender(&gender).await {
|
||||||
|
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_id() -> impl IntoResponse {
|
||||||
|
match User::read_all_id().await {
|
||||||
|
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_id_for_name(Path(name): Path<String>) -> impl IntoResponse {
|
||||||
|
match User::read_all_id_for_name(&name).await {
|
||||||
|
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_id_for_surname(Path(surname): Path<String>) -> impl IntoResponse {
|
||||||
|
match User::read_all_id_for_surname(&surname).await {
|
||||||
|
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_id_for_birth_date(Path(birth_date): Path<NaiveDate>) -> impl IntoResponse {
|
||||||
|
match User::read_all_id_for_birth_date(&birth_date).await {
|
||||||
|
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_id_for_role(Path(role_id): Path<i64>) -> impl IntoResponse {
|
||||||
|
match User::read_all_id_for_role(&role_id).await {
|
||||||
|
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_all_id_for_gender(Path(gender): Path<bool>) -> impl IntoResponse {
|
||||||
|
match User::read_all_id_for_gender(&gender).await {
|
||||||
|
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_all() -> impl IntoResponse {
|
||||||
|
match User::count_all().await {
|
||||||
|
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_all_for_name(Path(name): Path<String>) -> impl IntoResponse {
|
||||||
|
match User::count_all_for_name(&name).await {
|
||||||
|
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_all_for_surname(Path(surname): Path<String>) -> impl IntoResponse {
|
||||||
|
match User::count_all_for_surname(&surname).await {
|
||||||
|
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_all_for_birth_date(Path(birth_date): Path<NaiveDate>) -> impl IntoResponse {
|
||||||
|
match User::count_all_for_birth_date(&birth_date).await {
|
||||||
|
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_all_for_role(Path(role_id): Path<i64>) -> impl IntoResponse {
|
||||||
|
match User::count_all_for_role(&role_id).await {
|
||||||
|
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_all_for_gender(Path(gender): Path<bool>) -> impl IntoResponse {
|
||||||
|
match User::count_all_for_gender(&gender).await {
|
||||||
|
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::feature::{auth::OneTimePassword, login::Login, user::User, user_contact::UserContact};
|
use crate::feature::{auth::OneTimePassword, login::Login, user::User, user_contact::UserContact};
|
||||||
|
|
||||||
use super::middleware::{self, UserAndToken};
|
use super::middleware::{self, UserAndAuthorizationToken};
|
||||||
|
|
||||||
const CONTACT_EMAIL_DEFAULT_ID: i64 = 0;
|
const CONTACT_EMAIL_DEFAULT_ID: i64 = 0;
|
||||||
|
|
||||||
|
@ -92,8 +92,15 @@ async fn read(Path((user_id, token)): Path<(i64, String)>) -> impl IntoResponse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(Extension(user_and_token): Extension<Arc<UserAndToken>>) -> impl IntoResponse {
|
async fn update(
|
||||||
match Login::update(&user_and_token.user.user_id, &user_and_token.token).await {
|
Extension(user_and_authorization_token): Extension<Arc<UserAndAuthorizationToken>>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match Login::update(
|
||||||
|
&user_and_authorization_token.user.user_id,
|
||||||
|
&user_and_authorization_token.authorization_token,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(login) => (StatusCode::ACCEPTED, Json(serde_json::json!(login))),
|
Ok(login) => (StatusCode::ACCEPTED, Json(serde_json::json!(login))),
|
||||||
Err(err_val) => (
|
Err(err_val) => (
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
|
|
|
@ -1,154 +1,142 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::{to_bytes, Body},
|
|
||||||
extract::Request,
|
extract::Request,
|
||||||
http::{self, HeaderMap, Method, StatusCode},
|
http::{self, HeaderMap, StatusCode, Uri},
|
||||||
middleware::Next,
|
middleware::Next,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::feature::{login::TokenMeta, user::User};
|
use crate::{
|
||||||
|
error::ForumAuthError,
|
||||||
|
feature::{login::TokenMeta, user::User},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct UserAndRequest {
|
struct UserAndTargetUser {
|
||||||
user: User,
|
|
||||||
request: Request,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct TargetUserAndRequest {
|
|
||||||
target_user: User,
|
|
||||||
request: Request,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct UserAndTargetUserAndRequest {
|
|
||||||
user: User,
|
user: User,
|
||||||
target_user: User,
|
target_user: User,
|
||||||
request: Request,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct UserAndToken {
|
pub struct UserAndAuthorizationToken {
|
||||||
pub user: User,
|
pub user: User,
|
||||||
pub token: String,
|
pub authorization_token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn authorization_token_extraction(request_headers: &HeaderMap) -> Option<String> {
|
async fn authorization_token_extraction(
|
||||||
|
request_headers: &HeaderMap,
|
||||||
|
) -> Result<String, ForumAuthError> {
|
||||||
if let Some(authorization_header) = request_headers.get(http::header::AUTHORIZATION) {
|
if let Some(authorization_header) = request_headers.get(http::header::AUTHORIZATION) {
|
||||||
if let Ok(authorization_header) = authorization_header.to_str() {
|
if let Ok(authorization_header) = authorization_header.to_str() {
|
||||||
if let Some((bearer, authorization_token)) = authorization_header.split_once(' ') {
|
if let Some((bearer, authorization_token)) = authorization_header.split_once(' ') {
|
||||||
if bearer.to_lowercase() == "bearer" {
|
if bearer.to_lowercase() == "bearer" {
|
||||||
return Some(authorization_token.to_owned());
|
return Ok(authorization_token.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
Err(ForumAuthError::AuthenticationFailed("".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn user_extraction(request: Request) -> Option<UserAndRequest> {
|
async fn user_extraction_from_authorization_token(
|
||||||
if let Some(authorization_token) = authorization_token_extraction(&request.headers()).await {
|
authorization_token: &String,
|
||||||
match TokenMeta::verify_token(&authorization_token.to_string()).await {
|
) -> Result<User, ForumAuthError> {
|
||||||
Ok(claims) => {
|
match TokenMeta::verify_token(&authorization_token.to_string()).await {
|
||||||
return Some(UserAndRequest {
|
Ok(claims) => User::read(&claims.custom.user_id)
|
||||||
user: User::read(&claims.custom.user_id).await.ok()?,
|
.await
|
||||||
request,
|
.map_err(|err_val| ForumAuthError::AuthenticationFailed(err_val.to_string())),
|
||||||
});
|
Err(err_val) => Err(ForumAuthError::AuthenticationFailed(err_val.to_string())),
|
||||||
}
|
|
||||||
Err(err_val) => {
|
|
||||||
eprintln!("Verify Token | {}", err_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn target_user_extraction_from_uri(request: Request) -> Option<TargetUserAndRequest> {
|
async fn user_extraction_from_header(request_headers: &HeaderMap) -> Result<User, ForumAuthError> {
|
||||||
let uri_parts = request.uri().path().split('/').collect::<Vec<&str>>();
|
match authorization_token_extraction(request_headers).await {
|
||||||
for (index, uri_part) in uri_parts.iter().enumerate() {
|
Ok(authorization_token) => {
|
||||||
|
user_extraction_from_authorization_token(&authorization_token).await
|
||||||
|
}
|
||||||
|
Err(err_val) => Err(err_val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn user_extraction_from_uri(request_uri: &Uri) -> Result<User, ForumAuthError> {
|
||||||
|
let request_uri_parts = request_uri.path().split('/').collect::<Vec<&str>>();
|
||||||
|
for (index, uri_part) in request_uri_parts.iter().enumerate() {
|
||||||
if *uri_part == "users" {
|
if *uri_part == "users" {
|
||||||
if let Some(target_user_id) = uri_parts.get(index) {
|
if let Some(user_id) = request_uri_parts.get(index) {
|
||||||
if let Ok(target_user_id) = (*target_user_id).parse::<i64>() {
|
if let Ok(user_id) = (*user_id).parse::<i64>() {
|
||||||
if let Ok(target_user) = User::read(&target_user_id).await {
|
User::read(&user_id).await.map_err(|err_val| {
|
||||||
return Some(TargetUserAndRequest {
|
ForumAuthError::AuthenticationFailed(err_val.to_string())
|
||||||
target_user,
|
})?;
|
||||||
request,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
Err(ForumAuthError::AuthenticationFailed("".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn target_user_extraction_from_json(request: Request) -> Option<TargetUserAndRequest> {
|
async fn user_from_header_and_target_user_from_uri_extraction(
|
||||||
let (parts, body) = request.into_parts();
|
request_headers: &HeaderMap,
|
||||||
let bytes = to_bytes(body, usize::MAX).await.ok()?;
|
request_uri: &Uri,
|
||||||
let json: serde_json::Value = serde_json::from_slice(&bytes).ok()?;
|
) -> Result<UserAndTargetUser, ForumAuthError> {
|
||||||
|
let user = user_extraction_from_header(request_headers).await?;
|
||||||
|
let target_user = user_extraction_from_uri(request_uri).await?;
|
||||||
|
|
||||||
let body = Body::from(json.to_string());
|
Ok(UserAndTargetUser { user, target_user })
|
||||||
let request = Request::from_parts(parts, body);
|
}
|
||||||
|
|
||||||
if let Some(target_user_id) = json.get("user_id") {
|
pub async fn user_and_token(
|
||||||
if target_user_id.is_i64() {
|
mut request: Request,
|
||||||
if let Some(target_user_id) = target_user_id.as_i64() {
|
next: Next,
|
||||||
if let Ok(target_user) = User::read(&target_user_id).await {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
return Some(TargetUserAndRequest {
|
if let Ok(authorization_token) = authorization_token_extraction(&request.headers()).await {
|
||||||
target_user,
|
if let Ok(user) = user_extraction_from_authorization_token(&authorization_token).await {
|
||||||
request,
|
let user_and_token = Arc::new(UserAndAuthorizationToken {
|
||||||
});
|
user,
|
||||||
}
|
authorization_token,
|
||||||
}
|
});
|
||||||
|
|
||||||
|
request.extensions_mut().insert(user_and_token);
|
||||||
|
return Ok(next.run(request).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(StatusCode::FORBIDDEN)
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn user_and_target_user_extraction(request: Request) -> Option<UserAndTargetUserAndRequest> {
|
pub async fn pass_by_authorization_token(
|
||||||
let user_and_request = user_extraction(request).await?;
|
mut request: Request,
|
||||||
let user = user_and_request.user;
|
next: Next,
|
||||||
let request = user_and_request.request;
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
match user_extraction_from_header(request.headers()).await {
|
||||||
let target_user_and_request = if request.method() == Method::GET {
|
Ok(user) => {
|
||||||
target_user_extraction_from_uri(request).await
|
let user = Arc::new(user);
|
||||||
} else {
|
|
||||||
target_user_extraction_from_json(request).await
|
|
||||||
}?;
|
|
||||||
|
|
||||||
let target_user = target_user_and_request.target_user;
|
|
||||||
let request = target_user_and_request.request;
|
|
||||||
|
|
||||||
Some(UserAndTargetUserAndRequest {
|
|
||||||
user,
|
|
||||||
target_user,
|
|
||||||
request,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn pass(request: Request, next: Next) -> Result<impl IntoResponse, StatusCode> {
|
|
||||||
match user_extraction(request).await {
|
|
||||||
Some(user_and_request) => {
|
|
||||||
let user = Arc::new(user_and_request.user);
|
|
||||||
let mut request = user_and_request.request;
|
|
||||||
|
|
||||||
request.extensions_mut().insert(user);
|
request.extensions_mut().insert(user);
|
||||||
|
|
||||||
Ok(next.run(request).await)
|
Ok(next.run(request).await)
|
||||||
}
|
}
|
||||||
None => Err(StatusCode::FORBIDDEN),
|
Err(_) => Err(StatusCode::FORBIDDEN),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_builder(request: Request, next: Next) -> Result<impl IntoResponse, StatusCode> {
|
pub async fn pass_by_uri_user_extraction(
|
||||||
if let Some(user_and_request) = user_extraction(request).await {
|
mut request: Request,
|
||||||
let user = user_and_request.user;
|
next: Next,
|
||||||
let mut request = user_and_request.request;
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
if let Ok(target_user) = user_extraction_from_uri(request.uri()).await {
|
||||||
|
let target_user = Arc::new(target_user);
|
||||||
|
request.extensions_mut().insert(target_user);
|
||||||
|
|
||||||
|
return Ok(next.run(request).await);
|
||||||
|
}
|
||||||
|
Err(StatusCode::BAD_REQUEST)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn pass_builder_by_authorization_token(
|
||||||
|
mut request: Request,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
if let Ok(user) = user_extraction_from_header(request.headers()).await {
|
||||||
if User::is_builder(&user).await {
|
if User::is_builder(&user).await {
|
||||||
let user = Arc::new(user);
|
let user = Arc::new(user);
|
||||||
request.extensions_mut().insert(user);
|
request.extensions_mut().insert(user);
|
||||||
|
@ -159,14 +147,11 @@ pub async fn pass_builder(request: Request, next: Next) -> Result<impl IntoRespo
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_builder_or_admin(
|
pub async fn pass_builder_or_admin_by_authorization_token(
|
||||||
request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
if let Some(user_and_request) = user_extraction(request).await {
|
if let Ok(user) = user_extraction_from_header(request.headers()).await {
|
||||||
let user = user_and_request.user;
|
|
||||||
let mut request = user_and_request.request;
|
|
||||||
|
|
||||||
if User::is_builder_or_admin(&user).await {
|
if User::is_builder_or_admin(&user).await {
|
||||||
let user = Arc::new(user);
|
let user = Arc::new(user);
|
||||||
request.extensions_mut().insert(user);
|
request.extensions_mut().insert(user);
|
||||||
|
@ -177,50 +162,19 @@ pub async fn pass_builder_or_admin(
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_self(request: Request, next: Next) -> Result<impl IntoResponse, StatusCode> {
|
pub async fn pass_builder_by_authorization_token_with_target_user_by_request_uri(
|
||||||
if let Some(user_and_target_user_and_request) = user_and_target_user_extraction(request).await {
|
mut request: Request,
|
||||||
let user = user_and_target_user_and_request.user;
|
|
||||||
let target_user = user_and_target_user_and_request.target_user;
|
|
||||||
let mut request = user_and_target_user_and_request.request;
|
|
||||||
|
|
||||||
if User::is_self(&user, &target_user).await {
|
|
||||||
let user = Arc::new(user);
|
|
||||||
request.extensions_mut().insert(user);
|
|
||||||
|
|
||||||
return Ok(next.run(request).await);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(StatusCode::FORBIDDEN)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn pass_higher(request: Request, next: Next) -> Result<impl IntoResponse, StatusCode> {
|
|
||||||
if let Some(user_and_target_user_and_request) = user_and_target_user_extraction(request).await {
|
|
||||||
let user = user_and_target_user_and_request.user;
|
|
||||||
let target_user = user_and_target_user_and_request.target_user;
|
|
||||||
let mut request = user_and_target_user_and_request.request;
|
|
||||||
|
|
||||||
if User::is_higher(&user, &target_user).await {
|
|
||||||
let user = Arc::new(user);
|
|
||||||
request.extensions_mut().insert(user);
|
|
||||||
|
|
||||||
return Ok(next.run(request).await);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(StatusCode::FORBIDDEN)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn pass_higher_or_self(
|
|
||||||
request: Request,
|
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
if let Some(user_and_target_user_and_request) = user_and_target_user_extraction(request).await {
|
if let Ok(user_and_target_user) =
|
||||||
let user = user_and_target_user_and_request.user;
|
user_from_header_and_target_user_from_uri_extraction(request.headers(), request.uri()).await
|
||||||
let target_user = user_and_target_user_and_request.target_user;
|
{
|
||||||
let mut request = user_and_target_user_and_request.request;
|
let user = user_and_target_user.user;
|
||||||
|
let target_user = user_and_target_user.target_user;
|
||||||
|
|
||||||
if User::is_higher_or_self(&user, &target_user).await {
|
if User::is_builder(&user).await {
|
||||||
let user = Arc::new(user);
|
let target_user = Arc::new(target_user);
|
||||||
request.extensions_mut().insert(user);
|
request.extensions_mut().insert(target_user);
|
||||||
|
|
||||||
return Ok(next.run(request).await);
|
return Ok(next.run(request).await);
|
||||||
}
|
}
|
||||||
|
@ -228,14 +182,20 @@ pub async fn pass_higher_or_self(
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn user_and_token(request: Request, next: Next) -> Result<impl IntoResponse, StatusCode> {
|
pub async fn pass_builder_or_admin_by_authorization_token_with_target_user_by_request_uri(
|
||||||
if let Some(token) = authorization_token_extraction(&request.headers()).await {
|
mut request: Request,
|
||||||
if let Some(user_and_request) = user_extraction(request).await {
|
next: Next,
|
||||||
let user = user_and_request.user;
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
let mut request = user_and_request.request;
|
if let Ok(user_and_target_user) =
|
||||||
let user_and_token = Arc::new(UserAndToken { user, token });
|
user_from_header_and_target_user_from_uri_extraction(request.headers(), request.uri()).await
|
||||||
|
{
|
||||||
|
let user = user_and_target_user.user;
|
||||||
|
let target_user = user_and_target_user.target_user;
|
||||||
|
|
||||||
|
if User::is_builder_or_admin(&user).await {
|
||||||
|
let target_user = Arc::new(target_user);
|
||||||
|
request.extensions_mut().insert(target_user);
|
||||||
|
|
||||||
request.extensions_mut().insert(user_and_token);
|
|
||||||
return Ok(next.run(request).await);
|
return Ok(next.run(request).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,13 @@
|
||||||
use axum::{
|
use axum::{extract::Path, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
|
||||||
extract::Path,
|
|
||||||
http::StatusCode,
|
|
||||||
response::IntoResponse,
|
|
||||||
routing::{delete, get, patch, post},
|
|
||||||
Json, Router,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::feature::role::Role;
|
use crate::feature::role::Role;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct CreateRole {
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct UpdateRole {
|
|
||||||
id: i64,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn route() -> Router {
|
pub fn route() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", post(create))
|
|
||||||
.route("/{id}", get(read))
|
.route("/{id}", get(read))
|
||||||
.route("/", patch(update))
|
|
||||||
.route("/{id}", delete(delete_))
|
|
||||||
.route("/", get(read_all))
|
.route("/", get(read_all))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create(Json(create_role): Json<CreateRole>) -> impl IntoResponse {
|
|
||||||
match Role::create(&create_role.name).await {
|
|
||||||
Ok(role) => (StatusCode::CREATED, Json(serde_json::json!(role))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
||||||
match Role::read(&id).await {
|
match Role::read(&id).await {
|
||||||
Ok(role) => (StatusCode::OK, Json(serde_json::json!(role))),
|
Ok(role) => (StatusCode::OK, Json(serde_json::json!(role))),
|
||||||
|
@ -49,26 +18,6 @@ async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(Json(update_role): Json<UpdateRole>) -> impl IntoResponse {
|
|
||||||
match Role::update(&update_role.id, &update_role.name).await {
|
|
||||||
Ok(role) => (StatusCode::ACCEPTED, Json(serde_json::json!(role))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match Role::delete(&id).await {
|
|
||||||
Ok(role) => (StatusCode::NO_CONTENT, Json(serde_json::json!(role))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all() -> impl IntoResponse {
|
async fn read_all() -> impl IntoResponse {
|
||||||
match Role::read_all().await {
|
match Role::read_all().await {
|
||||||
Ok(roles) => (StatusCode::OK, Json(serde_json::json!(roles))),
|
Ok(roles) => (StatusCode::OK, Json(serde_json::json!(roles))),
|
||||||
|
|
|
@ -1,97 +1,16 @@
|
||||||
use axum::{
|
use axum::{extract::Path, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
|
||||||
extract::Path,
|
|
||||||
http::StatusCode,
|
|
||||||
response::IntoResponse,
|
|
||||||
routing::{delete, get, patch, post},
|
|
||||||
Json, Router,
|
|
||||||
};
|
|
||||||
use chrono::NaiveDate;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::feature::user::User;
|
use crate::feature::user::User;
|
||||||
|
|
||||||
use super::middleware;
|
use super::middleware;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct CreateUser {
|
|
||||||
name: String,
|
|
||||||
surname: String,
|
|
||||||
gender: bool,
|
|
||||||
birth_date: NaiveDate,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct UpdateUser {
|
|
||||||
user_id: i64,
|
|
||||||
name: String,
|
|
||||||
surname: String,
|
|
||||||
gender: bool,
|
|
||||||
birth_date: NaiveDate,
|
|
||||||
role_id: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn route() -> Router {
|
pub fn route() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", post(create))
|
.route("/{user_id}", get(read))
|
||||||
.route(
|
// todo just for beta I think
|
||||||
"/{user_id}",
|
.route_layer(axum::middleware::from_fn(
|
||||||
get(read).route_layer(axum::middleware::from_fn(middleware::pass)),
|
middleware::pass_by_authorization_token,
|
||||||
)
|
))
|
||||||
.route(
|
|
||||||
"/",
|
|
||||||
patch(update).route_layer(axum::middleware::from_fn(middleware::pass_higher_or_self)),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/{user_id}",
|
|
||||||
delete(delete_).route_layer(axum::middleware::from_fn(middleware::pass_higher_or_self)),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/",
|
|
||||||
get(read_all).route_layer(axum::middleware::from_fn(middleware::pass_builder_or_admin)),
|
|
||||||
)
|
|
||||||
.route("/names/{name}", get(read_all_for_name))
|
|
||||||
.route("/surnames/{surname}", get(read_all_for_surname))
|
|
||||||
.route("/birth_dates/{birth_date}", get(read_all_for_birth_date))
|
|
||||||
.route("/roles/{role}", get(read_all_for_role))
|
|
||||||
.route("/genders/{gender}", get(read_all_for_gender))
|
|
||||||
.route("/users_ids", get(read_all_id))
|
|
||||||
.route("/users_ids/names/{name}", get(read_all_id_for_name))
|
|
||||||
.route(
|
|
||||||
"/users_ids/surnames/{surname}",
|
|
||||||
get(read_all_id_for_surname),
|
|
||||||
)
|
|
||||||
.route(
|
|
||||||
"/users_ids/birth_dates/{birth_date}",
|
|
||||||
get(read_all_id_for_birth_date),
|
|
||||||
)
|
|
||||||
.route("/users_ids/roles/{role}", get(read_all_id_for_role))
|
|
||||||
.route("/users_ids/genders/{gender}", get(read_all_id_for_gender))
|
|
||||||
.route("/count", get(count_all))
|
|
||||||
.route("/count/names/{name}", get(count_all_for_name))
|
|
||||||
.route("/count/surnames/{surname}", get(count_all_for_surname))
|
|
||||||
.route(
|
|
||||||
"/count/birth_dates/{birth_date}",
|
|
||||||
get(count_all_for_birth_date),
|
|
||||||
)
|
|
||||||
.route("/count/roles/{role}", get(count_all_for_role))
|
|
||||||
.route("/count/genders/{gender}", get(count_all_for_gender))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create(Json(create_user): Json<CreateUser>) -> impl IntoResponse {
|
|
||||||
match User::create(
|
|
||||||
&create_user.name,
|
|
||||||
&create_user.surname,
|
|
||||||
&create_user.gender,
|
|
||||||
&create_user.birth_date,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(user) => (StatusCode::CREATED, Json(serde_json::json!(user))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||||
|
@ -103,212 +22,3 @@ async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(Json(update_user): Json<UpdateUser>) -> impl IntoResponse {
|
|
||||||
match User::update(
|
|
||||||
&update_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())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_(Path(user_id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match User::delete(&user_id).await {
|
|
||||||
Ok(user) => (StatusCode::NO_CONTENT, Json(serde_json::json!(user))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all() -> impl IntoResponse {
|
|
||||||
match User::read_all().await {
|
|
||||||
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_for_name(Path(name): Path<String>) -> impl IntoResponse {
|
|
||||||
match User::read_all_for_name(&name).await {
|
|
||||||
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_for_surname(Path(surname): Path<String>) -> impl IntoResponse {
|
|
||||||
match User::read_all_for_surname(&surname).await {
|
|
||||||
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_for_birth_date(Path(birth_date): Path<NaiveDate>) -> impl IntoResponse {
|
|
||||||
match User::read_all_for_birth_date(&birth_date).await {
|
|
||||||
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_for_role(Path(role_id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match User::read_all_for_role(&role_id).await {
|
|
||||||
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_for_gender(Path(gender): Path<bool>) -> impl IntoResponse {
|
|
||||||
match User::read_all_for_gender(&gender).await {
|
|
||||||
Ok(users) => (StatusCode::OK, Json(serde_json::json!(users))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_id() -> impl IntoResponse {
|
|
||||||
match User::read_all_id().await {
|
|
||||||
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_id_for_name(Path(name): Path<String>) -> impl IntoResponse {
|
|
||||||
match User::read_all_id_for_name(&name).await {
|
|
||||||
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_id_for_surname(Path(surname): Path<String>) -> impl IntoResponse {
|
|
||||||
match User::read_all_id_for_surname(&surname).await {
|
|
||||||
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_id_for_birth_date(Path(birth_date): Path<NaiveDate>) -> impl IntoResponse {
|
|
||||||
match User::read_all_id_for_birth_date(&birth_date).await {
|
|
||||||
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_id_for_role(Path(role_id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match User::read_all_id_for_role(&role_id).await {
|
|
||||||
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_all_id_for_gender(Path(gender): Path<bool>) -> impl IntoResponse {
|
|
||||||
match User::read_all_id_for_gender(&gender).await {
|
|
||||||
Ok(user_ids) => (StatusCode::OK, Json(serde_json::json!(user_ids))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn count_all() -> impl IntoResponse {
|
|
||||||
match User::count_all().await {
|
|
||||||
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn count_all_for_name(Path(name): Path<String>) -> impl IntoResponse {
|
|
||||||
match User::count_all_for_name(&name).await {
|
|
||||||
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn count_all_for_surname(Path(surname): Path<String>) -> impl IntoResponse {
|
|
||||||
match User::count_all_for_surname(&surname).await {
|
|
||||||
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn count_all_for_birth_date(Path(birth_date): Path<NaiveDate>) -> impl IntoResponse {
|
|
||||||
match User::count_all_for_birth_date(&birth_date).await {
|
|
||||||
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn count_all_for_role(Path(role_id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match User::count_all_for_role(&role_id).await {
|
|
||||||
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn count_all_for_gender(Path(gender): Path<bool>) -> impl IntoResponse {
|
|
||||||
match User::count_all_for_gender(&gender).await {
|
|
||||||
Ok(count) => (StatusCode::OK, Json(serde_json::json!(count))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue