style: cargo fmt across Phase 3.5 changes

Pure formatting pass — no behavior changes. Catches the line-wrapping
drift across the new authz / api_keys / middleware / handler edits
that piled up during the implementation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-26 22:21:37 +02:00
parent 063595be31
commit 2aab92af31
14 changed files with 166 additions and 89 deletions

View File

@@ -383,8 +383,9 @@ impl TryFrom<AdminUserRecord> for AdminUserRow {
id: r.id.into(),
username: r.username,
is_active: r.is_active,
instance_role: InstanceRole::from_db_str(&r.instance_role)
.ok_or(AdminUserRepositoryError::InvalidInstanceRole(r.instance_role))?,
instance_role: InstanceRole::from_db_str(&r.instance_role).ok_or(
AdminUserRepositoryError::InvalidInstanceRole(r.instance_role),
)?,
email: r.email,
created_at: r.created_at,
updated_at: r.updated_at,
@@ -410,8 +411,9 @@ impl TryFrom<AdminCredsRecord> for AdminUserCredentials {
username: r.username,
password_hash: r.password_hash,
is_active: r.is_active,
instance_role: InstanceRole::from_db_str(&r.instance_role)
.ok_or(AdminUserRepositoryError::InvalidInstanceRole(r.instance_role))?,
instance_role: InstanceRole::from_db_str(&r.instance_role).ok_or(
AdminUserRepositoryError::InvalidInstanceRole(r.instance_role),
)?,
})
}
}

View File

@@ -162,8 +162,7 @@ async fn create_admin(
// owner — admin cannot self-elevate (or elevate someone else)
// beyond their own ceiling. Owner-creation by env-var bootstrap
// bypasses this path.
if input.instance_role == InstanceRole::Owner
&& principal.instance_role != InstanceRole::Owner
if input.instance_role == InstanceRole::Owner && principal.instance_role != InstanceRole::Owner
{
return Err(AdminApiError::CannotEscalate);
}

View File

@@ -112,10 +112,8 @@ pub trait ApiKeyRepository: Send + Sync {
/// into `set_active(false)` so deactivation invalidates both
/// sessions (already done by `AdminSessionRepository::delete_for_user`)
/// and bearer keys at the same moment.
async fn expire_all_for_user(
&self,
user_id: AdminUserId,
) -> Result<u64, ApiKeyRepositoryError>;
async fn expire_all_for_user(&self, user_id: AdminUserId)
-> Result<u64, ApiKeyRepositoryError>;
}
pub struct PostgresApiKeyRepository {
@@ -132,7 +130,8 @@ impl PostgresApiKeyRepository {
#[async_trait]
impl ApiKeyRepository for PostgresApiKeyRepository {
async fn create(&self, key: NewApiKey) -> Result<ApiKeyRow, ApiKeyRepositoryError> {
let scope_strings: Vec<String> = key.scopes.iter().map(|s| s.as_str().to_string()).collect();
let scope_strings: Vec<String> =
key.scopes.iter().map(|s| s.as_str().to_string()).collect();
let row = sqlx::query_as::<_, ApiKeyRecord>(
"INSERT INTO api_keys \
(user_id, hash, prefix, name, scopes, app_id, expires_at) \

View File

@@ -19,10 +19,7 @@ pub enum AppMembersRepositoryError {
Db(#[from] sqlx::Error),
#[error("membership row not found: app={app_id}, user={user_id}")]
NotFound {
app_id: AppId,
user_id: AdminUserId,
},
NotFound { app_id: AppId, user_id: AdminUserId },
#[error("invalid app_role stored in DB: {0}")]
InvalidRole(String),

View File

@@ -27,10 +27,7 @@ pub trait AppRepository: Send + Sync {
async fn list(&self) -> Result<Vec<App>, ScriptRepositoryError>;
/// Only apps the user has an `app_members` row for. Drives the
/// membership-filtered `GET /admin/apps` for `member` callers.
async fn list_for_user(
&self,
user_id: AdminUserId,
) -> Result<Vec<App>, ScriptRepositoryError>;
async fn list_for_user(&self, user_id: AdminUserId) -> Result<Vec<App>, ScriptRepositoryError>;
async fn get_by_id(&self, id: AppId) -> Result<Option<App>, ScriptRepositoryError>;
async fn get_by_slug(&self, slug: &str) -> Result<Option<App>, ScriptRepositoryError>;
async fn get_by_slug_or_history(
@@ -100,10 +97,7 @@ impl AppRepository for PostgresAppRepository {
Ok(rows.into_iter().map(Into::into).collect())
}
async fn list_for_user(
&self,
user_id: AdminUserId,
) -> Result<Vec<App>, ScriptRepositoryError> {
async fn list_for_user(&self, user_id: AdminUserId) -> Result<Vec<App>, ScriptRepositoryError> {
let rows = sqlx::query_as::<_, AppRow>(
"SELECT a.id, a.slug, a.name, a.description, a.created_at, a.updated_at \
FROM apps a \

View File

@@ -223,6 +223,9 @@ mod tests {
let b = generate_api_key().expect("mint b");
assert_ne!(a.raw, b.raw);
assert_ne!(a.hash, b.hash);
assert_ne!(a.prefix, b.prefix, "32 random bytes → prefix collision is negligible");
assert_ne!(
a.prefix, b.prefix,
"32 random bytes → prefix collision is negligible"
);
}
}

View File

@@ -160,7 +160,10 @@ async fn logout(State(state): State<AuthState>, req: Request<Body>) -> Response
(StatusCode::NO_CONTENT, headers).into_response()
}
async fn me(State(state): State<AuthState>, Extension(principal): Extension<Principal>) -> Response {
async fn me(
State(state): State<AuthState>,
Extension(principal): Extension<Principal>,
) -> Response {
// /me consumes the resolved Principal directly; we re-fetch the
// user row only to surface a fresh username (it can change via
// PATCH while a session/key is still valid).

View File

@@ -272,7 +272,9 @@ mod tests {
#[tokio::test]
async fn populated_db_is_noop() {
let repo = InMemoryRepo::default();
repo.create("seeded", "x", InstanceRole::Owner).await.unwrap();
repo.create("seeded", "x", InstanceRole::Owner)
.await
.unwrap();
let env = BootstrapEnv {
username: Some("alice".into()),
password: Some("supersecret".into()),

View File

@@ -96,11 +96,7 @@ pub async fn require_authenticated(
/// `require_admin` keeps working without an immediate rename. New
/// wiring should call `require_authenticated`.
#[deprecated(note = "renamed to require_authenticated")]
pub async fn require_admin(
state: State<AuthState>,
req: Request<Body>,
next: Next,
) -> Response {
pub async fn require_admin(state: State<AuthState>, req: Request<Body>, next: Next) -> Response {
require_authenticated(state, req, next).await
}
@@ -164,10 +160,7 @@ async fn verify_session(
/// against the full `rest`. At most one match is expected; multiple
/// candidates with the same prefix is statistically negligible but
/// handled correctly (verify each, take the first match).
async fn verify_api_key(
state: &AuthState,
rest: &str,
) -> Result<Option<Principal>, InternalError> {
async fn verify_api_key(state: &AuthState, rest: &str) -> Result<Option<Principal>, InternalError> {
if rest.len() <= API_KEY_PREFIX_LEN {
return Ok(None);
}
@@ -224,7 +217,10 @@ async fn username_for(state: &AuthState, id: AdminUserId) -> Option<String> {
Ok(Some(u)) => Some(u.username),
Ok(None) => None,
Err(err) => {
tracing::warn!(?err, "username lookup for AuthedAdmin failed; skipping legacy ext");
tracing::warn!(
?err,
"username lookup for AuthedAdmin failed; skipping legacy ext"
);
None
}
}

View File

@@ -65,9 +65,9 @@ impl Capability {
#[must_use]
pub const fn app_id(self) -> Option<AppId> {
match self {
Self::InstanceCreateApp
| Self::InstanceManageUsers
| Self::InstanceManageSettings => None,
Self::InstanceCreateApp | Self::InstanceManageUsers | Self::InstanceManageSettings => {
None
}
Self::AppRead(id)
| Self::AppWriteScript(id)
| Self::AppWriteRoute(id)
@@ -85,9 +85,9 @@ impl Capability {
#[must_use]
pub const fn required_scope(self) -> Scope {
match self {
Self::InstanceCreateApp
| Self::InstanceManageUsers
| Self::InstanceManageSettings => Scope::InstanceAdmin,
Self::InstanceCreateApp | Self::InstanceManageUsers | Self::InstanceManageSettings => {
Scope::InstanceAdmin
}
Self::AppRead(_) => Scope::ScriptRead,
Self::AppWriteScript(_) => Scope::ScriptWrite,
Self::AppWriteRoute(_) => Scope::RouteWrite,
@@ -314,7 +314,12 @@ mod tests {
user_id: UserId,
app_id: AppId,
) -> Result<Option<AppRole>, AuthzError> {
Ok(self.memberships.lock().await.get(&(user_id, app_id)).copied())
Ok(self
.memberships
.lock()
.await
.get(&(user_id, app_id))
.copied())
}
}
@@ -361,25 +366,35 @@ mod tests {
Decision::Allow,
);
assert_eq!(
can(&repo, &p, Capability::InstanceManageUsers).await.unwrap(),
can(&repo, &p, Capability::InstanceManageUsers)
.await
.unwrap(),
Decision::Allow,
);
assert_eq!(
can(&repo, &p, Capability::InstanceManageSettings).await.unwrap(),
can(&repo, &p, Capability::InstanceManageSettings)
.await
.unwrap(),
Decision::Deny,
);
// Editor-like grants succeed
assert_eq!(
can(&repo, &p, Capability::AppWriteScript(app)).await.unwrap(),
can(&repo, &p, Capability::AppWriteScript(app))
.await
.unwrap(),
Decision::Allow,
);
assert_eq!(
can(&repo, &p, Capability::AppWriteRoute(app)).await.unwrap(),
can(&repo, &p, Capability::AppWriteRoute(app))
.await
.unwrap(),
Decision::Allow,
);
// App-admin grants do not
assert_eq!(
can(&repo, &p, Capability::AppManageDomains(app)).await.unwrap(),
can(&repo, &p, Capability::AppManageDomains(app))
.await
.unwrap(),
Decision::Deny,
);
assert_eq!(
@@ -418,10 +433,18 @@ mod tests {
let app = AppId::new();
repo.grant(p.user_id, app, AppRole::Viewer).await;
assert!(can(&repo, &p, Capability::AppRead(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppLogRead(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppRead(app))
.await
.unwrap()
.is_allow());
assert!(can(&repo, &p, Capability::AppLogRead(app))
.await
.unwrap()
.is_allow());
assert_eq!(
can(&repo, &p, Capability::AppWriteScript(app)).await.unwrap(),
can(&repo, &p, Capability::AppWriteScript(app))
.await
.unwrap(),
Decision::Deny
);
assert_eq!(
@@ -437,8 +460,14 @@ mod tests {
let app = AppId::new();
repo.grant(p.user_id, app, AppRole::Editor).await;
assert!(can(&repo, &p, Capability::AppWriteScript(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppWriteRoute(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppWriteScript(app))
.await
.unwrap()
.is_allow());
assert!(can(&repo, &p, Capability::AppWriteRoute(app))
.await
.unwrap()
.is_allow());
assert_eq!(
can(&repo, &p, Capability::AppAdmin(app)).await.unwrap(),
Decision::Deny
@@ -452,12 +481,20 @@ mod tests {
let app = AppId::new();
repo.grant(p.user_id, app, AppRole::AppAdmin).await;
assert!(can(&repo, &p, Capability::AppAdmin(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppManageDomains(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppAdmin(app))
.await
.unwrap()
.is_allow());
assert!(can(&repo, &p, Capability::AppManageDomains(app))
.await
.unwrap()
.is_allow());
// Membership in App A does NOT grant access to App B
let other_app = AppId::new();
assert_eq!(
can(&repo, &p, Capability::AppAdmin(other_app)).await.unwrap(),
can(&repo, &p, Capability::AppAdmin(other_app))
.await
.unwrap(),
Decision::Deny
);
}
@@ -473,9 +510,14 @@ mod tests {
scopes: Some(vec![Scope::ScriptRead]),
app_binding: None,
};
assert!(can(&repo, &p, Capability::AppRead(app)).await.unwrap().is_allow());
assert!(can(&repo, &p, Capability::AppRead(app))
.await
.unwrap()
.is_allow());
assert_eq!(
can(&repo, &p, Capability::AppWriteScript(app)).await.unwrap(),
can(&repo, &p, Capability::AppWriteScript(app))
.await
.unwrap(),
Decision::Deny
);
// Even though the user is owner — the key's scope set is the
@@ -502,7 +544,9 @@ mod tests {
.unwrap()
.is_allow());
assert_eq!(
can(&repo, &p, Capability::AppWriteScript(other_app)).await.unwrap(),
can(&repo, &p, Capability::AppWriteScript(other_app))
.await
.unwrap(),
Decision::Deny
);
}