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 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, _executor: AuthedUser, ) -> actix_web::Result { 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::>(), )) } pub async fn get_current_user( state: web::Data, executor: AuthedUser, ) -> actix_web::Result { 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, user: web::Json, executor: AuthedUser, ) -> actix_web::Result { 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, path: web::Path, executor: AuthedUser, ) -> actix_web::Result { 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()) } }