Updated all dependencies
This commit is contained in:
		
							
								
								
									
										1117
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1117
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -8,14 +8,14 @@ edition = "2021"
 | 
			
		||||
[dependencies]
 | 
			
		||||
actix = "0.13.3"
 | 
			
		||||
actix-identity = "0.7.0"
 | 
			
		||||
actix-web = "4"
 | 
			
		||||
actix-web = "4.5.1"
 | 
			
		||||
actix-session = { version = "0.9.0", features = ["cookie-session"] }
 | 
			
		||||
actix-remote-ip = "0.1.0"
 | 
			
		||||
clap = { version = "4.5.1", features = ["derive", "env"] }
 | 
			
		||||
include_dir = "0.7.3"
 | 
			
		||||
log = "0.4.20"
 | 
			
		||||
serde_json = "1.0.113"
 | 
			
		||||
serde_yaml = "0.9.30"
 | 
			
		||||
serde_yaml = "0.9.32"
 | 
			
		||||
env_logger = "0.11.2"
 | 
			
		||||
serde = { version = "1.0.196", features = ["derive"] }
 | 
			
		||||
bcrypt = "0.15.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,14 @@ use crate::utils::string_utils::rand_str;
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/clients_list.html")]
 | 
			
		||||
struct ClientsListTemplate<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    clients: Vec<Client>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/providers_list.html")]
 | 
			
		||||
struct ProvidersListTemplate<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    providers: Vec<Provider>,
 | 
			
		||||
    redirect_url: String,
 | 
			
		||||
}
 | 
			
		||||
@@ -35,14 +35,14 @@ struct ProvidersListTemplate<'a> {
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/users_list.html")]
 | 
			
		||||
struct UsersListTemplate<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    users: Vec<User>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/edit_user.html")]
 | 
			
		||||
struct EditUserTemplate<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    u: User,
 | 
			
		||||
    clients: Vec<Client>,
 | 
			
		||||
    providers: Vec<Provider>,
 | 
			
		||||
@@ -54,7 +54,7 @@ pub async fn clients_route(
 | 
			
		||||
) -> impl Responder {
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        ClientsListTemplate {
 | 
			
		||||
            _p: BaseSettingsPage::get("Clients list", &user, None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("Clients list", &user, None, None),
 | 
			
		||||
            clients: clients.cloned(),
 | 
			
		||||
        }
 | 
			
		||||
        .render()
 | 
			
		||||
@@ -68,7 +68,7 @@ pub async fn providers_route(
 | 
			
		||||
) -> impl Responder {
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        ProvidersListTemplate {
 | 
			
		||||
            _p: BaseSettingsPage::get("OpenID Providers list", &user, None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("OpenID Providers list", &user, None, None),
 | 
			
		||||
            providers: providers.cloned(),
 | 
			
		||||
            redirect_url: AppConfig::get().oidc_provider_redirect_url(),
 | 
			
		||||
        }
 | 
			
		||||
@@ -280,7 +280,7 @@ pub async fn users_route(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        UsersListTemplate {
 | 
			
		||||
            _p: BaseSettingsPage::get("Users list", &admin, danger, success),
 | 
			
		||||
            p: BaseSettingsPage::get("Users list", &admin, danger, success),
 | 
			
		||||
            users,
 | 
			
		||||
        }
 | 
			
		||||
        .render()
 | 
			
		||||
@@ -306,7 +306,7 @@ pub async fn create_user(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        EditUserTemplate {
 | 
			
		||||
            _p: BaseSettingsPage::get("Create a new user", admin.deref(), None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("Create a new user", admin.deref(), None, None),
 | 
			
		||||
            u: user,
 | 
			
		||||
            clients: clients.cloned(),
 | 
			
		||||
            providers: providers.cloned(),
 | 
			
		||||
@@ -336,7 +336,7 @@ pub async fn edit_user(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        EditUserTemplate {
 | 
			
		||||
            _p: BaseSettingsPage::get(
 | 
			
		||||
            p: BaseSettingsPage::get(
 | 
			
		||||
                "Edit user account",
 | 
			
		||||
                admin.deref(),
 | 
			
		||||
                match edited_account.is_none() {
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ pub struct BaseLoginPage<'a> {
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "login/login.html")]
 | 
			
		||||
struct LoginTemplate<'a> {
 | 
			
		||||
    _p: BaseLoginPage<'a>,
 | 
			
		||||
    p: BaseLoginPage<'a>,
 | 
			
		||||
    login: String,
 | 
			
		||||
    providers: Vec<Provider>,
 | 
			
		||||
}
 | 
			
		||||
@@ -38,27 +38,27 @@ struct LoginTemplate<'a> {
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "login/password_reset.html")]
 | 
			
		||||
struct PasswordResetTemplate<'a> {
 | 
			
		||||
    _p: BaseLoginPage<'a>,
 | 
			
		||||
    p: BaseLoginPage<'a>,
 | 
			
		||||
    min_pass_len: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "login/choose_second_factor.html")]
 | 
			
		||||
struct ChooseSecondFactorTemplate<'a> {
 | 
			
		||||
    _p: BaseLoginPage<'a>,
 | 
			
		||||
    p: BaseLoginPage<'a>,
 | 
			
		||||
    user: &'a User,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "login/otp_input.html")]
 | 
			
		||||
struct LoginWithOTPTemplate<'a> {
 | 
			
		||||
    _p: BaseLoginPage<'a>,
 | 
			
		||||
    p: BaseLoginPage<'a>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "login/webauthn_input.html")]
 | 
			
		||||
struct LoginWithWebauthnTemplate<'a> {
 | 
			
		||||
    _p: BaseLoginPage<'a>,
 | 
			
		||||
    p: BaseLoginPage<'a>,
 | 
			
		||||
    opaque_state: String,
 | 
			
		||||
    challenge_json: String,
 | 
			
		||||
}
 | 
			
		||||
@@ -199,7 +199,7 @@ pub async fn login_route(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().content_type("text/html").body(
 | 
			
		||||
        LoginTemplate {
 | 
			
		||||
            _p: BaseLoginPage {
 | 
			
		||||
            p: BaseLoginPage {
 | 
			
		||||
                page_title: "Login",
 | 
			
		||||
                danger,
 | 
			
		||||
                success,
 | 
			
		||||
@@ -273,7 +273,7 @@ pub async fn reset_password_route(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().content_type("text/html").body(
 | 
			
		||||
        PasswordResetTemplate {
 | 
			
		||||
            _p: BaseLoginPage {
 | 
			
		||||
            p: BaseLoginPage {
 | 
			
		||||
                page_title: "Password reset",
 | 
			
		||||
                danger,
 | 
			
		||||
                success: None,
 | 
			
		||||
@@ -323,7 +323,7 @@ pub async fn choose_2fa_method(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().content_type("text/html").body(
 | 
			
		||||
        ChooseSecondFactorTemplate {
 | 
			
		||||
            _p: BaseLoginPage {
 | 
			
		||||
            p: BaseLoginPage {
 | 
			
		||||
                page_title: "Two factor authentication",
 | 
			
		||||
                danger: None,
 | 
			
		||||
                success: None,
 | 
			
		||||
@@ -408,7 +408,7 @@ pub async fn login_with_otp(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        LoginWithOTPTemplate {
 | 
			
		||||
            _p: BaseLoginPage {
 | 
			
		||||
            p: BaseLoginPage {
 | 
			
		||||
                danger,
 | 
			
		||||
                success: None,
 | 
			
		||||
                page_title: "Two-Factor Auth",
 | 
			
		||||
@@ -473,7 +473,7 @@ pub async fn login_with_webauthn(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        LoginWithWebauthnTemplate {
 | 
			
		||||
            _p: BaseLoginPage {
 | 
			
		||||
            p: BaseLoginPage {
 | 
			
		||||
                danger: None,
 | 
			
		||||
                success: None,
 | 
			
		||||
                page_title: "Two-Factor Auth",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,14 +22,14 @@ use crate::data::session_identity::{SessionIdentity, SessionStatus};
 | 
			
		||||
#[derive(askama::Template)]
 | 
			
		||||
#[template(path = "login/prov_login_error.html")]
 | 
			
		||||
struct ProviderLoginError<'a> {
 | 
			
		||||
    _p: BaseLoginPage<'a>,
 | 
			
		||||
    p: BaseLoginPage<'a>,
 | 
			
		||||
    message: &'a str,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> ProviderLoginError<'a> {
 | 
			
		||||
    pub fn get(message: &'a str, redirect_uri: &'a LoginRedirect) -> HttpResponse {
 | 
			
		||||
        let body = Self {
 | 
			
		||||
            _p: BaseLoginPage {
 | 
			
		||||
            p: BaseLoginPage {
 | 
			
		||||
                danger: None,
 | 
			
		||||
                success: None,
 | 
			
		||||
                page_title: "Upstream login",
 | 
			
		||||
 
 | 
			
		||||
@@ -45,14 +45,14 @@ impl<'a> BaseSettingsPage<'a> {
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/account_details.html")]
 | 
			
		||||
struct AccountDetailsPage<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    remote_ip: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/change_password.html")]
 | 
			
		||||
struct ChangePasswordPage<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    min_pwd_len: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +61,7 @@ pub async fn account_settings_details_route(user: CurrentUser, ip: RemoteIP) ->
 | 
			
		||||
    let user = user.into();
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        AccountDetailsPage {
 | 
			
		||||
            _p: BaseSettingsPage::get("Account details", &user, None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("Account details", &user, None, None),
 | 
			
		||||
            remote_ip: ip.0.to_string(),
 | 
			
		||||
        }
 | 
			
		||||
        .render()
 | 
			
		||||
@@ -145,7 +145,7 @@ pub async fn change_password_route(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        ChangePasswordPage {
 | 
			
		||||
            _p: BaseSettingsPage::get("Change password", &user, danger, success),
 | 
			
		||||
            p: BaseSettingsPage::get("Change password", &user, danger, success),
 | 
			
		||||
            min_pwd_len: MIN_PASS_LEN,
 | 
			
		||||
        }
 | 
			
		||||
        .render()
 | 
			
		||||
 
 | 
			
		||||
@@ -17,14 +17,14 @@ use crate::data::webauthn_manager::WebAuthManagerReq;
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/two_factors_page.html")]
 | 
			
		||||
struct TwoFactorsPage<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    user: &'a User,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/add_2fa_totp_page.html")]
 | 
			
		||||
struct AddTotpPage<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    qr_code: String,
 | 
			
		||||
    account_name: String,
 | 
			
		||||
    secret_key: String,
 | 
			
		||||
@@ -34,7 +34,7 @@ struct AddTotpPage<'a> {
 | 
			
		||||
#[derive(Template)]
 | 
			
		||||
#[template(path = "settings/add_webauthn_page.html")]
 | 
			
		||||
struct AddWebauhtnPage<'a> {
 | 
			
		||||
    _p: BaseSettingsPage<'a>,
 | 
			
		||||
    p: BaseSettingsPage<'a>,
 | 
			
		||||
    opaque_state: String,
 | 
			
		||||
    challenge_json: String,
 | 
			
		||||
    max_name_len: usize,
 | 
			
		||||
@@ -44,7 +44,7 @@ struct AddWebauhtnPage<'a> {
 | 
			
		||||
pub async fn two_factors_route(user: CurrentUser) -> impl Responder {
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        TwoFactorsPage {
 | 
			
		||||
            _p: BaseSettingsPage::get("Two factor auth", &user, None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("Two factor auth", &user, None, None),
 | 
			
		||||
            user: user.deref(),
 | 
			
		||||
        }
 | 
			
		||||
        .render()
 | 
			
		||||
@@ -71,7 +71,7 @@ pub async fn add_totp_factor_route(user: CurrentUser) -> impl Responder {
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        AddTotpPage {
 | 
			
		||||
            _p: BaseSettingsPage::get("New authenticator app", &user, None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("New authenticator app", &user, None, None),
 | 
			
		||||
            qr_code: BASE64_STANDARD.encode(qr_code),
 | 
			
		||||
            account_name: key.account_name(&user, AppConfig::get()),
 | 
			
		||||
            secret_key: key.get_secret(),
 | 
			
		||||
@@ -106,7 +106,7 @@ pub async fn add_webauthn_factor_route(
 | 
			
		||||
 | 
			
		||||
    HttpResponse::Ok().body(
 | 
			
		||||
        AddWebauhtnPage {
 | 
			
		||||
            _p: BaseSettingsPage::get("New security key", &user, None, None),
 | 
			
		||||
            p: BaseSettingsPage::get("New security key", &user, None, None),
 | 
			
		||||
 | 
			
		||||
            opaque_state: registration_request.opaque_state,
 | 
			
		||||
            challenge_json: urlencoding::encode(&challenge_json).to_string(),
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
    <!-- No indexing -->
 | 
			
		||||
    <meta name="robots" content="noindex, nofollow">
 | 
			
		||||
 | 
			
		||||
    <title>{{ _p.app_name }} - {{ _p.page_title }}</title>
 | 
			
		||||
    <title>{{ p.app_name }} - {{ p.page_title }}</title>
 | 
			
		||||
 | 
			
		||||
    <!-- Bootstrap core CSS -->
 | 
			
		||||
    <link href="/assets/css/bootstrap.css" rel="stylesheet" crossorigin="anonymous"/>
 | 
			
		||||
@@ -43,15 +43,15 @@
 | 
			
		||||
 | 
			
		||||
<main class="form-signin">
 | 
			
		||||
 | 
			
		||||
    <h1 class="h3 mb-3 fw-normal" style="margin-bottom: 2rem !important;">{{ _p.page_title }}</h1>
 | 
			
		||||
    <h1 class="h3 mb-3 fw-normal" style="margin-bottom: 2rem !important;">{{ p.page_title }}</h1>
 | 
			
		||||
 | 
			
		||||
    {% if let Some(danger) = _p.danger %}
 | 
			
		||||
    {% if let Some(danger) = p.danger %}
 | 
			
		||||
    <div class="alert alert-danger" role="alert">
 | 
			
		||||
        {{ danger }}
 | 
			
		||||
    </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% if let Some(success) = _p.success %}
 | 
			
		||||
    {% if let Some(success) = p.success %}
 | 
			
		||||
    <div class="alert alert-success" role="alert">
 | 
			
		||||
        {{ success }}
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
    <p>You need to validate a second factor to complete your login.</p>
 | 
			
		||||
 | 
			
		||||
    {% for factor in user.get_distinct_factors_types() %}
 | 
			
		||||
    <a class="btn btn-primary btn-lg" href="{{ factor.login_url(_p.redirect_uri) }}" style="width: 100%; display: flex;">
 | 
			
		||||
    <a class="btn btn-primary btn-lg" href="{{ factor.login_url(p.redirect_uri) }}" style="width: 100%; display: flex;">
 | 
			
		||||
        <img src="{{ factor.type_image() }}" alt="Factor icon" style="margin-right: 1em;" />
 | 
			
		||||
        <div style="text-align: left;">
 | 
			
		||||
            {{ factor.type_str() }} <br/>
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<form action="/login?redirect={{ _p.redirect_uri.get_encoded() }}" method="post">
 | 
			
		||||
<form action="/login?redirect={{ p.redirect_uri.get_encoded() }}" method="post">
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="form-floating">
 | 
			
		||||
            <input name="login" type="text" required class="form-control" id="floatingName" placeholder="unsername"
 | 
			
		||||
@@ -41,7 +41,7 @@
 | 
			
		||||
{% if !providers.is_empty() %}
 | 
			
		||||
<div id="providers">
 | 
			
		||||
    {% for prov in providers %}
 | 
			
		||||
    <a class="btn btn-secondary btn-lg provider-button" href="{{ prov.login_url(_p.redirect_uri) }}">
 | 
			
		||||
    <a class="btn btn-secondary btn-lg provider-button" href="{{ prov.login_url(p.redirect_uri) }}">
 | 
			
		||||
        <img src="{{ prov.logo_url() }}" alt="Provider icon"/>
 | 
			
		||||
        <div style="text-align: left;">
 | 
			
		||||
            Login using {{ prov.name }} <br/>
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div style="margin-top: 10px;">
 | 
			
		||||
    <a href="/2fa_auth?force_display=true&redirect={{ _p.redirect_uri.get_encoded() }}">Sign in using another factor</a><br/>
 | 
			
		||||
    <a href="/2fa_auth?force_display=true&redirect={{ p.redirect_uri.get_encoded() }}">Sign in using another factor</a><br/>
 | 
			
		||||
    <a href="/logout">Sign out</a>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{% extends "base_login_page.html" %}
 | 
			
		||||
{% block content %}
 | 
			
		||||
<form action="/reset_password?redirect={{ _p.redirect_uri.get_encoded() }}" method="post" id="reset_password_form">
 | 
			
		||||
<form action="/reset_password?redirect={{ p.redirect_uri.get_encoded() }}" method="post" id="reset_password_form">
 | 
			
		||||
    <div>
 | 
			
		||||
        <p>You need to configure a new password:</p>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <p style="margin-top: 10px; text-align: justify;">{{ message }}</p>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<a href="/login?redirect={{ _p.redirect_uri.get_encoded() }}">Go back to login</a>
 | 
			
		||||
<a href="/login?redirect={{ p.redirect_uri.get_encoded() }}">Go back to login</a>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% endblock content %}
 | 
			
		||||
@@ -12,13 +12,13 @@
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div style="margin-top: 10px;">
 | 
			
		||||
    <a href="/2fa_auth?force_display=true&redirect={{ _p.redirect_uri.get_encoded() }}">Sign in using another factor</a><br/>
 | 
			
		||||
    <a href="/2fa_auth?force_display=true&redirect={{ p.redirect_uri.get_encoded() }}">Sign in using another factor</a><br/>
 | 
			
		||||
    <a href="/logout">Sign out</a>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script src="/assets/js/base64_lib.js"></script>
 | 
			
		||||
<script>
 | 
			
		||||
    const REDIRECT_URI = decodeURIComponent("{{ _p.redirect_uri.get_encoded() }}");
 | 
			
		||||
    const REDIRECT_URI = decodeURIComponent("{{ p.redirect_uri.get_encoded() }}");
 | 
			
		||||
    const OPAQUE_STATE = "{{ opaque_state }}";
 | 
			
		||||
    const AUTH_CHALLENGE = JSON.parse(decodeURIComponent("{{ challenge_json }}"));
 | 
			
		||||
    // Decode data
 | 
			
		||||
 
 | 
			
		||||
@@ -5,27 +5,27 @@
 | 
			
		||||
    <tbody>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">User ID</th>
 | 
			
		||||
        <td>{{ _p.user.uid.0 }}</td>
 | 
			
		||||
        <td>{{ p.user.uid.0 }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">First name</th>
 | 
			
		||||
        <td>{{ _p.user.first_name }}</td>
 | 
			
		||||
        <td>{{ p.user.first_name }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Last name</th>
 | 
			
		||||
        <td>{{ _p.user.last_name }}</td>
 | 
			
		||||
        <td>{{ p.user.last_name }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Username</th>
 | 
			
		||||
        <td>{{ _p.user.username }}</td>
 | 
			
		||||
        <td>{{ p.user.username }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Email</th>
 | 
			
		||||
        <td>{{ _p.user.email }}</td>
 | 
			
		||||
        <td>{{ p.user.email }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th scope="row">Account type</th>
 | 
			
		||||
        <td>{% if _p.user.admin %}Admin{% else %}Regular user{% endif %}</td>
 | 
			
		||||
        <td>{% if p.user.admin %}Admin{% else %}Regular user{% endif %}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    </tbody>
 | 
			
		||||
</table>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>{{ _p.page_title }} - {{ _p.app_name }}</title>
 | 
			
		||||
    <title>{{ p.page_title }} - {{ p.app_name }}</title>
 | 
			
		||||
 | 
			
		||||
    <!-- Bootstrap core CSS -->
 | 
			
		||||
    <link href="/assets/css/bootstrap.css" rel="stylesheet" crossorigin="anonymous"/>
 | 
			
		||||
@@ -12,10 +12,10 @@
 | 
			
		||||
<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">{{ _p.app_name }}</span>
 | 
			
		||||
        <span class="fs-4">{{ p.app_name }}</span>
 | 
			
		||||
    </a>
 | 
			
		||||
    {% if _p.user.admin %}
 | 
			
		||||
    <span>Version {{ _p.version }}</span>
 | 
			
		||||
    {% if p.user.admin %}
 | 
			
		||||
    <span>Version {{ p.version }}</span>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    <hr>
 | 
			
		||||
    <ul class="nav nav-pills flex-column mb-auto">
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
                Account details
 | 
			
		||||
            </a>
 | 
			
		||||
        </li>
 | 
			
		||||
        {% if _p.user.allow_local_login %}
 | 
			
		||||
        {% if p.user.allow_local_login %}
 | 
			
		||||
        <li>
 | 
			
		||||
            <a href="/settings/change_password" class="nav-link link-dark">
 | 
			
		||||
                Change password
 | 
			
		||||
@@ -37,7 +37,7 @@
 | 
			
		||||
            </a>
 | 
			
		||||
        </li>
 | 
			
		||||
 | 
			
		||||
        {% if _p.user.admin %}
 | 
			
		||||
        {% if p.user.admin %}
 | 
			
		||||
        <hr/>
 | 
			
		||||
        <li>
 | 
			
		||||
            <a href="/admin/clients" class="nav-link link-dark">
 | 
			
		||||
@@ -61,7 +61,7 @@
 | 
			
		||||
        <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>{{ _p.user.username }}</strong>
 | 
			
		||||
            <strong>{{ p.user.username }}</strong>
 | 
			
		||||
        </a>
 | 
			
		||||
        <ul class="dropdown-menu text-small shadow" aria-labelledby="dropdownUser">
 | 
			
		||||
            <li><a class="dropdown-item" href="/logout">Sign out</a></li>
 | 
			
		||||
@@ -70,14 +70,14 @@
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="page_body" style="flex: 1">
 | 
			
		||||
    {% if let Some(msg) = _p.danger_message %}
 | 
			
		||||
    {% if let Some(msg) = p.danger_message %}
 | 
			
		||||
    <div class="alert alert-danger">{{ msg }}</div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    {% if let Some(msg) = _p.success_message %}
 | 
			
		||||
    {% if let Some(msg) = p.success_message %}
 | 
			
		||||
    <div class="alert alert-success">{{ msg }}</div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    <h2 class="bd-title mt-0" style="margin-bottom: 40px;">{{ _p.page_title }}</h2>
 | 
			
		||||
    <h2 class="bd-title mt-0" style="margin-bottom: 40px;">{{ p.page_title }}</h2>
 | 
			
		||||
 | 
			
		||||
    {% block content %}
 | 
			
		||||
    TO_REPLACE
 | 
			
		||||
@@ -92,8 +92,8 @@
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
{% if _p.ip_location_api.is_some() %}
 | 
			
		||||
<script>const IP_LOCATION_API = "{{ _p.ip_location_api.unwrap() }}"</script>
 | 
			
		||||
{% if p.ip_location_api.is_some() %}
 | 
			
		||||
<script>const IP_LOCATION_API = "{{ p.ip_location_api.unwrap() }}"</script>
 | 
			
		||||
{% endif %}
 | 
			
		||||
<script src="/assets/js/ip_location_service.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 
 | 
			
		||||
@@ -195,7 +195,7 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    </fieldset>
 | 
			
		||||
 | 
			
		||||
    <input type="submit" class="btn btn-primary mt-4" value="{{ _p.page_title }}">
 | 
			
		||||
    <input type="submit" class="btn btn-primary mt-4" value="{{ p.page_title }}">
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user