refactor(auth,space,issues,user): use session::share imports, drop auth block/follow/device handlers
ZhenYi committed
Modified lib/auth/src/handlers/accept_agreement.rs lib/auth/src/handlers/accept_agreement.rs +1 −1 View lib/auth/src/handlers/accept_agreement.rs
@@ -5,7 +5,7 @@
55use utoipa::ToSchema;
66
77use crate::errors::ApiError;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99use crate::services::agreements::AcceptAgreementResp;
1010use crate::services::AuthService;
1111
Modified lib/auth/src/handlers/active_suspension.rs lib/auth/src/handlers/active_suspension.rs +1 −1 View lib/auth/src/handlers/active_suspension.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::suspensions::SuspensionDto;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/add_ssh_key.rs lib/auth/src/handlers/add_ssh_key.rs +1 −1 View lib/auth/src/handlers/add_ssh_key.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::ssh_keys::{AddSshKeyCmd, SshKeyDto};
88use crate::services::AuthService;
99
Deleted lib/auth/src/handlers/block_user.rs lib/auth/src/handlers/block_user.rs +0 −29
@@ -1,29 +0,0 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4use uuid::Uuid;
5
6use crate::errors::ApiError;
7use crate::share::session::require_uid;
8use crate::services::AuthService;
9
10#[utoipa::path(
11 put,
12 path = "/users/{uid}/block",
13 tag = "users",
14 params(
15 ("uid" = Uuid, Path, description = "user id to block")
16 ),
17 responses(
18 (status = 200, description = "block established", body = AppResponseData<NoData>)
19 )
20)]
21pub async fn block_user(
22 State(service): State<AuthService>,
23 session: Session,
24 Path(blocked_uid): Path<Uuid>,
25) -> Result<AppResponseData<NoData>, ApiError> {
26 let uid = require_uid(&session)?;
27 service.block(uid, blocked_uid).await.map_err(ApiError::from)?;
28 Ok(AppResponseData::empty())
29}
No newline at end of file
Modified lib/auth/src/handlers/cancel_deletion.rs lib/auth/src/handlers/cancel_deletion.rs +1 −1 View lib/auth/src/handlers/cancel_deletion.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::AuthService;
88
99#[utoipa::path(
Modified lib/auth/src/handlers/cancel_email_change.rs lib/auth/src/handlers/cancel_email_change.rs +1 −1 View lib/auth/src/handlers/cancel_email_change.rs
@@ -4,7 +4,7 @@
44use uuid::Uuid;
55
66use crate::errors::ApiError;
7use crate::share::session::require_uid;
7use session::share::session::require_uid;
88use crate::services::AuthService;
99
1010#[utoipa::path(
Modified lib/auth/src/handlers/change_password.rs lib/auth/src/handlers/change_password.rs +1 −1 View lib/auth/src/handlers/change_password.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::password::ChangePasswordCmd;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/confirm_email_change.rs lib/auth/src/handlers/confirm_email_change.rs +1 −1 View lib/auth/src/handlers/confirm_email_change.rs
@@ -6,7 +6,7 @@
66use uuid::Uuid;
77
88use crate::errors::ApiError;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010use crate::services::AuthService;
1111
1212#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
Modified lib/auth/src/handlers/create_access_key.rs lib/auth/src/handlers/create_access_key.rs +1 −1 View lib/auth/src/handlers/create_access_key.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::access_keys::{CreateAccessKeyCmd, CreateAccessKeyResp};
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/create_report.rs lib/auth/src/handlers/create_report.rs +1 −1 View lib/auth/src/handlers/create_report.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::reports::{CreateReportCmd, ReportDto};
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/delete_access_key.rs lib/auth/src/handlers/delete_access_key.rs +1 −1 View lib/auth/src/handlers/delete_access_key.rs
@@ -4,7 +4,7 @@
44use uuid::Uuid;
55
66use crate::errors::ApiError;
7use crate::share::session::require_uid;
7use session::share::session::require_uid;
88use crate::services::AuthService;
99
1010#[utoipa::path(
Deleted lib/auth/src/handlers/delete_device.rs lib/auth/src/handlers/delete_device.rs +0 −32
@@ -1,32 +0,0 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4use uuid::Uuid;
5
6use crate::errors::ApiError;
7use crate::share::session::require_uid;
8use crate::services::AuthService;
9
10#[utoipa::path(
11 delete,
12 path = "/auth/devices/{device_id}",
13 tag = "security",
14 params(
15 ("device_id" = Uuid, Path, description = "device id")
16 ),
17 responses(
18 (status = 200, description = "device record deleted", body = AppResponseData<NoData>)
19 )
20)]
21pub async fn delete_device(
22 State(service): State<AuthService>,
23 session: Session,
24 Path(device_id): Path<Uuid>,
25) -> Result<AppResponseData<NoData>, ApiError> {
26 let uid = require_uid(&session)?;
27 service
28 .delete_device(uid, device_id)
29 .await
30 .map_err(ApiError::from)?;
31 Ok(AppResponseData::empty())
32}
No newline at end of file
Modified lib/auth/src/handlers/delete_notification.rs lib/auth/src/handlers/delete_notification.rs +1 −1 View lib/auth/src/handlers/delete_notification.rs
@@ -4,7 +4,7 @@
44use uuid::Uuid;
55
66use crate::errors::ApiError;
7use crate::share::session::require_uid;
7use session::share::session::require_uid;
88use crate::services::AuthService;
99
1010#[utoipa::path(
Modified lib/auth/src/handlers/delete_ssh_key.rs lib/auth/src/handlers/delete_ssh_key.rs +1 −1 View lib/auth/src/handlers/delete_ssh_key.rs
@@ -4,7 +4,7 @@
44use uuid::Uuid;
55
66use crate::errors::ApiError;
7use crate::share::session::require_uid;
7use session::share::session::require_uid;
88use crate::services::AuthService;
99
1010#[utoipa::path(
Modified lib/auth/src/handlers/deletion_status.rs lib/auth/src/handlers/deletion_status.rs +1 −1 View lib/auth/src/handlers/deletion_status.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::deletion::DeletionDto;
88use crate::services::AuthService;
99
Deleted lib/auth/src/handlers/follow_user.rs lib/auth/src/handlers/follow_user.rs +0 −29
@@ -1,29 +0,0 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4use uuid::Uuid;
5
6use crate::errors::ApiError;
7use crate::share::session::require_uid;
8use crate::services::AuthService;
9
10#[utoipa::path(
11 put,
12 path = "/users/{uid}/follow",
13 tag = "users",
14 params(
15 ("uid" = Uuid, Path, description = "user id to follow")
16 ),
17 responses(
18 (status = 200, description = "follow relationship established", body = AppResponseData<NoData>)
19 )
20)]
21pub async fn follow_user(
22 State(service): State<AuthService>,
23 session: Session,
24 Path(followed_uid): Path<Uuid>,
25) -> Result<AppResponseData<NoData>, ApiError> {
26 let uid = require_uid(&session)?;
27 service.follow(uid, followed_uid).await.map_err(ApiError::from)?;
28 Ok(AppResponseData::empty())
29}
No newline at end of file
Modified lib/auth/src/handlers/get_preferences.rs lib/auth/src/handlers/get_preferences.rs +1 −1 View lib/auth/src/handlers/get_preferences.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::preferences::UserPreferencesDto;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/list_access_keys.rs lib/auth/src/handlers/list_access_keys.rs +1 −1 View lib/auth/src/handlers/list_access_keys.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::share::types::ListQuery;
88use crate::services::access_keys::AccessKeyDto;
99use crate::services::AuthService;
Deleted lib/auth/src/handlers/list_blocked_users.rs lib/auth/src/handlers/list_blocked_users.rs +0 −27
@@ -1,27 +0,0 @@
1use axum::extract::{Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::ApiError;
6use crate::share::session::require_uid;
7use crate::share::types::{ListQuery, UserPublic};
8use crate::services::AuthService;
9
10#[utoipa::path(
11 get,
12 path = "/users/blocks",
13 tag = "users",
14 params(ListQuery),
15 responses(
16 (status = 200, description = "users blocked by the current user", body = AppResponseData<Vec<UserPublic>>)
17 )
18)]
19pub async fn list_blocked_users(
20 State(service): State<AuthService>,
21 session: Session,
22 Query(query): Query<ListQuery>,
23) -> Result<AppResponseData<Vec<UserPublic>>, ApiError> {
24 let uid = require_uid(&session)?;
25 let users = service.blocked_users(uid, query).await.map_err(ApiError::from)?;
26 Ok(AppResponseData::ok(users))
27}
No newline at end of file
Deleted lib/auth/src/handlers/list_devices.rs lib/auth/src/handlers/list_devices.rs +0 −28
@@ -1,28 +0,0 @@
1use axum::extract::{Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::ApiError;
6use crate::share::session::require_uid;
7use crate::share::types::ListQuery;
8use crate::services::devices::DeviceDto;
9use crate::services::AuthService;
10
11#[utoipa::path(
12 get,
13 path = "/auth/devices",
14 tag = "security",
15 params(ListQuery),
16 responses(
17 (status = 200, description = "devices known for the current user", body = AppResponseData<Vec<DeviceDto>>)
18 )
19)]
20pub async fn list_devices(
21 State(service): State<AuthService>,
22 session: Session,
23 Query(query): Query<ListQuery>,
24) -> Result<AppResponseData<Vec<DeviceDto>>, ApiError> {
25 let uid = require_uid(&session)?;
26 let devices = service.list_devices(uid, query).await.map_err(ApiError::from)?;
27 Ok(AppResponseData::ok(devices))
28}
No newline at end of file
Deleted lib/auth/src/handlers/list_followers.rs lib/auth/src/handlers/list_followers.rs +0 −28
@@ -1,28 +0,0 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use uuid::Uuid;
4
5use crate::errors::ApiError;
6use crate::share::types::{ListQuery, UserPublic};
7use crate::services::AuthService;
8
9#[utoipa::path(
10 get,
11 path = "/users/{uid}/followers",
12 tag = "users",
13 params(
14 ("uid" = Uuid, Path, description = "user id"),
15 ListQuery
16 ),
17 responses(
18 (status = 200, description = "users following the given user", body = AppResponseData<Vec<UserPublic>>)
19 )
20)]
21pub async fn list_followers(
22 State(service): State<AuthService>,
23 Path(uid): Path<Uuid>,
24 Query(query): Query<ListQuery>,
25) -> Result<AppResponseData<Vec<UserPublic>>, ApiError> {
26 let users = service.followers(uid, query).await.map_err(ApiError::from)?;
27 Ok(AppResponseData::ok(users))
28}
No newline at end of file
Deleted lib/auth/src/handlers/list_following.rs lib/auth/src/handlers/list_following.rs +0 −28
@@ -1,28 +0,0 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use uuid::Uuid;
4
5use crate::errors::ApiError;
6use crate::share::types::{ListQuery, UserPublic};
7use crate::services::AuthService;
8
9#[utoipa::path(
10 get,
11 path = "/users/{uid}/following",
12 tag = "users",
13 params(
14 ("uid" = Uuid, Path, description = "user id"),
15 ListQuery
16 ),
17 responses(
18 (status = 200, description = "users the given user follows", body = AppResponseData<Vec<UserPublic>>)
19 )
20)]
21pub async fn list_following(
22 State(service): State<AuthService>,
23 Path(uid): Path<Uuid>,
24 Query(query): Query<ListQuery>,
25) -> Result<AppResponseData<Vec<UserPublic>>, ApiError> {
26 let users = service.following(uid, query).await.map_err(ApiError::from)?;
27 Ok(AppResponseData::ok(users))
28}
No newline at end of file
Modified lib/auth/src/handlers/list_notifications.rs lib/auth/src/handlers/list_notifications.rs +1 −1 View lib/auth/src/handlers/list_notifications.rs
@@ -5,7 +5,7 @@
55use utoipa::IntoParams;
66
77use crate::errors::ApiError;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99use crate::services::notifications::NotificationDto;
1010use crate::services::AuthService;
1111
Modified lib/auth/src/handlers/list_ssh_keys.rs lib/auth/src/handlers/list_ssh_keys.rs +1 −1 View lib/auth/src/handlers/list_ssh_keys.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::share::types::ListQuery;
88use crate::services::ssh_keys::SshKeyDto;
99use crate::services::AuthService;
Modified lib/auth/src/handlers/mark_all_notifications_read.rs lib/auth/src/handlers/mark_all_notifications_read.rs +1 −1 View lib/auth/src/handlers/mark_all_notifications_read.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::AuthService;
88
99#[utoipa::path(
Modified lib/auth/src/handlers/mark_notification_read.rs lib/auth/src/handlers/mark_notification_read.rs +1 −1 View lib/auth/src/handlers/mark_notification_read.rs
@@ -4,7 +4,7 @@
44use uuid::Uuid;
55
66use crate::errors::ApiError;
7use crate::share::session::require_uid;
7use session::share::session::require_uid;
88use crate::services::AuthService;
99
1010#[utoipa::path(
Modified lib/auth/src/handlers/me.rs lib/auth/src/handlers/me.rs +1 −1 View lib/auth/src/handlers/me.rs
@@ -5,7 +5,7 @@
55use utoipa::ToSchema;
66
77use crate::errors::ApiError;
8use crate::share::session::{require_uid, session_token_key};
8use session::share::session::{require_uid, session_token_key};
99use crate::services::profile::{ProfileDto, UserMeDto};
1010use crate::services::AuthService;
1111
Modified lib/auth/src/handlers/mod.rs lib/auth/src/handlers/mod.rs +0 −10 View lib/auth/src/handlers/mod.rs
@@ -2,7 +2,6 @@
22pub mod active_suspension;
33pub mod add_ssh_key;
44pub mod agreement_page;
5pub mod block_user;
65pub mod cancel_deletion;
76pub mod cancel_email_change;
87pub mod change_password;
@@ -10,20 +9,14 @@
109pub mod create_access_key;
1110pub mod create_report;
1211pub mod delete_access_key;
13pub mod delete_device;
1412pub mod delete_notification;
1513pub mod delete_ssh_key;
1614pub mod deletion_status;
17pub mod follow_user;
1815pub mod forgot_password;
1916pub mod get_preferences;
2017pub mod get_user;
2118pub mod list_access_keys;
2219pub mod list_agreements;
23pub mod list_blocked_users;
24pub mod list_devices;
25pub mod list_followers;
26pub mod list_following;
2720pub mod list_notifications;
2821pub mod list_ssh_keys;
2922pub mod login;
@@ -46,11 +39,8 @@
4639pub mod totp_enable;
4740pub mod totp_setup;
4841pub mod totp_status;
49pub mod unblock_user;
50pub mod unfollow_user;
5142pub mod unread_notifications_count;
5243pub mod update_birthday;
53pub mod update_device;
5444pub mod update_preferences;
5545pub mod update_profile;
5646pub mod verify_email;
Modified lib/auth/src/handlers/recovery_codes.rs lib/auth/src/handlers/recovery_codes.rs +1 −1 View lib/auth/src/handlers/recovery_codes.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::two_factor::RecoveryCodesResp;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/regenerate_recovery_codes.rs lib/auth/src/handlers/regenerate_recovery_codes.rs +1 −1 View lib/auth/src/handlers/regenerate_recovery_codes.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::two_factor::{RecoveryCodesResp, RegenerateRecoveryCodesCmd};
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/request_deletion.rs lib/auth/src/handlers/request_deletion.rs +1 −1 View lib/auth/src/handlers/request_deletion.rs
@@ -5,7 +5,7 @@
55use utoipa::ToSchema;
66
77use crate::errors::ApiError;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99use crate::services::deletion::DeletionDto;
1010use crate::services::AuthService;
1111
Modified lib/auth/src/handlers/request_email_change.rs lib/auth/src/handlers/request_email_change.rs +1 −1 View lib/auth/src/handlers/request_email_change.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::email::{EmailChangeTicketDto, RequestEmailChangeCmd};
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/totp_disable.rs lib/auth/src/handlers/totp_disable.rs +1 −1 View lib/auth/src/handlers/totp_disable.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::two_factor::TotpCodeCmd;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/totp_enable.rs lib/auth/src/handlers/totp_enable.rs +1 −1 View lib/auth/src/handlers/totp_enable.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::two_factor::{RecoveryCodesResp, TotpEnableCmd};
77use crate::services::AuthService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/auth/src/handlers/totp_setup.rs lib/auth/src/handlers/totp_setup.rs +1 −1 View lib/auth/src/handlers/totp_setup.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::two_factor::TotpSetupResp;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/totp_status.rs lib/auth/src/handlers/totp_status.rs +1 −1 View lib/auth/src/handlers/totp_status.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::two_factor::TotpStatusResp;
88use crate::services::AuthService;
99
Deleted lib/auth/src/handlers/unblock_user.rs lib/auth/src/handlers/unblock_user.rs +0 −29
@@ -1,29 +0,0 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4use uuid::Uuid;
5
6use crate::errors::ApiError;
7use crate::share::session::require_uid;
8use crate::services::AuthService;
9
10#[utoipa::path(
11 delete,
12 path = "/users/{uid}/block",
13 tag = "users",
14 params(
15 ("uid" = Uuid, Path, description = "user id to unblock")
16 ),
17 responses(
18 (status = 200, description = "block removed", body = AppResponseData<NoData>)
19 )
20)]
21pub async fn unblock_user(
22 State(service): State<AuthService>,
23 session: Session,
24 Path(blocked_uid): Path<Uuid>,
25) -> Result<AppResponseData<NoData>, ApiError> {
26 let uid = require_uid(&session)?;
27 service.unblock(uid, blocked_uid).await.map_err(ApiError::from)?;
28 Ok(AppResponseData::empty())
29}
No newline at end of file
Deleted lib/auth/src/handlers/unfollow_user.rs lib/auth/src/handlers/unfollow_user.rs +0 −29
@@ -1,29 +0,0 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4use uuid::Uuid;
5
6use crate::errors::ApiError;
7use crate::share::session::require_uid;
8use crate::services::AuthService;
9
10#[utoipa::path(
11 delete,
12 path = "/users/{uid}/follow",
13 tag = "users",
14 params(
15 ("uid" = Uuid, Path, description = "user id to unfollow")
16 ),
17 responses(
18 (status = 200, description = "follow relationship removed", body = AppResponseData<NoData>)
19 )
20)]
21pub async fn unfollow_user(
22 State(service): State<AuthService>,
23 session: Session,
24 Path(followed_uid): Path<Uuid>,
25) -> Result<AppResponseData<NoData>, ApiError> {
26 let uid = require_uid(&session)?;
27 service.unfollow(uid, followed_uid).await.map_err(ApiError::from)?;
28 Ok(AppResponseData::empty())
29}
No newline at end of file
Modified lib/auth/src/handlers/unread_notifications_count.rs lib/auth/src/handlers/unread_notifications_count.rs +1 −1 View lib/auth/src/handlers/unread_notifications_count.rs
@@ -5,7 +5,7 @@
55use utoipa::ToSchema;
66
77use crate::errors::ApiError;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99use crate::services::AuthService;
1010
1111#[derive(Debug, Clone, Serialize, ToSchema)]
Modified lib/auth/src/handlers/update_birthday.rs lib/auth/src/handlers/update_birthday.rs +1 −1 View lib/auth/src/handlers/update_birthday.rs
@@ -6,7 +6,7 @@
66use utoipa::ToSchema;
77
88use crate::errors::ApiError;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010use crate::services::AuthService;
1111
1212#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
Deleted lib/auth/src/handlers/update_device.rs lib/auth/src/handlers/update_device.rs +0 −35
@@ -1,35 +0,0 @@
1use axum::extract::{Path, State};
2use export::rest::{AppRequest, AppRequestData, AppResponseData, NoData};
3use session::Session;
4use uuid::Uuid;
5
6use crate::errors::ApiError;
7use crate::share::session::require_uid;
8use crate::services::devices::UpdateDeviceCmd;
9use crate::services::AuthService;
10
11#[utoipa::path(
12 patch,
13 path = "/auth/devices/{device_id}",
14 tag = "security",
15 params(
16 ("device_id" = Uuid, Path, description = "device id")
17 ),
18 request_body = AppRequestData<UpdateDeviceCmd>,
19 responses(
20 (status = 200, description = "device record updated", body = AppResponseData<NoData>)
21 )
22)]
23pub async fn update_device(
24 State(service): State<AuthService>,
25 session: Session,
26 Path(device_id): Path<Uuid>,
27 payload: AppRequest<UpdateDeviceCmd>,
28) -> Result<AppResponseData<NoData>, ApiError> {
29 let uid = require_uid(&session)?;
30 service
31 .update_device(uid, device_id, payload.into_inner())
32 .await
33 .map_err(ApiError::from)?;
34 Ok(AppResponseData::empty())
35}
No newline at end of file
Modified lib/auth/src/handlers/update_preferences.rs lib/auth/src/handlers/update_preferences.rs +1 −1 View lib/auth/src/handlers/update_preferences.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::preferences::UpdatePreferencesCmd;
88use crate::services::AuthService;
99
Modified lib/auth/src/handlers/update_profile.rs lib/auth/src/handlers/update_profile.rs +1 −1 View lib/auth/src/handlers/update_profile.rs
@@ -3,7 +3,7 @@
33use session::Session;
44
55use crate::errors::ApiError;
6use crate::share::session::require_uid;
6use session::share::session::require_uid;
77use crate::services::profile::UpdateProfileCmd;
88use crate::services::AuthService;
99
Modified lib/auth/src/services/login.rs lib/auth/src/services/login.rs +2 −2 View lib/auth/src/services/login.rs
@@ -262,9 +262,9 @@
262262 avatar_url: Some(user.avatar_url.clone()),
263263 email,
264264 };
265 crate::share::session::apply_login(session, auth_user, user.passwd_version);
265 session::share::session::apply_login(session, auth_user, user.passwd_version);
266266 session.set(
267 &crate::share::session::session_token_key(user.uid),
267 &session::share::session::session_token_key(user.uid),
268268 token_hash,
269269 );
270270
Modified lib/auth/src/services/logout.rs lib/auth/src/services/logout.rs +1 −1 View lib/auth/src/services/logout.rs
@@ -3,7 +3,7 @@
33
44use super::AuthService;
55use crate::errors::AuthError;
6use crate::share::session::session_token_key;
6use session::share::session::session_token_key;
77
88#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
99pub struct LogoutResp {
Modified lib/auth/src/services/mod.rs lib/auth/src/services/mod.rs +31 −1 View lib/auth/src/services/mod.rs
@@ -1,14 +1,19 @@
11use std::sync::Arc;
22
3use async_trait::async_trait;
34use config::AppConfig;
45use export::{AppDatabase, AppRedis, AppState};
6use models::users::user;
7use models::users::user_sessions;
8use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
9use session::share::guard::{SessionGuard, SessionWithUser};
10use session::SessionError;
511
612use crate::errors::AuthError;
713
814pub mod access_keys;
915pub mod agreements;
1016pub mod deletion;
11pub mod devices;
1217pub mod email;
1318pub mod login;
1419pub mod logout;
@@ -60,4 +65,29 @@
6065 .await
6166 .map_err(|error| AuthError::Internal(format!("email send failed: {error}")))
6267 }
68}
69
70#[async_trait]
71impl SessionGuard for AuthService {
72 async fn lookup_session_with_user(
73 &self,
74 token_hash: &str,
75 ) -> Result<Option<SessionWithUser>, SessionError> {
76 let outcome = user_sessions::Entity::find()
77 .filter(user_sessions::Column::TokenHash.eq(token_hash))
78 .find_also_related(user::Entity)
79 .one(self.db().read())
80 .await?;
81 Ok(outcome.and_then(|(row, current)| {
82 current.map(|c| SessionWithUser {
83 user_id: row.user_id,
84 is_revoked: row.is_revoked,
85 expires_at: row.expires_at,
86 is_active: c.is_active,
87 prohibit_login: c.prohibit_login,
88 is_restricted: c.is_restricted,
89 passwd_version: c.passwd_version,
90 })
91 }))
92 }
6393}
No newline at end of file
Modified lib/auth/src/services/users.rs lib/auth/src/services/users.rs +2 −164 View lib/auth/src/services/users.rs
@@ -1,15 +1,10 @@
11use models::users::user;
2use models::users::{user_blocks, user_followers};
3use sea_orm::{
4 ActiveModelTrait, ColumnTrait, Condition, EntityTrait, QueryFilter, QuerySelect, Set,
5 TransactionTrait,
6};
7use time::OffsetDateTime;
2use sea_orm::EntityTrait;
83use uuid::Uuid;
94
105use super::AuthService;
116use crate::errors::AuthError;
12use crate::share::types::{ListQuery, UserPublic};
7use crate::share::types::UserPublic;
138
149impl AuthService {
1510 pub async fn public_user(&self, uid: Uuid) -> Result<UserPublic, AuthError> {
@@ -22,162 +17,5 @@
2217 display_name: user.display_name,
2318 avatar_url: user.avatar_url,
2419 })
25 }
26
27 pub async fn follow(&self, follower_uid: Uuid, followed_uid: Uuid) -> Result<(), AuthError> {
28 if follower_uid == followed_uid {
29 return Err(AuthError::BadRequest(
30 "cannot follow yourself".to_string(),
31 ));
32 }
33 let db = self.db();
34 let followed_exists = user::Entity::find_by_id(followed_uid).one(db.read()).await?;
35 if followed_exists.is_none() {
36 return Err(AuthError::NotFound);
37 }
38 let existing = user_followers::Entity::find()
39 .filter(user_followers::Column::FollowerId.eq(follower_uid))
40 .filter(user_followers::Column::FollowedId.eq(followed_uid))
41 .one(db.write())
42 .await?;
43 if existing.is_some() {
44 return Ok(());
45 }
46 let row = user_followers::ActiveModel {
47 id: Set(Uuid::now_v7()),
48 follower_id: Set(follower_uid),
49 followed_id: Set(followed_uid),
50 created_at: Set(OffsetDateTime::now_utc()),
51 };
52 row.insert(db.write()).await?;
53 Ok(())
54 }
55
56 pub async fn unfollow(&self, follower_uid: Uuid, followed_uid: Uuid) -> Result<(), AuthError> {
57 let db = self.db();
58 user_followers::Entity::delete_many()
59 .filter(user_followers::Column::FollowerId.eq(follower_uid))
60 .filter(user_followers::Column::FollowedId.eq(followed_uid))
61 .exec(db.write())
62 .await?;
63 Ok(())
64 }
65
66 pub async fn followers(&self, uid: Uuid, query: ListQuery) -> Result<Vec<UserPublic>, AuthError> {
67 let (limit, offset) = query.page();
68 let rows = user_followers::Entity::find()
69 .filter(user_followers::Column::FollowedId.eq(uid))
70 .limit(limit)
71 .offset(offset)
72 .all(self.db().read())
73 .await?;
74 let ids: Vec<Uuid> = rows.into_iter().map(|row| row.follower_id).collect();
75 self.load_users_public(&ids).await
76 }
77
78 pub async fn following(&self, uid: Uuid, query: ListQuery) -> Result<Vec<UserPublic>, AuthError> {
79 let (limit, offset) = query.page();
80 let rows = user_followers::Entity::find()
81 .filter(user_followers::Column::FollowerId.eq(uid))
82 .limit(limit)
83 .offset(offset)
84 .all(self.db().read())
85 .await?;
86 let ids: Vec<Uuid> = rows.into_iter().map(|row| row.followed_id).collect();
87 self.load_users_public(&ids).await
88 }
89
90 pub async fn block(&self, blocker_uid: Uuid, blocked_uid: Uuid) -> Result<(), AuthError> {
91 if blocker_uid == blocked_uid {
92 return Err(AuthError::BadRequest("cannot block yourself".to_string()));
93 }
94 let db = self.db();
95 let blocked_exists = user::Entity::find_by_id(blocked_uid).one(db.read()).await?;
96 if blocked_exists.is_none() {
97 return Err(AuthError::NotFound);
98 }
99 let existing = user_blocks::Entity::find()
100 .filter(user_blocks::Column::BlockerId.eq(blocker_uid))
101 .filter(user_blocks::Column::BlockedId.eq(blocked_uid))
102 .one(db.write())
103 .await?;
104 if existing.is_some() {
105 return Ok(());
106 }
107 let now = OffsetDateTime::now_utc();
108 TransactionTrait::transaction(db.primary(), |txn| {
109 Box::pin(async move {
110 let row = user_blocks::ActiveModel {
111 id: Set(Uuid::now_v7()),
112 blocker_id: Set(blocker_uid),
113 blocked_id: Set(blocked_uid),
114 created_at: Set(now),
115 };
116 row.insert(txn).await?;
117
118 user_followers::Entity::delete_many()
119 .filter(
120 Condition::any()
121 .add(
122 Condition::all()
123 .add(user_followers::Column::FollowerId.eq(blocker_uid))
124 .add(user_followers::Column::FollowedId.eq(blocked_uid)),
125 )
126 .add(
127 Condition::all()
128 .add(user_followers::Column::FollowerId.eq(blocked_uid))
129 .add(user_followers::Column::FollowedId.eq(blocker_uid)),
130 ),
131 )
132 .exec(txn)
133 .await?;
134
135 Ok::<(), sea_orm::DbErr>(())
136 })
137 })
138 .await
139 .map_err(AuthError::from)?;
140 Ok(())
141 }
142
143 pub async fn unblock(&self, blocker_uid: Uuid, blocked_uid: Uuid) -> Result<(), AuthError> {
144 let db = self.db();
145 user_blocks::Entity::delete_many()
146 .filter(user_blocks::Column::BlockerId.eq(blocker_uid))
147 .filter(user_blocks::Column::BlockedId.eq(blocked_uid))
148 .exec(db.write())
149 .await?;
150 Ok(())
151 }
152
153 pub async fn blocked_users(&self, uid: Uuid, query: ListQuery) -> Result<Vec<UserPublic>, AuthError> {
154 let (limit, offset) = query.page();
155 let rows = user_blocks::Entity::find()
156 .filter(user_blocks::Column::BlockerId.eq(uid))
157 .limit(limit)
158 .offset(offset)
159 .all(self.db().read())
160 .await?;
161 let ids: Vec<Uuid> = rows.into_iter().map(|row| row.blocked_id).collect();
162 self.load_users_public(&ids).await
163 }
164
165 async fn load_users_public(&self, ids: &[Uuid]) -> Result<Vec<UserPublic>, AuthError> {
166 if ids.is_empty() {
167 return Ok(Vec::new());
168 }
169 let rows = user::Entity::find()
170 .filter(user::Column::Uid.is_in(ids.iter().copied()))
171 .all(self.db().read())
172 .await?;
173 Ok(rows
174 .into_iter()
175 .map(|user| UserPublic {
176 uid: user.uid,
177 username: user.username,
178 display_name: user.display_name,
179 avatar_url: user.avatar_url,
180 })
181 .collect())
18220 }
18321}
No newline at end of file
Modified lib/auth/src/share/guard.rs lib/auth/src/share/guard.rs +5 −37 View lib/auth/src/share/guard.rs
@@ -1,15 +1,10 @@
11use axum::extract::{Request, State};
22use axum::middleware::Next;
3use axum::response::{IntoResponse, Response};
4use models::users::user_sessions;
5use models::users::user;
6use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
7use session::{Session, SessionUser, SessionUserMut};
8use time::OffsetDateTime;
3use axum::response::Response;
4use session::Session;
5use session::share::guard::session_guard;
96
10use crate::errors::{ApiError, AuthError};
117use crate::services::AuthService;
12use crate::share::session::{pwd_version_matches, session_token_key};
138
149pub async fn auth_guard(
1510 State(service): State<AuthService>,
@@ -17,32 +12,5 @@
1712 request: Request,
1813 next: Next,
1914) -> Response {
20 let Some(uid) = session.uid() else {
21 return ApiError::from(AuthError::Unauthorized).into_response();
22 };
23 let Some(token_hash) = session.get::<String>(&session_token_key(uid)) else {
24 return ApiError::from(AuthError::Unauthorized).into_response();
25 };
26 let outcome = user_sessions::Entity::find()
27 .filter(user_sessions::Column::TokenHash.eq(&token_hash))
28 .find_also_related(user::Entity)
29 .one(service.db().read())
30 .await;
31 let authorized = match outcome {
32 Ok(Some((row, Some(current)))) => {
33 !row.is_revoked
34 && row.expires_at > OffsetDateTime::now_utc()
35 && current.is_active
36 && !current.prohibit_login
37 && !current.is_restricted
38 && pwd_version_matches(&session, current.passwd_version)
39 }
40 Ok(_) => false,
41 Err(error) => return ApiError::from(AuthError::from(error)).into_response(),
42 };
43 if !authorized {
44 session.logout_user(uid);
45 return ApiError::from(AuthError::Unauthorized).into_response();
46 }
47 next.run(request).await
48}
No newline at end of file
15 session_guard::<AuthService>(State(service), session, request, next).await
16}
Modified lib/auth/src/share/mod.rs lib/auth/src/share/mod.rs +0 −1 View lib/auth/src/share/mod.rs
@@ -2,7 +2,6 @@
22pub mod guard;
33pub mod rate;
44pub mod redis;
5pub mod session;
65pub mod totp;
76pub mod types;
87pub mod validate;
Deleted lib/auth/src/share/session.rs lib/auth/src/share/session.rs +0 −41
@@ -1,41 +0,0 @@
1use session::{AuthUser, Session, SessionUser, SessionUserMut};
2use uuid::Uuid;
3
4use crate::errors::{ApiError, AuthError};
5
6pub const PWD_VERSION_KEY: &str = "auth:pwd_version";
7
8pub fn session_token_key(uid: Uuid) -> String {
9 format!("auth:token_hash:{uid}")
10}
11
12pub fn require_uid(session: &Session) -> Result<Uuid, Box<ApiError>> {
13 match session.uid() {
14 Some(uid) => Ok(uid),
15 None => Err(Box::new(ApiError::from(AuthError::Unauthorized))),
16 }
17}
18
19pub fn apply_login(session: &Session, user: AuthUser, passwd_version: Option<i64>) {
20 session.login_user(user);
21 session.set(PWD_VERSION_KEY, passwd_version.unwrap_or(0));
22}
23
24pub fn pwd_version_matches(session: &Session, current: Option<i64>) -> bool {
25 let stored = session.get::<i64>(PWD_VERSION_KEY);
26 match (stored, current) {
27 (Some(stored_ver), Some(curr_ver)) => stored_ver == curr_ver,
28 (None, None) => true,
29 _ => false,
30 }
31}
32
33pub fn validate_session_pwd_version(session: &Session, current_passwd_version: Option<i64>) -> Result<(), AuthError> {
34 if !pwd_version_matches(session, current_passwd_version) {
35 if let Some(uid) = session.uid() {
36 session.logout_user(uid);
37 }
38 return Err(AuthError::Unauthorized);
39 }
40 Ok(())
41}
No newline at end of file
Modified lib/auth/src/errors.rs lib/auth/src/errors.rs +14 −0 View lib/auth/src/errors.rs
@@ -179,6 +179,20 @@
179179 }
180180}
181181
182impl From<session::SessionError> for ApiError {
183 fn from(error: session::SessionError) -> Self {
184 match error {
185 session::SessionError::Unauthorized => {
186 Self::Unauthorized(Self::payload(401, "unauthorized"))
187 }
188 session::SessionError::Database(message) => {
189 tracing::warn!(error = %message, "auth handler failed");
190 Self::Internal(Self::payload(500, "internal server error"))
191 }
192 }
193 }
194}
195
182196impl From<AppResponseData<()>> for ApiError {
183197 fn from(_error: AppResponseData<()>) -> Self {
184198 Self::BadRequest(Self::payload(400, "bad request"))
Modified lib/auth/src/openapi.rs lib/auth/src/openapi.rs +0 −13 View lib/auth/src/openapi.rs
@@ -18,7 +18,6 @@
1818use crate::services::access_keys::{AccessKeyDto, CreateAccessKeyCmd, CreateAccessKeyResp};
1919use crate::services::agreements::AcceptAgreementResp;
2020use crate::services::deletion::DeletionDto;
21use crate::services::devices::{DeviceDto, UpdateDeviceCmd};
2221use crate::services::email::{
2322 EmailChangeTicketDto, ReclaimCmd, ReclaimResp, RequestEmailChangeCmd, ResendCodeCmd,
2423 ResendCodeResp, VerifyEmailCmd, VerifyEmailResp,
@@ -48,7 +47,6 @@
4847 handlers::accept_agreement::accept_agreement,
4948 handlers::active_suspension::active_suspension,
5049 handlers::add_ssh_key::add_ssh_key,
51 handlers::block_user::block_user,
5250 handlers::cancel_deletion::cancel_deletion,
5351 handlers::cancel_email_change::cancel_email_change,
5452 handlers::change_password::change_password,
@@ -56,20 +54,14 @@
5654 handlers::create_access_key::create_access_key,
5755 handlers::create_report::create_report,
5856 handlers::delete_access_key::delete_access_key,
59 handlers::delete_device::delete_device,
6057 handlers::delete_notification::delete_notification,
6158 handlers::delete_ssh_key::delete_ssh_key,
6259 handlers::deletion_status::deletion_status,
63 handlers::follow_user::follow_user,
6460 handlers::forgot_password::forgot_password,
6561 handlers::get_preferences::get_preferences,
6662 handlers::get_user::get_user,
6763 handlers::list_access_keys::list_access_keys,
6864 handlers::list_agreements::list_agreements,
69 handlers::list_blocked_users::list_blocked_users,
70 handlers::list_devices::list_devices,
71 handlers::list_followers::list_followers,
72 handlers::list_following::list_following,
7365 handlers::list_notifications::list_notifications,
7466 handlers::list_ssh_keys::list_ssh_keys,
7567 handlers::login::login,
@@ -91,11 +83,8 @@
9183 handlers::totp_enable::totp_enable,
9284 handlers::totp_setup::totp_setup,
9385 handlers::totp_status::totp_status,
94 handlers::unblock_user::unblock_user,
95 handlers::unfollow_user::unfollow_user,
9686 handlers::unread_notifications_count::unread_notifications_count,
9787 handlers::update_birthday::update_birthday,
98 handlers::update_device::update_device,
9988 handlers::update_preferences::update_preferences,
10089 handlers::update_profile::update_profile,
10190 handlers::verify_email::verify_email,
@@ -130,8 +119,6 @@
130119 TotpEnableCmd,
131120 RegenerateRecoveryCodesCmd,
132121 RecoveryCodesResp,
133 DeviceDto,
134 UpdateDeviceCmd,
135122 CreateAccessKeyCmd,
136123 AccessKeyDto,
137124 CreateAccessKeyResp,
Modified lib/auth/src/routes.rs lib/auth/src/routes.rs +2 −22 View lib/auth/src/routes.rs
@@ -1,12 +1,11 @@
11use axum::middleware;
2use axum::routing::{delete, get, patch, post, put};
2use axum::routing::{delete, get, post, put};
33use axum::Router;
44
55use crate::handlers::accept_agreement::accept_agreement;
66use crate::handlers::active_suspension::active_suspension;
77use crate::handlers::add_ssh_key::add_ssh_key;
88use crate::handlers::agreement_page::agreement_page;
9use crate::handlers::block_user::block_user;
109use crate::handlers::cancel_deletion::cancel_deletion;
1110use crate::handlers::cancel_email_change::cancel_email_change;
1211use crate::handlers::change_password::change_password;
@@ -14,20 +13,14 @@
1413use crate::handlers::create_access_key::create_access_key;
1514use crate::handlers::create_report::create_report;
1615use crate::handlers::delete_access_key::delete_access_key;
17use crate::handlers::delete_device::delete_device;
1816use crate::handlers::delete_notification::delete_notification;
1917use crate::handlers::delete_ssh_key::delete_ssh_key;
2018use crate::handlers::deletion_status::deletion_status;
21use crate::handlers::follow_user::follow_user;
2219use crate::handlers::forgot_password::forgot_password;
2320use crate::handlers::get_preferences::get_preferences;
2421use crate::handlers::get_user::get_user;
2522use crate::handlers::list_access_keys::list_access_keys;
2623use crate::handlers::list_agreements::list_agreements;
27use crate::handlers::list_blocked_users::list_blocked_users;
28use crate::handlers::list_devices::list_devices;
29use crate::handlers::list_followers::list_followers;
30use crate::handlers::list_following::list_following;
3124use crate::handlers::list_notifications::list_notifications;
3225use crate::handlers::list_ssh_keys::list_ssh_keys;
3326use crate::handlers::login::login;
@@ -50,11 +43,8 @@
5043use crate::handlers::totp_enable::totp_enable;
5144use crate::handlers::totp_setup::totp_setup;
5245use crate::handlers::totp_status::totp_status;
53use crate::handlers::unblock_user::unblock_user;
54use crate::handlers::unfollow_user::unfollow_user;
5546use crate::handlers::unread_notifications_count::unread_notifications_count;
5647use crate::handlers::update_birthday::update_birthday;
57use crate::handlers::update_device::update_device;
5848use crate::handlers::update_preferences::update_preferences;
5949use crate::handlers::update_profile::update_profile;
6050use crate::handlers::verify_email::verify_email;
@@ -78,9 +68,7 @@
7868 .route("/auth/password/reset/page", get(reset_password_page))
7969 .route("/auth/agreements", get(list_agreements))
8070 .route("/auth/agreements/{key}/page", get(agreement_page))
81 .route("/users/{uid}", get(get_user))
82 .route("/users/{uid}/followers", get(list_followers))
83 .route("/users/{uid}/following", get(list_following));
71 .route("/users/{uid}", get(get_user));
8472
8573 let authed = Router::new()
8674 .route("/auth/email/change", post(request_email_change))
@@ -95,11 +83,6 @@
9583 "/auth/2fa/recovery-codes",
9684 get(recovery_codes).post(regenerate_recovery_codes),
9785 )
98 .route("/auth/devices", get(list_devices))
99 .route(
100 "/auth/devices/{device_id}",
101 patch(update_device).delete(delete_device),
102 )
10386 .route(
10487 "/auth/access-keys",
10588 get(list_access_keys).post(create_access_key),
@@ -114,9 +97,6 @@
11497 get(get_preferences).patch(update_preferences),
11598 )
11699 .route("/auth/agreements/{key}", put(accept_agreement))
117 .route("/users/{uid}/follow", put(follow_user).delete(unfollow_user))
118 .route("/users/{uid}/block", put(block_user).delete(unblock_user))
119 .route("/users/blocks", get(list_blocked_users))
120100 .route("/notifications", get(list_notifications))
121101 .route(
122102 "/notifications/unread-count",
Modified lib/auth/Cargo.toml lib/auth/Cargo.toml +1 −0 View lib/auth/Cargo.toml
@@ -4,6 +4,7 @@
44edition.workspace = true
55
66[dependencies]
7async-trait = { workspace = true }
78config = { workspace = true }
89session = { workspace = true }
910export = { workspace = true }
Modified lib/issues/src/handlers/boards/create_board.rs lib/issues/src/handlers/boards/create_board.rs +1 −1 View lib/issues/src/handlers/boards/create_board.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::boards::{BoardDto, CreateBoardCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99use space::services::spaces::SpaceNamePath;
1010
1111#[utoipa::path(
Modified lib/issues/src/handlers/boards/delete_board.rs lib/issues/src/handlers/boards/delete_board.rs +1 −1 View lib/issues/src/handlers/boards/delete_board.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::boards::BoardPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/boards/get_board.rs lib/issues/src/handlers/boards/get_board.rs +1 −1 View lib/issues/src/handlers/boards/get_board.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::boards::{BoardDto, BoardPath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/boards/list_boards.rs lib/issues/src/handlers/boards/list_boards.rs +1 −1 View lib/issues/src/handlers/boards/list_boards.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::boards::{BoardPage, ListBoardQuery};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99use space::services::spaces::SpaceNamePath;
1010
1111#[utoipa::path(
Modified lib/issues/src/handlers/boards/update_board.rs lib/issues/src/handlers/boards/update_board.rs +1 −1 View lib/issues/src/handlers/boards/update_board.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::boards::{BoardDto, BoardPath, UpdateBoardCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/issues/src/handlers/comments/create_comment.rs lib/issues/src/handlers/comments/create_comment.rs +1 −1 View lib/issues/src/handlers/comments/create_comment.rs
@@ -6,7 +6,7 @@
66use crate::services::comments::{CommentDto, CreateCommentCmd};
77use crate::services::issues::IssuePath;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/comments/delete_comment.rs lib/issues/src/handlers/comments/delete_comment.rs +1 −1 View lib/issues/src/handlers/comments/delete_comment.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::comments::CommentPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/comments/get_comment.rs lib/issues/src/handlers/comments/get_comment.rs +1 −1 View lib/issues/src/handlers/comments/get_comment.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::comments::{CommentDto, CommentPath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/comments/list_comments.rs lib/issues/src/handlers/comments/list_comments.rs +1 −1 View lib/issues/src/handlers/comments/list_comments.rs
@@ -6,7 +6,7 @@
66use crate::services::comments::{CommentPage, ListCommentQuery};
77use crate::services::issues::IssuePath;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/comments/update_comment.rs lib/issues/src/handlers/comments/update_comment.rs +1 −1 View lib/issues/src/handlers/comments/update_comment.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::comments::{CommentDto, CommentPath, UpdateCommentCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/issues/src/handlers/content_history/list_content_history.rs lib/issues/src/handlers/content_history/list_content_history.rs +1 −1 View lib/issues/src/handlers/content_history/list_content_history.rs
@@ -7,7 +7,7 @@
77 ContentHistoryPage, ContentHistoryPath, ListContentHistoryQuery,
88};
99use crate::services::service::IssueService;
10use crate::share::session::require_uid;
10use session::share::session::require_uid;
1111
1212#[utoipa::path(
1313 get,
Modified lib/issues/src/handlers/dependencies/create_dependency.rs lib/issues/src/handlers/dependencies/create_dependency.rs +1 −1 View lib/issues/src/handlers/dependencies/create_dependency.rs
@@ -6,7 +6,7 @@
66use crate::services::dependencies::{CreateDependencyCmd, DependencyDto};
77use crate::services::issues::IssuePath;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/dependencies/delete_dependency.rs lib/issues/src/handlers/dependencies/delete_dependency.rs +1 −1 View lib/issues/src/handlers/dependencies/delete_dependency.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::dependencies::DependencyPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/dependencies/list_dependencies.rs lib/issues/src/handlers/dependencies/list_dependencies.rs +1 −1 View lib/issues/src/handlers/dependencies/list_dependencies.rs
@@ -6,7 +6,7 @@
66use crate::services::dependencies::DependencyDto;
77use crate::services::issues::IssuePath;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/events/list_events.rs lib/issues/src/handlers/events/list_events.rs +1 −1 View lib/issues/src/handlers/events/list_events.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::events::{EventPage, EventPath, ListEventQuery};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/issue_users/list_issue_users.rs lib/issues/src/handlers/issue_users/list_issue_users.rs +1 −1 View lib/issues/src/handlers/issue_users/list_issue_users.rs
@@ -6,7 +6,7 @@
66use crate::services::issue_users::{IssueUserPage, ListIssueUserQuery};
77use crate::services::issues::IssuePath;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/issue_users/update_issue_user.rs lib/issues/src/handlers/issue_users/update_issue_user.rs +1 −1 View lib/issues/src/handlers/issue_users/update_issue_user.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::issue_users::{IssueUserDto, IssueUserPath, UpdateIssueUserCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/issues/src/handlers/issues/close_issue.rs lib/issues/src/handlers/issues/close_issue.rs +1 −1 View lib/issues/src/handlers/issues/close_issue.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::issues::{IssueDto, IssuePath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/issues/src/handlers/issues/create_issue.rs lib/issues/src/handlers/issues/create_issue.rs +1 −1 View lib/issues/src/handlers/issues/create_issue.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::issues::{CreateIssueCmd, IssueDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/issues/delete_issue.rs lib/issues/src/handlers/issues/delete_issue.rs +1 −1 View lib/issues/src/handlers/issues/delete_issue.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::issues::IssuePath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/issues/get_issue.rs lib/issues/src/handlers/issues/get_issue.rs +1 −1 View lib/issues/src/handlers/issues/get_issue.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::issues::{IssueDto, IssuePath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/issues/list_issues.rs lib/issues/src/handlers/issues/list_issues.rs +1 −1 View lib/issues/src/handlers/issues/list_issues.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::issues::{IssuePage, ListIssueQuery};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/issues/reopen_issue.rs lib/issues/src/handlers/issues/reopen_issue.rs +1 −1 View lib/issues/src/handlers/issues/reopen_issue.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::issues::{IssueDto, IssuePath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/issues/src/handlers/issues/update_issue.rs lib/issues/src/handlers/issues/update_issue.rs +1 −1 View lib/issues/src/handlers/issues/update_issue.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::issues::{IssueDto, IssuePath, UpdateIssueCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/issues/src/handlers/labels/bind_label.rs lib/issues/src/handlers/labels/bind_label.rs +1 −1 View lib/issues/src/handlers/labels/bind_label.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::labels::IssueLabelPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/issues/src/handlers/labels/create_label.rs lib/issues/src/handlers/labels/create_label.rs +1 −1 View lib/issues/src/handlers/labels/create_label.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::labels::{CreateLabelCmd, LabelDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/labels/delete_label.rs lib/issues/src/handlers/labels/delete_label.rs +1 −1 View lib/issues/src/handlers/labels/delete_label.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::labels::LabelPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/labels/get_label.rs lib/issues/src/handlers/labels/get_label.rs +1 −1 View lib/issues/src/handlers/labels/get_label.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::labels::{LabelDto, LabelPath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/labels/list_labels.rs lib/issues/src/handlers/labels/list_labels.rs +1 −1 View lib/issues/src/handlers/labels/list_labels.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::labels::{LabelPage, ListLabelQuery};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/labels/list_labels_for_issue.rs lib/issues/src/handlers/labels/list_labels_for_issue.rs +1 −1 View lib/issues/src/handlers/labels/list_labels_for_issue.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::labels::LabelDto;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/labels/unbind_label.rs lib/issues/src/handlers/labels/unbind_label.rs +1 −1 View lib/issues/src/handlers/labels/unbind_label.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::labels::IssueLabelPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/labels/update_label.rs lib/issues/src/handlers/labels/update_label.rs +1 −1 View lib/issues/src/handlers/labels/update_label.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::labels::{LabelDto, LabelPath, UpdateLabelCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/issues/src/handlers/members/create_member.rs lib/issues/src/handlers/members/create_member.rs +1 −1 View lib/issues/src/handlers/members/create_member.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::members::{CreateIssueMemberCmd, IssueMemberDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/members/delete_member.rs lib/issues/src/handlers/members/delete_member.rs +1 −1 View lib/issues/src/handlers/members/delete_member.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::members::IssueMemberPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/members/list_members.rs lib/issues/src/handlers/members/list_members.rs +1 −1 View lib/issues/src/handlers/members/list_members.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::members::{IssueMemberPage, ListIssueMemberQuery};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/milestones/create_milestone.rs lib/issues/src/handlers/milestones/create_milestone.rs +1 −1 View lib/issues/src/handlers/milestones/create_milestone.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::milestones::{CreateMilestoneCmd, MilestoneDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/milestones/delete_milestone.rs lib/issues/src/handlers/milestones/delete_milestone.rs +1 −1 View lib/issues/src/handlers/milestones/delete_milestone.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::milestones::MilestonePath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/milestones/get_milestone.rs lib/issues/src/handlers/milestones/get_milestone.rs +1 −1 View lib/issues/src/handlers/milestones/get_milestone.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::milestones::{MilestoneDto, MilestonePath};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/milestones/list_milestones.rs lib/issues/src/handlers/milestones/list_milestones.rs +1 −1 View lib/issues/src/handlers/milestones/list_milestones.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::milestones::{ListMilestoneQuery, MilestonePage};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/milestones/update_milestone.rs lib/issues/src/handlers/milestones/update_milestone.rs +1 −1 View lib/issues/src/handlers/milestones/update_milestone.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::milestones::{MilestoneDto, MilestonePath, UpdateMilestoneCmd};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/issues/src/handlers/pins/create_pin.rs lib/issues/src/handlers/pins/create_pin.rs +1 −1 View lib/issues/src/handlers/pins/create_pin.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::pins::{CreatePinCmd, PinDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/pins/delete_pin.rs lib/issues/src/handlers/pins/delete_pin.rs +1 −1 View lib/issues/src/handlers/pins/delete_pin.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::pins::PinPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/pins/list_pins.rs lib/issues/src/handlers/pins/list_pins.rs +1 −1 View lib/issues/src/handlers/pins/list_pins.rs
@@ -6,7 +6,7 @@
66use crate::services::boards::BoardPath;
77use crate::services::pins::PinDto;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/reactions/create_comment_reaction.rs lib/issues/src/handlers/reactions/create_comment_reaction.rs +1 −1 View lib/issues/src/handlers/reactions/create_comment_reaction.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::reactions::{CommentReactionPath, CreateReactionCmd, ReactionDto};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/issues/src/handlers/reactions/create_reaction.rs lib/issues/src/handlers/reactions/create_reaction.rs +1 −1 View lib/issues/src/handlers/reactions/create_reaction.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::reactions::{CreateReactionCmd, ReactionDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/reactions/delete_reaction.rs lib/issues/src/handlers/reactions/delete_reaction.rs +1 −1 View lib/issues/src/handlers/reactions/delete_reaction.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::reactions::ReactionPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/reactions/list_comment_reactions.rs lib/issues/src/handlers/reactions/list_comment_reactions.rs +1 −1 View lib/issues/src/handlers/reactions/list_comment_reactions.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::reactions::{CommentReactionPath, ReactionAggDto};
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/reactions/list_reactions.rs lib/issues/src/handlers/reactions/list_reactions.rs +1 −1 View lib/issues/src/handlers/reactions/list_reactions.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::reactions::ReactionAggDto;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/repo_relations/create_repo_relation.rs lib/issues/src/handlers/repo_relations/create_repo_relation.rs +1 −1 View lib/issues/src/handlers/repo_relations/create_repo_relation.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::repo_relations::{CreateRepoRelCmd, RepoRelDto};
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/issues/src/handlers/repo_relations/delete_repo_relation.rs lib/issues/src/handlers/repo_relations/delete_repo_relation.rs +1 −1 View lib/issues/src/handlers/repo_relations/delete_repo_relation.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::repo_relations::RepoRelPath;
77use crate::services::service::IssueService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/repo_relations/list_repo_relations.rs lib/issues/src/handlers/repo_relations/list_repo_relations.rs +1 −1 View lib/issues/src/handlers/repo_relations/list_repo_relations.rs
@@ -6,7 +6,7 @@
66use crate::services::issues::IssuePath;
77use crate::services::repo_relations::RepoRelDto;
88use crate::services::service::IssueService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/issues/src/handlers/stopwatch/get_stopwatch.rs lib/issues/src/handlers/stopwatch/get_stopwatch.rs +1 −1 View lib/issues/src/handlers/stopwatch/get_stopwatch.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::stopwatch::{StopwatchDto, StopwatchPath};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/stopwatch/start_stopwatch.rs lib/issues/src/handlers/stopwatch/start_stopwatch.rs +1 −1 View lib/issues/src/handlers/stopwatch/start_stopwatch.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::stopwatch::{StopwatchDto, StopwatchPath};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/issues/src/handlers/stopwatch/stop_stopwatch.rs lib/issues/src/handlers/stopwatch/stop_stopwatch.rs +1 −1 View lib/issues/src/handlers/stopwatch/stop_stopwatch.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::stopwatch::StopwatchPath;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/issues/src/handlers/tracked_time/list_tracked_time.rs lib/issues/src/handlers/tracked_time/list_tracked_time.rs +1 −1 View lib/issues/src/handlers/tracked_time/list_tracked_time.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::tracked_time::{ListTrackedTimeQuery, TrackedTimePage, TrackedTimePath};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/watches/delete_watch.rs lib/issues/src/handlers/watches/delete_watch.rs +1 −1 View lib/issues/src/handlers/watches/delete_watch.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::watches::WatchPath;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/issues/src/handlers/watches/get_watch.rs lib/issues/src/handlers/watches/get_watch.rs +1 −1 View lib/issues/src/handlers/watches/get_watch.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::watches::{WatchDto, WatchPath};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/issues/src/handlers/watches/upsert_watch.rs lib/issues/src/handlers/watches/upsert_watch.rs +1 −1 View lib/issues/src/handlers/watches/upsert_watch.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::IssueService;
77use crate::services::watches::{UpsertWatchCmd, WatchDto, WatchPath};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 put,
Modified lib/issues/src/services/service.rs lib/issues/src/services/service.rs +29 −0 View lib/issues/src/services/service.rs
@@ -1,6 +1,7 @@
11use std::collections::{HashMap, HashSet};
22use std::sync::Arc;
33
4use async_trait::async_trait;
45use config::AppConfig;
56use export::database::AppDatabase;
67use email::EmailService;
@@ -11,9 +12,12 @@
1112use models::users::user;
1213use models::users::user_emails;
1314use models::users::user_notifications::{self, NotificationType};
15use models::users::user_sessions;
1416use sea_orm::{
1517 ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, QueryFilter, Set,
1618};
19use session::share::guard::{SessionGuard, SessionWithUser};
20use session::SessionError;
1721use space::services::spaces::UserBriefDto;
1822use time::OffsetDateTime;
1923use uuid::Uuid;
@@ -218,3 +222,28 @@
218222 .map_err(|error| IssueError::Internal(format!("email send failed: {error}")))
219223 }
220224}
225
226#[async_trait]
227impl SessionGuard for IssueService {
228 async fn lookup_session_with_user(
229 &self,
230 token_hash: &str,
231 ) -> Result<Option<SessionWithUser>, SessionError> {
232 let outcome = user_sessions::Entity::find()
233 .filter(user_sessions::Column::TokenHash.eq(token_hash))
234 .find_also_related(user::Entity)
235 .one(self.db().read())
236 .await?;
237 Ok(outcome.and_then(|(row, current)| {
238 current.map(|c| SessionWithUser {
239 user_id: row.user_id,
240 is_revoked: row.is_revoked,
241 expires_at: row.expires_at,
242 is_active: c.is_active,
243 prohibit_login: c.prohibit_login,
244 is_restricted: c.is_restricted,
245 passwd_version: c.passwd_version,
246 })
247 }))
248 }
249}
Modified lib/issues/src/share/guard.rs lib/issues/src/share/guard.rs +4 −37 View lib/issues/src/share/guard.rs
@@ -1,15 +1,10 @@
11use axum::extract::{Request, State};
22use axum::middleware::Next;
3use axum::response::{IntoResponse, Response};
4use models::users::user;
5use models::users::user_sessions;
6use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
7use session::{Session, SessionUser, SessionUserMut};
8use time::OffsetDateTime;
3use axum::response::Response;
4use session::Session;
5use session::share::guard::session_guard;
96
10use crate::errors::{ApiError, IssueError};
117use crate::services::service::IssueService;
12use crate::share::session::{pwd_version_matches, session_token_key};
138
149pub async fn issue_guard(
1510 State(service): State<IssueService>,
@@ -17,33 +12,5 @@
1712 request: Request,
1813 next: Next,
1914) -> Response {
20 let Some(uid) = session.uid() else {
21 return ApiError::from(IssueError::Unauthorized).into_response();
22 };
23 let Some(token_hash) = session.get::<String>(&session_token_key(uid)) else {
24 return ApiError::from(IssueError::Unauthorized).into_response();
25 };
26 let outcome = user_sessions::Entity::find()
27 .filter(user_sessions::Column::TokenHash.eq(&token_hash))
28 .find_also_related(user::Entity)
29 .one(service.db().read())
30 .await;
31 let authorized = match outcome {
32 Ok(Some((row, Some(current)))) => {
33 !row.is_revoked
34 && row.user_id == uid
35 && row.expires_at > OffsetDateTime::now_utc()
36 && current.is_active
37 && !current.prohibit_login
38 && !current.is_restricted
39 && pwd_version_matches(&session, current.passwd_version)
40 }
41 Ok(_) => false,
42 Err(error) => return ApiError::from(IssueError::from(error)).into_response(),
43 };
44 if !authorized {
45 session.logout_user(uid);
46 return ApiError::from(IssueError::Unauthorized).into_response();
47 }
48 next.run(request).await
15 session_guard::<IssueService>(State(service), session, request, next).await
4916}
Modified lib/issues/src/share/mod.rs lib/issues/src/share/mod.rs +1 −2 View lib/issues/src/share/mod.rs
@@ -1,4 +1,3 @@
11pub mod authz;
22pub mod guard;
3pub mod lookup;
4pub mod session;
3pub mod lookup;
No newline at end of file
Deleted lib/issues/src/share/session.rs lib/issues/src/share/session.rs +0 −25
@@ -1,25 +0,0 @@
1use session::{Session, SessionUser};
2use uuid::Uuid;
3
4use crate::errors::{ApiError, IssueError};
5
6pub const PWD_VERSION_KEY: &str = "auth:pwd_version";
7
8pub fn session_token_key(uid: Uuid) -> String {
9 format!("auth:token_hash:{uid}")
10}
11
12pub fn require_uid(session: &Session) -> Result<Uuid, Box<ApiError>> {
13 session
14 .uid()
15 .ok_or_else(|| Box::new(ApiError::from(IssueError::Unauthorized)))
16}
17
18pub fn pwd_version_matches(session: &Session, current: Option<i64>) -> bool {
19 let session_ver: Option<i64> = session.get(PWD_VERSION_KEY);
20 match (session_ver, current) {
21 (None, None) => true,
22 (Some(s), Some(c)) => s == c,
23 _ => false,
24 }
25}
Modified lib/issues/src/errors.rs lib/issues/src/errors.rs +14 −0 View lib/issues/src/errors.rs
@@ -157,6 +157,20 @@
157157 }
158158}
159159
160impl From<session::SessionError> for ApiError {
161 fn from(error: session::SessionError) -> Self {
162 match error {
163 session::SessionError::Unauthorized => {
164 Self::Unauthorized(Self::payload(401, "unauthorized"))
165 }
166 session::SessionError::Database(message) => {
167 tracing::warn!(error = %message, "issues handler failed");
168 Self::Internal(Self::payload(500, "internal server error"))
169 }
170 }
171 }
172}
173
160174impl From<AppResponseData<()>> for ApiError {
161175 fn from(_error: AppResponseData<()>) -> Self {
162176 Self::BadRequest(Self::payload(400, "bad request"))
Modified lib/issues/Cargo.toml lib/issues/Cargo.toml +1 −0 View lib/issues/Cargo.toml
@@ -4,6 +4,7 @@
44edition.workspace = true
55
66[dependencies]
7async-trait = { workspace = true }
78config = { workspace = true }
89export = { workspace = true }
910email = { workspace = true }
Modified lib/space/src/handlers/accept_invite.rs lib/space/src/handlers/accept_invite.rs +1 −1 View lib/space/src/handlers/accept_invite.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::invites::AcceptInviteCmd;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/space/src/handlers/add_member.rs lib/space/src/handlers/add_member.rs +1 −1 View lib/space/src/handlers/add_member.rs
@@ -6,7 +6,7 @@
66use crate::services::members::{AddMemberCmd, MemberDto};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/assign_group.rs lib/space/src/handlers/assign_group.rs +1 −1 View lib/space/src/handlers/assign_group.rs
@@ -6,7 +6,7 @@
66use crate::handlers::get_member::MemberPath;
77use crate::services::groups::AssignGroupCmd;
88use crate::services::service::SpaceService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/ban_user.rs lib/space/src/handlers/ban_user.rs +1 −1 View lib/space/src/handlers/ban_user.rs
@@ -6,7 +6,7 @@
66use crate::services::bans::{BanDto, BanUserCmd};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/create_dir_node.rs lib/space/src/handlers/create_dir_node.rs +1 −1 View lib/space/src/handlers/create_dir_node.rs
@@ -6,7 +6,7 @@
66use crate::services::dir::{CreateDirCmd, DirNodeDto};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/create_group.rs lib/space/src/handlers/create_group.rs +1 −1 View lib/space/src/handlers/create_group.rs
@@ -6,7 +6,7 @@
66use crate::services::groups::{CreateGroupCmd, GroupDto};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/create_invite.rs lib/space/src/handlers/create_invite.rs +1 −1 View lib/space/src/handlers/create_invite.rs
@@ -6,7 +6,7 @@
66use crate::services::invites::{CreateInviteCmd, InviteDto};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/create_join_rule.rs lib/space/src/handlers/create_join_rule.rs +1 −1 View lib/space/src/handlers/create_join_rule.rs
@@ -6,7 +6,7 @@
66use crate::services::join_rules::{CreateJoinRuleCmd, JoinRuleDto};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/create_space.rs lib/space/src/handlers/create_space.rs +1 −1 View lib/space/src/handlers/create_space.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::SpaceService;
77use crate::services::spaces::{CreateSpaceCmd, SpaceDto};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/space/src/handlers/delete_group.rs lib/space/src/handlers/delete_group.rs +1 −1 View lib/space/src/handlers/delete_group.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::get_group::GroupPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/delete_join_rule.rs lib/space/src/handlers/delete_join_rule.rs +1 −1 View lib/space/src/handlers/delete_join_rule.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::join_rules::JoinRulePath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/delete_space.rs lib/space/src/handlers/delete_space.rs +1 −1 View lib/space/src/handlers/delete_space.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::SpaceService;
77use crate::services::spaces::SpaceNamePath;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/delete_space_avatar.rs lib/space/src/handlers/delete_space_avatar.rs +1 −1 View lib/space/src/handlers/delete_space_avatar.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::SpaceService;
77use crate::services::spaces::SpaceNamePath;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/delete_space_image.rs lib/space/src/handlers/delete_space_image.rs +1 −1 View lib/space/src/handlers/delete_space_image.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::images::SpaceImageKindPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/get_ban.rs lib/space/src/handlers/get_ban.rs +1 −1 View lib/space/src/handlers/get_ban.rs
@@ -6,7 +6,7 @@
66use crate::handlers::get_member::MemberPath;
77use crate::services::bans::BanDto;
88use crate::services::service::SpaceService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/get_member.rs lib/space/src/handlers/get_member.rs +1 −1 View lib/space/src/handlers/get_member.rs
@@ -8,7 +8,7 @@
88use crate::errors::ApiError;
99use crate::services::members::MemberDto;
1010use crate::services::service::SpaceService;
11use crate::share::session::require_uid;
11use session::share::session::require_uid;
1212
1313#[derive(Debug, Clone, Deserialize, IntoParams, ToSchema)]
1414pub struct MemberPath {
Modified lib/space/src/handlers/get_space_dir_tree.rs lib/space/src/handlers/get_space_dir_tree.rs +1 −1 View lib/space/src/handlers/get_space_dir_tree.rs
@@ -6,7 +6,7 @@
66use crate::services::dir::DirNodeDto;
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/join_group_self.rs lib/space/src/handlers/join_group_self.rs +1 −1 View lib/space/src/handlers/join_group_self.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::get_group::GroupPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/space/src/handlers/leave_group_self.rs lib/space/src/handlers/leave_group_self.rs +1 −1 View lib/space/src/handlers/leave_group_self.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::get_group::GroupPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/list_bans.rs lib/space/src/handlers/list_bans.rs +1 −1 View lib/space/src/handlers/list_bans.rs
@@ -6,7 +6,7 @@
66use crate::services::bans::BanPage;
77use crate::services::service::SpaceService;
88use crate::services::spaces::{PageQuery, SpaceNamePath};
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/list_dir_group_overwrites.rs lib/space/src/handlers/list_dir_group_overwrites.rs +1 −1 View lib/space/src/handlers/list_dir_group_overwrites.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::dir::{DirPath, GroupOverwriteDto};
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/space/src/handlers/list_dir_user_overwrites.rs lib/space/src/handlers/list_dir_user_overwrites.rs +1 −1 View lib/space/src/handlers/list_dir_user_overwrites.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::dir::{DirPath, UserOverwriteDto};
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/space/src/handlers/list_groups.rs lib/space/src/handlers/list_groups.rs +1 −1 View lib/space/src/handlers/list_groups.rs
@@ -6,7 +6,7 @@
66use crate::services::groups::GroupPage;
77use crate::services::service::SpaceService;
88use crate::services::spaces::{PageQuery, SpaceNamePath};
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/list_invites.rs lib/space/src/handlers/list_invites.rs +1 −1 View lib/space/src/handlers/list_invites.rs
@@ -6,7 +6,7 @@
66use crate::services::invites::InvitePage;
77use crate::services::service::SpaceService;
88use crate::services::spaces::{PageQuery, SpaceNamePath};
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/list_join_rules.rs lib/space/src/handlers/list_join_rules.rs +1 −1 View lib/space/src/handlers/list_join_rules.rs
@@ -6,7 +6,7 @@
66use crate::services::join_rules::JoinRuleDto;
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/list_members.rs lib/space/src/handlers/list_members.rs +1 −1 View lib/space/src/handlers/list_members.rs
@@ -6,7 +6,7 @@
66use crate::services::members::MemberPage;
77use crate::services::service::SpaceService;
88use crate::services::spaces::{PageQuery, SpaceNamePath};
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/space/src/handlers/list_spaces.rs lib/space/src/handlers/list_spaces.rs +1 −1 View lib/space/src/handlers/list_spaces.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::SpaceService;
77use crate::services::spaces::{PageQuery, SpacePage};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/space/src/handlers/move_dir_node.rs lib/space/src/handlers/move_dir_node.rs +1 −1 View lib/space/src/handlers/move_dir_node.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::dir::{DirPath, DirNodeDto, MoveDirCmd};
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/space/src/handlers/remove_dir_group_overwrite.rs lib/space/src/handlers/remove_dir_group_overwrite.rs +1 −1 View lib/space/src/handlers/remove_dir_group_overwrite.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::set_dir_group_overwrite::DirGroupPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/remove_dir_user_overwrite.rs lib/space/src/handlers/remove_dir_user_overwrite.rs +1 −1 View lib/space/src/handlers/remove_dir_user_overwrite.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::set_dir_user_overwrite::DirUserPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/remove_member.rs lib/space/src/handlers/remove_member.rs +1 −1 View lib/space/src/handlers/remove_member.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::get_member::MemberPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/repair_dir_parents.rs lib/space/src/handlers/repair_dir_parents.rs +1 −1 View lib/space/src/handlers/repair_dir_parents.rs
@@ -6,7 +6,7 @@
66use crate::services::dir::RepairDirResp;
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/space/src/handlers/revoke_invite.rs lib/space/src/handlers/revoke_invite.rs +1 −1 View lib/space/src/handlers/revoke_invite.rs
@@ -8,7 +8,7 @@
88use crate::errors::ApiError;
99use crate::services::invites::InviteDto;
1010use crate::services::service::SpaceService;
11use crate::share::session::require_uid;
11use session::share::session::require_uid;
1212
1313#[derive(Debug, Clone, Deserialize, IntoParams, ToSchema)]
1414pub struct InvitePath {
Modified lib/space/src/handlers/set_dir_group_overwrite.rs lib/space/src/handlers/set_dir_group_overwrite.rs +1 −1 View lib/space/src/handlers/set_dir_group_overwrite.rs
@@ -8,7 +8,7 @@
88use crate::errors::ApiError;
99use crate::services::dir::{GroupOverwriteDto, SetOverwriteCmd};
1010use crate::services::service::SpaceService;
11use crate::share::session::require_uid;
11use session::share::session::require_uid;
1212
1313#[derive(Debug, Clone, Deserialize, IntoParams, ToSchema)]
1414pub struct DirGroupPath {
Modified lib/space/src/handlers/set_dir_user_overwrite.rs lib/space/src/handlers/set_dir_user_overwrite.rs +1 −1 View lib/space/src/handlers/set_dir_user_overwrite.rs
@@ -8,7 +8,7 @@
88use crate::errors::ApiError;
99use crate::services::dir::{SetOverwriteCmd, UserOverwriteDto};
1010use crate::services::service::SpaceService;
11use crate::share::session::require_uid;
11use session::share::session::require_uid;
1212
1313#[derive(Debug, Clone, Deserialize, IntoParams, ToSchema)]
1414pub struct DirUserPath {
Modified lib/space/src/handlers/unassign_group.rs lib/space/src/handlers/unassign_group.rs +1 −1 View lib/space/src/handlers/unassign_group.rs
@@ -7,7 +7,7 @@
77
88use crate::errors::ApiError;
99use crate::services::service::SpaceService;
10use crate::share::session::require_uid;
10use session::share::session::require_uid;
1111
1212#[derive(Debug, Clone, Deserialize, IntoParams, ToSchema)]
1313pub struct MemberGroupPath {
Modified lib/space/src/handlers/unban_user.rs lib/space/src/handlers/unban_user.rs +1 −1 View lib/space/src/handlers/unban_user.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::handlers::get_member::MemberPath;
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/space/src/handlers/update_ban.rs lib/space/src/handlers/update_ban.rs +1 −1 View lib/space/src/handlers/update_ban.rs
@@ -6,7 +6,7 @@
66use crate::handlers::get_member::MemberPath;
77use crate::services::bans::{BanDto, UpdateBanCmd};
88use crate::services::service::SpaceService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 patch,
Modified lib/space/src/handlers/update_dir_node.rs lib/space/src/handlers/update_dir_node.rs +1 −1 View lib/space/src/handlers/update_dir_node.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::dir::{DirPath, DirNodeDto, UpdateDirCmd};
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/space/src/handlers/update_group.rs lib/space/src/handlers/update_group.rs +1 −1 View lib/space/src/handlers/update_group.rs
@@ -6,7 +6,7 @@
66use crate::handlers::get_group::GroupPath;
77use crate::services::groups::{GroupDto, UpdateGroupCmd};
88use crate::services::service::SpaceService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 patch,
Modified lib/space/src/handlers/update_join_rule.rs lib/space/src/handlers/update_join_rule.rs +1 −1 View lib/space/src/handlers/update_join_rule.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::join_rules::{JoinRuleDto, JoinRulePath, UpdateJoinRuleCmd};
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/space/src/handlers/update_member.rs lib/space/src/handlers/update_member.rs +1 −1 View lib/space/src/handlers/update_member.rs
@@ -6,7 +6,7 @@
66use crate::handlers::get_member::MemberPath;
77use crate::services::members::{MemberDto, UpdateMemberCmd};
88use crate::services::service::SpaceService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 patch,
Modified lib/space/src/handlers/update_space.rs lib/space/src/handlers/update_space.rs +1 −1 View lib/space/src/handlers/update_space.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::SpaceService;
77use crate::services::spaces::{SpaceDto, SpaceNamePath, UpdateSpaceCmd};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 patch,
Modified lib/space/src/handlers/upload_space_avatar.rs lib/space/src/handlers/upload_space_avatar.rs +1 −1 View lib/space/src/handlers/upload_space_avatar.rs
@@ -6,7 +6,7 @@
66use crate::services::avatar::{SpaceAvatarDto, UploadSpaceAvatarCmd};
77use crate::services::service::SpaceService;
88use crate::services::spaces::SpaceNamePath;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 put,
Modified lib/space/src/handlers/upload_space_image.rs lib/space/src/handlers/upload_space_image.rs +1 −1 View lib/space/src/handlers/upload_space_image.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::images::{SpaceImageDto, SpaceImageKindPath, UploadSpaceImageCmd};
77use crate::services::service::SpaceService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 put,
Modified lib/space/src/services/service.rs lib/space/src/services/service.rs +31 −0 View lib/space/src/services/service.rs
@@ -1,8 +1,14 @@
11use std::sync::Arc;
22
3use async_trait::async_trait;
34use config::AppConfig;
45use export::{AppDatabase, AppState, AppStorage};
56use email::EmailService;
7use models::users::user;
8use models::users::user_sessions;
9use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
10use session::share::guard::{SessionGuard, SessionWithUser};
11use session::SessionError;
612
713use crate::errors::SpaceError;
814
@@ -46,3 +52,28 @@
4652 .map_err(|error| SpaceError::Internal(format!("email send failed: {error}")))
4753 }
4854}
55
56#[async_trait]
57impl SessionGuard for SpaceService {
58 async fn lookup_session_with_user(
59 &self,
60 token_hash: &str,
61 ) -> Result<Option<SessionWithUser>, SessionError> {
62 let outcome = user_sessions::Entity::find()
63 .filter(user_sessions::Column::TokenHash.eq(token_hash))
64 .find_also_related(user::Entity)
65 .one(self.db().read())
66 .await?;
67 Ok(outcome.and_then(|(row, current)| {
68 current.map(|c| SessionWithUser {
69 user_id: row.user_id,
70 is_revoked: row.is_revoked,
71 expires_at: row.expires_at,
72 is_active: c.is_active,
73 prohibit_login: c.prohibit_login,
74 is_restricted: c.is_restricted,
75 passwd_version: c.passwd_version,
76 })
77 }))
78 }
79}
Modified lib/space/src/share/guard.rs lib/space/src/share/guard.rs +4 −37 View lib/space/src/share/guard.rs
@@ -1,15 +1,10 @@
11use axum::extract::{Request, State};
22use axum::middleware::Next;
3use axum::response::{IntoResponse, Response};
4use models::users::user;
5use models::users::user_sessions;
6use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
7use session::{Session, SessionUser, SessionUserMut};
8use time::OffsetDateTime;
3use axum::response::Response;
4use session::Session;
5use session::share::guard::session_guard;
96
10use crate::errors::{ApiError, SpaceError};
117use crate::services::service::SpaceService;
12use crate::share::session::{pwd_version_matches, session_token_key};
138
149pub async fn space_guard(
1510 State(service): State<SpaceService>,
@@ -17,33 +12,5 @@
1712 request: Request,
1813 next: Next,
1914) -> Response {
20 let Some(uid) = session.uid() else {
21 return ApiError::from(SpaceError::Unauthorized).into_response();
22 };
23 let Some(token_hash) = session.get::<String>(&session_token_key(uid)) else {
24 return ApiError::from(SpaceError::Unauthorized).into_response();
25 };
26 let outcome = user_sessions::Entity::find()
27 .filter(user_sessions::Column::TokenHash.eq(&token_hash))
28 .find_also_related(user::Entity)
29 .one(service.db().read())
30 .await;
31 let authorized = match outcome {
32 Ok(Some((row, Some(current)))) => {
33 !row.is_revoked
34 && row.user_id == uid
35 && row.expires_at > OffsetDateTime::now_utc()
36 && current.is_active
37 && !current.prohibit_login
38 && !current.is_restricted
39 && pwd_version_matches(&session, current.passwd_version)
40 }
41 Ok(_) => false,
42 Err(error) => return ApiError::from(SpaceError::from(error)).into_response(),
43 };
44 if !authorized {
45 session.logout_user(uid);
46 return ApiError::from(SpaceError::Unauthorized).into_response();
47 }
48 next.run(request).await
15 session_guard::<SpaceService>(State(service), session, request, next).await
4916}
Modified lib/space/src/share/mod.rs lib/space/src/share/mod.rs +1 −2 View lib/space/src/share/mod.rs
@@ -1,4 +1,3 @@
11pub mod authz;
22pub mod guard;
3pub mod lookup;
4pub mod session;
3pub mod lookup;
No newline at end of file
Deleted lib/space/src/share/session.rs lib/space/src/share/session.rs +0 −26
@@ -1,26 +0,0 @@
1use session::{Session, SessionUser};
2use uuid::Uuid;
3
4use crate::errors::{ApiError, SpaceError};
5
6pub const PWD_VERSION_KEY: &str = "auth:pwd_version";
7
8pub fn session_token_key(uid: Uuid) -> String {
9 format!("auth:token_hash:{uid}")
10}
11
12pub fn require_uid(session: &Session) -> Result<Uuid, Box<ApiError>> {
13 match session.uid() {
14 Some(uid) => Ok(uid),
15 None => Err(Box::new(ApiError::from(SpaceError::Unauthorized))),
16 }
17}
18
19pub fn pwd_version_matches(session: &Session, current: Option<i64>) -> bool {
20 let stored = session.get::<i64>(PWD_VERSION_KEY);
21 match (stored, current) {
22 (Some(stored_ver), Some(curr_ver)) => stored_ver == curr_ver,
23 (None, None) => true,
24 _ => false,
25 }
26}
Modified lib/space/src/errors.rs lib/space/src/errors.rs +14 −0 View lib/space/src/errors.rs
@@ -150,6 +150,20 @@
150150 }
151151}
152152
153impl From<session::SessionError> for ApiError {
154 fn from(error: session::SessionError) -> Self {
155 match error {
156 session::SessionError::Unauthorized => {
157 Self::Unauthorized(Self::payload(401, "unauthorized"))
158 }
159 session::SessionError::Database(message) => {
160 tracing::warn!(error = %message, "space handler failed");
161 Self::Internal(Self::payload(500, "internal server error"))
162 }
163 }
164 }
165}
166
153167impl From<AppResponseData<()>> for ApiError {
154168 fn from(_error: AppResponseData<()>) -> Self {
155169 Self::BadRequest(Self::payload(400, "bad request"))
Modified lib/space/Cargo.toml lib/space/Cargo.toml +1 −0 View lib/space/Cargo.toml
@@ -4,6 +4,7 @@
44edition.workspace = true
55
66[dependencies]
7async-trait = { workspace = true }
78config = { workspace = true }
89export = { workspace = true }
910email = { workspace = true }
Modified lib/user/src/handlers/add_email.rs lib/user/src/handlers/add_email.rs +1 −1 View lib/user/src/handlers/add_email.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::emails::{AddEmailCmd, AddEmailResp};
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/user/src/handlers/cancel_scheduled_message.rs lib/user/src/handlers/cancel_scheduled_message.rs +1 −1 View lib/user/src/handlers/cancel_scheduled_message.rs
@@ -5,7 +5,7 @@
55
66use crate::errors::ApiError;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/confirm_deletion.rs lib/user/src/handlers/confirm_deletion.rs +1 −1 View lib/user/src/handlers/confirm_deletion.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::deletion::DeletionDto;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 post,
Modified lib/user/src/handlers/create_meme.rs lib/user/src/handlers/create_meme.rs +1 −1 View lib/user/src/handlers/create_meme.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::profile::{MemeDto, UpsertMemeCmd};
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/user/src/handlers/delete_avatar.rs lib/user/src/handlers/delete_avatar.rs +1 −1 View lib/user/src/handlers/delete_avatar.rs
@@ -4,7 +4,7 @@
44
55use crate::errors::ApiError;
66use crate::services::service::UserService;
7use crate::share::session::require_uid;
7use session::share::session::require_uid;
88
99#[utoipa::path(
1010 delete,
Modified lib/user/src/handlers/delete_email.rs lib/user/src/handlers/delete_email.rs +1 −1 View lib/user/src/handlers/delete_email.rs
@@ -5,7 +5,7 @@
55
66use crate::errors::ApiError;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/delete_meme.rs lib/user/src/handlers/delete_meme.rs +1 −1 View lib/user/src/handlers/delete_meme.rs
@@ -5,7 +5,7 @@
55
66use crate::errors::ApiError;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/delete_push_subscription.rs lib/user/src/handlers/delete_push_subscription.rs +1 −1 View lib/user/src/handlers/delete_push_subscription.rs
@@ -5,7 +5,7 @@
55
66use crate::errors::ApiError;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/get_avatar.rs lib/user/src/handlers/get_avatar.rs +1 −1 View lib/user/src/handlers/get_avatar.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::avatar::AvatarDto;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/user/src/handlers/list_emails.rs lib/user/src/handlers/list_emails.rs +1 −1 View lib/user/src/handlers/list_emails.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::emails::EmailDto;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/user/src/handlers/list_memes.rs lib/user/src/handlers/list_memes.rs +1 −1 View lib/user/src/handlers/list_memes.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::profile::{ListLimitQuery, MemeDto};
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/user/src/handlers/list_push_subscriptions.rs lib/user/src/handlers/list_push_subscriptions.rs +1 −1 View lib/user/src/handlers/list_push_subscriptions.rs
@@ -6,7 +6,7 @@
66use crate::services::push_subscriptions::PushSubscriptionDto;
77use crate::services::service::UserService;
88use crate::share::page::PageQuery;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/user/src/handlers/list_saved_messages.rs lib/user/src/handlers/list_saved_messages.rs +1 −1 View lib/user/src/handlers/list_saved_messages.rs
@@ -6,7 +6,7 @@
66use crate::services::notifications::SavedMessageDto;
77use crate::services::service::UserService;
88use crate::share::page::PageQuery;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/user/src/handlers/list_scheduled_messages.rs lib/user/src/handlers/list_scheduled_messages.rs +1 −1 View lib/user/src/handlers/list_scheduled_messages.rs
@@ -6,7 +6,7 @@
66use crate::services::notifications::ScheduledMessageDto;
77use crate::services::service::UserService;
88use crate::share::page::PageQuery;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/user/src/handlers/list_sessions.rs lib/user/src/handlers/list_sessions.rs +1 −1 View lib/user/src/handlers/list_sessions.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::UserService;
77use crate::services::sessions::{ListSessionsQuery, SessionDto};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/user/src/handlers/my_reports.rs lib/user/src/handlers/my_reports.rs +1 −1 View lib/user/src/handlers/my_reports.rs
@@ -6,7 +6,7 @@
66use crate::services::notifications::ReportDto;
77use crate::services::service::UserService;
88use crate::share::page::PageQuery;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/user/src/handlers/my_spaces.rs lib/user/src/handlers/my_spaces.rs +1 −1 View lib/user/src/handlers/my_spaces.rs
@@ -6,7 +6,7 @@
66use crate::services::profile::MySpaceDto;
77use crate::services::service::UserService;
88use crate::share::page::PageQuery;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/user/src/handlers/my_suspensions.rs lib/user/src/handlers/my_suspensions.rs +1 −1 View lib/user/src/handlers/my_suspensions.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::UserService;
77use crate::services::suspensions::{IncludeRevokedQuery, SuspensionDto};
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 get,
Modified lib/user/src/handlers/recent_mentions.rs lib/user/src/handlers/recent_mentions.rs +1 −1 View lib/user/src/handlers/recent_mentions.rs
@@ -6,7 +6,7 @@
66use crate::services::notifications::RecentMentionDto;
77use crate::services::profile::ListLimitQuery;
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 get,
Modified lib/user/src/handlers/revoke_all_sessions.rs lib/user/src/handlers/revoke_all_sessions.rs +1 −1 View lib/user/src/handlers/revoke_all_sessions.rs
@@ -5,7 +5,7 @@
55use crate::errors::ApiError;
66use crate::services::service::UserService;
77use crate::services::sessions::CountResp;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/revoke_session.rs lib/user/src/handlers/revoke_session.rs +1 −1 View lib/user/src/handlers/revoke_session.rs
@@ -5,7 +5,7 @@
55
66use crate::errors::ApiError;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/save_message.rs lib/user/src/handlers/save_message.rs +1 −1 View lib/user/src/handlers/save_message.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::notifications::{SaveMessageCmd, SavedMessageDto};
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/user/src/handlers/set_primary_email.rs lib/user/src/handlers/set_primary_email.rs +1 −1 View lib/user/src/handlers/set_primary_email.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::emails::EmailDto;
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 patch,
Modified lib/user/src/handlers/unsave_message.rs lib/user/src/handlers/unsave_message.rs +1 −1 View lib/user/src/handlers/unsave_message.rs
@@ -5,7 +5,7 @@
55
66use crate::errors::ApiError;
77use crate::services::service::UserService;
8use crate::share::session::require_uid;
8use session::share::session::require_uid;
99
1010#[utoipa::path(
1111 delete,
Modified lib/user/src/handlers/upload_avatar.rs lib/user/src/handlers/upload_avatar.rs +1 −1 View lib/user/src/handlers/upload_avatar.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::avatar::{AvatarDto, UploadAvatarCmd};
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 put,
Modified lib/user/src/handlers/upsert_push_subscription.rs lib/user/src/handlers/upsert_push_subscription.rs +1 −1 View lib/user/src/handlers/upsert_push_subscription.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::push_subscriptions::{PushSubscriptionDto, UpsertPushCmd};
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/user/src/handlers/verify_add_email.rs lib/user/src/handlers/verify_add_email.rs +1 −1 View lib/user/src/handlers/verify_add_email.rs
@@ -6,7 +6,7 @@
66use crate::errors::ApiError;
77use crate::services::emails::{EmailDto, VerifyEmailCmd};
88use crate::services::service::UserService;
9use crate::share::session::require_uid;
9use session::share::session::require_uid;
1010
1111#[utoipa::path(
1212 post,
Modified lib/user/src/services/service.rs lib/user/src/services/service.rs +31 −0 View lib/user/src/services/service.rs
@@ -1,7 +1,13 @@
11use std::sync::Arc;
22
3use async_trait::async_trait;
34use config::AppConfig;
45use export::{AppDatabase, AppState, AppStorage};
6use models::users::user;
7use models::users::user_sessions;
8use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
9use session::share::guard::{SessionGuard, SessionWithUser};
10use session::SessionError;
511
612#[derive(Clone)]
713pub struct UserService {
@@ -25,3 +31,28 @@
2531 &self.state.storage
2632 }
2733}
34
35#[async_trait]
36impl SessionGuard for UserService {
37 async fn lookup_session_with_user(
38 &self,
39 token_hash: &str,
40 ) -> Result<Option<SessionWithUser>, SessionError> {
41 let outcome = user_sessions::Entity::find()
42 .filter(user_sessions::Column::TokenHash.eq(token_hash))
43 .find_also_related(user::Entity)
44 .one(self.db().read())
45 .await?;
46 Ok(outcome.and_then(|(row, current)| {
47 current.map(|c| SessionWithUser {
48 user_id: row.user_id,
49 is_revoked: row.is_revoked,
50 expires_at: row.expires_at,
51 is_active: c.is_active,
52 prohibit_login: c.prohibit_login,
53 is_restricted: c.is_restricted,
54 passwd_version: c.passwd_version,
55 })
56 }))
57 }
58}
Modified lib/user/src/share/guard.rs lib/user/src/share/guard.rs +4 −37 View lib/user/src/share/guard.rs
@@ -1,15 +1,10 @@
11use axum::extract::{Request, State};
22use axum::middleware::Next;
3use axum::response::{IntoResponse, Response};
4use models::users::user;
5use models::users::user_sessions;
6use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
7use session::{Session, SessionUser, SessionUserMut};
8use time::OffsetDateTime;
3use axum::response::Response;
4use session::Session;
5use session::share::guard::session_guard;
96
10use crate::errors::{ApiError, UserError};
117use crate::services::service::UserService;
12use crate::share::session::{pwd_version_matches, session_token_key};
138
149pub async fn user_guard(
1510 State(service): State<UserService>,
@@ -17,33 +12,5 @@
1712 request: Request,
1813 next: Next,
1914) -> Response {
20 let Some(uid) = session.uid() else {
21 return ApiError::from(UserError::Unauthorized).into_response();
22 };
23 let Some(token_hash) = session.get::<String>(&session_token_key(uid)) else {
24 return ApiError::from(UserError::Unauthorized).into_response();
25 };
26 let outcome = user_sessions::Entity::find()
27 .filter(user_sessions::Column::TokenHash.eq(&token_hash))
28 .find_also_related(user::Entity)
29 .one(service.db().read())
30 .await;
31 let authorized = match outcome {
32 Ok(Some((row, Some(current)))) => {
33 !row.is_revoked
34 && row.user_id == uid
35 && row.expires_at > OffsetDateTime::now_utc()
36 && current.is_active
37 && !current.prohibit_login
38 && !current.is_restricted
39 && pwd_version_matches(&session, current.passwd_version)
40 }
41 Ok(_) => false,
42 Err(error) => return ApiError::from(UserError::from(error)).into_response(),
43 };
44 if !authorized {
45 session.logout_user(uid);
46 return ApiError::from(UserError::Unauthorized).into_response();
47 }
48 next.run(request).await
15 session_guard::<UserService>(State(service), session, request, next).await
4916}
Modified lib/user/src/share/mod.rs lib/user/src/share/mod.rs +1 −1 View lib/user/src/share/mod.rs
@@ -2,4 +2,4 @@
22pub mod guard;
33pub mod page;
44pub mod redis;
5pub mod session;
5pub mod types;
No newline at end of file
Deleted lib/user/src/share/session.rs lib/user/src/share/session.rs +0 −26
@@ -1,26 +0,0 @@
1use session::{Session, SessionUser};
2use uuid::Uuid;
3
4use crate::errors::{ApiError, UserError};
5
6pub const PWD_VERSION_KEY: &str = "auth:pwd_version";
7
8pub fn session_token_key(uid: Uuid) -> String {
9 format!("auth:token_hash:{uid}")
10}
11
12pub fn require_uid(session: &Session) -> Result<Uuid, Box<ApiError>> {
13 match session.uid() {
14 Some(uid) => Ok(uid),
15 None => Err(Box::new(ApiError::from(UserError::Unauthorized))),
16 }
17}
18
19pub fn pwd_version_matches(session: &Session, current: Option<i64>) -> bool {
20 let stored = session.get::<i64>(PWD_VERSION_KEY);
21 match (stored, current) {
22 (Some(stored_ver), Some(curr_ver)) => stored_ver == curr_ver,
23 (None, None) => true,
24 _ => false,
25 }
26}
Added lib/user/src/share/types.rs lib/user/src/share/types.rs +25 −0 View lib/user/src/share/types.rs
@@ -0,0 +1,25 @@
1use serde::{Deserialize, Serialize};
2use utoipa::{IntoParams, ToSchema};
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
6pub struct UserPublic {
7 pub uid: Uuid,
8 pub username: String,
9 pub display_name: String,
10 pub avatar_url: String,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, IntoParams)]
14pub struct ListQuery {
15 pub limit: Option<u64>,
16 pub offset: Option<u64>,
17}
18
19impl ListQuery {
20 pub fn page(&self) -> (u64, u64) {
21 let limit = self.limit.unwrap_or(50).clamp(1, 100);
22 let offset = self.offset.unwrap_or(0);
23 (limit, offset)
24 }
25}
Modified lib/user/src/errors.rs lib/user/src/errors.rs +14 −0 View lib/user/src/errors.rs
@@ -156,6 +156,20 @@
156156 }
157157}
158158
159impl From<session::SessionError> for ApiError {
160 fn from(error: session::SessionError) -> Self {
161 match error {
162 session::SessionError::Unauthorized => {
163 Self::Unauthorized(Self::payload(401, "unauthorized"))
164 }
165 session::SessionError::Database(message) => {
166 tracing::warn!(error = %message, "user handler failed");
167 Self::Internal(Self::payload(500, "internal server error"))
168 }
169 }
170 }
171}
172
159173impl From<AppResponseData<()>> for ApiError {
160174 fn from(_error: AppResponseData<()>) -> Self {
161175 Self::BadRequest(Self::payload(400, "bad request"))
Modified lib/user/Cargo.toml lib/user/Cargo.toml +1 −0 View lib/user/Cargo.toml
@@ -4,6 +4,7 @@
44edition.workspace = true
55
66[dependencies]
7async-trait = { workspace = true }
78config = { workspace = true }
89export = { workspace = true }
910models = { workspace = true }