mirror of
				https://github.com/nitnelave/lldap.git
				synced 2023-04-12 14:25:13 +00:00 
			
		
		
		
	app: probe for password reset support
This commit is contained in:
		
							parent
							
								
									6dc0377f6f
								
							
						
					
					
						commit
						f68d38d543
					
				@ -13,10 +13,13 @@ use crate::{
 | 
				
			|||||||
        user_details::UserDetails,
 | 
					        user_details::UserDetails,
 | 
				
			||||||
        user_table::UserTable,
 | 
					        user_table::UserTable,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    infra::cookies::get_cookie,
 | 
					    infra::{api::HostService, cookies::get_cookie},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use yew::{
 | 
				
			||||||
 | 
					    prelude::*,
 | 
				
			||||||
 | 
					    services::{fetch::FetchTask, ConsoleService},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use yew::prelude::*;
 | 
					 | 
				
			||||||
use yew::services::ConsoleService;
 | 
					 | 
				
			||||||
use yew_router::{
 | 
					use yew_router::{
 | 
				
			||||||
    agent::{RouteAgentDispatcher, RouteRequest},
 | 
					    agent::{RouteAgentDispatcher, RouteRequest},
 | 
				
			||||||
    route::Route,
 | 
					    route::Route,
 | 
				
			||||||
@ -29,11 +32,14 @@ pub struct App {
 | 
				
			|||||||
    user_info: Option<(String, bool)>,
 | 
					    user_info: Option<(String, bool)>,
 | 
				
			||||||
    redirect_to: Option<AppRoute>,
 | 
					    redirect_to: Option<AppRoute>,
 | 
				
			||||||
    route_dispatcher: RouteAgentDispatcher,
 | 
					    route_dispatcher: RouteAgentDispatcher,
 | 
				
			||||||
 | 
					    password_reset_enabled: bool,
 | 
				
			||||||
 | 
					    task: Option<FetchTask>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum Msg {
 | 
					pub enum Msg {
 | 
				
			||||||
    Login((String, bool)),
 | 
					    Login((String, bool)),
 | 
				
			||||||
    Logout,
 | 
					    Logout,
 | 
				
			||||||
 | 
					    PasswordResetProbeFinished(anyhow::Result<bool>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Component for App {
 | 
					impl Component for App {
 | 
				
			||||||
@ -58,7 +64,15 @@ impl Component for App {
 | 
				
			|||||||
                }),
 | 
					                }),
 | 
				
			||||||
            redirect_to: Self::get_redirect_route(),
 | 
					            redirect_to: Self::get_redirect_route(),
 | 
				
			||||||
            route_dispatcher: RouteAgentDispatcher::new(),
 | 
					            route_dispatcher: RouteAgentDispatcher::new(),
 | 
				
			||||||
 | 
					            password_reset_enabled: false,
 | 
				
			||||||
 | 
					            task: None,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        app.task = Some(
 | 
				
			||||||
 | 
					            HostService::probe_password_reset(
 | 
				
			||||||
 | 
					                app.link.callback_once(Msg::PasswordResetProbeFinished),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap(),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
        app.apply_initial_redirections();
 | 
					        app.apply_initial_redirections();
 | 
				
			||||||
        app
 | 
					        app
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -82,6 +96,16 @@ impl Component for App {
 | 
				
			|||||||
                self.user_info = None;
 | 
					                self.user_info = None;
 | 
				
			||||||
                self.redirect_to = None;
 | 
					                self.redirect_to = None;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            Msg::PasswordResetProbeFinished(Ok(enabled)) => {
 | 
				
			||||||
 | 
					                self.task = None;
 | 
				
			||||||
 | 
					                self.password_reset_enabled = enabled;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Msg::PasswordResetProbeFinished(Err(err)) => {
 | 
				
			||||||
 | 
					                self.task = None;
 | 
				
			||||||
 | 
					                ConsoleService::error(&format!(
 | 
				
			||||||
 | 
					                    "Could not probe for password reset support: {err:#}"
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if self.user_info.is_none() {
 | 
					        if self.user_info.is_none() {
 | 
				
			||||||
            self.route_dispatcher
 | 
					            self.route_dispatcher
 | 
				
			||||||
@ -97,6 +121,7 @@ impl Component for App {
 | 
				
			|||||||
    fn view(&self) -> Html {
 | 
					    fn view(&self) -> Html {
 | 
				
			||||||
        let link = self.link.clone();
 | 
					        let link = self.link.clone();
 | 
				
			||||||
        let is_admin = self.is_admin();
 | 
					        let is_admin = self.is_admin();
 | 
				
			||||||
 | 
					        let password_reset_enabled = self.password_reset_enabled;
 | 
				
			||||||
        html! {
 | 
					        html! {
 | 
				
			||||||
          <div>
 | 
					          <div>
 | 
				
			||||||
            {self.view_banner()}
 | 
					            {self.view_banner()}
 | 
				
			||||||
@ -104,7 +129,7 @@ impl Component for App {
 | 
				
			|||||||
              <div class="row justify-content-center" style="padding-bottom: 80px;">
 | 
					              <div class="row justify-content-center" style="padding-bottom: 80px;">
 | 
				
			||||||
                <div class="py-3" style="max-width: 1000px">
 | 
					                <div class="py-3" style="max-width: 1000px">
 | 
				
			||||||
                  <Router<AppRoute>
 | 
					                  <Router<AppRoute>
 | 
				
			||||||
                    render = Router::render(move |s| Self::dispatch_route(s, &link, is_admin))
 | 
					                    render = Router::render(move |s| Self::dispatch_route(s, &link, is_admin, password_reset_enabled))
 | 
				
			||||||
                  />
 | 
					                  />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
@ -135,6 +160,10 @@ impl App {
 | 
				
			|||||||
        let route_service = RouteService::<()>::new();
 | 
					        let route_service = RouteService::<()>::new();
 | 
				
			||||||
        let current_route = route_service.get_path();
 | 
					        let current_route = route_service.get_path();
 | 
				
			||||||
        if current_route.contains("reset-password") {
 | 
					        if current_route.contains("reset-password") {
 | 
				
			||||||
 | 
					            if !self.password_reset_enabled {
 | 
				
			||||||
 | 
					                self.route_dispatcher
 | 
				
			||||||
 | 
					                    .send(RouteRequest::ReplaceRoute(Route::from(AppRoute::Login)));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        match &self.user_info {
 | 
					        match &self.user_info {
 | 
				
			||||||
@ -162,10 +191,15 @@ impl App {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dispatch_route(switch: AppRoute, link: &ComponentLink<Self>, is_admin: bool) -> Html {
 | 
					    fn dispatch_route(
 | 
				
			||||||
 | 
					        switch: AppRoute,
 | 
				
			||||||
 | 
					        link: &ComponentLink<Self>,
 | 
				
			||||||
 | 
					        is_admin: bool,
 | 
				
			||||||
 | 
					        password_reset_enabled: bool,
 | 
				
			||||||
 | 
					    ) -> Html {
 | 
				
			||||||
        match switch {
 | 
					        match switch {
 | 
				
			||||||
            AppRoute::Login => html! {
 | 
					            AppRoute::Login => html! {
 | 
				
			||||||
                <LoginForm on_logged_in=link.callback(Msg::Login)/>
 | 
					                <LoginForm on_logged_in=link.callback(Msg::Login) password_reset_enabled=password_reset_enabled/>
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            AppRoute::CreateUser => html! {
 | 
					            AppRoute::CreateUser => html! {
 | 
				
			||||||
                <CreateUserForm/>
 | 
					                <CreateUserForm/>
 | 
				
			||||||
@ -200,11 +234,23 @@ impl App {
 | 
				
			|||||||
            AppRoute::ChangePassword(username) => html! {
 | 
					            AppRoute::ChangePassword(username) => html! {
 | 
				
			||||||
                <ChangePasswordForm username=username is_admin=is_admin />
 | 
					                <ChangePasswordForm username=username is_admin=is_admin />
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            AppRoute::StartResetPassword => html! {
 | 
					            AppRoute::StartResetPassword => {
 | 
				
			||||||
 | 
					                if password_reset_enabled {
 | 
				
			||||||
 | 
					                    html! {
 | 
				
			||||||
                      <ResetPasswordStep1Form />
 | 
					                      <ResetPasswordStep1Form />
 | 
				
			||||||
            },
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    App::dispatch_route(AppRoute::Login, link, is_admin, password_reset_enabled)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            AppRoute::FinishResetPassword(token) => html! {
 | 
					            AppRoute::FinishResetPassword(token) => html! {
 | 
				
			||||||
 | 
					                if password_reset_enabled {
 | 
				
			||||||
 | 
					                    html! {
 | 
				
			||||||
                      <ResetPasswordStep2Form token=token />
 | 
					                      <ResetPasswordStep2Form token=token />
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    App::dispatch_route(AppRoute::Login, link, is_admin, password_reset_enabled)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ pub struct FormModel {
 | 
				
			|||||||
#[derive(Clone, PartialEq, Properties)]
 | 
					#[derive(Clone, PartialEq, Properties)]
 | 
				
			||||||
pub struct Props {
 | 
					pub struct Props {
 | 
				
			||||||
    pub on_logged_in: Callback<(String, bool)>,
 | 
					    pub on_logged_in: Callback<(String, bool)>,
 | 
				
			||||||
 | 
					    pub password_reset_enabled: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum Msg {
 | 
					pub enum Msg {
 | 
				
			||||||
@ -147,6 +148,7 @@ impl Component for LoginForm {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn view(&self) -> Html {
 | 
					    fn view(&self) -> Html {
 | 
				
			||||||
        type Field = yew_form::Field<FormModel>;
 | 
					        type Field = yew_form::Field<FormModel>;
 | 
				
			||||||
 | 
					        let password_reset_enabled = self.common.password_reset_enabled;
 | 
				
			||||||
        if self.refreshing {
 | 
					        if self.refreshing {
 | 
				
			||||||
            html! {
 | 
					            html! {
 | 
				
			||||||
              <div>
 | 
					              <div>
 | 
				
			||||||
@ -198,12 +200,18 @@ impl Component for LoginForm {
 | 
				
			|||||||
                      <i class="bi-box-arrow-in-right me-2"/>
 | 
					                      <i class="bi-box-arrow-in-right me-2"/>
 | 
				
			||||||
                      {"Login"}
 | 
					                      {"Login"}
 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
 | 
					                    { if password_reset_enabled {
 | 
				
			||||||
 | 
					                      html! {
 | 
				
			||||||
                        <NavButton
 | 
					                        <NavButton
 | 
				
			||||||
                          classes="btn-link btn"
 | 
					                          classes="btn-link btn"
 | 
				
			||||||
                          disabled=self.common.is_task_running()
 | 
					                          disabled=self.common.is_task_running()
 | 
				
			||||||
                          route=AppRoute::StartResetPassword>
 | 
					                          route=AppRoute::StartResetPassword>
 | 
				
			||||||
                          {"Forgot your password?"}
 | 
					                          {"Forgot your password?"}
 | 
				
			||||||
                        </NavButton>
 | 
					                        </NavButton>
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                      html!{}
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
                  <div class="form-group">
 | 
					                  <div class="form-group">
 | 
				
			||||||
                  { if let Some(e) = &self.common.error {
 | 
					                  { if let Some(e) = &self.common.error {
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,11 @@ use anyhow::{anyhow, Context, Result};
 | 
				
			|||||||
use graphql_client::GraphQLQuery;
 | 
					use graphql_client::GraphQLQuery;
 | 
				
			||||||
use lldap_auth::{login, registration, JWTClaims};
 | 
					use lldap_auth::{login, registration, JWTClaims};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use yew::callback::Callback;
 | 
					use yew::{
 | 
				
			||||||
use yew::format::Json;
 | 
					    callback::Callback,
 | 
				
			||||||
use yew::services::fetch::{Credentials, FetchOptions, FetchService, FetchTask, Request, Response};
 | 
					    format::Json,
 | 
				
			||||||
 | 
					    services::fetch::{Credentials, FetchOptions, FetchService, FetchTask, Request, Response},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct HostService {}
 | 
					pub struct HostService {}
 | 
				
			||||||
@ -286,4 +288,17 @@ impl HostService {
 | 
				
			|||||||
            "Could not validate token",
 | 
					            "Could not validate token",
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn probe_password_reset(callback: Callback<Result<bool>>) -> Result<FetchTask> {
 | 
				
			||||||
 | 
					        let request = Request::get("/auth/reset/step1/lldap_unlikely_very_long_user_name")
 | 
				
			||||||
 | 
					            .header("Content-Type", "application/json")
 | 
				
			||||||
 | 
					            .body(yew::format::Nothing)?;
 | 
				
			||||||
 | 
					        FetchService::fetch_with_options(
 | 
				
			||||||
 | 
					            request,
 | 
				
			||||||
 | 
					            get_default_options(),
 | 
				
			||||||
 | 
					            create_handler(callback, move |status: http::StatusCode, _data: String| {
 | 
				
			||||||
 | 
					                Ok(status != http::StatusCode::NOT_FOUND)
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user