Display account details
This commit is contained in:
		
							
								
								
									
										14
									
								
								assets/css/base_settings_page.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								assets/css/base_settings_page.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
html {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.page_body {
 | 
			
		||||
    padding: 3rem;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								assets/css/bootstrap.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								assets/css/bootstrap.css
									
									
									
									
										vendored
									
									
								
							@@ -12,7 +12,7 @@
 | 
			
		||||
 * Copyright 2011-2021 Twitter, Inc.
 | 
			
		||||
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 | 
			
		||||
 */
 | 
			
		||||
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
 | 
			
		||||
@import url("../robotfont/font.css");
 | 
			
		||||
:root {
 | 
			
		||||
  --bs-blue: #2a9fd6;
 | 
			
		||||
  --bs-indigo: #6610f2;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								assets/img/account.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/img/account.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 675 B  | 
							
								
								
									
										7
									
								
								assets/js/bootstrap.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								assets/js/bootstrap.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/robotfont/KFOlCnqEu92Fr1MmWUlvAw.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/robotfont/KFOlCnqEu92Fr1MmWUlvAw.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/robotfont/KFOmCnqEu92Fr1Me5Q.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/robotfont/KFOmCnqEu92Fr1Me5Q.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										14
									
								
								assets/robotfont/font.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								assets/robotfont/font.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
@font-face {
 | 
			
		||||
    font-family: 'Roboto';
 | 
			
		||||
    font-style: normal;
 | 
			
		||||
    font-weight: 400;
 | 
			
		||||
    font-display: swap;
 | 
			
		||||
    src: url(./KFOmCnqEu92Fr1Me5Q.ttf) format('truetype');
 | 
			
		||||
}
 | 
			
		||||
@font-face {
 | 
			
		||||
    font-family: 'Roboto';
 | 
			
		||||
    font-style: normal;
 | 
			
		||||
    font-weight: 700;
 | 
			
		||||
    font-display: swap;
 | 
			
		||||
    src: url(./KFOlCnqEu92Fr1MmWUlvAw.ttf) format('truetype');
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
use actix::{Actor, Context, Handler, Message, MessageResult};
 | 
			
		||||
 | 
			
		||||
use crate::data::entity_manager::EntityManager;
 | 
			
		||||
use crate::data::user::{verify_password, User, UserID};
 | 
			
		||||
use crate::data::user::{User, UserID, verify_password};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum LoginResult {
 | 
			
		||||
@@ -21,6 +21,13 @@ pub struct LoginRequest {
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct ChangePasswordResult(pub bool);
 | 
			
		||||
 | 
			
		||||
#[derive(Message)]
 | 
			
		||||
#[rtype(GetUserResult)]
 | 
			
		||||
pub struct GetUserRequest(pub UserID);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct GetUserResult(pub Option<User>);
 | 
			
		||||
 | 
			
		||||
#[derive(Message)]
 | 
			
		||||
#[rtype(ChangePasswordResult)]
 | 
			
		||||
pub struct ChangePasswordRequest {
 | 
			
		||||
@@ -75,3 +82,11 @@ impl Handler<ChangePasswordRequest> for UsersActor {
 | 
			
		||||
        )))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Handler<GetUserRequest> for UsersActor {
 | 
			
		||||
    type Result = MessageResult<GetUserRequest>;
 | 
			
		||||
 | 
			
		||||
    fn handle(&mut self, msg: GetUserRequest, _ctx: &mut Self::Context) -> Self::Result {
 | 
			
		||||
        MessageResult(GetUserResult(self.manager.find_by_user_id(&msg.0)))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
pub mod assets_controller;
 | 
			
		||||
pub mod base_controller;
 | 
			
		||||
pub mod login_controller;
 | 
			
		||||
pub mod settings_controller;
 | 
			
		||||
							
								
								
									
										62
									
								
								src/controllers/settings_controller.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/controllers/settings_controller.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
use actix::Addr;
 | 
			
		||||
use actix_identity::Identity;
 | 
			
		||||
use actix_web::{HttpResponse, Responder, web};
 | 
			
		||||
use askama::Template;
 | 
			
		||||
 | 
			
		||||
use crate::actors::users_actor;
 | 
			
		||||
use crate::actors::users_actor::UsersActor;
 | 
			
		||||
use crate::constants::APP_NAME;
 | 
			
		||||
use crate::data::session_identity::SessionIdentity;
 | 
			
		||||
use crate::data::user::User;
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/base_settings_page.html")]
 | 
			
		||||
struct BaseSettingsPage {
 | 
			
		||||
    danger_message: Option<String>,
 | 
			
		||||
    success_message: Option<String>,
 | 
			
		||||
    page_title: &'static str,
 | 
			
		||||
    app_name: &'static str,
 | 
			
		||||
    is_admin: bool,
 | 
			
		||||
    user_name: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BaseSettingsPage {
 | 
			
		||||
    async fn get(user: &User) -> BaseSettingsPage {
 | 
			
		||||
        Self {
 | 
			
		||||
            danger_message: None,
 | 
			
		||||
            success_message: None,
 | 
			
		||||
            page_title: "Account details",
 | 
			
		||||
            app_name: APP_NAME,
 | 
			
		||||
            is_admin: user.admin,
 | 
			
		||||
            user_name: user.username.to_string(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/account_details.html")]
 | 
			
		||||
struct AccountDetailsPage {
 | 
			
		||||
    _parent: BaseSettingsPage,
 | 
			
		||||
    user_id: String,
 | 
			
		||||
    first_name: String,
 | 
			
		||||
    last_name: String,
 | 
			
		||||
    username: String,
 | 
			
		||||
    email: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Account details page
 | 
			
		||||
pub async fn account_settings_details_route(id: Identity, user_actor: web::Data<Addr<UsersActor>>) -> impl Responder {
 | 
			
		||||
    let user: User = user_actor.send(
 | 
			
		||||
        users_actor::GetUserRequest(SessionIdentity(&id).user_id())
 | 
			
		||||
    ).await.unwrap().0.unwrap();
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok()
 | 
			
		||||
        .body(AccountDetailsPage {
 | 
			
		||||
            _parent: BaseSettingsPage::get(&user).await,
 | 
			
		||||
            user_id: user.uid,
 | 
			
		||||
            first_name: user.first_name,
 | 
			
		||||
            last_name: user.last_last,
 | 
			
		||||
            username: user.username,
 | 
			
		||||
            email: user.email,
 | 
			
		||||
        }.render().unwrap())
 | 
			
		||||
}
 | 
			
		||||
@@ -86,6 +86,10 @@ impl<'a> SessionIdentity<'a> {
 | 
			
		||||
            .unwrap_or(false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn is_admin(&self) -> bool {
 | 
			
		||||
        self.get_session_data().unwrap_or_default().is_admin
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn user_id(&self) -> UserID {
 | 
			
		||||
        self.get_session_data().unwrap_or_default().id
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -14,6 +14,7 @@ use basic_oidc::constants::{
 | 
			
		||||
};
 | 
			
		||||
use basic_oidc::controllers::assets_controller::assets_route;
 | 
			
		||||
use basic_oidc::controllers::login_controller::{login_route, logout_route};
 | 
			
		||||
use basic_oidc::controllers::settings_controller;
 | 
			
		||||
use basic_oidc::data::app_config::AppConfig;
 | 
			
		||||
use basic_oidc::data::entity_manager::EntityManager;
 | 
			
		||||
use basic_oidc::data::user::{hash_password, User};
 | 
			
		||||
@@ -81,18 +82,26 @@ async fn main() -> std::io::Result<()> {
 | 
			
		||||
            .app_data(web::Data::new(users_actor.clone()))
 | 
			
		||||
            .app_data(web::Data::new(bruteforce_actor.clone()))
 | 
			
		||||
            .app_data(web::Data::new(config.clone()))
 | 
			
		||||
 | 
			
		||||
            .wrap(Logger::default())
 | 
			
		||||
            .wrap(AuthMiddleware {})
 | 
			
		||||
            .wrap(IdentityService::new(policy))
 | 
			
		||||
            // /health route
 | 
			
		||||
 | 
			
		||||
            // health route
 | 
			
		||||
            .service(health)
 | 
			
		||||
 | 
			
		||||
            // Assets serving
 | 
			
		||||
            .route("/assets/{path:.*}", web::get().to(assets_route))
 | 
			
		||||
 | 
			
		||||
            // Login page
 | 
			
		||||
            .route("/login", web::get().to(login_route))
 | 
			
		||||
            .route("/login", web::post().to(login_route))
 | 
			
		||||
 | 
			
		||||
            // Logout page
 | 
			
		||||
            .route("/logout", web::get().to(logout_route))
 | 
			
		||||
 | 
			
		||||
            // Settings routes
 | 
			
		||||
            .route("/settings", web::get().to(settings_controller::account_settings_details_route))
 | 
			
		||||
    })
 | 
			
		||||
        .bind(listen_address)?
 | 
			
		||||
        .run()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								templates/settings/account_details.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								templates/settings/account_details.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
{% extends "base_settings_page.html" %}
 | 
			
		||||
{% block content %}
 | 
			
		||||
 | 
			
		||||
<table class="table table-hover" style="max-width: 600px;" aria-describedby="Account details">
 | 
			
		||||
    <tbody>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">User ID</th>
 | 
			
		||||
        <td>{{ user_id }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">First name</th>
 | 
			
		||||
        <td>{{ first_name }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Last name</th>
 | 
			
		||||
        <td>{{ last_name }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Username</th>
 | 
			
		||||
        <td>{{ username }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Email</th>
 | 
			
		||||
        <td>{{ email }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Account type</th>
 | 
			
		||||
        <td>{% if is_admin %}Admin{% else %}Regular account{% endif %}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    </tbody>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
{% endblock content %}
 | 
			
		||||
							
								
								
									
										69
									
								
								templates/settings/base_settings_page.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								templates/settings/base_settings_page.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="UTF-8">
 | 
			
		||||
  <title>{{ page_title }} - {{ app_name }}</title>
 | 
			
		||||
  
 | 
			
		||||
  <!-- Bootstrap core CSS -->
 | 
			
		||||
  <link href="/assets/css/bootstrap.css" rel="stylesheet" crossorigin="anonymous"/>
 | 
			
		||||
  
 | 
			
		||||
  <link rel="stylesheet" href="/assets/css/base_settings_page.css">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
  <div class="d-flex flex-column flex-shrink-0 p-3 bg-light" style="width: 280px;">
 | 
			
		||||
    <a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-dark text-decoration-none">
 | 
			
		||||
      <span class="fs-4">{{ app_name }}</span>
 | 
			
		||||
    </a>
 | 
			
		||||
    <hr>
 | 
			
		||||
    <ul class="nav nav-pills flex-column mb-auto">
 | 
			
		||||
      <li class="nav-item">
 | 
			
		||||
        <a href="/settings" class="nav-link active" aria-current="page">
 | 
			
		||||
          Account details
 | 
			
		||||
        </a>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <a href="/settings/change_password" class="nav-link link-dark">
 | 
			
		||||
          Change password
 | 
			
		||||
        </a>
 | 
			
		||||
      </li>
 | 
			
		||||
      
 | 
			
		||||
      <hr />
 | 
			
		||||
      {% if is_admin %}
 | 
			
		||||
      <li>
 | 
			
		||||
        <a href="/admin/apps" class="nav-link link-dark">
 | 
			
		||||
          Applications
 | 
			
		||||
        </a>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <a href="/admin/users" class="nav-link link-dark">
 | 
			
		||||
          Users
 | 
			
		||||
        </a>
 | 
			
		||||
      </li>
 | 
			
		||||
      {% endif %}
 | 
			
		||||
    </ul>
 | 
			
		||||
    <hr>
 | 
			
		||||
    <div class="dropdown">
 | 
			
		||||
      <a href="#" class="d-flex align-items-center link-dark text-decoration-none dropdown-toggle" id="dropdownUser" data-bs-toggle="dropdown" aria-expanded="false">
 | 
			
		||||
        <img src="/assets/img/account.png" alt="" width="32" height="32" class="rounded-circle me-2">
 | 
			
		||||
        <strong>{{ user_name }}</strong>
 | 
			
		||||
      </a>
 | 
			
		||||
      <ul class="dropdown-menu text-small shadow" aria-labelledby="dropdownUser">
 | 
			
		||||
        <li><a class="dropdown-item" href="/logout">Sign out</a></li>
 | 
			
		||||
      </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  
 | 
			
		||||
  <div class="page_body" style="flex: 1">
 | 
			
		||||
    {% if let Some(msg) = danger_message %}<div class="alert alert-danger">{{ msg }}</div>{% endif %}
 | 
			
		||||
    {% if let Some(msg) = success_message %}<div class="alert alert-success">{{ msg }}</div>{% endif %}
 | 
			
		||||
 | 
			
		||||
    <h2 class="bd-title mt-0" style="margin-bottom: 40px;">{{ page_title }}</h2>
 | 
			
		||||
 | 
			
		||||
    {% block content %}
 | 
			
		||||
    TO_REPLACE
 | 
			
		||||
    {% endblock content %}
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
<script src="/assets/js/bootstrap.bundle.min.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user