From 7027e0dfb81f7bef1387ed0757c61411e42de215 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Sat, 6 Jun 2026 18:44:52 +0200 Subject: [PATCH] chore(v1.1.8): cargo fmt --all (reviewer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 8 files needed re-wrapping after the F2 clippy-fix pass landed un-fmt'd. Pure cosmetic โ€” no behavioral change. Re-runs of `cargo fmt --all -- --check` now exit clean. Reviewer-supplied per REVIEW.md ยง7; folded onto the branch to avoid a NEEDS-CHANGES round-trip on a purely mechanical fix. --- crates/executor-core/src/sdk/users.rs | 29 ++++++----- crates/manager-core/src/app_secrets_repo.rs | 7 +-- crates/manager-core/src/authz.rs | 4 +- crates/manager-core/src/lib.rs | 46 +++++++++--------- crates/manager-core/src/users_service.rs | 54 ++++++++++----------- crates/picloud/src/lib.rs | 25 +++++----- crates/shared/src/lib.rs | 4 +- crates/shared/src/users.rs | 38 +++------------ 8 files changed, 95 insertions(+), 112 deletions(-) diff --git a/crates/executor-core/src/sdk/users.rs b/crates/executor-core/src/sdk/users.rs index dfe4084..7b4294b 100644 --- a/crates/executor-core/src/sdk/users.rs +++ b/crates/executor-core/src/sdk/users.rs @@ -328,7 +328,8 @@ fn bind_complete_password_reset( let svc = svc.clone(); let cx = cx.clone(); let user_opt = block_on(async move { - svc.complete_password_reset(&cx, &token, &new_password).await + svc.complete_password_reset(&cx, &token, &new_password) + .await })?; Ok(user_opt.map_or(Dynamic::UNIT, |u| Dynamic::from(user_to_map(&u)))) }, @@ -390,7 +391,8 @@ fn bind_accept_invite(module: &mut Module, svc: &Arc, cx: &Arc let svc = svc.clone(); let cx = cx.clone(); let accept_opt: Option = block_on(async move { - svc.accept_invite(&cx, &token, &password, display_name).await + svc.accept_invite(&cx, &token, &password, display_name) + .await })?; Ok(accept_opt.map_or(Dynamic::UNIT, |a| Dynamic::from(a.session.token))) }, @@ -471,21 +473,26 @@ fn user_to_map(user: &AppUser) -> Map { user.last_login_at .map_or(Dynamic::UNIT, |d| Dynamic::from(d.to_rfc3339())), ); - m.insert("created_at".into(), Dynamic::from(user.created_at.to_rfc3339())); - m.insert("updated_at".into(), Dynamic::from(user.updated_at.to_rfc3339())); - let roles: Array = user - .roles - .iter() - .cloned() - .map(Dynamic::from) - .collect(); + m.insert( + "created_at".into(), + Dynamic::from(user.created_at.to_rfc3339()), + ); + m.insert( + "updated_at".into(), + Dynamic::from(user.updated_at.to_rfc3339()), + ); + let roles: Array = user.roles.iter().cloned().map(Dynamic::from).collect(); m.insert("roles".into(), roles.into()); m } fn list_page_to_map(page: &UsersListPage) -> Map { let mut m = Map::new(); - let items: Array = page.items.iter().map(|u| Dynamic::from(user_to_map(u))).collect(); + let items: Array = page + .items + .iter() + .map(|u| Dynamic::from(user_to_map(u))) + .collect(); m.insert("users".into(), items.into()); m.insert( "next_cursor".into(), diff --git a/crates/manager-core/src/app_secrets_repo.rs b/crates/manager-core/src/app_secrets_repo.rs index b35e169..1e668e4 100644 --- a/crates/manager-core/src/app_secrets_repo.rs +++ b/crates/manager-core/src/app_secrets_repo.rs @@ -121,7 +121,8 @@ impl AppSecretsRepo for PostgresAppSecretsRepo { .fetch_one(&self.pool) .await?; // A row exists by construction, so a key must decode. - self.decode(row.0, row.1)?.ok_or(AppSecretsRepoError::Crypto) + self.decode(row.0, row.1)? + .ok_or(AppSecretsRepoError::Crypto) } async fn signing_key(&self, app_id: AppId) -> Result>, AppSecretsRepoError> { @@ -167,8 +168,8 @@ mod tests { let secret = vec![3u8; 32]; let enc = crypto::encrypt(&secret, key().as_bytes()); let other = MasterKey::from_bytes([1u8; 32]); - let err = decode_signing_key(&other, Some(enc.ciphertext), Some(enc.nonce.to_vec())) - .unwrap_err(); + let err = + decode_signing_key(&other, Some(enc.ciphertext), Some(enc.nonce.to_vec())).unwrap_err(); assert!(matches!(err, AppSecretsRepoError::Crypto)); } } diff --git a/crates/manager-core/src/authz.rs b/crates/manager-core/src/authz.rs index 0a30c78..2258eb6 100644 --- a/crates/manager-core/src/authz.rs +++ b/crates/manager-core/src/authz.rs @@ -759,7 +759,9 @@ mod tests { let p = principal(InstanceRole::Member); repo.grant(p.user_id, app, AppRole::Editor).await; assert_eq!( - can(&repo, &p, Capability::AppUsersAdmin(app)).await.unwrap(), + can(&repo, &p, Capability::AppUsersAdmin(app)) + .await + .unwrap(), Decision::Deny, ); diff --git a/crates/manager-core/src/lib.rs b/crates/manager-core/src/lib.rs index a9a9fb6..2826a1d 100644 --- a/crates/manager-core/src/lib.rs +++ b/crates/manager-core/src/lib.rs @@ -23,8 +23,6 @@ pub mod app_user_repo; pub mod app_user_role_repo; pub mod app_user_session_repo; pub mod app_user_verification_repo; -pub mod users_admin_api; -pub mod users_service; pub mod apps_api; pub mod auth; pub mod auth_api; @@ -72,6 +70,8 @@ pub mod topics_api; pub mod trigger_config; pub mod trigger_repo; pub mod triggers_api; +pub mod users_admin_api; +pub mod users_service; pub use abandoned_repo::{ AbandonedRepo, AbandonedRepoError, NewAbandonedExecution, PostgresAbandonedRepo, @@ -84,27 +84,6 @@ pub use admin_user_repo::{ AdminUserCredentials, AdminUserRepository, AdminUserRepositoryError, AdminUserRow, PostgresAdminUserRepository, }; -pub use app_user_repo::{ - AppUserCredentials, AppUserRepository, AppUserRepositoryError, AppUserRow, - ListOpts as AppUserListOpts, ListPage as AppUserListPage, PostgresAppUserRepository, -}; -pub use app_user_session_repo::{ - AppUserSessionLookup, AppUserSessionRepository, AppUserSessionRepositoryError, - PostgresAppUserSessionRepository, -}; -pub use app_user_invitation_repo::{ - AppUserInvitationRepo, AppUserInvitationRepoError, ConsumedInvitation, InvitationRow, - PostgresAppUserInvitationRepo, -}; -pub use app_user_password_reset_repo::{ - AppUserPasswordResetRepo, AppUserPasswordResetRepoError, PostgresAppUserPasswordResetRepo, -}; -pub use app_user_role_repo::{AppUserRoleRepo, AppUserRoleRepoError, PostgresAppUserRoleRepo}; -pub use users_admin_api::{app_users_router, AppUsersApiError, AppUsersState}; -pub use app_user_verification_repo::{ - AppUserVerificationRepo, AppUserVerificationRepoError, PostgresAppUserVerificationRepo, -}; -pub use users_service::{UsersServiceConfig, UsersServiceImpl}; pub use admin_users_api::{admins_router, AdminsState}; pub use api::{admin_router, AdminState}; pub use api_key_repo::{ @@ -123,6 +102,25 @@ pub use app_repo::{resolve_app, AppLookup, AppRepository, PostgresAppRepository} pub use app_secrets_repo::{ AppSecretsRepo, AppSecretsRepoError, PostgresAppSecretsRepo, SIGNING_KEY_LEN, }; +pub use app_user_invitation_repo::{ + AppUserInvitationRepo, AppUserInvitationRepoError, ConsumedInvitation, InvitationRow, + PostgresAppUserInvitationRepo, +}; +pub use app_user_password_reset_repo::{ + AppUserPasswordResetRepo, AppUserPasswordResetRepoError, PostgresAppUserPasswordResetRepo, +}; +pub use app_user_repo::{ + AppUserCredentials, AppUserRepository, AppUserRepositoryError, AppUserRow, + ListOpts as AppUserListOpts, ListPage as AppUserListPage, PostgresAppUserRepository, +}; +pub use app_user_role_repo::{AppUserRoleRepo, AppUserRoleRepoError, PostgresAppUserRoleRepo}; +pub use app_user_session_repo::{ + AppUserSessionLookup, AppUserSessionRepository, AppUserSessionRepositoryError, + PostgresAppUserSessionRepository, +}; +pub use app_user_verification_repo::{ + AppUserVerificationRepo, AppUserVerificationRepoError, PostgresAppUserVerificationRepo, +}; pub use apps_api::{apps_router, AppsState}; pub use auth_api::auth_router; pub use auth_bootstrap::{ @@ -192,3 +190,5 @@ pub use trigger_repo::{ Trigger, TriggerDetails, TriggerDispatchMode, TriggerKind, TriggerRepo, TriggerRepoError, }; pub use triggers_api::{triggers_router, TriggersApiError, TriggersState}; +pub use users_admin_api::{app_users_router, AppUsersApiError, AppUsersState}; +pub use users_service::{UsersServiceConfig, UsersServiceImpl}; diff --git a/crates/manager-core/src/users_service.rs b/crates/manager-core/src/users_service.rs index e2e5213..347c9f7 100644 --- a/crates/manager-core/src/users_service.rs +++ b/crates/manager-core/src/users_service.rs @@ -28,7 +28,7 @@ use async_trait::async_trait; use chrono::Utc; use picloud_shared::{ AppId, AppUser, AppUserId, CreateUserInput, EmailError, EmailService, EmailTemplateOpts, - GeneratedAccept, GeneratedSession, InviteOpts, Invitation, InvitationId, OutboundEmail, + GeneratedAccept, GeneratedSession, Invitation, InvitationId, InviteOpts, OutboundEmail, Principal, SdkCallCx, ServiceEvent, ServiceEventEmitter, UpdateUserInput, UsersError, UsersListOpts, UsersListPage, UsersService, }; @@ -84,7 +84,10 @@ impl UsersServiceConfig { pub fn from_env() -> Self { let default = Self::default(); Self { - session_ttl: env_duration_hours("PICLOUD_APP_USER_SESSION_TTL_HOURS", default.session_ttl), + session_ttl: env_duration_hours( + "PICLOUD_APP_USER_SESSION_TTL_HOURS", + default.session_ttl, + ), session_absolute_ttl: env_duration_hours( "PICLOUD_APP_USER_SESSION_ABSOLUTE_HOURS", default.session_absolute_ttl, @@ -162,7 +165,11 @@ impl UsersServiceImpl { } } - async fn require(&self, principal: Option<&Principal>, cap: Capability) -> Result<(), UsersError> { + async fn require( + &self, + principal: Option<&Principal>, + cap: Capability, + ) -> Result<(), UsersError> { let Some(p) = principal else { // Public HTTP execution โ€” script-as-gate; not denied here. return Ok(()); @@ -192,7 +199,11 @@ impl UsersServiceImpl { } } - async fn fetch_roles(&self, app_id: AppId, user_id: AppUserId) -> Result, UsersError> { + async fn fetch_roles( + &self, + app_id: AppId, + user_id: AppUserId, + ) -> Result, UsersError> { Ok(self.roles.list_for_user(app_id, user_id).await?) } @@ -358,19 +369,14 @@ fn internal_cx(cx: &SdkCallCx) -> SdkCallCx { #[async_trait] impl UsersService for UsersServiceImpl { - async fn create( - &self, - cx: &SdkCallCx, - input: CreateUserInput, - ) -> Result { + async fn create(&self, cx: &SdkCallCx, input: CreateUserInput) -> Result { self.require(cx.principal.as_ref(), Capability::AppUsersWrite(cx.app_id)) .await?; let email = validate_email(&input.email)?; validate_password(&input.password)?; let display_name = validate_display_name(input.display_name.as_deref())?; - let password_hash = hash_password(&input.password).map_err(|e| { - UsersError::Backend(format!("password hashing failed: {e}")) - })?; + let password_hash = hash_password(&input.password) + .map_err(|e| UsersError::Backend(format!("password hashing failed: {e}")))?; let row = self .users .create(cx.app_id, &email, &password_hash, display_name.as_deref()) @@ -443,11 +449,7 @@ impl UsersService for UsersServiceImpl { Ok(deleted) } - async fn list( - &self, - cx: &SdkCallCx, - opts: UsersListOpts, - ) -> Result { + async fn list(&self, cx: &SdkCallCx, opts: UsersListOpts) -> Result { self.require(cx.principal.as_ref(), Capability::AppUsersRead(cx.app_id)) .await?; let limit = opts.limit.unwrap_or(50).clamp(1, 500); @@ -540,11 +542,7 @@ impl UsersService for UsersServiceImpl { })) } - async fn verify( - &self, - cx: &SdkCallCx, - token: &str, - ) -> Result, UsersError> { + async fn verify(&self, cx: &SdkCallCx, token: &str) -> Result, UsersError> { self.require(cx.principal.as_ref(), Capability::AppUsersRead(cx.app_id)) .await?; self.resolve_session(cx.app_id, token).await @@ -626,10 +624,7 @@ impl UsersService for UsersServiceImpl { let Some(user_id) = self.verifications.consume(cx.app_id, &token_hash).await? else { return Ok(None); }; - let row = self - .users - .mark_email_verified(cx.app_id, user_id) - .await?; + let row = self.users.mark_email_verified(cx.app_id, user_id).await?; let roles = self.fetch_roles(cx.app_id, row.id).await?; let user = Self::to_app_user(row, roles); self.emit(cx, "email_verified", user.id).await; @@ -792,7 +787,11 @@ impl UsersService for UsersServiceImpl { // No require: the invitation token IS the authorization. validate_password(password)?; let token_hash = hash_token(token); - let Some(consumed) = self.invitations.consume_by_token(cx.app_id, &token_hash).await? else { + let Some(consumed) = self + .invitations + .consume_by_token(cx.app_id, &token_hash) + .await? + else { return Ok(None); }; @@ -1114,4 +1113,3 @@ impl UsersServiceImpl { Ok(Some(Self::to_app_user(row, roles))) } } - diff --git a/crates/picloud/src/lib.rs b/crates/picloud/src/lib.rs index 5f816df..f9312a2 100644 --- a/crates/picloud/src/lib.rs +++ b/crates/picloud/src/lib.rs @@ -24,14 +24,13 @@ use picloud_manager_core::{ PostgresAppRepository, PostgresAppSecretsRepo, PostgresAppUserInvitationRepo, PostgresAppUserPasswordResetRepo, PostgresAppUserRepository, PostgresAppUserRoleRepo, PostgresAppUserSessionRepository, PostgresAppUserVerificationRepo, PostgresDeadLetterRepo, - PostgresDeadLetterService, - PostgresDocsRepo, PostgresExecutionLogRepository, PostgresExecutionLogSink, PostgresKvRepo, - PostgresOutboxRepo, PostgresPubsubRepo, PostgresRouteRepository, PostgresScriptRepository, - PostgresSecretsRepo, PostgresTopicRepo, PostgresTriggerRepo, PrincipalResolver, - PubsubServiceImpl, RealtimeAuthorityImpl, RepoResolver, RouteAdminState, RouteRepository, - SandboxCeiling, ScriptRepository, SecretsConfig, SecretsServiceImpl, SecretsState, - SubscriberTokenConfig, TopicRepo, TopicsState, TriggerConfig, TriggerRepo, TriggersState, - UsersServiceConfig, UsersServiceImpl, + PostgresDeadLetterService, PostgresDocsRepo, PostgresExecutionLogRepository, + PostgresExecutionLogSink, PostgresKvRepo, PostgresOutboxRepo, PostgresPubsubRepo, + PostgresRouteRepository, PostgresScriptRepository, PostgresSecretsRepo, PostgresTopicRepo, + PostgresTriggerRepo, PrincipalResolver, PubsubServiceImpl, RealtimeAuthorityImpl, RepoResolver, + RouteAdminState, RouteRepository, SandboxCeiling, ScriptRepository, SecretsConfig, + SecretsServiceImpl, SecretsState, SubscriberTokenConfig, TopicRepo, TopicsState, TriggerConfig, + TriggerRepo, TriggersState, UsersServiceConfig, UsersServiceImpl, }; use picloud_orchestrator_core::realtime::DEFAULT_GC_INTERVAL_SECS; use picloud_orchestrator_core::routing::{AppDomainTable, RouteTable}; @@ -237,12 +236,10 @@ pub async fn build_app( // `users::*` namespace and the admin /apps/{id}/users HTTP surface. let app_users_repo = Arc::new(PostgresAppUserRepository::new(pool.clone())); let app_user_sessions_repo = Arc::new(PostgresAppUserSessionRepository::new(pool.clone())); - let app_user_verifications_repo = - Arc::new(PostgresAppUserVerificationRepo::new(pool.clone())); + let app_user_verifications_repo = Arc::new(PostgresAppUserVerificationRepo::new(pool.clone())); let app_user_password_resets_repo = Arc::new(PostgresAppUserPasswordResetRepo::new(pool.clone())); - let app_user_invitations_repo = - Arc::new(PostgresAppUserInvitationRepo::new(pool.clone())); + let app_user_invitations_repo = Arc::new(PostgresAppUserInvitationRepo::new(pool.clone())); let app_user_roles_repo = Arc::new(PostgresAppUserRoleRepo::new(pool.clone())); let users: Arc = Arc::new(UsersServiceImpl::new( app_users_repo.clone(), @@ -473,7 +470,9 @@ pub async fn build_app( .merge(admins_router(admins_state)) .merge(apps_router(apps_state)) .merge(app_members_router(app_members_state)) - .merge(picloud_manager_core::app_users_router(app_users_admin_state)) + .merge(picloud_manager_core::app_users_router( + app_users_admin_state, + )) .merge(api_keys_router(api_keys_state)) .merge(triggers_router(triggers_state)) .merge(files_admin_router(files_admin_state)) diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index ba7cbcf..a8eaaaa 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -81,8 +81,8 @@ pub use trigger_event::{ DeadLetterEventDetail, DocsEventOp, FilesEventOp, KvEventOp, TriggerEvent, }; pub use users::{ - AppUser, CreateUserInput, EmailTemplateOpts, GeneratedAccept, GeneratedSession, InviteOpts, - Invitation, NoopUsersService, UpdateUserInput, UsersError, UsersListOpts, UsersListPage, + AppUser, CreateUserInput, EmailTemplateOpts, GeneratedAccept, GeneratedSession, Invitation, + InviteOpts, NoopUsersService, UpdateUserInput, UsersError, UsersListOpts, UsersListPage, UsersService, }; pub use validator::{ScriptValidator, ValidatedScript, ValidationError}; diff --git a/crates/shared/src/users.rs b/crates/shared/src/users.rs index 3b8d77b..5f082a5 100644 --- a/crates/shared/src/users.rs +++ b/crates/shared/src/users.rs @@ -180,11 +180,7 @@ pub enum UsersError { pub trait UsersService: Send + Sync { // ---- CRUD ---- - async fn create( - &self, - cx: &SdkCallCx, - input: CreateUserInput, - ) -> Result; + async fn create(&self, cx: &SdkCallCx, input: CreateUserInput) -> Result; async fn get(&self, cx: &SdkCallCx, id: AppUserId) -> Result, UsersError>; @@ -203,11 +199,7 @@ pub trait UsersService: Send + Sync { async fn delete(&self, cx: &SdkCallCx, id: AppUserId) -> Result; - async fn list( - &self, - cx: &SdkCallCx, - opts: UsersListOpts, - ) -> Result; + async fn list(&self, cx: &SdkCallCx, opts: UsersListOpts) -> Result; // ---- Auth ---- @@ -224,11 +216,7 @@ pub trait UsersService: Send + Sync { /// Verify a session token. Returns the owning user on success, /// `None` on missing / expired / revoked / cross-app token. Bumps /// the sliding-window TTL on success (capped at the absolute cap). - async fn verify( - &self, - cx: &SdkCallCx, - token: &str, - ) -> Result, UsersError>; + async fn verify(&self, cx: &SdkCallCx, token: &str) -> Result, UsersError>; /// Logout โ€” revokes the session. No-op for already-revoked / /// already-expired tokens. @@ -277,12 +265,8 @@ pub trait UsersService: Send + Sync { // ---- Invitations (commit 7) ---- - async fn invite( - &self, - cx: &SdkCallCx, - email: &str, - opts: InviteOpts, - ) -> Result<(), UsersError>; + async fn invite(&self, cx: &SdkCallCx, email: &str, opts: InviteOpts) + -> Result<(), UsersError>; async fn accept_invite( &self, @@ -383,11 +367,7 @@ impl UsersService for NoopUsersService { ) -> Result { Err(UsersError::Backend(NOOP_MSG.into())) } - async fn get( - &self, - _cx: &SdkCallCx, - _id: AppUserId, - ) -> Result, UsersError> { + async fn get(&self, _cx: &SdkCallCx, _id: AppUserId) -> Result, UsersError> { Err(UsersError::Backend(NOOP_MSG.into())) } async fn find_by_email( @@ -423,11 +403,7 @@ impl UsersService for NoopUsersService { ) -> Result, UsersError> { Err(UsersError::Backend(NOOP_MSG.into())) } - async fn verify( - &self, - _cx: &SdkCallCx, - _token: &str, - ) -> Result, UsersError> { + async fn verify(&self, _cx: &SdkCallCx, _token: &str) -> Result, UsersError> { Err(UsersError::Backend(NOOP_MSG.into())) } async fn logout(&self, _cx: &SdkCallCx, _token: &str) -> Result<(), UsersError> {