feat(user): add TOTP 2FA handler module under user/security
zhenyi committed
Added lib/user/handler/security/totp/disable.rs lib/user/handler/security/totp/disable.rs +26 −0 View lib/user/handler/security/totp/disable.rs
@@ -0,0 +1,26 @@
1use axum::extract::State;
2use export::data::{AppRequest, AppRequestData, AppResponseData, NoData};
3use jwt::extractor::AuthUser;
4
5use crate::error::UserResult;
6use crate::features::UserService;
7use crate::features::security::DisableTwoFactorCmd;
8
9#[utoipa::path(
10 post,
11 path = "/user/me/two-factor/disable",
12 tag = "user",
13 request_body = AppRequestData<DisableTwoFactorCmd>,
14 responses(
15 (status = 200, description = "Two-factor authentication disabled.", body = AppResponseData<NoData>),
16 ),
17 security(("bearer_auth" = [])),
18)]
19pub(crate) async fn handler(
20 State(svc): State<UserService>,
21 AuthUser { claims }: AuthUser,
22 cmd: AppRequest<DisableTwoFactorCmd>,
23) -> UserResult<AppResponseData<NoData>> {
24 svc.disable_two_factor(claims.sub, cmd.into_inner()).await?;
25 Ok(AppResponseData::<NoData>::empty())
26}
Added lib/user/handler/security/totp/enable.rs lib/user/handler/security/totp/enable.rs +26 −0 View lib/user/handler/security/totp/enable.rs
@@ -0,0 +1,26 @@
1use axum::extract::State;
2use export::data::{AppRequest, AppRequestData, AppResponseData, NoData};
3use jwt::extractor::AuthUser;
4
5use crate::error::UserResult;
6use crate::features::UserService;
7use crate::features::security::EnableTwoFactorCmd;
8
9#[utoipa::path(
10 post,
11 path = "/user/me/two-factor/enable",
12 tag = "user",
13 request_body = AppRequestData<EnableTwoFactorCmd>,
14 responses(
15 (status = 200, description = "Two-factor authentication enabled.", body = AppResponseData<NoData>),
16 ),
17 security(("bearer_auth" = [])),
18)]
19pub(crate) async fn handler(
20 State(svc): State<UserService>,
21 AuthUser { claims }: AuthUser,
22 cmd: AppRequest<EnableTwoFactorCmd>,
23) -> UserResult<AppResponseData<NoData>> {
24 svc.enable_two_factor(claims.sub, cmd.into_inner()).await?;
25 Ok(AppResponseData::<NoData>::empty())
26}
Added lib/user/handler/security/totp/mod.rs lib/user/handler/security/totp/mod.rs +4 −0 View lib/user/handler/security/totp/mod.rs
@@ -0,0 +1,4 @@
1pub(crate) mod disable;
2pub(crate) mod enable;
3pub(crate) mod setup;
4pub(crate) mod status;
Added lib/user/handler/security/totp/setup.rs lib/user/handler/security/totp/setup.rs +23 −0 View lib/user/handler/security/totp/setup.rs
@@ -0,0 +1,23 @@
1use axum::extract::State;
2use export::data::AppResponseData;
3use jwt::extractor::AuthUser;
4
5use crate::error::UserResult;
6use crate::features::UserService;
7use crate::features::security::TwoFactorSetupResp;
8
9#[utoipa::path(
10 post,
11 path = "/user/me/two-factor/setup",
12 tag = "user",
13 responses(
14 (status = 200, description = "Two-factor setup started (base32 secret returned once).", body = AppResponseData<TwoFactorSetupResp>),
15 ),
16 security(("bearer_auth" = [])),
17)]
18pub(crate) async fn handler(
19 State(svc): State<UserService>,
20 AuthUser { claims }: AuthUser,
21) -> UserResult<AppResponseData<TwoFactorSetupResp>> {
22 Ok(AppResponseData::ok(svc.two_factor_setup(claims.sub).await?))
23}
Added lib/user/handler/security/totp/status.rs lib/user/handler/security/totp/status.rs +25 −0 View lib/user/handler/security/totp/status.rs
@@ -0,0 +1,25 @@
1use axum::extract::State;
2use export::data::AppResponseData;
3use jwt::extractor::AuthUser;
4
5use crate::error::UserResult;
6use crate::features::UserService;
7use crate::features::security::TwoFactorStatusResp;
8
9#[utoipa::path(
10 get,
11 path = "/user/me/two-factor",
12 tag = "user",
13 responses(
14 (status = 200, description = "Two-factor authentication status for the caller.", body = AppResponseData<TwoFactorStatusResp>),
15 ),
16 security(("bearer_auth" = [])),
17)]
18pub(crate) async fn handler(
19 State(svc): State<UserService>,
20 AuthUser { claims }: AuthUser,
21) -> UserResult<AppResponseData<TwoFactorStatusResp>> {
22 Ok(AppResponseData::ok(
23 svc.two_factor_status(claims.sub).await?,
24 ))
25}