From a1fdab82cc34d4b862225d9c7792ab97ca5aa4ba Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 17:56:48 +0100 Subject: [PATCH 01/13] Added full E2E test --- .../Altinn.Broker.Tests.csproj | 3 +- .../FileControllerTests.cs | 78 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Test/Altinn.Broker.Tests/FileControllerTests.cs diff --git a/Test/Altinn.Broker.Tests/Altinn.Broker.Tests.csproj b/Test/Altinn.Broker.Tests/Altinn.Broker.Tests.csproj index b01f362f..3c39a1b9 100644 --- a/Test/Altinn.Broker.Tests/Altinn.Broker.Tests.csproj +++ b/Test/Altinn.Broker.Tests/Altinn.Broker.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -10,6 +10,7 @@ + diff --git a/Test/Altinn.Broker.Tests/FileControllerTests.cs b/Test/Altinn.Broker.Tests/FileControllerTests.cs new file mode 100644 index 00000000..e076a7c3 --- /dev/null +++ b/Test/Altinn.Broker.Tests/FileControllerTests.cs @@ -0,0 +1,78 @@ +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json; + +using Altinn.Broker.Core.Models; +using Altinn.Broker.Enums; +using Altinn.Broker.Models; + +using Microsoft.AspNetCore.Mvc.Testing; + +namespace Altinn.Broker.Tests; +public class FileControllerTests : IClassFixture> +{ + private readonly WebApplicationFactory _factory; + private readonly HttpClient _client; + private readonly JsonSerializerOptions _responseSerializerOptions; + + public FileControllerTests(WebApplicationFactory factory) + { + _factory = factory; + _client = factory.CreateClient(); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMTkyOjk5MTgyNTgyNyJ9.exFSD-mL1fzoWhg8IKcVeCeEyJ5qpABPU9A1AXHDa_k"); + _responseSerializerOptions = new JsonSerializerOptions(new JsonSerializerOptions() + { + PropertyNameCaseInsensitive = true + }); + _responseSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter()); + } + + + [Fact] + public async Task WhenAllIsOk_NormalFlow_Success() + { + var initializeFileResponse = await _client.PostAsJsonAsync("broker/api/v1/file", new FileInitalizeExt() + { + Checksum = null, + FileName = "input.txt", + PropertyList = [], + Recipients = new List { "974761076" }, + Sender = "991825827", + SendersFileReference = "test-data" + }); + var fileId = await initializeFileResponse.Content.ReadAsStringAsync(); + + var initializedFile = await _client.GetFromJsonAsync($"broker/api/v1/file/{fileId}", _responseSerializerOptions); + Assert.NotNull(initializedFile); + Assert.True(initializedFile.FileStatus == FileStatusExt.Initialized); + + var uploadedFileBytes = Encoding.UTF8.GetBytes("This is the contents of the uploaded file"); + using (var content = new ByteArrayContent(uploadedFileBytes)) + { + content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); + var uploadResponse = await _client.PostAsync($"broker/api/v1/file/{fileId}/upload", content); + Assert.True(uploadResponse.IsSuccessStatusCode); + } + + var uploadedFile = await _client.GetFromJsonAsync($"broker/api/v1/file/{fileId}", _responseSerializerOptions); + Assert.NotNull(uploadedFile); + Assert.True(uploadedFile.FileStatus == FileStatusExt.Published); // When running integration test this happens instantly as of now. + + var downloadedFile = await _client.GetAsync($"broker/api/v1/file/{fileId}/download"); + var downloadedFileBytes = await downloadedFile.Content.ReadAsByteArrayAsync(); + Assert.Equal(uploadedFileBytes, downloadedFileBytes); + + var downloadedFileDetails = await _client.GetFromJsonAsync($"broker/api/v1/file/{fileId}/details", _responseSerializerOptions); + Assert.NotNull(downloadedFileDetails); + Assert.True(downloadedFileDetails.FileStatus == FileStatusExt.Published); + Assert.Contains(downloadedFileDetails.RecipientFileStatusHistory, recipient => recipient.RecipientFileStatusCode == RecipientFileStatusExt.DownloadStarted); + + await _client.PostAsync($"broker/api/v1/file/{fileId}/confirmdownload", null); + + var confirmedFileDetails = await _client.GetFromJsonAsync($"broker/api/v1/file/{fileId}/details", _responseSerializerOptions); + Assert.NotNull(confirmedFileDetails); + Assert.True(confirmedFileDetails.FileStatus == FileStatusExt.AllConfirmedDownloaded); + Assert.Contains(confirmedFileDetails.RecipientFileStatusHistory, recipient => recipient.RecipientFileStatusCode == RecipientFileStatusExt.DownloadConfirmed); + } +} From a6708065376fab30e34f53702a2632684a1378f3 Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 17:57:23 +0100 Subject: [PATCH 02/13] Fixed our method for determining if we are in development or test --- .../Azure/AzureBrokerStorageService.cs | 7 +++++-- src/Altinn.Broker/Program.cs | 9 ++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs index 0f37932d..69ff6377 100644 --- a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs +++ b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs @@ -2,6 +2,7 @@ using Altinn.Broker.Core.Services; using Altinn.Broker.Repositories; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; namespace Altinn.Broker.Integrations.Azure; @@ -9,12 +10,14 @@ public class AzureBrokerStorageService : IBrokerStorageService { private readonly IFileStore _fileStore; private readonly IResourceManager _resourceManager; + private readonly IHostEnvironment _hostEnvironment; private readonly AzureStorageOptions _azureStorageOptions; - public AzureBrokerStorageService(IFileStore fileStore, IResourceManager resourceManager, IOptions options) + public AzureBrokerStorageService(IFileStore fileStore, IResourceManager resourceManager, IHostEnvironment hostEnvironment, IOptions options) { _fileStore = fileStore; _resourceManager = resourceManager; + _hostEnvironment = hostEnvironment; _azureStorageOptions = options.Value; } @@ -32,7 +35,7 @@ public async Task DownloadFile(ServiceOwnerEntity serviceOwnerEntity, Fi private async Task GetConnectionString(ServiceOwnerEntity serviceOwnerEntity) { - if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development") + if (_hostEnvironment.IsDevelopment()) { return _azureStorageOptions.ConnectionString; } diff --git a/src/Altinn.Broker/Program.cs b/src/Altinn.Broker/Program.cs index 83ef1308..67ac6fea 100644 --- a/src/Altinn.Broker/Program.cs +++ b/src/Altinn.Broker/Program.cs @@ -1,4 +1,3 @@ -using System.IdentityModel.Tokens.Jwt; using System.Text.Json.Serialization; using Altinn.Broker.Core.Repositories; @@ -10,14 +9,13 @@ using Altinn.Broker.Persistence.Repositories; using Altinn.Broker.Repositories; -using Azure.Identity; - using Hangfire; using Hangfire.MemoryStorage; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); @@ -45,7 +43,6 @@ app.UseSwagger(); app.UseSwaggerUI(); } - app.UseAuthorization(); app.MapControllers(); @@ -90,7 +87,7 @@ void ConfigureServices(IServiceCollection services, IConfiguration config) RequireSignedTokens = false, SignatureValidator = delegate (string token, TokenValidationParameters parameters) { - var jwt = new JwtSecurityToken(token); + var jwt = new JsonWebToken(token); return jwt; }, @@ -108,3 +105,5 @@ void ConfigureServices(IServiceCollection services, IConfiguration config) options.MultipartHeadersLengthLimit = int.MaxValue; }); } + +public partial class Program { } // For compatibility with WebApplicationFactory From 3b76aef8e3680ff70969108ad76438155e6a5712 Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 17:58:11 +0100 Subject: [PATCH 03/13] Fixed found when testing --- src/Altinn.Broker/Altinn.Broker.csproj | 4 ---- src/Altinn.Broker/Controllers/FileController.cs | 7 ++++--- src/Altinn.Broker/Models/FileInitializeExt.cs | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Altinn.Broker/Altinn.Broker.csproj b/src/Altinn.Broker/Altinn.Broker.csproj index 0fd5ffba..51effde0 100644 --- a/src/Altinn.Broker/Altinn.Broker.csproj +++ b/src/Altinn.Broker/Altinn.Broker.csproj @@ -23,8 +23,4 @@ - - - - diff --git a/src/Altinn.Broker/Controllers/FileController.cs b/src/Altinn.Broker/Controllers/FileController.cs index be89faf3..5b370f79 100644 --- a/src/Altinn.Broker/Controllers/FileController.cs +++ b/src/Altinn.Broker/Controllers/FileController.cs @@ -53,7 +53,7 @@ public async Task> InitializeFile(FileInitalizeExt initialize var file = FileInitializeExtMapper.MapToDomain(initializeExt, serviceOwner.Id); var fileId = await _fileRepository.AddFileAsync(file, serviceOwner); - return Ok(fileId); + return Ok(fileId.ToString()); } /// @@ -90,7 +90,7 @@ public async Task UploadFileStreamed( await _fileRepository.InsertFileStatus(fileId, FileStatus.UploadProcessing); await _fileRepository.InsertFileStatus(fileId, FileStatus.Published); - return Ok(fileId); + return Ok(fileId.ToString()); } /// @@ -122,7 +122,7 @@ [FromForm] FileInitializeAndUploadExt form // TODO: Queue Kafka jobs await _fileRepository.InsertFileStatus(fileId, FileStatus.UploadProcessing); await _fileRepository.InsertFileStatus(fileId, FileStatus.Published); - return Ok(fileId); + return Ok(fileId.ToString()); } /// @@ -239,6 +239,7 @@ public async Task> DownloadFile(Guid fileId) } var downloadStream = await _brokerStorageService.DownloadFile(serviceOwner, file); + await _fileRepository.AddReceipt(fileId, ActorFileStatus.DownloadStarted, caller); return File(downloadStream, "application/force-download", file.Filename); } diff --git a/src/Altinn.Broker/Models/FileInitializeExt.cs b/src/Altinn.Broker/Models/FileInitializeExt.cs index eac3ba5d..a72f978f 100644 --- a/src/Altinn.Broker/Models/FileInitializeExt.cs +++ b/src/Altinn.Broker/Models/FileInitializeExt.cs @@ -23,7 +23,7 @@ public class FileInitalizeExt /// Gets or sets checksum for file data. /// [JsonPropertyName("checksum")] - public string Checksum { get; set; } = string.Empty; + public string? Checksum { get; set; } = string.Empty; /// /// Gets or sets the sender of the broker file. From 90e7f1abbe447222cf0386e2ca7d4c26fec27fe8 Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 17:58:17 +0100 Subject: [PATCH 04/13] No need to pin versions --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b56e5332..04a5a18f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ networks: services: storage: - image: mcr.microsoft.com/azure-storage/azurite + image: mcr.microsoft.com/azure-storage/azurite:latest ports: - "10000:10000" - "10001:10001" @@ -38,7 +38,7 @@ services: POSTGRES_PASSWORD: postgres POSTGRES_DB: broker database_migration: - image: flyway/flyway@sha256:54414197790fe7aa1da07b8034f82e40b7e33a8b3f67f27972c2f3f73271147f + image: flyway/flyway@sha256:latest command: -url='jdbc:postgresql://database:5432/broker' -user=postgres -password=postgres -connectRetries=60 migrate -validateMigrationNaming='true' volumes: - ./src/Altinn.Broker.Persistence/Migrations:/flyway/sql @@ -49,7 +49,7 @@ services: "flyway", ] prepare_test_data: - image: flyway/flyway@sha256:54414197790fe7aa1da07b8034f82e40b7e33a8b3f67f27972c2f3f73271147f + image: flyway/flyway@sha256:latest command: -url='jdbc:postgresql://database:5432/broker' -user=postgres -password=postgres -connectRetries=60 migrate volumes: - ./Test/Altinn.Broker.Tests/Data:/flyway/sql From 677d9b985d1f3a45e48c07ddfb9b51a956f47370 Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 17:59:16 +0100 Subject: [PATCH 05/13] Deleting brittle tests in favor of E2E --- .../Persistence/RepositoryTests.cs | 210 ------------------ 1 file changed, 210 deletions(-) delete mode 100644 Test/Altinn.Broker.Tests/Persistence/RepositoryTests.cs diff --git a/Test/Altinn.Broker.Tests/Persistence/RepositoryTests.cs b/Test/Altinn.Broker.Tests/Persistence/RepositoryTests.cs deleted file mode 100644 index 09e5c614..00000000 --- a/Test/Altinn.Broker.Tests/Persistence/RepositoryTests.cs +++ /dev/null @@ -1,210 +0,0 @@ -using Altinn.Broker.Core.Domain; -using Altinn.Broker.Core.Domain.Enums; -using Altinn.Broker.Persistence; -using Altinn.Broker.Persistence.Options; -using Altinn.Broker.Persistence.Repositories; - -using Microsoft.Extensions.Options; - -namespace Altinn.Broker.Tests.Persistence; - -public class RepositoryTests -{ - private readonly string DATABASE_CONNECTION_STRING = "Host=localhost:5432;Username=postgres;Password=postgres;Database=broker"; - private readonly DatabaseConnectionProvider _databaseConnectionProvider; - private FileRepository _fileRepository; - private ActorRepository _actorRepository; - - public RepositoryTests() - { - IOptions databaseOptions = Options.Create(new DatabaseOptions() - { - ConnectionString = DATABASE_CONNECTION_STRING - }); - _databaseConnectionProvider = new DatabaseConnectionProvider(databaseOptions); - - _actorRepository = new ActorRepository(_databaseConnectionProvider); - _fileRepository = new FileRepository(_databaseConnectionProvider, _actorRepository); - } - - [Fact] - public async Task AddFileStorageReference_WhenAddFile_ShouldBeCreated() - { - // Arrange - string fileLocation = "path/to/file"; - - - // Act - var fileId = await _fileRepository.AddFileAsync(new FileEntity() - { - SendersFileReference = "1", - FileStatus = Core.Domain.Enums.FileStatus.Initialized, - Uploaded = DateTime.UtcNow, - Sender = "1", - Filename = "document.pdf", - Checksum = null, - PropertyList = new Dictionary(), - FileStatusChanged = DateTime.UtcNow, - ActorEvents = new List() - { - new ActorFileStatusEntity(){ - Actor = new ActorEntity() - { - ActorExternalId= "2" - }, - Date= DateTime.UtcNow, - Status = ActorFileStatus.Initialized - } - } - }, new ServiceOwnerEntity() - { - Id = "0192:991825827", - Name = "Integration test", - StorageProvider = new StorageProviderEntity() - { - Id = 1, - Created = DateTime.UtcNow, - ResourceName = "dummy-value", - Type = StorageProviderType.Altinn3Azure - } - }); - - await _fileRepository.SetStorageReference(fileId, 1, fileLocation); - - // Assert - var savedFile = await _fileRepository.GetFileAsync(fileId); - Assert.Equal(fileLocation, savedFile.FileLocation); - } - - [Fact] - public async Task AddReceipt_WhenCalled_ShouldSaveReceipt() - { - // Arrange - Guid fileId = await _fileRepository.AddFileAsync(new Core.Domain.FileEntity() - { - Sender = "1", - SendersFileReference = "1", - FileStatus = Core.Domain.Enums.FileStatus.Initialized, - Uploaded = DateTime.UtcNow, - FileLocation = "path/to/file", - FileStatusChanged = DateTime.UtcNow, - Filename = "document.pdf", - Checksum = null, - PropertyList = new Dictionary(), - ActorEvents = new List() - { - new ActorFileStatusEntity(){ - Actor = new ActorEntity() - { - ActorExternalId= "2" - }, - Date= DateTime.UtcNow, - Status = ActorFileStatus.Initialized - } - } - }, new ServiceOwnerEntity() - { - Id = "0192:991825827", - Name = "Integration test", - StorageProvider = new StorageProviderEntity() - { - Id = 1, - Created = DateTime.UtcNow, - ResourceName = "dummy-value", - Type = StorageProviderType.Altinn3Azure - } - }); - - // Act - await _fileRepository.AddReceiptAsync(new ActorFileStatusEntity() - { - Actor = new ActorEntity() - { - ActorExternalId = "2" - }, - Date = DateTime.UtcNow, - FileId = fileId, - Status = Core.Domain.Enums.ActorFileStatus.DownloadConfirmed - }); - - // Assert - var savedFile = await _fileRepository.GetFileAsync(fileId); - Assert.NotNull(savedFile); - Assert.NotEmpty(savedFile.ActorEvents); - Assert.Equal(2, savedFile.ActorEvents.Count); - } - - [Fact] - public async Task GetFile_ExistingFileId_ShouldReturnFile() - { - // Arrange - var fileId = await _fileRepository.AddFileAsync(new Core.Domain.FileEntity() - { - SendersFileReference = "1", - FileStatus = Core.Domain.Enums.FileStatus.Initialized, - Uploaded = DateTime.UtcNow, - FileLocation = "path/to/file", - Sender = "altinn", - Filename = "document.pdf", - Checksum = null, - PropertyList = new Dictionary(), - FileStatusChanged = DateTime.UtcNow, - ActorEvents = new List() - { - new ActorFileStatusEntity(){ - Actor = new ActorEntity() - { - ActorExternalId= "2" - }, - Date= DateTime.UtcNow, - Status = ActorFileStatus.Initialized - } - } - }, new ServiceOwnerEntity() - { - Id = "0192:991825827", - Name = "Integration test", - StorageProvider = new StorageProviderEntity() - { - Id = 1, - Created = DateTime.UtcNow, - ResourceName = "dummy-value", - Type = StorageProviderType.Altinn3Azure - } - }); - - // Act - var result = await _fileRepository.GetFileAsync(fileId); - - // Assert - Assert.NotNull(result); - } - - [Fact] - public async Task GetFile_NonExistingFileId_ShouldReturnNull() - { - // Arrange - // Act - var result = await _fileRepository.GetFileAsync(Guid.NewGuid()); - - // Assert - Assert.Null(result); - } - - [Fact] - public async Task SaveActor_Successful_CanRetrieveActor() - { - // Arrange - var actor = new ActorEntity() - { - ActorExternalId = Guid.NewGuid().ToString() - }; - - // Act - var actorId = await _actorRepository.AddActorAsync(actor); - var savedActor = await _actorRepository.GetActorAsync(actor.ActorExternalId); - - // Assert - Assert.Equal(savedActor.ActorId, actorId); - } -} From 754a98cf8eb52ac07068006b9446c000d0bc21ec Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:03:55 +0100 Subject: [PATCH 06/13] Fix docker compose --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 04a5a18f..3937fdc5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,7 @@ services: POSTGRES_PASSWORD: postgres POSTGRES_DB: broker database_migration: - image: flyway/flyway@sha256:latest + image: flyway/flyway:latest command: -url='jdbc:postgresql://database:5432/broker' -user=postgres -password=postgres -connectRetries=60 migrate -validateMigrationNaming='true' volumes: - ./src/Altinn.Broker.Persistence/Migrations:/flyway/sql @@ -49,7 +49,7 @@ services: "flyway", ] prepare_test_data: - image: flyway/flyway@sha256:latest + image: flyway/flyway:latest command: -url='jdbc:postgresql://database:5432/broker' -user=postgres -password=postgres -connectRetries=60 migrate volumes: - ./Test/Altinn.Broker.Tests/Data:/flyway/sql From 90bc82ecfeb0d62f0537a2f7433b9dc18c64e1f6 Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:09:30 +0100 Subject: [PATCH 07/13] Try to set environment strict --- .github/workflows/build-and-analyze.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-and-analyze.yml b/.github/workflows/build-and-analyze.yml index e0aa1d7d..d32347d4 100644 --- a/.github/workflows/build-and-analyze.yml +++ b/.github/workflows/build-and-analyze.yml @@ -46,6 +46,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + ASPNETCORE_ENVIRONMENT: "Development" run: | dotnet-sonarscanner begin /k:"Altinn_altinn-broker" /o:"altinn" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.cpd.exclusions="src/Altinn.broker.Persistence/Migration/**/*.sql" /d:sonar.coverage.exclusions="src/Altinn.broker.Persistence/Migration/" From ce869d3160b88bd2d83cd3ffbca38eb619fba3eb Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:13:53 +0100 Subject: [PATCH 08/13] Without quotes --- .github/workflows/build-and-analyze.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-analyze.yml b/.github/workflows/build-and-analyze.yml index d32347d4..64effe5a 100644 --- a/.github/workflows/build-and-analyze.yml +++ b/.github/workflows/build-and-analyze.yml @@ -46,7 +46,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - ASPNETCORE_ENVIRONMENT: "Development" + ASPNETCORE_ENVIRONMENT: Development run: | dotnet-sonarscanner begin /k:"Altinn_altinn-broker" /o:"altinn" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.cpd.exclusions="src/Altinn.broker.Persistence/Migration/**/*.sql" /d:sonar.coverage.exclusions="src/Altinn.broker.Persistence/Migration/" From eebb9d0bfa65c56c9aad2bfbe5137b1c7bcfdd3c Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:20:06 +0100 Subject: [PATCH 09/13] Attempt to set ASPNETCORE_ENVIRONMENT in the webapplicationfactory instead --- .github/workflows/build-and-analyze.yml | 1 - Test/Altinn.Broker.Tests/FileControllerTests.cs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-analyze.yml b/.github/workflows/build-and-analyze.yml index 64effe5a..e0aa1d7d 100644 --- a/.github/workflows/build-and-analyze.yml +++ b/.github/workflows/build-and-analyze.yml @@ -46,7 +46,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - ASPNETCORE_ENVIRONMENT: Development run: | dotnet-sonarscanner begin /k:"Altinn_altinn-broker" /o:"altinn" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.cpd.exclusions="src/Altinn.broker.Persistence/Migration/**/*.sql" /d:sonar.coverage.exclusions="src/Altinn.broker.Persistence/Migration/" diff --git a/Test/Altinn.Broker.Tests/FileControllerTests.cs b/Test/Altinn.Broker.Tests/FileControllerTests.cs index e076a7c3..6cd50967 100644 --- a/Test/Altinn.Broker.Tests/FileControllerTests.cs +++ b/Test/Altinn.Broker.Tests/FileControllerTests.cs @@ -18,6 +18,7 @@ public class FileControllerTests : IClassFixture> public FileControllerTests(WebApplicationFactory factory) { + factory.WithWebHostBuilder(configuration => configuration.UseSetting("ASPNETCORE_ENVIRONMENT", "Development")); _factory = factory; _client = factory.CreateClient(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMTkyOjk5MTgyNTgyNyJ9.exFSD-mL1fzoWhg8IKcVeCeEyJ5qpABPU9A1AXHDa_k"); From 6bf8e215d8c8c0dbbc6d6f3a89850e307eafe23d Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:24:06 +0100 Subject: [PATCH 10/13] Verify that my assumption is correct --- .../Azure/AzureBrokerStorageService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs index 69ff6377..8ce66730 100644 --- a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs +++ b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs @@ -39,6 +39,6 @@ private async Task GetConnectionString(ServiceOwnerEntity serviceOwnerEn { return _azureStorageOptions.ConnectionString; } - return await _resourceManager.GetStorageConnectionString(serviceOwnerEntity); + return _azureStorageOptions.ConnectionString; } } From 51af2d25a95449c3a727b03bc398ca615c0707ae Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:27:09 +0100 Subject: [PATCH 11/13] Revert "Verify that my assumption is correct" This reverts commit 6bf8e215d8c8c0dbbc6d6f3a89850e307eafe23d. --- .../Azure/AzureBrokerStorageService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs index 8ce66730..69ff6377 100644 --- a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs +++ b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs @@ -39,6 +39,6 @@ private async Task GetConnectionString(ServiceOwnerEntity serviceOwnerEn { return _azureStorageOptions.ConnectionString; } - return _azureStorageOptions.ConnectionString; + return await _resourceManager.GetStorageConnectionString(serviceOwnerEntity); } } From 9ba607e4c4edc2137f717a0a60f841c8b71de725 Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:38:30 +0100 Subject: [PATCH 12/13] Handle development check of storage account --- .../Azure/AzureBrokerStorageService.cs | 6 +++++- .../Azure/AzureResourceManager.cs | 11 ++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs index 69ff6377..5461552e 100644 --- a/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs +++ b/src/Altinn.Broker.Integrations/Azure/AzureBrokerStorageService.cs @@ -3,6 +3,7 @@ using Altinn.Broker.Repositories; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Altinn.Broker.Integrations.Azure; @@ -12,13 +13,15 @@ public class AzureBrokerStorageService : IBrokerStorageService private readonly IResourceManager _resourceManager; private readonly IHostEnvironment _hostEnvironment; private readonly AzureStorageOptions _azureStorageOptions; + private readonly ILogger _logger; - public AzureBrokerStorageService(IFileStore fileStore, IResourceManager resourceManager, IHostEnvironment hostEnvironment, IOptions options) + public AzureBrokerStorageService(IFileStore fileStore, IResourceManager resourceManager, IHostEnvironment hostEnvironment, IOptions options, ILogger logger) { _fileStore = fileStore; _resourceManager = resourceManager; _hostEnvironment = hostEnvironment; _azureStorageOptions = options.Value; + _logger = logger; } public async Task UploadFile(ServiceOwnerEntity serviceOwnerEntity, FileEntity fileEntity, Stream stream) @@ -37,6 +40,7 @@ private async Task GetConnectionString(ServiceOwnerEntity serviceOwnerEn { if (_hostEnvironment.IsDevelopment()) { + _logger.LogInformation("Running in development. Using local development storage."); return _azureStorageOptions.ConnectionString; } return await _resourceManager.GetStorageConnectionString(serviceOwnerEntity); diff --git a/src/Altinn.Broker.Integrations/Azure/AzureResourceManager.cs b/src/Altinn.Broker.Integrations/Azure/AzureResourceManager.cs index a24145bd..aad61a3a 100644 --- a/src/Altinn.Broker.Integrations/Azure/AzureResourceManager.cs +++ b/src/Altinn.Broker.Integrations/Azure/AzureResourceManager.cs @@ -13,6 +13,7 @@ using Azure.Storage.Blobs; using Azure.Storage.Sas; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -20,17 +21,17 @@ namespace Altinn.Broker.Integrations.Azure; public class AzureResourceManager : IResourceManager { private readonly AzureResourceManagerOptions _resourceManagerOptions; - private readonly AzureStorageOptions _storageOptions; + private readonly IHostingEnvironment _hostingEnvironment; private readonly ArmClient _armClient; private readonly IServiceOwnerRepository _serviceOwnerRepository; private readonly ILogger _logger; public string GetResourceGroupName(ServiceOwnerEntity serviceOwnerEntity) => $"serviceowner-{_resourceManagerOptions.Environment}-{serviceOwnerEntity.Id.Replace(":", "-")}-rg"; public string GetStorageAccountName(ServiceOwnerEntity serviceOwnerEntity) => $"ai{_resourceManagerOptions.Environment.ToLowerInvariant()}{serviceOwnerEntity.Id.Replace(":", "")}sa"; - public AzureResourceManager(IOptions resourceManagerOptions, IOptions storageOptions, IServiceOwnerRepository serviceOwnerRepository, ILogger logger) + public AzureResourceManager(IOptions resourceManagerOptions, IHostingEnvironment hostingEnvironment, IServiceOwnerRepository serviceOwnerRepository, ILogger logger) { _resourceManagerOptions = resourceManagerOptions.Value; - _storageOptions = storageOptions.Value; + _hostingEnvironment = hostingEnvironment; if (string.IsNullOrWhiteSpace(_resourceManagerOptions.ClientId)) { _armClient = new ArmClient(new DefaultAzureCredential()); @@ -80,6 +81,10 @@ public async Task Deploy(ServiceOwnerEntity serviceOwnerEntity) public async Task GetDeploymentStatus(ServiceOwnerEntity serviceOwnerEntity) { + if (_hostingEnvironment.IsDevelopment()) + { + return DeploymentStatus.Ready; + } var resourceGroupCollection = _armClient.GetDefaultSubscription().GetResourceGroups(); var resourceGroupExists = await resourceGroupCollection.ExistsAsync(GetResourceGroupName(serviceOwnerEntity)); if (!resourceGroupExists) From 2c1e49cccedb3d4c404b2ba1d4bae6c3272d00ac Mon Sep 17 00:00:00 2001 From: Roar Mjelde Date: Mon, 27 Nov 2023 18:42:30 +0100 Subject: [PATCH 13/13] Remove possibly useless code --- Test/Altinn.Broker.Tests/FileControllerTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Test/Altinn.Broker.Tests/FileControllerTests.cs b/Test/Altinn.Broker.Tests/FileControllerTests.cs index 6cd50967..e076a7c3 100644 --- a/Test/Altinn.Broker.Tests/FileControllerTests.cs +++ b/Test/Altinn.Broker.Tests/FileControllerTests.cs @@ -18,7 +18,6 @@ public class FileControllerTests : IClassFixture> public FileControllerTests(WebApplicationFactory factory) { - factory.WithWebHostBuilder(configuration => configuration.UseSetting("ASPNETCORE_ENVIRONMENT", "Development")); _factory = factory; _client = factory.CreateClient(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMTkyOjk5MTgyNTgyNyJ9.exFSD-mL1fzoWhg8IKcVeCeEyJ5qpABPU9A1AXHDa_k");