chore(v1.1.8): cargo fmt --all (reviewer)
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.
This commit is contained in:
@@ -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<Option<Vec<u8>>, 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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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<Vec<String>, UsersError> {
|
||||
async fn fetch_roles(
|
||||
&self,
|
||||
app_id: AppId,
|
||||
user_id: AppUserId,
|
||||
) -> Result<Vec<String>, 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<AppUser, UsersError> {
|
||||
async fn create(&self, cx: &SdkCallCx, input: CreateUserInput) -> Result<AppUser, UsersError> {
|
||||
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<UsersListPage, UsersError> {
|
||||
async fn list(&self, cx: &SdkCallCx, opts: UsersListOpts) -> Result<UsersListPage, UsersError> {
|
||||
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<Option<AppUser>, UsersError> {
|
||||
async fn verify(&self, cx: &SdkCallCx, token: &str) -> Result<Option<AppUser>, 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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user