Skip to content

Commit

Permalink
Merge pull request #904 from dlcs/feature/default_storagepolicy
Browse files Browse the repository at this point in the history
Create default storagePolicy on setup
  • Loading branch information
donaldgray authored Oct 16, 2024
2 parents 3a541a3 + 51e2a5a commit bcbcd53
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 35 deletions.
15 changes: 9 additions & 6 deletions src/protagonist/API.Tests/Integration/ApplicationTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using API.Client;
using API.Tests.Integration.Infrastructure;
using DLCS.HydraModel;
using DLCS.Repository;
using Microsoft.EntityFrameworkCore;
Expand All @@ -11,17 +9,17 @@
namespace API.Tests.Integration;

[Trait("Category", "Integration")]
[Collection(CollectionDefinitions.DatabaseCollection.CollectionName)]
public class ApplicationTests : IClassFixture<ProtagonistAppFactory<Startup>>
{
private readonly HttpClient httpClient;
private readonly DlcsContext dlcsContext;

public ApplicationTests(DlcsDatabaseFixture dbFixture, ProtagonistAppFactory<Startup> factory)
public ApplicationTests(ProtagonistAppFactory<Startup> factory)
{
var dbFixture = new DlcsDefaultDatabaseFixture();
dbFixture.InitializeAsync().Wait();
dlcsContext = dbFixture.DbContext;
httpClient = factory.WithConnectionString(dbFixture.ConnectionString).CreateClient();
dbFixture.CleanUp();
}

[Fact]
Expand All @@ -39,7 +37,7 @@ public async Task SetupApplication_Fail_Customer1AlreadyExists()
}

[Fact]
public async Task SetupApplication_Success_CreatesCustomerAndCounter()
public async Task SetupApplication_Success_CreatesCustomerCounterAndStoragePolicy()
{
// Act
var response = await httpClient.PostAsync("/setup", null!);
Expand All @@ -53,5 +51,10 @@ public async Task SetupApplication_Success_CreatesCustomerAndCounter()
(await dlcsContext.EntityCounters
.AnyAsync(c => c.Scope == "1" && c.Customer == 1 && c.Type == "space"))
.Should().BeTrue();

// Note: -99 value comes from appsttings.Testing.json
var storagePolicy = await dlcsContext.StoragePolicies.SingleAsync(s => s.Id == "default");
storagePolicy.MaximumNumberOfStoredImages.Should().Be(-99);
storagePolicy.MaximumTotalSizeOfStoredImages.Should().Be(-99);
}
}
4 changes: 3 additions & 1 deletion src/protagonist/API.Tests/appsettings.Testing.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"DLCS": {
"ApiRoot": "https://api.dlcs.digirati.io",
"ResourceRoot": "https://dlcs.digirati.io",
"EngineRoot": "http://engine.dlcs.digirati.io"
"EngineRoot": "http://engine.dlcs.digirati.io",
"DefaultPolicyMaxNumber": -99,
"DefaultPolicyMaxSize": -99
},
"PageSize": 100,
"ApiSalt": "this-is-a-salt",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using API.Auth;
using API.Features.Customer.Requests;
using API.Settings;
using DLCS.Core.Settings;
using DLCS.Model;
using DLCS.Model.Storage;
using DLCS.Repository;
using DLCS.Repository.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace API.Features.Application.Requests;

Expand All @@ -20,13 +24,15 @@ public class SetupApplicationHandler : IRequestHandler<SetupApplication, CreateA
private readonly DlcsContext dbContext;
private readonly ApiKeyGenerator apiKeyGenerator;
private readonly IEntityCounterRepository entityCounterRepository;
private readonly DlcsSettings dlcsSettings;

public SetupApplicationHandler(DlcsContext dbContext, ApiKeyGenerator apiKeyGenerator,
IEntityCounterRepository entityCounterRepository)
IEntityCounterRepository entityCounterRepository, IOptions<ApiSettings> apiOptions)
{
this.dbContext = dbContext;
this.apiKeyGenerator = apiKeyGenerator;
this.entityCounterRepository = entityCounterRepository;
dlcsSettings = apiOptions.Value.DLCS;
}

public async Task<CreateApiKeyResult> Handle(SetupApplication request, CancellationToken cancellationToken)
Expand All @@ -48,14 +54,26 @@ public async Task<CreateApiKeyResult> Handle(SetupApplication request, Cancellat
};
var (apiKey, apiSecret) = apiKeyGenerator.CreateApiKey(adminCustomer);
adminCustomer.Keys = new[] { apiKey };

await dbContext.Customers.AddAsync(adminCustomer, cancellationToken);

await CreateDefaultStoragePolicy(cancellationToken);
var updateCount = await dbContext.SaveChangesAsync(cancellationToken);

await entityCounterRepository.Create(adminCustomer.Id, KnownEntityCounters.CustomerSpaces, adminCustomer.Id.ToString());

return updateCount == 1
return updateCount == 2
? CreateApiKeyResult.Success(apiKey, apiSecret)
: CreateApiKeyResult.Fail("Error creating customer");
}

private async Task CreateDefaultStoragePolicy(CancellationToken cancellationToken)
{
var storagePolicy = new StoragePolicy
{
Id = StoragePolicy.DefaultStoragePolicyName,
MaximumNumberOfStoredImages = dlcsSettings.DefaultPolicyMaxNumber,
MaximumTotalSizeOfStoredImages = dlcsSettings.DefaultPolicyMaxSize,
};
await dbContext.StoragePolicies.AddAsync(storagePolicy, cancellationToken);
}
}
14 changes: 13 additions & 1 deletion src/protagonist/DLCS.Core/Settings/DlcsSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,16 @@ public class DlcsSettings
/// List of valid issuers of JWT for authentication
/// </summary>
public string[] JwtValidIssuers { get; set; } = Array.Empty<string>();
}

/// <summary>
/// Max number of stored items for "default" storage policy
/// </summary>
/// <remarks>These are used during 1 off setup only</remarks>
public long DefaultPolicyMaxNumber { get; set; } = 1000000000;

/// <summary>
/// Max number of stored bytes for "default" storage policy
/// </summary>
/// <remarks>These are used during 1 off setup only</remarks>
public long DefaultPolicyMaxSize { get; set; } = 1000000000000000;
}
4 changes: 3 additions & 1 deletion src/protagonist/DLCS.Model/Storage/StoragePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
namespace DLCS.Model.Storage;

[DebuggerDisplay("{Id}")]
public partial class StoragePolicy
public class StoragePolicy
{
public string Id { get; set; }
public long MaximumNumberOfStoredImages { get; set; }
public long MaximumTotalSizeOfStoredImages { get; set; }

public const string DefaultStoragePolicyName = "default";
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ await dlcsContext.CustomerStorages.SingleOrDefaultAsync(cs =>

if (spaceId == 0)
{
storageForSpace.StoragePolicy = "default"; // this isn't set on Customer
storageForSpace.StoragePolicy = StoragePolicy.DefaultStoragePolicyName; // this isn't set on Customer
// This space0 row isn't created when a customer is created, either - but should it?
}

Expand Down
50 changes: 28 additions & 22 deletions src/protagonist/Test.Helpers/Integration/DlcsDatabaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Threading.Tasks;
using DLCS.Model.Auth.Entities;
using DLCS.Model.Customers;
using DLCS.Model.DeliveryChannels;
using DLCS.Model.Policies;
using DLCS.Model.Spaces;
using DLCS.Model.Storage;
Expand All @@ -20,27 +19,9 @@ namespace Test.Helpers.Integration;
/// Xunit fixture that manages lifecycle for Postgres 12 container with basic migration applied.
/// Seeds Customer 99 with 1 space and default thumbnailPolicy
/// </summary>
public class DlcsDatabaseFixture : IAsyncLifetime
public class DlcsDatabaseFixture : DlcsDefaultDatabaseFixture
{
private readonly PostgreSqlTestcontainer postgresContainer;

public DlcsContext DbContext { get; private set; }
public string ConnectionString { get; private set; }

public DlcsDatabaseFixture()
{
var postgresBuilder = new TestcontainersBuilder<PostgreSqlTestcontainer>()
.WithDatabase(new PostgreSqlTestcontainerConfiguration("postgres:13-alpine")
{
Database = "db",
Password = "postgres_pword",
Username = "postgres"
})
.WithCleanUp(true)
.WithLabel("protagonist_test", "True");

postgresContainer = postgresBuilder.Build();
}
protected override Task InitialiseDb() => SeedCustomer();

/// <summary>
/// Delete any standing data - leaves data set in Seed method
Expand Down Expand Up @@ -189,6 +170,31 @@ await DbContext.Roles.AddAsync(new Role

await DbContext.SaveChangesAsync();
}
}

public class DlcsDefaultDatabaseFixture : IAsyncLifetime
{
private readonly PostgreSqlTestcontainer postgresContainer;

public DlcsContext DbContext { get; private set; }
public string ConnectionString { get; private set; }

public DlcsDefaultDatabaseFixture()
{
var postgresBuilder = new TestcontainersBuilder<PostgreSqlTestcontainer>()
.WithDatabase(new PostgreSqlTestcontainerConfiguration("postgres:13-alpine")
{
Database = "db",
Password = "postgres_pword",
Username = "postgres"
})
.WithCleanUp(true)
.WithLabel("protagonist_test", "True");

postgresContainer = postgresBuilder.Build();
}

protected virtual Task InitialiseDb() => Task.CompletedTask;

public async Task InitializeAsync()
{
Expand All @@ -198,7 +204,7 @@ public async Task InitializeAsync()
await postgresContainer.StartAsync();
SetPropertiesFromContainer();
await DbContext.Database.MigrateAsync();
await SeedCustomer();
await InitialiseDb();
}
catch (Exception ex)
{
Expand Down

0 comments on commit bcbcd53

Please sign in to comment.