139 lines
3.6 KiB
Rust
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);
|
|
}
|