bazzar/web/src/routes/admin/mod.rs
2022-04-14 21:40:26 +02:00

139 lines
3.6 KiB
Rust

use actix::Addr;
use actix_session::Session;
use actix_web::web::{Data, Json, ServiceConfig};
use actix_web::{delete, get, post, HttpResponse};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use crate::database::Database;
use crate::logic::hash_pass;
use crate::model::{Account, Email, Login, PassHash, Password, PasswordConfirmation, Role};
use crate::routes::{RequireLogin, Result};
use crate::{database, routes, Config};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Can't register new account")]
Register,
#[error("Can't hash password")]
HashPass,
#[error("Internal server error")]
DatabaseConnection,
#[error("{0}")]
Database(#[from] database::Error),
}
#[derive(Serialize)]
pub struct LogoutResponse {}
#[delete("/admin/logout")]
async fn logout(session: Session) -> Result<HttpResponse> {
session.require_admin()?;
Ok(HttpResponse::NotImplemented().body(""))
}
#[post("/admin/sign-in")]
async fn sign_in(_session: Session) -> Result<HttpResponse> {
Ok(HttpResponse::NotImplemented().body(""))
}
#[derive(Deserialize)]
pub struct RegisterInput {
pub login: Login,
pub email: Email,
pub password: Password,
pub password_confirmation: PasswordConfirmation,
pub role: Role,
}
#[derive(Serialize, Default)]
pub struct RegisterResponse {
pub success: bool,
pub errors: Vec<RegisterError>,
pub account: Option<Account>,
}
#[derive(Serialize)]
pub enum RegisterError {
PasswordDiffer,
}
// login_required
#[post("/admin/register")]
async fn register(
session: Session,
Json(input): Json<RegisterInput>,
db: Data<Addr<Database>>,
config: Data<Arc<Config>>,
) -> Result<HttpResponse> {
let mut response = RegisterResponse::default();
session.require_admin()?;
if input.password != input.password_confirmation {
response.errors.push(RegisterError::PasswordDiffer);
}
let hash = match hash_pass(&input.password.0, &config.pass_salt) {
Ok(s) => s,
Err(e) => {
log::error!("{e:?}");
return Err(routes::Error::Admin(Error::HashPass));
}
};
match db
.send(database::CreateAccount {
email: input.email,
login: input.login,
pass_hash: PassHash(hash),
role: input.role,
})
.await
{
Ok(Ok(account)) => {
response.account = Some(account.into());
}
Ok(Err(e)) => {
log::error!("{}", e);
return Err(super::Error::Admin(Error::Register));
}
Err(e) => {
log::error!("{}", e);
return Err(super::Error::Admin(Error::Register));
}
};
response.success = response.errors.is_empty();
Ok(if response.success {
HttpResponse::NotImplemented().json(response)
} else {
HttpResponse::BadRequest().json(response)
})
}
#[get("/admin/api/v1/products")]
async fn api_v1_products(session: Session, db: Data<Addr<Database>>) -> Result<HttpResponse> {
session.require_admin()?;
match db.send(database::AllProducts).await {
Ok(Ok(products)) => Ok(HttpResponse::Ok().json(products)),
Ok(Err(e)) => {
log::error!("{}", e);
Err(super::Error::Admin(Error::Database(e)))
}
Err(e) => {
log::error!("{}", e);
Err(super::Error::Admin(Error::DatabaseConnection))
}
}
}
#[get("/admin")]
async fn landing() -> Result<HttpResponse> {
Ok(HttpResponse::NotImplemented().body(""))
}
pub fn configure(config: &mut ServiceConfig) {
config.service(landing).service(sign_in).service(logout).service(register);
}