feat: ✨ admin routing part 2
This commit is contained in:
parent
a462d3a82d
commit
bf2b0a439c
13 changed files with 370 additions and 171 deletions
|
@ -124,49 +124,25 @@ impl User {
|
||||||
user::count_all_for_gender(gender).await
|
user::count_all_for_gender(gender).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_builder(user: &User) -> bool {
|
async fn is_normal(&self) -> bool {
|
||||||
if user.role_id == 0 {
|
if self.role_id == 0 {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_admin(user: &User) -> bool {
|
async fn is_same_level(&self, target_user: &User) -> bool {
|
||||||
if user.role_id == 1 {
|
if self.role_id == target_user.role_id {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_banned(user: &User) -> bool {
|
async fn is_higher(&self, target_user: &User) -> bool {
|
||||||
if user.role_id == -1 {
|
if self.user_id >= 0 {
|
||||||
true
|
if self.user_id < target_user.user_id {
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn is_builder_or_admin(user: &User) -> bool {
|
|
||||||
if user.role_id == 0 || user.role_id == 1 {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn is_self(user: &User, target_user: &User) -> bool {
|
|
||||||
if user.user_id == target_user.user_id {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn is_higher(user: &User, target_user: &User) -> bool {
|
|
||||||
if user.user_id >= 0 {
|
|
||||||
if user.user_id < target_user.user_id {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,11 +150,55 @@ impl User {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_higher_or_self(user: &User, target_user: &User) -> bool {
|
pub async fn is_builder(&self) -> bool {
|
||||||
if User::is_self(user, target_user).await {
|
if self.role_id == 0 {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
User::is_higher(user, target_user).await
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_admin(&self) -> bool {
|
||||||
|
if self.role_id == 1 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_banned(&self) -> bool {
|
||||||
|
if self.role_id == -1 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_builder_or_admin(&self) -> bool {
|
||||||
|
if self.role_id == 0 || self.role_id == 1 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_default(&self, target_user: &User) -> bool {
|
||||||
|
if self.is_banned().await {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
if self.is_normal().await {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
if self.is_same_level(target_user).await {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
if self.is_higher(target_user).await {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::database::user_contact;
|
use crate::database::user_contact;
|
||||||
|
|
||||||
|
use super::user::User;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct UserContact {
|
pub struct UserContact {
|
||||||
pub user_id: i64,
|
pub user_id: i64,
|
||||||
|
@ -11,34 +13,34 @@ pub struct UserContact {
|
||||||
|
|
||||||
impl UserContact {
|
impl UserContact {
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
user_id: &i64,
|
user: &User,
|
||||||
contact_id: &i64,
|
contact_id: &i64,
|
||||||
contact_value: &String,
|
contact_value: &String,
|
||||||
) -> Result<UserContact, sqlx::Error> {
|
) -> Result<UserContact, sqlx::Error> {
|
||||||
user_contact::create(user_id, contact_id, contact_value).await
|
user_contact::create(&user.user_id, contact_id, contact_value).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(user_id: &i64, contact_id: &i64) -> Result<UserContact, sqlx::Error> {
|
pub async fn read(user: &User, contact_id: &i64) -> Result<UserContact, sqlx::Error> {
|
||||||
user_contact::read(user_id, contact_id).await
|
user_contact::read(&user.user_id, contact_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(
|
pub async fn update(
|
||||||
user_id: &i64,
|
user: &User,
|
||||||
contact_id: &i64,
|
contact_id: &i64,
|
||||||
contact_value: &String,
|
contact_value: &String,
|
||||||
) -> Result<UserContact, sqlx::Error> {
|
) -> Result<UserContact, sqlx::Error> {
|
||||||
user_contact::update(user_id, contact_id, contact_value).await
|
user_contact::update(&user.user_id, contact_id, contact_value).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete(user_id: &i64, contact_id: &i64) -> Result<UserContact, sqlx::Error> {
|
pub async fn delete(user: &User, contact_id: &i64) -> Result<UserContact, sqlx::Error> {
|
||||||
user_contact::delete(user_id, contact_id).await
|
user_contact::delete(&user.user_id, contact_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read_all_for_user(user_id: &i64) -> Result<Vec<UserContact>, sqlx::Error> {
|
pub async fn read_all_for_user(user: &User) -> Result<Vec<UserContact>, sqlx::Error> {
|
||||||
user_contact::read_all_for_user(user_id).await
|
user_contact::read_all_for_user(&user.user_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_all_for_user(user_id: &i64) -> Result<Vec<UserContact>, sqlx::Error> {
|
pub async fn delete_all_for_user(user: &User) -> Result<Vec<UserContact>, sqlx::Error> {
|
||||||
user_contact::delete_all_for_user(user_id).await
|
user_contact::delete_all_for_user(&user.user_id).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub mod user;
|
||||||
pub mod user_contact;
|
pub mod user_contact;
|
||||||
|
|
||||||
use axum::{http::StatusCode, response::IntoResponse, routing::get, Router};
|
use axum::{http::StatusCode, response::IntoResponse, routing::get, Router};
|
||||||
|
use middleware::by_authorization_token;
|
||||||
use tower::limit::ConcurrencyLimitLayer;
|
use tower::limit::ConcurrencyLimitLayer;
|
||||||
use tower_http::{cors::CorsLayer, trace::TraceLayer};
|
use tower_http::{cors::CorsLayer, trace::TraceLayer};
|
||||||
|
|
||||||
|
@ -31,6 +32,8 @@ pub async fn route(concurrency_limit: &usize) -> Router {
|
||||||
.nest("/contacts", contact::route())
|
.nest("/contacts", contact::route())
|
||||||
.nest("/user_contacts", user_contact::route())
|
.nest("/user_contacts", user_contact::route())
|
||||||
.nest("/admin", admin::route())
|
.nest("/admin", admin::route())
|
||||||
|
// todo just for beta I think
|
||||||
|
.route_layer(axum::middleware::from_fn(by_authorization_token))
|
||||||
.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())
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
|
pub mod contact;
|
||||||
pub mod role;
|
pub mod role;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
pub mod user_contact;
|
||||||
|
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
|
||||||
use super::middleware::pass_builder_or_admin_by_authorization_token;
|
use super::middleware::builder_or_admin_by_authorization_token;
|
||||||
|
|
||||||
pub fn route() -> Router {
|
pub fn route() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.nest("/users", user::route())
|
.nest("/users", user::route())
|
||||||
.nest("/roles", role::route())
|
.nest("/roles", role::route())
|
||||||
|
.nest("/contacts", contact::route())
|
||||||
|
.nest("/user_contacts", user_contact::route())
|
||||||
.route_layer(axum::middleware::from_fn(
|
.route_layer(axum::middleware::from_fn(
|
||||||
pass_builder_or_admin_by_authorization_token,
|
builder_or_admin_by_authorization_token,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
58
src/routing/admin/contact.rs
Normal file
58
src/routing/admin/contact.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::contact::Contact;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct CreateContact {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct UpdateContact {
|
||||||
|
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_contact): Json<CreateContact>) -> impl IntoResponse {
|
||||||
|
match Contact::create(&create_contact.name).await {
|
||||||
|
Ok(contact) => (StatusCode::CREATED, Json(serde_json::json!(contact))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(Json(update_contact): Json<UpdateContact>) -> impl IntoResponse {
|
||||||
|
match Contact::update(&update_contact.id, &update_contact.name).await {
|
||||||
|
Ok(contact) => (StatusCode::ACCEPTED, Json(serde_json::json!(contact))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
||||||
|
match Contact::delete(&id).await {
|
||||||
|
Ok(contact) => (StatusCode::NO_CONTENT, Json(serde_json::json!(contact))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,18 +2,13 @@ use axum::{
|
||||||
extract::Path,
|
extract::Path,
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
routing::{delete, patch, post},
|
routing::{delete, patch},
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
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)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct UpdateRole {
|
struct UpdateRole {
|
||||||
id: i64,
|
id: i64,
|
||||||
|
@ -22,21 +17,10 @@ struct UpdateRole {
|
||||||
|
|
||||||
pub fn route() -> Router {
|
pub fn route() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", post(create))
|
|
||||||
.route("/", patch(update))
|
.route("/", patch(update))
|
||||||
.route("/{id}", delete(delete_))
|
.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 {
|
async fn update(Json(update_role): Json<UpdateRole>) -> impl IntoResponse {
|
||||||
match Role::update(&update_role.id, &update_role.name).await {
|
match Role::update(&update_role.id, &update_role.name).await {
|
||||||
Ok(role) => (StatusCode::ACCEPTED, Json(serde_json::json!(role))),
|
Ok(role) => (StatusCode::ACCEPTED, Json(serde_json::json!(role))),
|
||||||
|
|
|
@ -10,7 +10,7 @@ use axum::{
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{feature::user::User, routing::middleware::pass_by_uri_user_extraction};
|
use crate::{feature::user::User, routing::middleware::by_uri_then_insert};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct CreateUser {
|
struct CreateUser {
|
||||||
|
@ -34,11 +34,11 @@ pub fn route() -> Router {
|
||||||
.route("/", post(create))
|
.route("/", post(create))
|
||||||
.route(
|
.route(
|
||||||
"/{user_id}",
|
"/{user_id}",
|
||||||
patch(update).route_layer(axum::middleware::from_fn(pass_by_uri_user_extraction)),
|
patch(update).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/{user_id}",
|
"/{user_id}",
|
||||||
delete(delete_).route_layer(axum::middleware::from_fn(pass_by_uri_user_extraction)),
|
delete(delete_).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
)
|
)
|
||||||
.route("/", get(read_all))
|
.route("/", get(read_all))
|
||||||
.route("/names/{name}", get(read_all_for_name))
|
.route("/names/{name}", get(read_all_for_name))
|
||||||
|
|
128
src/routing/admin/user_contact.rs
Normal file
128
src/routing/admin/user_contact.rs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::Path,
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
routing::{delete, get, patch, post},
|
||||||
|
Extension, Json, Router,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
feature::{user::User, user_contact::UserContact},
|
||||||
|
routing::middleware::by_uri_then_insert,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct CreateUserContact {
|
||||||
|
pub contact_id: i64,
|
||||||
|
pub contact_value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct UpdateUserContact {
|
||||||
|
pub contact_id: i64,
|
||||||
|
pub contact_value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn route() -> Router {
|
||||||
|
Router::new()
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}",
|
||||||
|
post(create).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}/contacts/{contact_id}",
|
||||||
|
get(read).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}",
|
||||||
|
patch(update).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}/contacts/{contact_id}",
|
||||||
|
delete(delete_).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}",
|
||||||
|
delete(delete_all_for_user).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create(
|
||||||
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Json(create_user_contact): Json<CreateUserContact>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match UserContact::create(
|
||||||
|
&user,
|
||||||
|
&create_user_contact.contact_id,
|
||||||
|
&create_user_contact.contact_value,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(user_contact) => (StatusCode::CREATED, Json(serde_json::json!(user_contact))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read(
|
||||||
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Path(contact_id): Path<i64>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match UserContact::read(&user, &contact_id).await {
|
||||||
|
Ok(user_contact) => (StatusCode::OK, Json(serde_json::json!(user_contact))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Json(update_user_contact): Json<UpdateUserContact>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match UserContact::update(
|
||||||
|
&user,
|
||||||
|
&update_user_contact.contact_id,
|
||||||
|
&update_user_contact.contact_value,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(user_contact) => (StatusCode::ACCEPTED, Json(serde_json::json!(user_contact))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_(
|
||||||
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Path(contact_id): Path<i64>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match UserContact::delete(&user, &contact_id).await {
|
||||||
|
Ok(user_contact) => (
|
||||||
|
StatusCode::NO_CONTENT,
|
||||||
|
Json(serde_json::json!(user_contact)),
|
||||||
|
),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_all_for_user(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||||
|
match UserContact::delete_all_for_user(&user).await {
|
||||||
|
Ok(user_contacts) => (StatusCode::OK, Json(serde_json::json!(user_contacts))),
|
||||||
|
Err(err_val) => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
|
@ -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::contact::Contact;
|
use crate::feature::contact::Contact;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct CreateContact {
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct UpdateContact {
|
|
||||||
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_contact): Json<CreateContact>) -> impl IntoResponse {
|
|
||||||
match Contact::create(&create_contact.name).await {
|
|
||||||
Ok(contact) => (StatusCode::CREATED, Json(serde_json::json!(contact))),
|
|
||||||
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 Contact::read(&id).await {
|
match Contact::read(&id).await {
|
||||||
Ok(contact) => (StatusCode::OK, Json(serde_json::json!(contact))),
|
Ok(contact) => (StatusCode::OK, Json(serde_json::json!(contact))),
|
||||||
|
@ -49,26 +18,6 @@ async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(Json(update_contact): Json<UpdateContact>) -> impl IntoResponse {
|
|
||||||
match Contact::update(&update_contact.id, &update_contact.name).await {
|
|
||||||
Ok(contact) => (StatusCode::ACCEPTED, Json(serde_json::json!(contact))),
|
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match Contact::delete(&id).await {
|
|
||||||
Ok(contact) => (StatusCode::NO_CONTENT, Json(serde_json::json!(contact))),
|
|
||||||
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 Contact::read_all().await {
|
match Contact::read_all().await {
|
||||||
Ok(contacts) => (StatusCode::OK, Json(serde_json::json!(contacts))),
|
Ok(contacts) => (StatusCode::OK, Json(serde_json::json!(contacts))),
|
||||||
|
|
|
@ -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, UserAndAuthorizationToken};
|
use super::middleware::{user_and_token_then_insert, UserAndAuthorizationToken};
|
||||||
|
|
||||||
const CONTACT_EMAIL_DEFAULT_ID: i64 = 0;
|
const CONTACT_EMAIL_DEFAULT_ID: i64 = 0;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ pub fn route() -> Router {
|
||||||
.route("/users/{user_id}/tokens/{token}", get(read))
|
.route("/users/{user_id}/tokens/{token}", get(read))
|
||||||
.route(
|
.route(
|
||||||
"/",
|
"/",
|
||||||
patch(update).route_layer(axum::middleware::from_fn(middleware::user_and_token)),
|
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}/tokens/{token}", delete(delete_))
|
||||||
.route("/users/{user_id}", get(read_all_for_user))
|
.route("/users/{user_id}", get(read_all_for_user))
|
||||||
|
@ -45,7 +45,7 @@ async fn create_one_time_password(
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
//todo get user from middleware or something
|
//todo get user from middleware or something
|
||||||
let user = User::read(&create_one_time_password.user_id).await.unwrap();
|
let user = User::read(&create_one_time_password.user_id).await.unwrap();
|
||||||
match UserContact::read(&user.user_id, &CONTACT_EMAIL_DEFAULT_ID).await {
|
match UserContact::read(&user, &CONTACT_EMAIL_DEFAULT_ID).await {
|
||||||
Ok(user_email) => match OneTimePassword::new(&user, &user_email.contact_value).await {
|
Ok(user_email) => match OneTimePassword::new(&user, &user_email.contact_value).await {
|
||||||
Ok(_) => (StatusCode::CREATED, Json(serde_json::json!(""))),
|
Ok(_) => (StatusCode::CREATED, Json(serde_json::json!(""))),
|
||||||
Err(err_val) => (
|
Err(err_val) => (
|
||||||
|
|
|
@ -86,7 +86,7 @@ async fn user_from_header_and_target_user_from_uri_extraction(
|
||||||
Ok(UserAndTargetUser { user, target_user })
|
Ok(UserAndTargetUser { user, target_user })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn user_and_token(
|
pub async fn user_and_token_then_insert(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -104,7 +104,17 @@ pub async fn user_and_token(
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_by_authorization_token(
|
pub async fn by_authorization_token(
|
||||||
|
request: Request,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
match user_extraction_from_header(request.headers()).await {
|
||||||
|
Ok(_) => Ok(next.run(request).await),
|
||||||
|
Err(_) => Err(StatusCode::FORBIDDEN),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn by_authorization_token_then_insert(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -119,7 +129,7 @@ pub async fn pass_by_authorization_token(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_by_uri_user_extraction(
|
pub async fn by_uri_then_insert(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -132,7 +142,19 @@ pub async fn pass_by_uri_user_extraction(
|
||||||
Err(StatusCode::BAD_REQUEST)
|
Err(StatusCode::BAD_REQUEST)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_builder_by_authorization_token(
|
pub async fn builder_by_authorization_token(
|
||||||
|
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 {
|
||||||
|
return Ok(next.run(request).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(StatusCode::FORBIDDEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn builder_by_authorization_token_then_insert(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -147,7 +169,19 @@ pub async fn pass_builder_by_authorization_token(
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_builder_or_admin_by_authorization_token(
|
pub async fn builder_or_admin_by_authorization_token(
|
||||||
|
request: Request,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
if let Ok(user) = user_extraction_from_header(request.headers()).await {
|
||||||
|
if User::is_builder_or_admin(&user).await {
|
||||||
|
return Ok(next.run(request).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(StatusCode::FORBIDDEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn builder_or_admin_by_authorization_token_then_insert(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -162,7 +196,7 @@ pub async fn pass_builder_or_admin_by_authorization_token(
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_builder_by_authorization_token_with_target_user_by_request_uri(
|
pub async fn builder_by_authorization_token_and_target_user_by_uri_then_insert_target(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -172,7 +206,7 @@ pub async fn pass_builder_by_authorization_token_with_target_user_by_request_uri
|
||||||
let user = user_and_target_user.user;
|
let user = user_and_target_user.user;
|
||||||
let target_user = user_and_target_user.target_user;
|
let target_user = user_and_target_user.target_user;
|
||||||
|
|
||||||
if User::is_builder(&user).await {
|
if user.is_builder().await && user.is_default(&target_user).await {
|
||||||
let target_user = Arc::new(target_user);
|
let target_user = Arc::new(target_user);
|
||||||
request.extensions_mut().insert(target_user);
|
request.extensions_mut().insert(target_user);
|
||||||
|
|
||||||
|
@ -182,7 +216,7 @@ pub async fn pass_builder_by_authorization_token_with_target_user_by_request_uri
|
||||||
Err(StatusCode::FORBIDDEN)
|
Err(StatusCode::FORBIDDEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pass_builder_or_admin_by_authorization_token_with_target_user_by_request_uri(
|
pub async fn builder_or_admin_by_authorization_token_and_target_user_by_uri_then_insert_target(
|
||||||
mut request: Request,
|
mut request: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
|
@ -192,7 +226,7 @@ pub async fn pass_builder_or_admin_by_authorization_token_with_target_user_by_re
|
||||||
let user = user_and_target_user.user;
|
let user = user_and_target_user.user;
|
||||||
let target_user = user_and_target_user.target_user;
|
let target_user = user_and_target_user.target_user;
|
||||||
|
|
||||||
if User::is_builder_or_admin(&user).await {
|
if user.is_default(&target_user).await {
|
||||||
let target_user = Arc::new(target_user);
|
let target_user = Arc::new(target_user);
|
||||||
request.extensions_mut().insert(target_user);
|
request.extensions_mut().insert(target_user);
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,8 @@ use axum::{extract::Path, http::StatusCode, response::IntoResponse, routing::get
|
||||||
|
|
||||||
use crate::feature::user::User;
|
use crate::feature::user::User;
|
||||||
|
|
||||||
use super::middleware;
|
|
||||||
|
|
||||||
pub fn route() -> Router {
|
pub fn route() -> Router {
|
||||||
Router::new()
|
Router::new().route("/{user_id}", get(read))
|
||||||
.route("/{user_id}", get(read))
|
|
||||||
// todo just for beta I think
|
|
||||||
.route_layer(axum::middleware::from_fn(
|
|
||||||
middleware::pass_by_authorization_token,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||||
|
|
|
@ -1,41 +1,66 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::Path,
|
extract::Path,
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
routing::{delete, get, patch, post},
|
routing::{delete, get, patch, post},
|
||||||
Json, Router,
|
Extension, Json, Router,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::feature::user_contact::UserContact;
|
use crate::feature::{user::User, user_contact::UserContact};
|
||||||
|
|
||||||
|
use super::middleware::{by_authorization_token_then_insert, by_uri_then_insert};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct CreateUserContact {
|
struct CreateUserContact {
|
||||||
pub user_id: i64,
|
|
||||||
pub contact_id: i64,
|
pub contact_id: i64,
|
||||||
pub contact_value: String,
|
pub contact_value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct UpdateUserContact {
|
struct UpdateUserContact {
|
||||||
pub user_id: i64,
|
|
||||||
pub contact_id: i64,
|
pub contact_id: i64,
|
||||||
pub contact_value: String,
|
pub contact_value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route() -> Router {
|
pub fn route() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", post(create))
|
.route(
|
||||||
.route("/roles/{user_id}/contacts/{contact_id}", get(read))
|
"/",
|
||||||
.route("/", patch(update))
|
post(create).route_layer(axum::middleware::from_fn(
|
||||||
.route("/roles/{user_id}/contacts/{contact_id}", delete(delete_))
|
by_authorization_token_then_insert,
|
||||||
.route("/users/{user_id}", get(read_all_for_user))
|
)),
|
||||||
.route("/users/{user_id}", delete(delete_all_for_user))
|
)
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}/contacts/{contact_id}",
|
||||||
|
get(read).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/",
|
||||||
|
patch(update).route_layer(axum::middleware::from_fn(
|
||||||
|
by_authorization_token_then_insert,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users/contacts/{contact_id}",
|
||||||
|
delete(delete_).route_layer(axum::middleware::from_fn(
|
||||||
|
by_authorization_token_then_insert,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/users/{user_id}",
|
||||||
|
get(read_all_for_user).route_layer(axum::middleware::from_fn(by_uri_then_insert)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create(Json(create_user_contact): Json<CreateUserContact>) -> impl IntoResponse {
|
async fn create(
|
||||||
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Json(create_user_contact): Json<CreateUserContact>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
match UserContact::create(
|
match UserContact::create(
|
||||||
&create_user_contact.user_id,
|
&user,
|
||||||
&create_user_contact.contact_id,
|
&create_user_contact.contact_id,
|
||||||
&create_user_contact.contact_value,
|
&create_user_contact.contact_value,
|
||||||
)
|
)
|
||||||
|
@ -49,8 +74,11 @@ async fn create(Json(create_user_contact): Json<CreateUserContact>) -> impl Into
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read(Path((user_id, contact_id)): Path<(i64, i64)>) -> impl IntoResponse {
|
async fn read(
|
||||||
match UserContact::read(&user_id, &contact_id).await {
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Path(contact_id): Path<i64>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match UserContact::read(&user, &contact_id).await {
|
||||||
Ok(user_contact) => (StatusCode::OK, Json(serde_json::json!(user_contact))),
|
Ok(user_contact) => (StatusCode::OK, Json(serde_json::json!(user_contact))),
|
||||||
Err(err_val) => (
|
Err(err_val) => (
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
|
@ -59,9 +87,12 @@ async fn read(Path((user_id, contact_id)): Path<(i64, i64)>) -> impl IntoRespons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(Json(update_user_contact): Json<UpdateUserContact>) -> impl IntoResponse {
|
async fn update(
|
||||||
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Json(update_user_contact): Json<UpdateUserContact>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
match UserContact::update(
|
match UserContact::update(
|
||||||
&update_user_contact.user_id,
|
&user,
|
||||||
&update_user_contact.contact_id,
|
&update_user_contact.contact_id,
|
||||||
&update_user_contact.contact_value,
|
&update_user_contact.contact_value,
|
||||||
)
|
)
|
||||||
|
@ -75,8 +106,11 @@ async fn update(Json(update_user_contact): Json<UpdateUserContact>) -> impl Into
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_(Path((user_id, contact_id)): Path<(i64, i64)>) -> impl IntoResponse {
|
async fn delete_(
|
||||||
match UserContact::delete(&user_id, &contact_id).await {
|
Extension(user): Extension<Arc<User>>,
|
||||||
|
Path(contact_id): Path<i64>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
match UserContact::delete(&user, &contact_id).await {
|
||||||
Ok(user_contact) => (
|
Ok(user_contact) => (
|
||||||
StatusCode::NO_CONTENT,
|
StatusCode::NO_CONTENT,
|
||||||
Json(serde_json::json!(user_contact)),
|
Json(serde_json::json!(user_contact)),
|
||||||
|
@ -88,19 +122,9 @@ async fn delete_(Path((user_id, contact_id)): Path<(i64, i64)>) -> impl IntoResp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_all_for_user(Path(user_id): Path<i64>) -> impl IntoResponse {
|
async fn read_all_for_user(Extension(user): Extension<Arc<User>>) -> impl IntoResponse {
|
||||||
match UserContact::read_all_for_user(&user_id).await {
|
match UserContact::read_all_for_user(&user).await {
|
||||||
Ok(role_contacts) => (StatusCode::OK, Json(serde_json::json!(role_contacts))),
|
Ok(user_contacts) => (StatusCode::OK, Json(serde_json::json!(user_contacts))),
|
||||||
Err(err_val) => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_all_for_user(Path(user_id): Path<i64>) -> impl IntoResponse {
|
|
||||||
match UserContact::delete_all_for_user(&user_id).await {
|
|
||||||
Ok(role_contacts) => (StatusCode::OK, Json(serde_json::json!(role_contacts))),
|
|
||||||
Err(err_val) => (
|
Err(err_val) => (
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Json(serde_json::json!(err_val.to_string())),
|
Json(serde_json::json!(err_val.to_string())),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue