yavsc/src/Yavsc.Org/Contants.cs

46 lines
2.6 KiB
C#
Raw Normal View History

2026-06-06 21:30:41 +01:00
2026-06-25 20:22:41 +01:00
using IdentityServer8.EntityFramework.Entities;
2026-06-06 21:30:41 +01:00
public static class Constants
{
// ApiScopes seeded explicitly by EnsureDefaultApplicationScopes.
// IMPORTANT: only application-defined API scopes go here. Do NOT add
// "openid", "profile", or "offline_access" — those are identity scopes
// and IdentityServer8 refuses to start when an IdentityResource and an
// ApiScope share the same Name ("Found identity scopes and API scopes
// that use the same names"). 'openid' and 'profile' are seeded as
// IdentityResources via IdentityResources.OpenId().ToEntity() /
// IdentityResources.Profile().ToEntity() further down;
// 'offline_access' is handled by IdentityServer8 itself and never
// needs an explicit ApiScope row.
public static readonly string[] BuildInApiScopes = {
2026-06-25 20:22:41 +01:00
"admin", "moderation", "performer", "client" };
Seed ApiResources + ApiResourceScopes, run seeder on every startup The previous commit (37440171) added ApiScope rows for the application scopes (admin, moderation, performer, client, blogs). It was a partial fix: an ApiScope alone is not a valid scope from DefaultResourceValidator's point of view. The validator only recognises a scope if it can find an ApiResource that exposes it (via ApiResourceScopes). Without that link, /connect/authorize rejects the request with 'Scope X not found in store', even though the scope row exists. This is what killed the PostIt login in production. This commit: 1. Extends Constants.ApiResourcesScopes with ResourceName + ResourceDisplayName. Topology: one ApiResource per scope ('admin' resource exposes 'admin' scope, 'blogs' resource exposes 'blogs' scope, etc.) — keeps each scope's audience specific if/when we split products across separate audiences. 2. Ensures EnsureDefaultApplicationScopes also inserts the matching ApiResource rows (deduped on Name) and ApiResourceScope rows linking each resource to its scope. Idempotent: missing rows are added, nothing is removed. 3. Removes the b.UseSeeding(...) call inside AddConfigurationStore. EF Core's UseSeeding callback only fires when the database is empty, so on a live ConfigurationDb (which already had Clients and ClientScopes) it never ran — that is why the previous commit had no visible effect on production. The seeder is now invoked explicitly from MigrateDatabase via SeedConfigurationDatabase, which resolves ConfigurationDbContext from the DI and runs EnsureDefaultConfiguration on every startup, regardless of whether the database was fresh. Seeding failures are caught and logged (best-effort) so a misconfigured seeder cannot prevent the host from booting. Live data on yavsc.pschneider.fr is still missing the ApiResource/ApiResourceScope rows; a one-shot SQL or a redeploy with this commit is needed before PostIt can log in. Production fix to follow.
2026-06-25 21:28:13 +01:00
// One ApiResource per application scope. Each scope is exposed by
// exactly one resource, named after the scope ("admin" -> "admin"
// resource, "blogs" -> "blogs" resource). IdentityServer8's
// DefaultResourceValidator only recognises a scope at the
// /connect/authorize endpoint if it can find an ApiResource that
// exposes it — an orphaned ApiScope row is rejected with
// "Scope X not found in store" even though the row exists.
2026-06-25 20:22:41 +01:00
public static readonly ApiResourceScopeSpecification[] ApiResourcesScopes = {
Seed ApiResources + ApiResourceScopes, run seeder on every startup The previous commit (37440171) added ApiScope rows for the application scopes (admin, moderation, performer, client, blogs). It was a partial fix: an ApiScope alone is not a valid scope from DefaultResourceValidator's point of view. The validator only recognises a scope if it can find an ApiResource that exposes it (via ApiResourceScopes). Without that link, /connect/authorize rejects the request with 'Scope X not found in store', even though the scope row exists. This is what killed the PostIt login in production. This commit: 1. Extends Constants.ApiResourcesScopes with ResourceName + ResourceDisplayName. Topology: one ApiResource per scope ('admin' resource exposes 'admin' scope, 'blogs' resource exposes 'blogs' scope, etc.) — keeps each scope's audience specific if/when we split products across separate audiences. 2. Ensures EnsureDefaultApplicationScopes also inserts the matching ApiResource rows (deduped on Name) and ApiResourceScope rows linking each resource to its scope. Idempotent: missing rows are added, nothing is removed. 3. Removes the b.UseSeeding(...) call inside AddConfigurationStore. EF Core's UseSeeding callback only fires when the database is empty, so on a live ConfigurationDb (which already had Clients and ClientScopes) it never ran — that is why the previous commit had no visible effect on production. The seeder is now invoked explicitly from MigrateDatabase via SeedConfigurationDatabase, which resolves ConfigurationDbContext from the DI and runs EnsureDefaultConfiguration on every startup, regardless of whether the database was fresh. Seeding failures are caught and logged (best-effort) so a misconfigured seeder cannot prevent the host from booting. Live data on yavsc.pschneider.fr is still missing the ApiResource/ApiResourceScope rows; a one-shot SQL or a redeploy with this commit is needed before PostIt can log in. Production fix to follow.
2026-06-25 21:28:13 +01:00
new ApiResourceScopeSpecification { ScopeName = "admin", Description = "Admin access", ResourceName = "admin", ResourceDisplayName = "Admin API" },
new ApiResourceScopeSpecification { ScopeName = "moderation", Description = "Moderation access", ResourceName = "moderation", ResourceDisplayName = "Moderation API" },
new ApiResourceScopeSpecification { ScopeName = "performer", Description = "Performer access", ResourceName = "performer", ResourceDisplayName = "Performer API" },
new ApiResourceScopeSpecification { ScopeName = "client", Description = "Client access", ResourceName = "client", ResourceDisplayName = "Client API" },
new ApiResourceScopeSpecification { ScopeName = "blogs", Description = "Blogs access", ResourceName = "blogs", ResourceDisplayName = "Yavsc Blogs API" }
2026-06-25 20:22:41 +01:00
};
}
public class ApiResourceScopeSpecification
{
public string ScopeName { get; set; }
public string Description { get; set; }
Seed ApiResources + ApiResourceScopes, run seeder on every startup The previous commit (37440171) added ApiScope rows for the application scopes (admin, moderation, performer, client, blogs). It was a partial fix: an ApiScope alone is not a valid scope from DefaultResourceValidator's point of view. The validator only recognises a scope if it can find an ApiResource that exposes it (via ApiResourceScopes). Without that link, /connect/authorize rejects the request with 'Scope X not found in store', even though the scope row exists. This is what killed the PostIt login in production. This commit: 1. Extends Constants.ApiResourcesScopes with ResourceName + ResourceDisplayName. Topology: one ApiResource per scope ('admin' resource exposes 'admin' scope, 'blogs' resource exposes 'blogs' scope, etc.) — keeps each scope's audience specific if/when we split products across separate audiences. 2. Ensures EnsureDefaultApplicationScopes also inserts the matching ApiResource rows (deduped on Name) and ApiResourceScope rows linking each resource to its scope. Idempotent: missing rows are added, nothing is removed. 3. Removes the b.UseSeeding(...) call inside AddConfigurationStore. EF Core's UseSeeding callback only fires when the database is empty, so on a live ConfigurationDb (which already had Clients and ClientScopes) it never ran — that is why the previous commit had no visible effect on production. The seeder is now invoked explicitly from MigrateDatabase via SeedConfigurationDatabase, which resolves ConfigurationDbContext from the DI and runs EnsureDefaultConfiguration on every startup, regardless of whether the database was fresh. Seeding failures are caught and logged (best-effort) so a misconfigured seeder cannot prevent the host from booting. Live data on yavsc.pschneider.fr is still missing the ApiResource/ApiResourceScope rows; a one-shot SQL or a redeploy with this commit is needed before PostIt can log in. Production fix to follow.
2026-06-25 21:28:13 +01:00
// The ApiResource that exposes this scope. IdentityServer8 requires
// scopes to be linked back to an ApiResource via the ApiResourceScopes
// table — without that link the scope is considered unknown.
public string ResourceName { get; set; }
public string ResourceDisplayName { get; set; }
2026-06-06 21:30:41 +01:00
}