Can customize login background image
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		| @@ -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(), | ||||
|   | ||||
| @@ -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, | ||||
|         } | ||||
|   | ||||
| @@ -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! { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user