Display the list of users

This commit is contained in:
Pierre HUBERT 2022-04-06 18:03:00 +02:00
parent da6a494875
commit 754814f04a
6 changed files with 76 additions and 3 deletions

View File

@ -28,6 +28,13 @@ pub struct GetUserRequest(pub UserID);
#[derive(Debug)] #[derive(Debug)]
pub struct GetUserResult(pub Option<User>); pub struct GetUserResult(pub Option<User>);
#[derive(Message)]
#[rtype(GetAllUsersResult)]
pub struct GetAllUsersRequest;
#[derive(Debug)]
pub struct GetAllUsersResult(pub Vec<User>);
#[derive(Message)] #[derive(Message)]
#[rtype(ChangePasswordResult)] #[rtype(ChangePasswordResult)]
pub struct ChangePasswordRequest { pub struct ChangePasswordRequest {
@ -90,3 +97,11 @@ impl Handler<GetUserRequest> for UsersActor {
MessageResult(GetUserResult(self.manager.find_by_user_id(&msg.0))) MessageResult(GetUserResult(self.manager.find_by_user_id(&msg.0)))
} }
} }
impl Handler<GetAllUsersRequest> for UsersActor {
type Result = MessageResult<GetAllUsersRequest>;
fn handle(&mut self, _msg: GetAllUsersRequest, _ctx: &mut Self::Context) -> Self::Result {
MessageResult(GetAllUsersResult(self.manager.cloned()))
}
}

View File

@ -1,9 +1,13 @@
use actix::Addr;
use actix_web::{HttpResponse, Responder, web}; use actix_web::{HttpResponse, Responder, web};
use askama::Template; use askama::Template;
use crate::actors::users_actor;
use crate::actors::users_actor::UsersActor;
use crate::controllers::settings_controller::BaseSettingsPage; use crate::controllers::settings_controller::BaseSettingsPage;
use crate::data::client::{Client, ClientManager}; use crate::data::client::{Client, ClientManager};
use crate::data::current_user::CurrentUser; use crate::data::current_user::CurrentUser;
use crate::data::user::User;
#[derive(Template)] #[derive(Template)]
#[template(path = "settings/clients_list.html")] #[template(path = "settings/clients_list.html")]
@ -12,6 +16,14 @@ struct ClientsListTemplate {
clients: Vec<Client>, clients: Vec<Client>,
} }
#[derive(Template)]
#[template(path = "settings/users_list.html")]
struct UsersListTemplate {
_parent: BaseSettingsPage,
users: Vec<User>,
}
pub async fn clients_route(user: CurrentUser, clients: web::Data<ClientManager>) -> impl Responder { pub async fn clients_route(user: CurrentUser, clients: web::Data<ClientManager>) -> impl Responder {
HttpResponse::Ok().body(ClientsListTemplate { HttpResponse::Ok().body(ClientsListTemplate {
_parent: BaseSettingsPage::get( _parent: BaseSettingsPage::get(
@ -23,3 +35,17 @@ pub async fn clients_route(user: CurrentUser, clients: web::Data<ClientManager>)
clients: clients.cloned(), clients: clients.cloned(),
}.render().unwrap()) }.render().unwrap())
} }
pub async fn users_route(user: CurrentUser, users: web::Data<Addr<UsersActor>>) -> impl Responder {
let users = users.send(users_actor::GetAllUsersRequest).await.unwrap().0;
HttpResponse::Ok().body(UsersListTemplate {
_parent: BaseSettingsPage::get(
"Users list",
&user,
None,
None,
),
users,
}.render().unwrap())
}

View File

@ -61,7 +61,7 @@ pub async fn account_settings_details_route(user: CurrentUser) -> impl Responder
_parent: BaseSettingsPage::get("Account details", &user, None, None), _parent: BaseSettingsPage::get("Account details", &user, None, None),
user_id: user.uid, user_id: user.uid,
first_name: user.first_name, first_name: user.first_name,
last_name: user.last_last, last_name: user.last_name,
username: user.username, username: user.username,
email: user.email, email: user.email,
}.render().unwrap()) }.render().unwrap())

View File

@ -8,7 +8,7 @@ pub type UserID = String;
pub struct User { pub struct User {
pub uid: UserID, pub uid: UserID,
pub first_name: String, pub first_name: String,
pub last_last: String, pub last_name: String,
pub username: String, pub username: String,
pub email: String, pub email: String,
pub password: String, pub password: String,
@ -40,7 +40,7 @@ impl Default for User {
Self { Self {
uid: uuid::Uuid::new_v4().to_string(), uid: uuid::Uuid::new_v4().to_string(),
first_name: "".to_string(), first_name: "".to_string(),
last_last: "".to_string(), last_name: "".to_string(),
username: "".to_string(), username: "".to_string(),
email: "".to_string(), email: "".to_string(),
password: "".to_string(), password: "".to_string(),

View File

@ -115,7 +115,10 @@ async fn main() -> std::io::Result<()> {
.route("/settings/change_password", web::post().to(settings_controller::change_password_route)) .route("/settings/change_password", web::post().to(settings_controller::change_password_route))
// Admin routes // Admin routes
.route("/admin", web::get()
.to(|| async { HttpResponse::Found().append_header(("Location", "/settings")).finish() }))
.route("/admin/clients", web::get().to(admin_controller::clients_route)) .route("/admin/clients", web::get().to(admin_controller::clients_route))
.route("/admin/users", web::get().to(admin_controller::users_route))
}) })
.bind(listen_address)? .bind(listen_address)?
.run() .run()

View File

@ -0,0 +1,29 @@
{% extends "base_settings_page.html" %}
{% block content %}
<table class="table table-hover" style="max-width: 600px;" aria-describedby="Clients list">
<thead>
<tr>
<th scope="col">Username</th>
<th scope="col">First name</th>
<th scope="col">Last name</th>
<th scope="col">Email</th>
<th scope="col">Account type</th>
<th scope="col">Enabled</th>
</tr>
</thead>
<tbody>
{% for u in users %}
<tr>
<td>{{ u.username }}</td>
<td>{{ u.first_name }}</td>
<td>{{ u.last_name }}</td>
<td>{{ u.email }}</td>
<td>{% if u.admin %}Admin{% else %}Regular account{% endif %}</td>
<td>{% if u.enabled %}Enabled{% else %}Disabled{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}