Implemented basic auth logic + other stuff
This commit is contained in:
parent
cb26393fcd
commit
260f887d22
45
Cargo.lock
generated
45
Cargo.lock
generated
@ -43,6 +43,7 @@ dependencies = [
|
|||||||
"actix-identity",
|
"actix-identity",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
|
"actix-threadpool",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"actix-web-httpauth",
|
"actix-web-httpauth",
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
@ -50,7 +51,9 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"comp",
|
"comp",
|
||||||
"custom_error",
|
"custom_error",
|
||||||
|
"derive-new",
|
||||||
"diesel",
|
"diesel",
|
||||||
|
"diesel_migrations",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"env_logger 0.7.1",
|
"env_logger 0.7.1",
|
||||||
"futures",
|
"futures",
|
||||||
@ -832,6 +835,17 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive-new"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.12",
|
||||||
|
"quote 1.0.4",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_builder"
|
name = "derive_builder"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -892,6 +906,16 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_migrations"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c"
|
||||||
|
dependencies = [
|
||||||
|
"migrations_internals",
|
||||||
|
"migrations_macros",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "directories"
|
name = "directories"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
@ -1610,6 +1634,27 @@ version = "2.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrations_internals"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860"
|
||||||
|
dependencies = [
|
||||||
|
"diesel",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrations_macros"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
||||||
|
dependencies = [
|
||||||
|
"migrations_internals",
|
||||||
|
"proc-macro2 1.0.12",
|
||||||
|
"quote 1.0.4",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.16"
|
version = "0.3.16"
|
||||||
|
@ -33,6 +33,9 @@ regex = '1.3.7'
|
|||||||
lazy_static = '1.4.0'
|
lazy_static = '1.4.0'
|
||||||
lazy-regex = '0.1.2'
|
lazy-regex = '0.1.2'
|
||||||
custom_error = '1.7.1'
|
custom_error = '1.7.1'
|
||||||
|
derive-new = '0.5.8'
|
||||||
|
diesel_migrations = '1.4.0'
|
||||||
|
actix-threadpool = '0.3.1'
|
||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = '1.0.106'
|
version = '1.0.106'
|
||||||
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
@ -0,0 +1 @@
|
|||||||
|
max_width = 80
|
@ -1,8 +1,9 @@
|
|||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use diesel::sqlite::Sqlite;
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::models;
|
use crate::models;
|
||||||
use bcrypt::{hash, DEFAULT_COST};
|
use bcrypt::{hash, verify, DEFAULT_COST};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn find_user_by_uid(
|
pub fn find_user_by_uid(
|
||||||
@ -24,11 +25,7 @@ pub fn _find_user_by_name(
|
|||||||
user_name: String,
|
user_name: String,
|
||||||
conn: &SqliteConnection,
|
conn: &SqliteConnection,
|
||||||
) -> Result<Option<models::UserDTO>, errors::DomainError> {
|
) -> Result<Option<models::UserDTO>, errors::DomainError> {
|
||||||
use crate::schema::users::dsl::*;
|
let maybe_user = _get_user_by_name(user_name)
|
||||||
|
|
||||||
let maybe_user = users
|
|
||||||
.select((name, created_at))
|
|
||||||
.filter(name.eq(user_name))
|
|
||||||
.first::<models::UserDTO>(conn)
|
.first::<models::UserDTO>(conn)
|
||||||
.optional();
|
.optional();
|
||||||
|
|
||||||
@ -75,9 +72,33 @@ pub fn insert_new_user(
|
|||||||
diesel::insert_into(users)
|
diesel::insert_into(users)
|
||||||
.values(nu.as_ref())
|
.values(nu.as_ref())
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
let user = users
|
let user =
|
||||||
.select((name, created_at))
|
_get_user_by_name(nu.name.clone()).first::<models::UserDTO>(conn)?;
|
||||||
.filter(name.eq(nu.name.clone()))
|
Ok(user)
|
||||||
.first::<models::UserDTO>(conn);
|
}
|
||||||
Ok(user?)
|
|
||||||
|
pub fn verify_password(
|
||||||
|
user_name: String,
|
||||||
|
given_password: String,
|
||||||
|
conn: &SqliteConnection,
|
||||||
|
) -> Result<bool, errors::DomainError> {
|
||||||
|
use crate::schema::users::dsl::*;
|
||||||
|
let password_hash = users
|
||||||
|
.select(password)
|
||||||
|
.filter(name.eq(user_name))
|
||||||
|
.first::<String>(conn)?;
|
||||||
|
Ok(verify(given_password.as_str(), password_hash.as_str())?)
|
||||||
|
}
|
||||||
|
fn _get_user_by_name(
|
||||||
|
user_name: String,
|
||||||
|
) -> crate::schema::users::BoxedQuery<
|
||||||
|
'static,
|
||||||
|
Sqlite,
|
||||||
|
(diesel::sql_types::Text, diesel::sql_types::Timestamp),
|
||||||
|
> {
|
||||||
|
use crate::schema::users::dsl::*;
|
||||||
|
users
|
||||||
|
.select((name, created_at))
|
||||||
|
.filter(name.eq(user_name))
|
||||||
|
.into_boxed()
|
||||||
}
|
}
|
||||||
|
@ -6,24 +6,6 @@ use custom_error::custom_error;
|
|||||||
use crate::models::errors::*;
|
use crate::models::errors::*;
|
||||||
use r2d2;
|
use r2d2;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
// use std::error::Error;
|
|
||||||
|
|
||||||
// pub enum DomainError {
|
|
||||||
// #[display(fmt = "PasswordHashError")]
|
|
||||||
// PwdHashError,
|
|
||||||
// #[display(fmt = "Bad Id")]
|
|
||||||
// IdError,
|
|
||||||
// #[display(fmt = "Generic Error")]
|
|
||||||
// GenericError,
|
|
||||||
// DuplicateValue,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Error for DomainError {
|
|
||||||
// fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
|
||||||
// // Generic error, underlying cause isn't tracked.
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl From<DBError> for DomainError {
|
// impl From<DBError> for DomainError {
|
||||||
// fn from(error: DBError) -> DomainError {
|
// fn from(error: DBError) -> DomainError {
|
||||||
@ -41,47 +23,43 @@ use std::convert::From;
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
custom_error! { pub DomainError
|
custom_error! { #[derive(new)] pub DomainError
|
||||||
PwdHashError {source: BcryptError} = "Failed to has password",
|
PwdHashError {source: BcryptError} = "Failed to has password",
|
||||||
DbError {source: diesel::result::Error} = "Database error",
|
DbError {source: diesel::result::Error} = "Database error",
|
||||||
DbPoolError {source: r2d2::Error} = "Failed to get connection from pool",
|
DbPoolError {source: r2d2::Error} = "Failed to get connection from pool",
|
||||||
|
PasswordError {cause: String} = "Failed to validate password - {cause}",
|
||||||
GenericError {cause: String} = "Generic Error - Reason: {cause}"
|
GenericError {cause: String} = "Generic Error - Reason: {cause}"
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseError for DomainError {
|
impl ResponseError for DomainError {
|
||||||
fn error_response(&self) -> HttpResponse {
|
fn error_response(&self) -> HttpResponse {
|
||||||
|
let err = self;
|
||||||
match self {
|
match self {
|
||||||
DomainError::PwdHashError { source } => {
|
DomainError::PwdHashError { source } => {
|
||||||
HttpResponse::InternalServerError().json(ErrorModel {
|
HttpResponse::InternalServerError().json(ErrorModel {
|
||||||
status_code: 500,
|
error_code: 500,
|
||||||
reason: format!(
|
reason: format!("{} {}", err.to_string(), source).as_str(),
|
||||||
"{} {}",
|
|
||||||
"Unexpected Error - Failed to hash password", source
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
DomainError::DbError { source } => {
|
DomainError::DbError { source } => {
|
||||||
HttpResponse::InternalServerError().json(ErrorModel {
|
HttpResponse::InternalServerError().json(ErrorModel {
|
||||||
status_code: 500,
|
error_code: 500,
|
||||||
reason: format!("{} {}", "Unexpected Database Error", source),
|
reason: format!("{} {}", err.to_string(), source).as_str(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
DomainError::DbPoolError { source } => {
|
DomainError::DbPoolError { source } => {
|
||||||
HttpResponse::InternalServerError().json(ErrorModel {
|
HttpResponse::InternalServerError().json(ErrorModel {
|
||||||
status_code: 500,
|
error_code: 500,
|
||||||
reason: format!(
|
reason: format!("{} {}", err.to_string(), source).as_str(),
|
||||||
"{} {}",
|
|
||||||
"Unexpected Error - Failed to get connection from pool", source
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
DomainError::PasswordError { cause } => HttpResponse::BadRequest().json(ErrorModel {
|
||||||
|
error_code: 400,
|
||||||
|
reason: format!("{} {}, ", err.to_string(), cause.clone()).as_str(),
|
||||||
|
}),
|
||||||
DomainError::GenericError { cause } => HttpResponse::BadRequest().json(ErrorModel {
|
DomainError::GenericError { cause } => HttpResponse::BadRequest().json(ErrorModel {
|
||||||
status_code: 400,
|
error_code: 400,
|
||||||
reason: format!(
|
reason: format!("{} {}, ", err.to_string(), cause.clone()).as_str(),
|
||||||
"{} {}, ",
|
|
||||||
"Unexpected Database Error - ".to_owned(),
|
|
||||||
cause.clone()
|
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
src/main.rs
15
src/main.rs
@ -1,17 +1,17 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate comp;
|
extern crate derive_new;
|
||||||
#[macro_use]
|
// #[macro_use]
|
||||||
extern crate validator_derive;
|
// extern crate comp;
|
||||||
|
// #[macro_use]
|
||||||
|
// extern crate validator_derive;
|
||||||
extern crate bcrypt;
|
extern crate bcrypt;
|
||||||
extern crate custom_error;
|
extern crate custom_error;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
extern crate validator;
|
extern crate validator;
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{error, get, middleware, post, web, App, Error, HttpResponse, HttpServer};
|
||||||
error, get, middleware, post, web, App, Error, HttpRequest, HttpResponse, HttpServer, Responder,
|
|
||||||
};
|
|
||||||
|
|
||||||
use yarte::Template;
|
use yarte::Template;
|
||||||
|
|
||||||
@ -94,6 +94,9 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.build(manager)
|
.build(manager)
|
||||||
.expect("Failed to create pool.");
|
.expect("Failed to create pool.");
|
||||||
|
|
||||||
|
diesel_migrations::run_pending_migrations(&pool.get().unwrap())
|
||||||
|
.expect("Error running migrations");
|
||||||
|
|
||||||
let addr = std::env::var("BIND_ADDRESS").expect("BIND ADDRESS NOT FOUND");
|
let addr = std::env::var("BIND_ADDRESS").expect("BIND ADDRESS NOT FOUND");
|
||||||
info!("Starting server {}", addr);
|
info!("Starting server {}", addr);
|
||||||
let private_key = rand::thread_rng().gen::<[u8; 32]>();
|
let private_key = rand::thread_rng().gen::<[u8; 32]>();
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize, new)]
|
||||||
pub struct JsonErrorModel {
|
pub struct JsonErrorModel<'a> {
|
||||||
status_code: i16,
|
status_code: i16,
|
||||||
pub line: String,
|
pub line: String,
|
||||||
pub reason: String,
|
pub reason: &'a str,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize, new)]
|
||||||
pub struct ErrorModel {
|
pub struct ErrorModel<'a> {
|
||||||
pub status_code: i16,
|
pub error_code: i16,
|
||||||
pub reason: String,
|
pub reason: &'a str,
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,11 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::schema::users;
|
use crate::schema::users;
|
||||||
use crate::utils::regexs;
|
use crate::utils::regexs;
|
||||||
use chrono;
|
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
use validator_derive::*;
|
use validator_derive::*;
|
||||||
use yarte::Template;
|
use yarte::Template;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Queryable, Identifiable, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Queryable, Identifiable, Deserialize)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -15,7 +14,7 @@ pub struct User {
|
|||||||
pub created_at: chrono::NaiveDateTime,
|
pub created_at: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Insertable, Deserialize, Validate)]
|
#[derive(Debug, Clone, Insertable, Deserialize, Validate)]
|
||||||
#[table_name = "users"]
|
#[table_name = "users"]
|
||||||
pub struct NewUser {
|
pub struct NewUser {
|
||||||
#[validate(regex = "regexs::USERNAME_REG", length(min = 4, max = 10))]
|
#[validate(regex = "regexs::USERNAME_REG", length(min = 4, max = 10))]
|
||||||
|
@ -1,27 +1,53 @@
|
|||||||
|
use crate::types::DbPool;
|
||||||
|
use actix_threadpool::BlockingError;
|
||||||
|
use actix_web::{web, ResponseError};
|
||||||
use actix_web_httpauth::extractors::basic::BasicAuth;
|
use actix_web_httpauth::extractors::basic::BasicAuth;
|
||||||
|
|
||||||
|
use crate::actions::users;
|
||||||
|
use crate::errors;
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{get, post, Error, HttpResponse};
|
use actix_web::{get, Error, HttpResponse};
|
||||||
|
|
||||||
#[get("/login")]
|
#[get("/login")]
|
||||||
pub async fn login(id: Identity, credentials: BasicAuth) -> Result<HttpResponse, Error> {
|
pub async fn login(
|
||||||
|
id: Identity,
|
||||||
|
credentials: BasicAuth,
|
||||||
|
pool: web::Data<DbPool>,
|
||||||
|
) -> Result<HttpResponse, impl ResponseError> {
|
||||||
let maybe_identity = id.identity();
|
let maybe_identity = id.identity();
|
||||||
let response = if let Some(identity) = maybe_identity {
|
let response = if let Some(identity) = maybe_identity {
|
||||||
HttpResponse::Found()
|
Ok(HttpResponse::Found()
|
||||||
.header("location", "/")
|
.header("location", "/")
|
||||||
.content_type("text/plain")
|
.content_type("text/plain")
|
||||||
.json(format!("Already logged in as {}", identity))
|
.json(format!("Already logged in as {}", identity)))
|
||||||
} else {
|
} else {
|
||||||
|
let credentials2 = credentials.clone();
|
||||||
|
web::block(move || validate_basic_auth(credentials2, &pool))
|
||||||
|
.await
|
||||||
|
.and_then(|valid| {
|
||||||
|
if valid {
|
||||||
id.remember(credentials.user_id().to_string());
|
id.remember(credentials.user_id().to_string());
|
||||||
HttpResponse::Found().header("location", "/").finish()
|
Ok(HttpResponse::Found().header("location", "/").finish())
|
||||||
|
} else {
|
||||||
|
Err(BlockingError::Error(
|
||||||
|
errors::DomainError::new_password_error(
|
||||||
|
"Wrong password or account does not exist"
|
||||||
|
.to_string(),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})
|
||||||
};
|
};
|
||||||
println!("{}", credentials.user_id());
|
// println!("{}", credentials.user_id());
|
||||||
println!("{:?}", credentials.password());
|
// println!("{:?}", credentials.password());
|
||||||
Ok(response)
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/logout")]
|
#[get("/logout")]
|
||||||
pub async fn logout(id: Identity, _credentials: BasicAuth) -> Result<HttpResponse, Error> {
|
pub async fn logout(
|
||||||
|
id: Identity,
|
||||||
|
_credentials: BasicAuth,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
let maybe_identity = id.identity();
|
let maybe_identity = id.identity();
|
||||||
let response = if let Some(identity) = maybe_identity {
|
let response = if let Some(identity) = maybe_identity {
|
||||||
info!("Logging out {user}", user = identity);
|
info!("Logging out {user}", user = identity);
|
||||||
@ -43,3 +69,24 @@ pub async fn index(id: Identity) -> String {
|
|||||||
id.identity().unwrap_or_else(|| "Anonymous".to_owned())
|
id.identity().unwrap_or_else(|| "Anonymous".to_owned())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_basic_auth(
|
||||||
|
credentials: BasicAuth,
|
||||||
|
pool: &web::Data<DbPool>,
|
||||||
|
) -> Result<bool, errors::DomainError> {
|
||||||
|
let result = if let Some(password_ref) = credentials.password() {
|
||||||
|
let conn = pool.get()?;
|
||||||
|
let password = password_ref.clone().into_owned();
|
||||||
|
let valid = users::verify_password(
|
||||||
|
credentials.user_id().clone().into_owned(),
|
||||||
|
password,
|
||||||
|
&conn,
|
||||||
|
)?;
|
||||||
|
Ok(valid)
|
||||||
|
} else {
|
||||||
|
Err(errors::DomainError::new_password_error(
|
||||||
|
"No password given".to_owned(),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
result
|
||||||
|
}
|
||||||
|
@ -23,8 +23,8 @@ pub async fn get_user(
|
|||||||
if let Some(user) = maybe_user {
|
if let Some(user) = maybe_user {
|
||||||
Ok(HttpResponse::Ok().json(user))
|
Ok(HttpResponse::Ok().json(user))
|
||||||
} else {
|
} else {
|
||||||
let res =
|
let res = HttpResponse::NotFound()
|
||||||
HttpResponse::NotFound().body(format!("No user found with uid: {}", user_uid));
|
.body(format!("No user found with uid: {}", user_uid));
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -32,7 +32,9 @@ pub async fn get_user(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/api/authzd/users/get")]
|
#[get("/api/authzd/users/get")]
|
||||||
pub async fn get_all_users(pool: web::Data<DbPool>) -> Result<HttpResponse, impl ResponseError> {
|
pub async fn get_all_users(
|
||||||
|
pool: web::Data<DbPool>,
|
||||||
|
) -> Result<HttpResponse, impl ResponseError> {
|
||||||
// use web::block to offload blocking Diesel code without blocking server thread
|
// use web::block to offload blocking Diesel code without blocking server thread
|
||||||
let res = web::block(move || {
|
let res = web::block(move || {
|
||||||
let conn = pool.get()?;
|
let conn = pool.get()?;
|
||||||
@ -43,19 +45,16 @@ pub async fn get_all_users(pool: web::Data<DbPool>) -> Result<HttpResponse, impl
|
|||||||
debug!("{:?}", maybe_users);
|
debug!("{:?}", maybe_users);
|
||||||
if let Some(users) = maybe_users {
|
if let Some(users) = maybe_users {
|
||||||
if users.is_empty() {
|
if users.is_empty() {
|
||||||
let res = HttpResponse::Ok().json(models::ErrorModel {
|
let res = HttpResponse::NotFound()
|
||||||
status_code: 200,
|
.json(models::ErrorModel::new(40, "No users available"));
|
||||||
reason: "No users available".to_string(),
|
// let res = crate::errors::DomainError::new_generic_error("".to_owned());
|
||||||
});
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
} else {
|
} else {
|
||||||
Ok(HttpResponse::Ok().json(users))
|
Ok(HttpResponse::Ok().json(users))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let res = HttpResponse::Ok().json(models::ErrorModel {
|
let res = HttpResponse::NotFound()
|
||||||
status_code: 200,
|
.json(models::ErrorModel::new(40, "No users available"));
|
||||||
reason: "No users available".to_string(),
|
|
||||||
});
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user