Log all user actions on stdout
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:
@ -10,6 +10,7 @@ use crate::constants::{APP_NAME, MAX_FAILED_LOGIN_ATTEMPTS, MIN_PASS_LEN};
|
||||
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::login_redirect::LoginRedirect;
|
||||
use crate::data::remote_ip::RemoteIP;
|
||||
use crate::data::session_identity::{SessionIdentity, SessionStatus};
|
||||
@ -73,6 +74,7 @@ pub struct LoginRequestQuery {
|
||||
}
|
||||
|
||||
/// Authenticate user
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn login_route(
|
||||
remote_ip: RemoteIP,
|
||||
users: web::Data<Addr<UsersActor>>,
|
||||
@ -81,6 +83,7 @@ pub async fn login_route(
|
||||
req: Option<web::Form<LoginRequestBody>>,
|
||||
id: Option<Identity>,
|
||||
http_req: HttpRequest,
|
||||
logger: ActionLogger,
|
||||
) -> impl Responder {
|
||||
let mut danger = None;
|
||||
let mut success = None;
|
||||
@ -102,6 +105,7 @@ pub async fn login_route(
|
||||
// Check if user session must be closed
|
||||
if let Some(true) = query.logout {
|
||||
if let Some(id) = id {
|
||||
logger.log(Action::Signout);
|
||||
id.logout();
|
||||
}
|
||||
success = Some("Goodbye!".to_string());
|
||||
@ -138,11 +142,14 @@ pub async fn login_route(
|
||||
match response {
|
||||
LoginResult::Success(user) => {
|
||||
let status = if user.need_reset_password {
|
||||
logger.log(Action::UserNeedNewPasswordOnLogin(&user));
|
||||
SessionStatus::NeedNewPassword
|
||||
} else if user.has_two_factor() && !user.can_bypass_two_factors_for_ip(remote_ip.0)
|
||||
{
|
||||
logger.log(Action::UserNeed2FAOnLogin(&user));
|
||||
SessionStatus::Need2FA
|
||||
} else {
|
||||
logger.log(Action::UserSuccessfullyAuthenticated(&user));
|
||||
SessionStatus::SignedIn
|
||||
};
|
||||
|
||||
@ -151,7 +158,8 @@ pub async fn login_route(
|
||||
}
|
||||
|
||||
LoginResult::AccountDisabled => {
|
||||
log::warn!("Failed login for username {} : account is disabled", login);
|
||||
log::warn!("Failed login for username {} : account is disabled", &login);
|
||||
logger.log(Action::TryLoginWithDisabledAccount(&login));
|
||||
danger = Some("Your account is disabled!".to_string());
|
||||
}
|
||||
|
||||
@ -162,6 +170,7 @@ pub async fn login_route(
|
||||
login,
|
||||
c
|
||||
);
|
||||
logger.log(Action::FailedLoginWithBadCredentials(&login));
|
||||
danger = Some("Login failed.".to_string());
|
||||
|
||||
bruteforce
|
||||
@ -213,6 +222,7 @@ pub async fn reset_password_route(
|
||||
req: Option<web::Form<ChangePasswordRequestBody>>,
|
||||
users: web::Data<Addr<UsersActor>>,
|
||||
http_req: HttpRequest,
|
||||
logger: ActionLogger,
|
||||
) -> impl Responder {
|
||||
let mut danger = None;
|
||||
|
||||
@ -220,6 +230,8 @@ pub async fn reset_password_route(
|
||||
return redirect_user_for_login(query.redirect.get());
|
||||
}
|
||||
|
||||
let user_id = SessionIdentity(id.as_ref()).user_id();
|
||||
|
||||
// Check if user is setting a new password
|
||||
if let Some(req) = &req {
|
||||
if req.password.len() < MIN_PASS_LEN {
|
||||
@ -227,7 +239,7 @@ pub async fn reset_password_route(
|
||||
} else {
|
||||
let res: ChangePasswordResult = users
|
||||
.send(users_actor::ChangePasswordRequest {
|
||||
user_id: SessionIdentity(id.as_ref()).user_id(),
|
||||
user_id: user_id.clone(),
|
||||
new_password: req.password.clone(),
|
||||
temporary: false,
|
||||
})
|
||||
@ -238,6 +250,7 @@ pub async fn reset_password_route(
|
||||
danger = Some("Failed to change password!".to_string());
|
||||
} else {
|
||||
SessionIdentity(id.as_ref()).set_status(&http_req, SessionStatus::SignedIn);
|
||||
logger.log(Action::UserChangedPasswordOnLogin(&user_id));
|
||||
return redirect_user(query.redirect.get());
|
||||
}
|
||||
}
|
||||
@ -328,6 +341,7 @@ pub async fn login_with_otp(
|
||||
users: web::Data<Addr<UsersActor>>,
|
||||
http_req: HttpRequest,
|
||||
remote_ip: RemoteIP,
|
||||
logger: ActionLogger,
|
||||
) -> impl Responder {
|
||||
let mut danger = None;
|
||||
|
||||
@ -354,14 +368,25 @@ pub async fn login_with_otp(
|
||||
.iter()
|
||||
.any(|k| k.check_code(&form.code).unwrap_or(false))
|
||||
{
|
||||
logger.log(Action::OTPLoginAttempt {
|
||||
success: false,
|
||||
user: &user,
|
||||
});
|
||||
danger = Some("Specified code is invalid!".to_string());
|
||||
} else {
|
||||
users
|
||||
.send(users_actor::AddSuccessful2FALogin(user.uid, remote_ip.0))
|
||||
.send(users_actor::AddSuccessful2FALogin(
|
||||
user.uid.clone(),
|
||||
remote_ip.0,
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
SessionIdentity(id.as_ref()).set_status(&http_req, SessionStatus::SignedIn);
|
||||
logger.log(Action::OTPLoginAttempt {
|
||||
success: true,
|
||||
user: &user,
|
||||
});
|
||||
return redirect_user(query.redirect.get());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user