| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- //! Schema contract for the `resource_servers` catalog and the per-client
- //! `oauth_clients.access_token_format` column (plan todo 2).
- //!
- //! Compose-first: the test connects to the shared external Postgres started by
- //! `docker compose -f compose.test.yaml up -d` and applies every embedded
- //! migration to a freshly created database, matching the rest of the migration
- //! suites.
- //!
- //! The single test name contains `resource_catalog_crud` so
- //! `cargo nextest run -E 'test(resource_catalog_crud)'` selects exactly it.
- mod common;
- use common::{TestError, insert_client, is_unique_violation};
- /// The catalog round-trips insert / list / disable, rejects a duplicate
- /// identifier, and `oauth_clients.access_token_format` accepts only the
- /// `opaque`/`jwt` pair while every existing row reads back `opaque`.
- #[tokio::test]
- async fn resource_catalog_crud() -> Result<(), TestError> {
- let pool = common::fresh_migrated_db().await?;
- // Insert -> read back -> list.
- let id = uuid::Uuid::new_v4();
- sqlx::query(
- "INSERT INTO resource_servers (id, identifier, description, created_at) \
- VALUES ($1, $2, $3, now())",
- )
- .bind(id)
- .bind("https://api.example.test")
- .bind("Example API")
- .execute(&pool)
- .await?;
- let (identifier, description, enabled): (String, String, bool) =
- sqlx::query_as("SELECT identifier, description, enabled FROM resource_servers WHERE id = $1")
- .bind(id)
- .fetch_one(&pool)
- .await?;
- assert_eq!(
- identifier, "https://api.example.test",
- "identifier round-trips"
- );
- assert_eq!(description, "Example API", "description round-trips");
- assert!(enabled, "a new resource server is enabled by default");
- let listed: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM resource_servers")
- .fetch_one(&pool)
- .await?;
- assert_eq!(listed, 1, "the inserted resource server is listed");
- // Disable round-trip.
- let updated = sqlx::query("UPDATE resource_servers SET enabled = false WHERE id = $1")
- .bind(id)
- .execute(&pool)
- .await?;
- assert_eq!(
- updated.rows_affected(),
- 1,
- "disable updates exactly one row"
- );
- let enabled_after: bool =
- sqlx::query_scalar("SELECT enabled FROM resource_servers WHERE id = $1")
- .bind(id)
- .fetch_one(&pool)
- .await?;
- assert!(!enabled_after, "the resource server is disabled");
- // A duplicate identifier is rejected by the unique constraint.
- let duplicate =
- sqlx::query("INSERT INTO resource_servers (id, identifier, created_at) VALUES ($1, $2, now())")
- .bind(uuid::Uuid::new_v4())
- .bind("https://api.example.test")
- .execute(&pool)
- .await
- .err();
- assert!(
- matches!(duplicate.as_ref(), Some(err) if is_unique_violation(err)),
- "duplicate identifier was accepted: {duplicate:?}"
- );
- // Omitted columns take their defaults (empty description, enabled true).
- let default_id = uuid::Uuid::new_v4();
- sqlx::query("INSERT INTO resource_servers (id, identifier, created_at) VALUES ($1, $2, now())")
- .bind(default_id)
- .bind("https://other.example.test")
- .execute(&pool)
- .await?;
- let (description, enabled): (String, bool) =
- sqlx::query_as("SELECT description, enabled FROM resource_servers WHERE id = $1")
- .bind(default_id)
- .fetch_one(&pool)
- .await?;
- assert_eq!(description, "", "description defaults to empty");
- assert!(enabled, "enabled defaults to true");
- // An existing client reads back `opaque` without setting the column.
- insert_client(
- &pool,
- uuid::Uuid::new_v4(),
- "resource-catalog-client",
- None,
- None,
- )
- .await?;
- let format: String =
- sqlx::query_scalar("SELECT access_token_format FROM oauth_clients WHERE client_id = $1")
- .bind("resource-catalog-client")
- .fetch_one(&pool)
- .await?;
- assert_eq!(
- format, "opaque",
- "an omitted access_token_format defaults to opaque"
- );
- // The `jwt` value is accepted.
- sqlx::query("UPDATE oauth_clients SET access_token_format = 'jwt' WHERE client_id = $1")
- .bind("resource-catalog-client")
- .execute(&pool)
- .await?;
- // An unknown format is rejected by the CHECK constraint.
- let bad =
- sqlx::query("UPDATE oauth_clients SET access_token_format = 'bogus' WHERE client_id = $1")
- .bind("resource-catalog-client")
- .execute(&pool)
- .await
- .err();
- assert!(
- matches!(bad.as_ref(), Some(sqlx::Error::Database(db)) if db.code().as_deref() == Some("23514")),
- "the CHECK must reject an unknown access_token_format: {bad:?}"
- );
- Ok(())
- }
|