Can customize login background image
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-28 18:05:35 +01:00
parent 2a729d4153
commit ffd93c5435
5 changed files with 50 additions and 33 deletions

View File

@@ -14,7 +14,6 @@ body {
/* background */
@media screen and (min-width: 767px) {
.bg-login {
background-image: url(/assets/img/forest.jpg);
width: 100%;
height: 100%;
position: fixed;

View File

@@ -13,6 +13,7 @@ use crate::controllers::base_controller::{
build_fatal_error_page, redirect_user, redirect_user_for_login,
};
use crate::data::action_logger::{Action, ActionLogger};
use crate::data::app_config::AppConfig;
use crate::data::force_2fa_auth::Force2FAAuth;
use crate::data::login_redirect::{LoginRedirect, get_2fa_url};
use crate::data::provider::{Provider, ProvidersManager};
@@ -21,46 +22,60 @@ use crate::data::user::User;
use crate::data::webauthn_manager::WebAuthManagerReq;
use crate::utils::string_utils;
pub struct BaseLoginPage<'a> {
pub struct BaseLoginPage {
pub danger: Option<String>,
pub success: Option<String>,
pub background_image: &'static str,
pub page_title: &'static str,
pub app_name: &'static str,
pub redirect_uri: &'a LoginRedirect,
pub redirect_uri: LoginRedirect,
}
impl Default for BaseLoginPage {
fn default() -> Self {
Self {
page_title: "Login",
danger: None,
success: None,
background_image: &AppConfig::get().login_background_image,
app_name: APP_NAME,
redirect_uri: LoginRedirect::default(),
}
}
}
#[derive(Template)]
#[template(path = "login/login.html")]
struct LoginTemplate<'a> {
p: BaseLoginPage<'a>,
struct LoginTemplate {
p: BaseLoginPage,
login: String,
providers: Vec<Provider>,
}
#[derive(Template)]
#[template(path = "login/password_reset.html")]
struct PasswordResetTemplate<'a> {
p: BaseLoginPage<'a>,
struct PasswordResetTemplate {
p: BaseLoginPage,
min_pass_len: usize,
}
#[derive(Template)]
#[template(path = "login/choose_second_factor.html")]
struct ChooseSecondFactorTemplate<'a> {
p: BaseLoginPage<'a>,
p: BaseLoginPage,
user: &'a User,
}
#[derive(Template)]
#[template(path = "login/otp_input.html")]
struct LoginWithOTPTemplate<'a> {
p: BaseLoginPage<'a>,
struct LoginWithOTPTemplate {
p: BaseLoginPage,
}
#[derive(Template)]
#[template(path = "login/webauthn_input.html")]
struct LoginWithWebauthnTemplate<'a> {
p: BaseLoginPage<'a>,
struct LoginWithWebauthnTemplate {
p: BaseLoginPage,
opaque_state: String,
challenge_json: String,
}
@@ -216,8 +231,8 @@ pub async fn login_route(
page_title: "Login",
danger,
success,
app_name: APP_NAME,
redirect_uri: &query.redirect,
redirect_uri: query.0.redirect,
..Default::default()
},
login,
providers: providers.cloned(),
@@ -289,9 +304,8 @@ pub async fn reset_password_route(
p: BaseLoginPage {
page_title: "Password reset",
danger,
success: None,
app_name: APP_NAME,
redirect_uri: &query.redirect,
redirect_uri: query.0.redirect,
..Default::default()
},
min_pass_len: MIN_PASS_LEN,
}
@@ -339,10 +353,8 @@ pub async fn choose_2fa_method(
ChooseSecondFactorTemplate {
p: BaseLoginPage {
page_title: "Two factor authentication",
danger: None,
success: None,
app_name: APP_NAME,
redirect_uri: &query.redirect,
redirect_uri: query.0.redirect,
..Default::default()
},
user: &user,
}
@@ -430,8 +442,8 @@ pub async fn login_with_otp(
danger,
success: None,
page_title: "Two-Factor Auth",
app_name: APP_NAME,
redirect_uri: &query.redirect,
redirect_uri: query.0.redirect,
..Default::default()
},
}
.render()
@@ -493,11 +505,9 @@ pub async fn login_with_webauthn(
HttpResponse::Ok().body(
LoginWithWebauthnTemplate {
p: BaseLoginPage {
danger: None,
success: None,
page_title: "Two-Factor Auth",
app_name: APP_NAME,
redirect_uri: &query.redirect,
redirect_uri: query.0.redirect,
..Default::default()
},
opaque_state: challenge.opaque_state,
challenge_json: urlencoding::encode(&challenge_json).to_string(),

View File

@@ -10,7 +10,7 @@ use crate::actors::bruteforce_actor::BruteForceActor;
use crate::actors::providers_states_actor::{ProviderLoginState, ProvidersStatesActor};
use crate::actors::users_actor::{LoginResult, UsersActor};
use crate::actors::{bruteforce_actor, providers_states_actor, users_actor};
use crate::constants::{APP_NAME, MAX_FAILED_LOGIN_ATTEMPTS};
use crate::constants::MAX_FAILED_LOGIN_ATTEMPTS;
use crate::controllers::base_controller::{build_fatal_error_page, redirect_user};
use crate::controllers::login_controller::BaseLoginPage;
use crate::data::action_logger::{Action, ActionLogger};
@@ -22,7 +22,7 @@ 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,
message: &'a str,
}
@@ -30,11 +30,9 @@ impl<'a> ProviderLoginError<'a> {
pub fn get(message: &'a str, redirect_uri: &'a LoginRedirect) -> HttpResponse {
let body = Self {
p: BaseLoginPage {
danger: None,
success: None,
page_title: "Upstream login",
app_name: APP_NAME,
redirect_uri,
redirect_uri: redirect_uri.clone(),
..Default::default()
},
message,
}

View File

@@ -58,6 +58,10 @@ pub struct AppConfig {
/// Action logger output format
#[arg(long, env, default_value_t, value_enum)]
pub action_logger_format: ActionLoggerFormat,
/// Login background image
#[arg(long, env, default_value = "/assets/img/forest.jpg")]
pub login_background_image: String,
}
lazy_static::lazy_static! {

View File

@@ -30,6 +30,12 @@
font-size: 3.5rem;
}
}
@media screen and (min-width: 767px) {
.bg-login {
background-image: url({{ p.background_image }});
}
}
</style>