From 2aab92af3116c1ef692b7bc3165519e9c0c1ac5b Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Tue, 26 May 2026 22:21:37 +0200 Subject: [PATCH] style: cargo fmt across Phase 3.5 changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- crates/manager-core/src/admin_user_repo.rs | 10 ++- crates/manager-core/src/admin_users_api.rs | 3 +- crates/manager-core/src/api_key_repo.rs | 9 +-- crates/manager-core/src/app_members_repo.rs | 5 +- crates/manager-core/src/app_repo.rs | 10 +-- crates/manager-core/src/auth.rs | 5 +- crates/manager-core/src/auth_api.rs | 5 +- crates/manager-core/src/auth_bootstrap.rs | 4 +- crates/manager-core/src/auth_middleware.rs | 16 ++-- crates/manager-core/src/authz.rs | 90 +++++++++++++++------ crates/picloud/src/lib.rs | 16 ++-- crates/picloud/src/main.rs | 5 +- crates/picloud/tests/authz.rs | 71 +++++++++++----- crates/shared/src/auth.rs | 6 +- 14 files changed, 166 insertions(+), 89 deletions(-) diff --git a/crates/manager-core/src/admin_user_repo.rs b/crates/manager-core/src/admin_user_repo.rs index 122d029..dfa8b22 100644 --- a/crates/manager-core/src/admin_user_repo.rs +++ b/crates/manager-core/src/admin_user_repo.rs @@ -383,8 +383,9 @@ impl TryFrom 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 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), + )?, }) } } diff --git a/crates/manager-core/src/admin_users_api.rs b/crates/manager-core/src/admin_users_api.rs index a1dd465..bd9354b 100644 --- a/crates/manager-core/src/admin_users_api.rs +++ b/crates/manager-core/src/admin_users_api.rs @@ -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); } diff --git a/crates/manager-core/src/api_key_repo.rs b/crates/manager-core/src/api_key_repo.rs index 3980100..343939e 100644 --- a/crates/manager-core/src/api_key_repo.rs +++ b/crates/manager-core/src/api_key_repo.rs @@ -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; + async fn expire_all_for_user(&self, user_id: AdminUserId) + -> Result; } pub struct PostgresApiKeyRepository { @@ -132,7 +130,8 @@ impl PostgresApiKeyRepository { #[async_trait] impl ApiKeyRepository for PostgresApiKeyRepository { async fn create(&self, key: NewApiKey) -> Result { - let scope_strings: Vec = key.scopes.iter().map(|s| s.as_str().to_string()).collect(); + let scope_strings: Vec = + 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) \ diff --git a/crates/manager-core/src/app_members_repo.rs b/crates/manager-core/src/app_members_repo.rs index a018299..d8af940 100644 --- a/crates/manager-core/src/app_members_repo.rs +++ b/crates/manager-core/src/app_members_repo.rs @@ -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), diff --git a/crates/manager-core/src/app_repo.rs b/crates/manager-core/src/app_repo.rs index 152eda9..c2523a2 100644 --- a/crates/manager-core/src/app_repo.rs +++ b/crates/manager-core/src/app_repo.rs @@ -27,10 +27,7 @@ pub trait AppRepository: Send + Sync { async fn list(&self) -> Result, 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, ScriptRepositoryError>; + async fn list_for_user(&self, user_id: AdminUserId) -> Result, ScriptRepositoryError>; async fn get_by_id(&self, id: AppId) -> Result, ScriptRepositoryError>; async fn get_by_slug(&self, slug: &str) -> Result, 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, ScriptRepositoryError> { + async fn list_for_user(&self, user_id: AdminUserId) -> Result, 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 \ diff --git a/crates/manager-core/src/auth.rs b/crates/manager-core/src/auth.rs index ac838bb..9203646 100644 --- a/crates/manager-core/src/auth.rs +++ b/crates/manager-core/src/auth.rs @@ -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" + ); } } diff --git a/crates/manager-core/src/auth_api.rs b/crates/manager-core/src/auth_api.rs index 1d1ca81..44ecb28 100644 --- a/crates/manager-core/src/auth_api.rs +++ b/crates/manager-core/src/auth_api.rs @@ -160,7 +160,10 @@ async fn logout(State(state): State, req: Request) -> Response (StatusCode::NO_CONTENT, headers).into_response() } -async fn me(State(state): State, Extension(principal): Extension) -> Response { +async fn me( + State(state): State, + Extension(principal): Extension, +) -> 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). diff --git a/crates/manager-core/src/auth_bootstrap.rs b/crates/manager-core/src/auth_bootstrap.rs index ed984b3..fd910c5 100644 --- a/crates/manager-core/src/auth_bootstrap.rs +++ b/crates/manager-core/src/auth_bootstrap.rs @@ -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()), diff --git a/crates/manager-core/src/auth_middleware.rs b/crates/manager-core/src/auth_middleware.rs index c300e48..754b5ce 100644 --- a/crates/manager-core/src/auth_middleware.rs +++ b/crates/manager-core/src/auth_middleware.rs @@ -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, - req: Request, - next: Next, -) -> Response { +pub async fn require_admin(state: State, req: Request, 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, InternalError> { +async fn verify_api_key(state: &AuthState, rest: &str) -> Result, InternalError> { if rest.len() <= API_KEY_PREFIX_LEN { return Ok(None); } @@ -224,7 +217,10 @@ async fn username_for(state: &AuthState, id: AdminUserId) -> Option { 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 } } diff --git a/crates/manager-core/src/authz.rs b/crates/manager-core/src/authz.rs index 0152fca..d066030 100644 --- a/crates/manager-core/src/authz.rs +++ b/crates/manager-core/src/authz.rs @@ -65,9 +65,9 @@ impl Capability { #[must_use] pub const fn app_id(self) -> Option { 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, 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 ); } diff --git a/crates/picloud/src/lib.rs b/crates/picloud/src/lib.rs index 3bf929d..52f1aab 100644 --- a/crates/picloud/src/lib.rs +++ b/crates/picloud/src/lib.rs @@ -12,12 +12,12 @@ use picloud_executor_core::{Engine, Limits}; use picloud_manager_core::{ admin_router, admins_router, api_keys_router, apps_api, apps_router, auth_router, compile_routes, migrations, require_authenticated, route_admin_router, AdminSessionRepository, - AdminState, AdminUserRepository, AdminsState, ApiKeyRepository, ApiKeysState, AppDomainRepository, - AppRepository, AppsState, AuthState, AuthzRepo, PostgresAdminSessionRepository, - PostgresAdminUserRepository, PostgresApiKeyRepository, PostgresAppDomainRepository, - PostgresAppMembersRepository, PostgresAppRepository, PostgresExecutionLogRepository, - PostgresExecutionLogSink, PostgresRouteRepository, PostgresScriptRepository, RepoResolver, - RouteAdminState, RouteRepository, SandboxCeiling, + AdminState, AdminUserRepository, AdminsState, ApiKeyRepository, ApiKeysState, + AppDomainRepository, AppRepository, AppsState, AuthState, AuthzRepo, + PostgresAdminSessionRepository, PostgresAdminUserRepository, PostgresApiKeyRepository, + PostgresAppDomainRepository, PostgresAppMembersRepository, PostgresAppRepository, + PostgresExecutionLogRepository, PostgresExecutionLogSink, PostgresRouteRepository, + PostgresScriptRepository, RepoResolver, RouteAdminState, RouteRepository, SandboxCeiling, }; use picloud_orchestrator_core::routing::{AppDomainTable, RouteTable}; use picloud_orchestrator_core::{ @@ -164,9 +164,7 @@ pub async fn build_app(pool: PgPool, auth: AuthDeps) -> anyhow::Result { keys: auth.keys.clone(), authz, }; - let api_keys_state = ApiKeysState { - keys: auth.keys, - }; + let api_keys_state = ApiKeysState { keys: auth.keys }; // /admin/auth/login + /logout are unguarded by design (login is how // you get in). /admin/auth/me applies the middleware internally so diff --git a/crates/picloud/src/main.rs b/crates/picloud/src/main.rs index 8e675af..08a71b3 100644 --- a/crates/picloud/src/main.rs +++ b/crates/picloud/src/main.rs @@ -100,7 +100,10 @@ async fn warn_on_multi_owner_install(users: &dyn AdminUserRepository) { } Ok(_) => {} Err(err) => { - tracing::warn!(?err, "could not count active owners for multi-owner startup check"); + tracing::warn!( + ?err, + "could not count active owners for multi-owner startup check" + ); } } } diff --git a/crates/picloud/tests/authz.rs b/crates/picloud/tests/authz.rs index 2718ee0..1e44921 100644 --- a/crates/picloud/tests/authz.rs +++ b/crates/picloud/tests/authz.rs @@ -57,7 +57,9 @@ async fn boot(pool: PgPool) -> Seeded { .await .expect("seed owner"); - let app = picloud::build_app(pool.clone(), auth).await.expect("build_app"); + let app = picloud::build_app(pool.clone(), auth) + .await + .expect("build_app"); let server = TestServer::new(app).expect("TestServer"); // Default app id (seeded by migration 0005). @@ -109,18 +111,33 @@ async fn login_token(server: &TestServer, username: &str, password: &str) -> Str /// at arbitrary roles. The API enforces "owners only create owners" /// which is correct production behavior but inconvenient for test /// fixtures. -async fn seed_user(pool: &PgPool, username: &str, password: &str, role: InstanceRole) -> AdminUserId { +async fn seed_user( + pool: &PgPool, + username: &str, + password: &str, + role: InstanceRole, +) -> AdminUserId { let repo = PostgresAdminUserRepository::new(pool.clone()); let hash = hash_password(password).expect("hash"); - repo.create(username, &hash, role).await.expect("seed user").id + repo.create(username, &hash, role) + .await + .expect("seed user") + .id } async fn grant_membership(pool: &PgPool, user: AdminUserId, app: AppId, role: AppRole) { let repo = PostgresAppMembersRepository::new(pool.clone()); - repo.upsert(app, user, role).await.expect("grant membership"); + repo.upsert(app, user, role) + .await + .expect("grant membership"); } -async fn create_script_via_api(server: &TestServer, token: &str, app_id: AppId, name: &str) -> Value { +async fn create_script_via_api( + server: &TestServer, + token: &str, + app_id: AppId, + name: &str, +) -> Value { let r = server .post("/api/v1/admin/scripts") .add_header("authorization", format!("Bearer {token}")) @@ -135,11 +152,7 @@ async fn create_script_via_api(server: &TestServer, token: &str, app_id: AppId, } /// Mint an API key for the caller — wraps POST /api-keys. -async fn mint_key( - server: &TestServer, - cred_token: &str, - body: Value, -) -> axum_test::TestResponse { +async fn mint_key(server: &TestServer, cred_token: &str, body: Value) -> axum_test::TestResponse { server .post("/api/v1/admin/api-keys") .add_header("authorization", format!("Bearer {cred_token}")) @@ -329,7 +342,10 @@ async fn bearer_and_cookie_produce_same_principal(pool: PgPool) { .await; via_key.assert_status_ok(); - assert_eq!(via_session.json::()["id"], via_key.json::()["id"]); + assert_eq!( + via_session.json::()["id"], + via_key.json::()["id"] + ); assert_eq!( via_session.json::()["username"], via_key.json::()["username"] @@ -352,7 +368,10 @@ async fn read_only_key_cannot_write_scripts(pool: PgPool) { ) .await; mint.assert_status(axum::http::StatusCode::CREATED); - let raw = mint.json::()["raw_token"].as_str().unwrap().to_string(); + let raw = mint.json::()["raw_token"] + .as_str() + .unwrap() + .to_string(); let denied = s .server @@ -399,7 +418,10 @@ async fn bound_key_cannot_escape_its_app(pool: PgPool) { ) .await; mint.assert_status(axum::http::StatusCode::CREATED); - let raw = mint.json::()["raw_token"].as_str().unwrap().to_string(); + let raw = mint.json::()["raw_token"] + .as_str() + .unwrap() + .to_string(); // Writing into the bound app: allowed. let ok = s @@ -473,7 +495,11 @@ async fn member_list_endpoints_filter_at_sql(pool: PgPool) { .iter() .map(|a| a["slug"].as_str().unwrap().to_string()) .collect(); - assert_eq!(app_slugs, vec!["default"], "member must see only their apps"); + assert_eq!( + app_slugs, + vec!["default"], + "member must see only their apps" + ); let scripts = s .server @@ -489,8 +515,7 @@ async fn member_list_endpoints_filter_at_sql(pool: PgPool) { .map(|s| s["name"].as_str().unwrap().to_string()) .collect(); assert!( - names.iter().any(|n| n == "default-script") - && !names.iter().any(|n| n == "secret-script"), + names.iter().any(|n| n == "default-script") && !names.iter().any(|n| n == "secret-script"), "member listing leaked another app's script: {names:?}" ); } @@ -515,7 +540,10 @@ async fn deactivating_user_revokes_their_api_keys(pool: PgPool) { ) .await; mint.assert_status(axum::http::StatusCode::CREATED); - let raw = mint.json::()["raw_token"].as_str().unwrap().to_string(); + let raw = mint.json::()["raw_token"] + .as_str() + .unwrap() + .to_string(); // Key works. let before = s @@ -549,7 +577,9 @@ async fn deactivating_user_revokes_their_api_keys(pool: PgPool) { rows.iter().all(|r| r.expires_at.is_some()), "every key must have an expiry after deactivation" ); - assert!(rows.iter().all(|r| r.expires_at.unwrap() <= chrono::Utc::now())); + assert!(rows + .iter() + .all(|r| r.expires_at.unwrap() <= chrono::Utc::now())); } // ---------------------------------------------------------------------------- @@ -571,7 +601,10 @@ async fn bound_key_with_instance_scope_is_rejected(pool: PgPool) { "app_id": s.default_app.to_string(), })) .await; - assert_eq!(r.status_code(), axum::http::StatusCode::UNPROCESSABLE_ENTITY); + assert_eq!( + r.status_code(), + axum::http::StatusCode::UNPROCESSABLE_ENTITY + ); let body: Value = r.json(); assert!( body["error"].as_str().unwrap().contains("bound"), diff --git a/crates/shared/src/auth.rs b/crates/shared/src/auth.rs index 7957d0c..1b6cf40 100644 --- a/crates/shared/src/auth.rs +++ b/crates/shared/src/auth.rs @@ -196,7 +196,11 @@ mod tests { #[test] fn instance_role_round_trip() { - for role in [InstanceRole::Owner, InstanceRole::Admin, InstanceRole::Member] { + for role in [ + InstanceRole::Owner, + InstanceRole::Admin, + InstanceRole::Member, + ] { assert_eq!(InstanceRole::from_db_str(role.as_str()), Some(role)); } assert_eq!(InstanceRole::from_db_str("bogus"), None);