Alisa/crates/backend/src/controller/user.rs

122 lines
3.4 KiB
Rust

use actix_web::{
error::{ErrorInternalServerError, ErrorNotFound, ErrorUnauthorized},
web, HttpResponse, Responder,
};
use argon2::{
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
Argon2,
};
use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{auth::AuthedUser, AppState};
pub struct UserController;
#[derive(Serialize)]
pub struct UserWithoutPassword {
id: Uuid,
name: String,
email: String,
admin: bool,
}
#[derive(Deserialize)]
pub struct CreateUserDto {
name: String,
email: String,
password: String,
admin: bool,
}
impl From<entity::user::Model> for UserWithoutPassword {
fn from(value: entity::user::Model) -> Self {
Self {
id: value.id,
name: value.name,
email: value.email,
admin: value.admin,
}
}
}
impl UserController {
pub async fn list_users(
state: web::Data<AppState>,
_executor: AuthedUser,
) -> actix_web::Result<impl Responder> {
let db = &state.db;
let users = entity::prelude::User::find()
.all(db)
.await
.map_err(ErrorInternalServerError)?;
Ok(web::Json(
users
.into_iter()
.map(UserWithoutPassword::from)
.collect::<Vec<_>>(),
))
}
pub async fn get_current_user(
state: web::Data<AppState>,
executor: AuthedUser,
) -> actix_web::Result<impl Responder> {
let db = &state.db;
let user = entity::prelude::User::find_by_id(executor.0.id)
.one(db)
.await
.map_err(ErrorInternalServerError)?
.ok_or(ErrorNotFound("Not Found"))?;
Ok(web::Json(UserWithoutPassword::from(user)))
}
pub async fn create_user(
state: web::Data<AppState>,
user: web::Json<CreateUserDto>,
executor: AuthedUser,
) -> actix_web::Result<impl Responder> {
if !executor.0.admin {
return Err(ErrorUnauthorized("Invalid Permissions"));
}
let db = &state.db;
let user = user.into_inner();
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let password_hash = argon2
.hash_password(user.password.as_bytes(), &salt)
.map_err(ErrorInternalServerError)?;
let user = entity::user::ActiveModel {
id: ActiveValue::NotSet,
name: ActiveValue::Set(user.name),
email: ActiveValue::Set(user.email),
hash: ActiveValue::Set(password_hash.to_string()),
admin: ActiveValue::Set(user.admin),
};
let result = user.insert(db).await.map_err(ErrorInternalServerError)?;
Ok(web::Json(UserWithoutPassword::from(result)))
}
pub async fn delete_user(
state: web::Data<AppState>,
path: web::Path<Uuid>,
executor: AuthedUser,
) -> actix_web::Result<impl Responder> {
let id = path.into_inner();
if !executor.0.admin || executor.0.id == id {
return Err(ErrorUnauthorized("Invalid Permissions"));
}
let db = &state.db;
entity::license::Entity::delete_by_id(id)
.exec(db)
.await
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().finish())
}
}