This commit is contained in:
Paul Schneider 2026-04-19 20:36:03 +01:00
commit 5620213cf5
5 changed files with 33 additions and 47 deletions

View file

@ -2,9 +2,9 @@ namespace Yavsc.Models.Billing
{ {
public static class BillingCodes public static class BillingCodes
{ {
public const string Rdv = "Rdv"; public const string Rdv = nameof(Rdv);
public const string MBrush = "MBrush"; public const string MBrush = nameof(MBrush);
public const string Brush = "Brush"; public const string Brush = nameof(Brush);
} }
} }

View file

@ -46,26 +46,15 @@ namespace Yavsc.Helpers
lock (_billingLock) lock (_billingLock)
{ {
string typeName = typeof(T).Name; string typeName = typeof(T).Name;
if (BillingService.GlobalBillingMap.ContainsKey(typeName))
// Only add if not already present (idempotent operation)
if (!BillingService.Billing.ContainsKey(code))
{
BillingService.Billing.Add(code, getter);
}
else if (!BillingService.GlobalBillingMap.ContainsKey(typeName) ||
BillingService.GlobalBillingMap[typeName] != code)
{
throw new InvalidOperationException($"Billing setup: code '{code}' already registered");
}
if (!BillingService.GlobalBillingMap.ContainsKey(typeName))
{
BillingService.GlobalBillingMap.Add(typeName, code);
}
else if (BillingService.GlobalBillingMap[typeName] != code)
{ {
throw new InvalidOperationException($"Billing setup: type '{typeName}' already registered with different code"); throw new InvalidOperationException($"Billing setup: type '{typeName}' already registered with different code");
} }
if (BillingService.Billing.ContainsKey(code))
{
throw new InvalidOperationException($"Billing setup: code '{code}' already registered with different type");
}
BillingService.Billing.Add(code, getter);
} }
} }

View file

@ -348,7 +348,6 @@ namespace Yavsc.Models
public DbSet<PersistedGrant> PersistedGrants { get; set; } public DbSet<PersistedGrant> PersistedGrants { get; set; }
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; } public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
public DbSet<YavscApiScope> YavscApiScopes { get; set; }
public string NOW_SQL { get; private set; } public string NOW_SQL { get; private set; }
} }
} }

View file

@ -39,7 +39,7 @@ namespace yavscTests
var firstRegistrar = new Func<ApplicationDbContext, long, IDecidableQuery>((db, id) => var firstRegistrar = new Func<ApplicationDbContext, long, IDecidableQuery>((db, id) =>
db.HairCutQueries.Include(q => q.Prestation).Include(q => q.Regularisation).Single(q => q.Id == id)); db.HairCutQueries.Include(q => q.Prestation).Include(q => q.Regularisation).Single(q => q.Id == id));
const string testCode = "TestBrush"; const string testCode = "Brush";
Assert.Throws<InvalidOperationException>(() => Assert.Throws<InvalidOperationException>(() =>
WorkflowHelpers.RegisterBilling<HairCutQuery>(testCode, firstRegistrar)); WorkflowHelpers.RegisterBilling<HairCutQuery>(testCode, firstRegistrar));

View file

@ -155,7 +155,9 @@ namespace isnd.tests
["Smtp:Host"] = "localhost", ["Smtp:Host"] = "localhost",
["Smtp:Port"] = "25", ["Smtp:Port"] = "25",
["Smtp:SenderName"] = "Yavsc Test", ["Smtp:SenderName"] = "Yavsc Test",
["Smtp:SenderEmail"] = "test@example.com" ["Smtp:SenderEmail"] = "test@example.com",
["Site:Audience"] = "https://localhost",
["Site:Authority"] = "https://localhost"
}); });
// Configure Kestrel for HTTPS with self-signed certificate on a dynamic port // Configure Kestrel for HTTPS with self-signed certificate on a dynamic port
@ -207,7 +209,13 @@ namespace isnd.tests
{ {
Name = "test", Name = "test",
Enabled = true, Enabled = true,
DisplayName = "Test API Scope" DisplayName = "Test API Scope",
Description = "Scope for testing purposes",
UserClaims = new List<IdentityServer8.EntityFramework.Entities.ApiScopeClaim>
{
new IdentityServer8.EntityFramework.Entities.ApiScopeClaim { Type = "role" },
new IdentityServer8.EntityFramework.Entities.ApiScopeClaim { Type = "email" }
}
}); });
// Add a basic API resource for the test scope // Add a basic API resource for the test scope
@ -267,7 +275,7 @@ namespace isnd.tests
private void AddAuthorizedClient(IServiceScope scope, string testClientId, string testClientSecret) private void AddAuthorizedClient(IServiceScope scope, string testClientId, string testClientSecret)
{ {
var configDb = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>(); var configDb = scope.ServiceProvider.GetRequiredService<IdentityServer8.EntityFramework.DbContexts.ConfigurationDbContext>();
if (configDb == null) if (configDb == null)
throw new InvalidOperationException("ConfigurationDbContext is not available for IdentityServer client seeding."); throw new InvalidOperationException("ConfigurationDbContext is not available for IdentityServer client seeding.");
@ -276,14 +284,25 @@ namespace isnd.tests
ClientId = testClientId, ClientId = testClientId,
AccessTokenLifetime = 3600000, AccessTokenLifetime = 3600000,
AccessTokenType = 1, AccessTokenType = 1,
BackChannelLogoutUri = SiteSettings!.Audience,
ClientName = "Testing client", ClientName = "Testing client",
Enabled = true, Enabled = true,
RequireClientSecret = true RequireClientSecret = true
}; };
configDb.Clients.Add(testingClient); configDb.Set<Client>().Add(testingClient);
configDb.SaveChanges(); configDb.SaveChanges();
var apiScope = new IdentityServer8.EntityFramework.Entities.ApiScope
{
Name = "test",
DisplayName = "Test Scope",
Description = "Scope for testing",
Enabled = true,
Required = false,
ShowInDiscoveryDocument = true,
Emphasize = false
};
configDb.Set<IdentityServer8.EntityFramework.Entities.ApiScope>().Add(apiScope);
ClientSecret secret = new ClientSecret ClientSecret secret = new ClientSecret
{ {
Value = testClientSecret.Sha256(), Value = testClientSecret.Sha256(),
@ -292,12 +311,6 @@ namespace isnd.tests
}; };
configDb.Set<ClientSecret>().Add(secret); configDb.Set<ClientSecret>().Add(secret);
configDb.Set<ClientCorsOrigin>().Add(new ClientCorsOrigin
{
ClientId = testingClient.Id,
Origin = SiteSettings!.Audience
});
configDb.Set<ClientGrantType>().Add(new ClientGrantType configDb.Set<ClientGrantType>().Add(new ClientGrantType
{ {
ClientId = testingClient.Id, ClientId = testingClient.Id,
@ -308,26 +321,11 @@ namespace isnd.tests
ClientId = testingClient.Id, ClientId = testingClient.Id,
GrantType = "password" GrantType = "password"
}); });
configDb.Set<ClientGrantType>().Add(new ClientGrantType
{
ClientId = testingClient.Id,
GrantType = "code"
});
configDb.Set<ClientScope>().Add(new ClientScope configDb.Set<ClientScope>().Add(new ClientScope
{ {
ClientId = testingClient.Id, ClientId = testingClient.Id,
Scope = "test" Scope = "test"
}); });
configDb.Set<IdentityServer8.EntityFramework.Entities.ApiScope>().Add(new IdentityServer8.EntityFramework.Entities.ApiScope
{
Name = "test",
Enabled = true
});
configDb.Set<ClientRedirectUri>().Add(new ClientRedirectUri
{
ClientId = testingClient.Id,
RedirectUri = SiteSettings!.Audience
});
configDb.SaveChanges(); configDb.SaveChanges();
} }