2022-04-07 15:04:05 +00:00
|
|
|
use std::ops::Deref;
|
|
|
|
|
2022-04-06 16:03:00 +00:00
|
|
|
use actix::Addr;
|
2022-04-06 15:18:06 +00:00
|
|
|
use actix_web::{HttpResponse, Responder, web};
|
|
|
|
use askama::Template;
|
|
|
|
|
2022-04-06 16:03:00 +00:00
|
|
|
use crate::actors::users_actor;
|
|
|
|
use crate::actors::users_actor::UsersActor;
|
2022-04-07 16:59:48 +00:00
|
|
|
use crate::constants::TEMPORARY_PASSWORDS_LEN;
|
2022-04-06 15:18:06 +00:00
|
|
|
use crate::controllers::settings_controller::BaseSettingsPage;
|
2022-04-07 16:59:48 +00:00
|
|
|
use crate::data::client::{Client, ClientID, ClientManager};
|
2022-04-06 15:18:06 +00:00
|
|
|
use crate::data::current_user::CurrentUser;
|
2022-04-07 16:59:48 +00:00
|
|
|
use crate::data::user::{hash_password, User, UserID};
|
|
|
|
use crate::utils::string_utils::rand_str;
|
2022-04-06 15:18:06 +00:00
|
|
|
|
|
|
|
#[derive(Template)]
|
|
|
|
#[template(path = "settings/clients_list.html")]
|
|
|
|
struct ClientsListTemplate {
|
|
|
|
_parent: BaseSettingsPage,
|
|
|
|
clients: Vec<Client>,
|
|
|
|
}
|
|
|
|
|
2022-04-06 16:03:00 +00:00
|
|
|
#[derive(Template)]
|
|
|
|
#[template(path = "settings/users_list.html")]
|
|
|
|
struct UsersListTemplate {
|
|
|
|
_parent: BaseSettingsPage,
|
|
|
|
users: Vec<User>,
|
|
|
|
}
|
|
|
|
|
2022-04-07 15:04:05 +00:00
|
|
|
#[derive(Template)]
|
|
|
|
#[template(path = "settings/edit_user.html")]
|
|
|
|
struct EditUserTemplate {
|
|
|
|
_parent: BaseSettingsPage,
|
|
|
|
u: User,
|
|
|
|
clients: Vec<Client>,
|
|
|
|
}
|
|
|
|
|
2022-04-06 16:03:00 +00:00
|
|
|
|
2022-04-06 15:18:06 +00:00
|
|
|
pub async fn clients_route(user: CurrentUser, clients: web::Data<ClientManager>) -> impl Responder {
|
|
|
|
HttpResponse::Ok().body(ClientsListTemplate {
|
|
|
|
_parent: BaseSettingsPage::get(
|
|
|
|
"Clients list",
|
|
|
|
&user,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
clients: clients.cloned(),
|
|
|
|
}.render().unwrap())
|
2022-04-06 16:03:00 +00:00
|
|
|
}
|
|
|
|
|
2022-04-07 16:59:48 +00:00
|
|
|
#[derive(serde::Deserialize, Debug)]
|
|
|
|
pub struct UpdateUserQuery {
|
|
|
|
uid: UserID,
|
|
|
|
username: String,
|
|
|
|
first_name: String,
|
|
|
|
last_name: String,
|
|
|
|
email: String,
|
|
|
|
gen_new_password: Option<String>,
|
|
|
|
enabled: Option<String>,
|
|
|
|
admin: Option<String>,
|
|
|
|
grant_type: String,
|
|
|
|
granted_clients: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn users_route(user: CurrentUser, users: web::Data<Addr<UsersActor>>, update_query: Option<web::Form<UpdateUserQuery>>) -> impl Responder {
|
|
|
|
let mut danger = None;
|
|
|
|
let mut success = None;
|
|
|
|
|
|
|
|
if let Some(update) = update_query {
|
|
|
|
let current_user: Option<User> = users.send(users_actor::FindUserByUsername(update.username.to_string()))
|
|
|
|
.await.unwrap().0;
|
|
|
|
let is_creating = current_user.is_none();
|
|
|
|
|
|
|
|
let mut user = current_user.unwrap_or_default();
|
|
|
|
user.uid = update.0.uid;
|
|
|
|
user.username = update.0.username;
|
|
|
|
user.first_name = update.0.first_name;
|
|
|
|
user.last_name = update.0.last_name;
|
|
|
|
user.email = update.0.email;
|
|
|
|
user.enabled = update.0.enabled.is_some();
|
|
|
|
user.admin = update.0.admin.is_some();
|
|
|
|
|
|
|
|
user.authorized_clients = match update.0.grant_type.as_str() {
|
|
|
|
"all_clients" => None,
|
|
|
|
"custom_clients" => Some(update.0.granted_clients.split(',')
|
|
|
|
.map(|c| ClientID(c.to_string()))
|
|
|
|
.collect::<Vec<_>>()),
|
|
|
|
_ => Some(Vec::new())
|
|
|
|
};
|
|
|
|
|
|
|
|
let new_password = match update.0.gen_new_password.is_some() {
|
|
|
|
false => None,
|
|
|
|
true => {
|
|
|
|
let temp_pass = rand_str(TEMPORARY_PASSWORDS_LEN);
|
|
|
|
user.password = hash_password(&temp_pass)
|
|
|
|
.expect("Failed to hash password");
|
|
|
|
user.need_reset_password = true;
|
|
|
|
Some(temp_pass)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let res = users.send(users_actor::UpdateUserRequest(user.clone())).await.unwrap().0;
|
|
|
|
|
|
|
|
if !res {
|
|
|
|
danger = Some(match is_creating {
|
|
|
|
true => "Failed to create user!",
|
|
|
|
false => "Failed to update user!"
|
|
|
|
}.to_string())
|
|
|
|
} else {
|
|
|
|
success = Some(match is_creating {
|
|
|
|
true => format!("User {} was successfully updated!", user.full_name()),
|
|
|
|
false => format!("Failed to update {}'s account!", user.full_name())
|
|
|
|
}.to_string());
|
|
|
|
|
|
|
|
if let Some(pass) = new_password {
|
|
|
|
danger = Some(format!("{}'s temporary time password is {}", user.full_name(), pass));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-06 16:03:00 +00:00
|
|
|
let users = users.send(users_actor::GetAllUsersRequest).await.unwrap().0;
|
|
|
|
|
|
|
|
HttpResponse::Ok().body(UsersListTemplate {
|
|
|
|
_parent: BaseSettingsPage::get(
|
|
|
|
"Users list",
|
|
|
|
&user,
|
2022-04-07 16:59:48 +00:00
|
|
|
danger,
|
|
|
|
success,
|
2022-04-06 16:03:00 +00:00
|
|
|
),
|
|
|
|
users,
|
|
|
|
}.render().unwrap())
|
2022-04-07 15:04:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn create_user(user: CurrentUser, clients: web::Data<ClientManager>) -> impl Responder {
|
|
|
|
HttpResponse::Ok().body(EditUserTemplate {
|
|
|
|
_parent: BaseSettingsPage::get("Create a new user", user.deref(), None, None),
|
|
|
|
u: Default::default(),
|
|
|
|
clients: clients.cloned(),
|
|
|
|
}.render().unwrap())
|
2022-04-06 15:18:06 +00:00
|
|
|
}
|