57 Commits
Author SHA1 Message Date
khwezi 4de23d27b3 Merge pull request 'Commented out pfm-console to see if the api image will build' (#56) from garages3 into main
Reviewed-on: #56
2026-09-14 09:06:50 +02:00
khwezi d4bce12dbb Merge pull request 'Removed stream redirection' (#55) from garages3 into main
Reviewed-on: #55
2026-09-13 18:15:33 +02:00
khwezi 299b876e1c Merge pull request 'Fixed Api docker file paths' (#54) from garages3 into main
Reviewed-on: #54
2026-09-13 18:13:13 +02:00
khwezi dde1dbe056 Merge pull request 'Added debug code to dotnet build and publish lines' (#53) from garages3 into main
Reviewed-on: #53
2026-09-13 18:09:51 +02:00
khwezi b81e6feb45 Merge pull request 'Moved api dockerfile to project folder' (#52) from garages3 into main
Reviewed-on: #52
2026-09-13 18:07:52 +02:00
khwezi 4138a1941f Merge pull request 'Corrected compose service contexts' (#51) from garages3 into main
Reviewed-on: #51
2026-09-13 18:01:52 +02:00
khwezi 17af31d810 Merge pull request 'Fixed dockerfile paths' (#50) from garages3 into main
Reviewed-on: #50
2026-09-13 17:56:19 +02:00
khwezi b85cf6a1cb Merge pull request 'Light refactor' (#49) from garages3 into main
Reviewed-on: #49
2026-09-13 17:51:45 +02:00
khwezi 81ddc11746 Merge pull request 'Refactored API dockerfile' (#48) from garages3 into main
Reviewed-on: #48
2026-09-13 17:50:29 +02:00
khwezi 5b94672ff5 Merge pull request 'Stable API run' (#47) from garages3 into main
Reviewed-on: #47
2026-09-13 17:41:42 +02:00
khwezi c535392ef1 Merge pull request 'Added debug term' (#46) from garages3 into main
Reviewed-on: #46
2026-09-12 12:22:43 +02:00
khwezi 0607de1802 Merge pull request 'Second fix' (#45) from garages3 into main
Reviewed-on: #45
2026-09-12 12:19:34 +02:00
khwezi 4c1e52e452 Merge pull request 'Light refactor' (#44) from garages3 into main
Reviewed-on: #44
2026-09-12 12:14:13 +02:00
khwezi 2414d74d1c Merge pull request 'Light refactor' (#43) from garages3 into main
Reviewed-on: #43
2026-09-12 12:10:17 +02:00
khwezi 93d9661a7f Merge pull request 'Rewrite pfm-api docker file' (#42) from garages3 into main
Reviewed-on: #42
2026-09-12 12:04:47 +02:00
khwezi dba401fe94 Merge pull request 'Fixed publish alias' (#41) from garages3 into main
Reviewed-on: #41
2026-09-12 11:58:37 +02:00
khwezi 42d73fe6cb Merge pull request 'Added error output to dotnet build line' (#40) from garages3 into main
Reviewed-on: #40
2026-09-12 11:54:57 +02:00
khwezi 1475887a7f Merge pull request 'Added working directory switch' (#39) from garages3 into main
Reviewed-on: #39
2026-09-12 11:49:52 +02:00
khwezi 730664d9c4 Merge pull request 'PFM Api docker refactor' (#38) from garages3 into main
Reviewed-on: #38
2026-09-12 11:45:32 +02:00
khwezi f38e569a34 Merge pull request 'Implemented missing file handling endpoints' (#37) from garages3 into main
Reviewed-on: #37
2026-09-12 11:26:45 +02:00
khwezi 7e79171f97 Merge pull request 'Added image name to compose file for console' (#36) from endpoints into main
Reviewed-on: #36
2026-09-11 16:24:11 +02:00
khwezi d7b868f2c1 Merge pull request 'Added more cors origins' (#35) from endpoints into main
Reviewed-on: #35
2026-09-11 16:17:07 +02:00
khwezi d43a09b371 Merge pull request 'Refactored console dockerfile' (#34) from endpoints into main
Reviewed-on: #34
2026-09-11 16:05:21 +02:00
khwezi 0dc0de1502 Merge pull request 'Fixed dockerfile paths' (#33) from endpoints into main
Reviewed-on: #33
2026-09-11 15:47:30 +02:00
khwezi de47dd4a4f Merge pull request 'Supplied defaults to compose env variables' (#32) from endpoints into main
Reviewed-on: #32
2026-09-11 15:33:47 +02:00
khwezi 2810cc669b Merge pull request 'Fixed compose syntax error' (#31) from endpoints into main
Reviewed-on: #31
2026-09-11 15:30:40 +02:00
khwezi 734af8c86f Merge pull request 'Refactored compose file to include the ui in deployment' (#30) from endpoints into main
Reviewed-on: #30
2026-09-11 15:29:21 +02:00
khwezi a754c42d14 Merge pull request 'Updated Console compose file to use variables' (#29) from endpoints into main
Reviewed-on: #29
2026-09-11 15:19:31 +02:00
khwezi bd7ca9372f Merge pull request 'Added specific origin' (#28) from endpoints into main
Reviewed-on: #28
2026-09-11 14:59:34 +02:00
khwezi 0d01d91ab4 Merge pull request 'Added cors after routes' (#27) from endpoints into main
Reviewed-on: #27
2026-09-11 14:54:47 +02:00
khwezi 2c817a8818 Merge pull request 'Endpoints' (#26) from endpoints into main
Reviewed-on: #26
2026-09-11 14:35:02 +02:00
khwezi 4c3a96917b Merge pull request 'Improved results handling in service layer' (#25) from endpoints into main
Reviewed-on: #25
2026-09-11 10:33:47 +02:00
khwezi e5c3a75795 Merge pull request 'Stable run with validations' (#24) from endpoints into main
Reviewed-on: #24
2026-09-06 10:49:57 +02:00
khwezi 1bc7e65960 Merge pull request 'Added tooling' (#23) from endpoints into main
Reviewed-on: #23
2026-09-05 18:27:35 +02:00
khwezi 094126d84b Merge pull request 'Fixed endpointname uniqueness' (#22) from endpoints into main
Reviewed-on: #22
2026-09-05 13:07:41 +02:00
khwezi 2506241a25 Merge pull request 'Fixed endpoint uniqueness' (#21) from endpoints into main
Reviewed-on: #21
2026-09-05 12:58:17 +02:00
khwezi cfe3530639 Merge pull request 'Endpoints' (#20) from endpoints into main
Reviewed-on: #20
2026-09-05 12:50:04 +02:00
khwezi 985557bee4 Merge pull request 'Implemented caching on all get endpoints and service layer' (#19) from endpoints into main
Reviewed-on: #19
2026-09-05 08:30:16 +02:00
khwezi f0b8b3051a Merge pull request 'Improved getusers cache key' (#18) from endpoints into main
Reviewed-on: #18
2026-09-04 06:08:39 +02:00
khwezi 6c88b9e533 Merge pull request 'Endpoints' (#17) from endpoints into main
Reviewed-on: #17
2026-09-04 05:54:30 +02:00
khwezi 7d67408d2c Merge pull request 'Additional redis configs' (#16) from endpoints into main
Reviewed-on: #16
2026-09-04 05:39:44 +02:00
khwezi d1d58a6183 Merge pull request 'Added service level caching to IdentityService, Communication and Evidence' (#15) from endpoints into main
Reviewed-on: #15
2026-09-03 16:38:08 +02:00
khwezi 60ad154841 Merge pull request 'Implemented distributed caching' (#14) from endpoints into main
Reviewed-on: #14
2026-09-03 11:09:52 +02:00
khwezi 2c13170859 Merge pull request 'Endpoints' (#13) from endpoints into main
Reviewed-on: #13
2026-09-02 16:14:34 +02:00
khwezi d87c8aa3c9 Merge pull request 'Updated configurations' (#12) from endpoints into main
Reviewed-on: #12
2026-09-02 09:45:38 +02:00
khwezi 6af7815ad1 Merge pull request 'Removed node tooling install' (#11) from endpoints into main
Reviewed-on: #11
2026-09-02 09:30:06 +02:00
khwezi a169f6c3f6 Merge pull request 'Endpoints' (#10) from endpoints into main
Reviewed-on: #10
2026-09-02 09:28:17 +02:00
khwezi 65ea753c19 Merge pull request 'Endpoints' (#9) from endpoints into main
Reviewed-on: #9
2026-09-01 12:29:47 +02:00
khwezi e6d2663265 Merge pull request 'Endpoints' (#8) from endpoints into main
Reviewed-on: #8
2026-08-30 17:47:24 +02:00
khwezi 91b5814b60 Merge pull request 'Endpoints' (#7) from endpoints into main
Reviewed-on: #7
2026-08-30 16:27:37 +02:00
khwezi 0c4c848568 Merge pull request 'Endpoints' (#6) from endpoints into main
Reviewed-on: #6
2026-08-30 16:11:53 +02:00
khwezi fb05150ebf Merge pull request 'Endpoints' (#5) from endpoints into main
Reviewed-on: #5
2026-08-30 15:47:32 +02:00
khwezi 2f9c20020b Merge pull request 'Reogranised API and Security assets' (#4) from endpoints into main
Reviewed-on: #4
2026-08-30 15:09:32 +02:00
khwezi a771957db3 Merge pull request 'Endpoints' (#3) from endpoints into main
Reviewed-on: #3
2026-08-30 14:54:58 +02:00
khwezi 46267a2a34 Merge pull request 'Endpoints' (#2) from endpoints into main
Reviewed-on: #2
2026-08-30 14:26:08 +02:00
khwezi a7f360cc2a Merge pull request 'Security' (#1) from security into main
Reviewed-on: #1
2026-08-21 11:47:36 +02:00
hermes 67c08b40ca Refactored gitignore 2026-08-21 11:45:33 +02:00
156 changed files with 11892 additions and 34997 deletions
-21
View File
@@ -1,21 +0,0 @@
# Exclude build output and caches
**/bin/
**/obj/
**/out/
.vs/
.vscode/
# Exclude git internal files
.git/
.gitignore
# Exclude local environment/secret files
.env
*.env
*.user
*.suo
# Exclude node modules and temporary logs
**/node_modules/
**/dist/
*.log
+3 -12
View File
@@ -11,7 +11,6 @@
*.sln.docstates *.sln.docstates
*.env *.env
*.env.json *.env.json
certificates/
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs
@@ -52,8 +51,6 @@ bld/
# Build results on 'Bin' directories # Build results on 'Bin' directories
**/[Bb]in/* **/[Bb]in/*
dist/assets/
dist/
# Uncomment if you have tasks that rely on *.refresh files to move binaries # Uncomment if you have tasks that rely on *.refresh files to move binaries
# (https://github.com/github/gitignore/pull/3736) # (https://github.com/github/gitignore/pull/3736)
#!**/[Bb]in/*.refresh #!**/[Bb]in/*.refresh
@@ -61,7 +58,8 @@ dist/
# Visual Studio 2015/2017 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/
.vscode/ .vscode/
bin/
certificates/
# Uncomment if you have tasks that create the project's static files in wwwroot # Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/ #wwwroot/
@@ -349,7 +347,6 @@ _Pvt_Extensions
# Paket dependency manager # Paket dependency manager
**/.paket/paket.exe **/.paket/paket.exe
**/.paket/paket.exe
paket-files/ paket-files/
# FAKE - F# Make # FAKE - F# Make
@@ -434,10 +431,4 @@ FodyWeavers.xsd
*.msi *.msi
*.msix *.msix
*.msm *.msm
*.msp *.msp
/PostFundManagement.ConsoleUI/dist/config.json
/PostFundManagement.ConsoleUI/dist/env-config.js
/PostFundManagement.ConsoleUI/dist/assets/index-BaOzkVJi.css
/PostFundManagement.ConsoleUI/dist/assets/index-BU8qSe7k.js
/PostFundManagement.ConsoleUI/dist/favicon.svg
/PostFundManagement.ConsoleUI/dist/index.html
+12 -12
View File
@@ -1,35 +1,35 @@
# Stage 1: Runtime base # Base image for running the app
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
USER app
WORKDIR /app WORKDIR /app
EXPOSE 8080 EXPOSE 8080
EXPOSE 8081
# Stage 2: Build & Restore # Build stage
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src WORKDIR /src
# Copy csproj files for layer caching # Copy project files for dependency restoration
COPY ["PostFundManagement.Api/PostFundManagement.Api.csproj", "PostFundManagement.Api/"] COPY ["PostFundManagement.Api/PostFundManagement.Api.csproj", "PostFundManagement.Api/"]
COPY ["PostFundManagement.Application/PostFundManagement.Application.csproj", "PostFundManagement.Application/"] COPY ["PostFundManagement.Application/PostFundManagement.Application.csproj", "PostFundManagement.Application/"]
COPY ["PostFundManagement.Domain/PostFundManagement.Domain.csproj", "PostFundManagement.Domain/"] COPY ["PostFundManagement.Domain/PostFundManagement.Domain.csproj", "PostFundManagement.Domain/"]
COPY ["PostFundManagement.Infrastructure/PostFundManagement.Infrastructure.csproj", "PostFundManagement.Infrastructure/"] COPY ["PostFundManagement.Infrastructure/PostFundManagement.Infrastructure.csproj", "PostFundManagement.Infrastructure/"]
# Restore packages # Restore dependencies
RUN dotnet restore "PostFundManagement.Api/PostFundManagement.Api.csproj" RUN dotnet restore "PostFundManagement.Api/PostFundManagement.Api.csproj"
# Copy full source code # Copy full source tree
COPY . . COPY . .
# Build from the project folder using relative filename # Build the API project
WORKDIR "/src/PostFundManagement.Api" RUN dotnet build "PostFundManagement.Api/PostFundManagement.Api.csproj" -c $BUILD_CONFIGURATION -o /app/build
RUN dotnet build "PostFundManagement.Api.csproj" -c Release -o /app/build
# Stage 3: Publish # Publish stage
FROM build AS publish FROM build AS publish
ARG BUILD_CONFIGURATION=Release ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "PostFundManagement.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false RUN dotnet publish "PostFundManagement.Api/PostFundManagement.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
# Stage 4: Final Runtime # Final runtime stage
FROM base AS final FROM base AS final
WORKDIR /app WORKDIR /app
COPY --from=publish /app/publish . COPY --from=publish /app/publish .
@@ -23,7 +23,6 @@ public sealed class GetApplicantInviteEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Gets an applicant's invite") .WithDescription("Gets an applicant's invite")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetApplicantInviteEndpoint).ToEndpointName()) .WithName(typeof(GetApplicantInviteEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Invite>(StatusCodes.Status200OK) .Produces<Invite>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetApplicantInvitesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Gets an applicant's invite list") .WithDescription("Gets an applicant's invite list")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetApplicantInvitesEndpoint).ToEndpointName()) .WithName(typeof(GetApplicantInvitesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Invite[]>(StatusCodes.Status200OK) .Produces<Invite[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetInvitesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of sent invitations") .WithDescription("Get a list of sent invitations")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetInvitesEndpoint).ToEndpointName()) .WithName(typeof(GetInvitesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Invite[]>(StatusCodes.Status200OK) .Produces<Invite[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class SendInviteEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Trigger an invite to an organization or candidate (specifying NotificationPlatform)") .WithDescription("Trigger an invite to an organization or candidate (specifying NotificationPlatform)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(SendInviteEndpoint).ToEndpointName()) .WithName(typeof(SendInviteEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Invite>(StatusCodes.Status200OK) .Produces<Invite>(StatusCodes.Status200OK)
@@ -34,9 +34,9 @@ public class CreateEvidenceEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}; };
}) })
.WithDescription("Upload supporting evidence file to S3 and register metadata (M14)") .RequireAuthorization()
.DisableAntiforgery() .DisableAntiforgery()
.RequireAuthorization(Constants.MainScope) .WithDescription("Upload supporting evidence file to S3 and register metadata (M14)")
.WithName(typeof(CreateEvidenceEndpoint).ToEndpointName()) .WithName(typeof(CreateEvidenceEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class CreateIndicatorEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Define indicators and baselines/targets (M08)") .WithDescription("Define indicators and baselines/targets (M08)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateIndicatorEndpoint).ToEndpointName()) .WithName(typeof(CreateIndicatorEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class CreateMilestoneEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Define contractual milestones (M07)") .WithDescription("Define contractual milestones (M07)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateMilestoneRequest).ToEndpointName()) .WithName(typeof(CreateMilestoneRequest).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetEvidenceEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a specific evidence record and assiciated file URLs") .WithDescription("Get a specific evidence record and assiciated file URLs")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetEvidenceEndpoint).ToEndpointName()) .WithName(typeof(GetEvidenceEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Domain.Models.Evidence>(StatusCodes.Status200OK) .Produces<Domain.Models.Evidence>(StatusCodes.Status200OK)
@@ -21,7 +21,6 @@ public class GetEvidenceFilesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of all uploaded evidence files metadata") .WithDescription("Get a list of all uploaded evidence files metadata")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetEvidenceFilesEndpoint).ToEndpointName()) .WithName(typeof(GetEvidenceFilesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Domain.Models.Evidence[]>(StatusCodes.Status200OK) .Produces<Domain.Models.Evidence[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetEvidenceUrlEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Gets a secure download URL of the evidence file, URL expires (default: 15min)") .WithDescription("Gets a secure download URL of the evidence file, URL expires (default: 15min)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetEvidenceUrlEndpoint).ToEndpointName()) .WithName(typeof(GetEvidenceUrlEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<string>(StatusCodes.Status200OK) .Produces<string>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class GetIndicatorEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a specific indicator.") .WithDescription("Get a specific indicator.")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetIndicatorEndpoint).ToEndpointName()) .WithName(typeof(GetIndicatorEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Indicator>(StatusCodes.Status200OK) .Produces<Indicator>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetIndicatorsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Get a list of indicators") .WithDescription("Get a list of indicators")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetIndicatorsEndpoint).ToEndpointName()) .WithName(typeof(GetIndicatorsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Indicator[]>(StatusCodes.Status200OK) .Produces<Indicator[]>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetMilestoneEvidenceEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of all uploaded evidence metadata for a specific mliestone") .WithDescription("Get a list of all uploaded evidence metadata for a specific mliestone")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetMilestoneEvidenceEndpoint).ToEndpointName()) .WithName(typeof(GetMilestoneEvidenceEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Domain.Models.Evidence[]>(StatusCodes.Status200OK) .Produces<Domain.Models.Evidence[]>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetProjectEvidenceEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Get a list of all uploaded evidence metadata for a specific project") .WithDescription("Get a list of all uploaded evidence metadata for a specific project")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProjectEvidenceEndpoint).ToEndpointName()) .WithName(typeof(GetProjectEvidenceEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Domain.Models.Evidence[]>(StatusCodes.Status200OK) .Produces<Domain.Models.Evidence[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class RecordIndicatorAmountEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Record actual values for indicators (M08)") .WithDescription("Record actual values for indicators (M08)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(RecordIndicatorAmountEndpoint).ToEndpointName()) .WithName(typeof(RecordIndicatorAmountEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,8 +24,6 @@ public sealed class UpdateEvidenceEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Updates a specific evidence record metadata") .WithDescription("Updates a specific evidence record metadata")
.RequireAuthorization(Constants.MainScope)
.DisableAntiforgery()
.WithName(typeof(UpdateEvidenceEndpoint).ToEndpointName()) .WithName(typeof(UpdateEvidenceEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class ApproveDisbursementEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Approve disbursement and release payment (M06)") .WithDescription("Approve disbursement and release payment (M06)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(ApproveDisbursementEndpoint).ToEndpointName()) .WithName(typeof(ApproveDisbursementEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class CreateDisbursementEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Create a new disbursement schedule (M06)") .WithDescription("Create a new disbursement schedule (M06)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateDisbursementEndpoint).ToEndpointName()) .WithName(typeof(CreateDisbursementEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class CreateRiskEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Add risk to risk register (M09)") .WithDescription("Add risk to risk register (M09)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateRiskEndpoint).ToEndpointName()) .WithName(typeof(CreateRiskEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class GetDisbursementEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a specific disbursement") .WithDescription("Get a specific disbursement")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetDisbursementEndpoint).ToEndpointName()) .WithName(typeof(GetDisbursementEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Disbursement>(StatusCodes.Status200OK) .Produces<Disbursement>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetDisbursementsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of disbursements") .WithDescription("Get a list of disbursements")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetDisbursementsEndpoint).ToEndpointName()) .WithName(typeof(GetDisbursementsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Disbursement[]>(StatusCodes.Status200OK) .Produces<Disbursement[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class GetRiskEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a specific risk") .WithDescription("Get a specific risk")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetRiskEndpoint).ToEndpointName()) .WithName(typeof(GetRiskEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Risk>(StatusCodes.Status200OK) .Produces<Risk>(StatusCodes.Status200OK)
@@ -21,7 +21,6 @@ public class GetRisksEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of all risks") .WithDescription("Get a list of all risks")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetRisksEndpoint).ToEndpointName()) .WithName(typeof(GetRisksEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class UpdateDisbursementEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update the details of a specific disbursement") .WithDescription("Update the details of a specific disbursement")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateDisbursementEndpoint).ToEndpointName()) .WithName(typeof(UpdateDisbursementEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class UpdateRiskEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update the details of a specific risk") .WithDescription("Update the details of a specific risk")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateRiskEndpoint).ToEndpointName()) .WithName(typeof(UpdateRiskEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class CreateOrganisationEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Create a new organization profile") .WithDescription("Create a new organization profile")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateOrganisationEndpoint).ToEndpointName()) .WithName(typeof(CreateOrganisationEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -25,7 +25,6 @@ public sealed class CreatePortfolioEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Create a new organization portfolio") .WithDescription("Create a new organization portfolio")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreatePortfolioEndpoint).ToEndpointName()) .WithName(typeof(CreatePortfolioEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -21,7 +21,6 @@ public class DashboardEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get executive portfolio dashboard metrics and KPIs") .WithDescription("Get executive portfolio dashboard metrics and KPIs")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(DashboardEndpoint).ToEndpointName()) .WithName(typeof(DashboardEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Dashboard>(StatusCodes.Status200OK) .Produces<Dashboard>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetInstrumentsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Get all funding instruments") .WithDescription("Get all funding instruments")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetInstrumentsEndpoint).ToEndpointName()) .WithName(typeof(GetInstrumentsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Instrument[]>(StatusCodes.Status200OK) .Produces<Instrument[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class GetOrganisationEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get organization profile by ID") .WithDescription("Get organization profile by ID")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetOrganisationEndpoint).ToEndpointName()) .WithName(typeof(GetOrganisationEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Organisation>(StatusCodes.Status200OK) .Produces<Organisation>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetOrganisationsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a paginated directory of organizations") .WithDescription("Get a paginated directory of organizations")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetOrganisationsEndpoint).ToEndpointName()) .WithName(typeof(GetOrganisationsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Organisation[]>(StatusCodes.Status200OK) .Produces<Organisation[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetPortfolioEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a specific portfolios") .WithDescription("Get a specific portfolios")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetPortfolioEndpoint).ToEndpointName()) .WithName(typeof(GetPortfolioEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Portfolio[]>(StatusCodes.Status200OK) .Produces<Portfolio[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class GetPortfolioProgrammesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a programme's portfolios") .WithDescription("Get a programme's portfolios")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetPortfolioProgrammesEndpoint).ToEndpointName()) .WithName(typeof(GetPortfolioProgrammesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Programme[]>(StatusCodes.Status200OK) .Produces<Programme[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetPortfoliosEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get all portfolios") .WithDescription("Get all portfolios")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetPortfoliosEndpoint).ToEndpointName()) .WithName(typeof(GetPortfoliosEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Portfolio[]>(StatusCodes.Status200OK) .Produces<Portfolio[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetProgrammesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get all programmes") .WithDescription("Get all programmes")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProgrammesEndpoint).ToEndpointName()) .WithName(typeof(GetProgrammesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Programme[]>(StatusCodes.Status200OK) .Produces<Programme[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class UpdateOrganisationEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update an existing organization profile") .WithDescription("Update an existing organization profile")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateOrganisationEndpoint).ToEndpointName()) .WithName(typeof(UpdateOrganisationEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -25,7 +25,6 @@ public sealed class UpdatePortfolioEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update an existing organization portfolio") .WithDescription("Update an existing organization portfolio")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdatePortfolioEndpoint).ToEndpointName()) .WithName(typeof(UpdatePortfolioEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -25,7 +25,6 @@ public class CreateAwardEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Register an approved funding award (M01)") .WithDescription("Register an approved funding award (M01)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateAwardEndpoint).ToEndpointName()) .WithName(typeof(CreateAwardEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -25,7 +25,6 @@ public class CreateBudgetEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Create a new budget line (M05)") .WithDescription("Create a new budget line (M05)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateBudgetEndpoint).ToEndpointName()) .WithName(typeof(CreateBudgetEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class CreateContractEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Create a contract record from an approved award (M02)") .WithDescription("Create a contract record from an approved award (M02)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateContractEndpoint).ToEndpointName()) .WithName(typeof(CreateContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class ExecuteContractEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Execute the contract and lock the contractual version") .WithDescription("Execute the contract and lock the contractual version")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(ExecuteContractEndpoint).ToEndpointName()) .WithName(typeof(ExecuteContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class GetAwardEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get award by ID") .WithDescription("Get award by ID")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetAwardEndpoint).ToEndpointName()) .WithName(typeof(GetAwardEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Award>(StatusCodes.Status200OK) .Produces<Award>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetAwardsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of awards") .WithDescription("Get a list of awards")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetAwardsEndpoint).ToEndpointName()) .WithName(typeof(GetAwardsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Award[]>(StatusCodes.Status200OK) .Produces<Award[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class GetBudgetEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get budget by ID") .WithDescription("Get budget by ID")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetBudgetEndpoint).ToEndpointName()) .WithName(typeof(GetBudgetEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Budget>(StatusCodes.Status200OK) .Produces<Budget>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetBudgetsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get all budgets") .WithDescription("Get all budgets")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetBudgetsEndpoint).ToEndpointName()) .WithName(typeof(GetBudgetsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Budget[]>(StatusCodes.Status200OK) .Produces<Budget[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class GetContractEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get contract by ID") .WithDescription("Get contract by ID")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetContractEndpoint).ToEndpointName()) .WithName(typeof(GetContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Contract>(StatusCodes.Status200OK) .Produces<Contract>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetContractUrlEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Gets a secure download URL, has expiry period (default 15min)") .WithDescription("Gets a secure download URL, has expiry period (default 15min)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetContractUrlEndpoint).ToEndpointName()) .WithName(typeof(GetContractUrlEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<string>(StatusCodes.Status200OK) .Produces<string>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetContractsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get all contracts") .WithDescription("Get all contracts")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetContractsEndpoint).ToEndpointName()) .WithName(typeof(GetContractsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Contract[]>(StatusCodes.Status200OK) .Produces<Contract[]>(StatusCodes.Status200OK)
@@ -25,7 +25,6 @@ public sealed class UpdateContractEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Updates a specific contract") .WithDescription("Updates a specific contract")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateContractEndpoint).ToEndpointName()) .WithName(typeof(UpdateContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -33,8 +33,6 @@ public sealed class UploadContractEndpoint : IEndpoint
}; };
}) })
.WithDescription("Uploads a contract file securely") .WithDescription("Uploads a contract file securely")
.RequireAuthorization(Constants.MainScope)
.DisableAntiforgery()
.WithName(typeof(UploadContractEndpoint).ToEndpointName()) .WithName(typeof(UploadContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class CreateActivityEndpoint : IEndpoint
var r when r.HasError<CreateError>() => Results.BadRequest(r.Errors.ToProblems()), var r when r.HasError<CreateError>() => Results.BadRequest(r.Errors.ToProblems()),
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.RequireAuthorization(Constants.MainScope)
.WithDescription("Add a new activity under project (M04)") .WithDescription("Add a new activity under project (M04)")
.WithName(typeof(CreateActivityEndpoint).ToEndpointName()) .WithName(typeof(CreateActivityEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
@@ -25,7 +25,6 @@ public sealed class CreateProgrammeEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Create programme") .WithDescription("Create programme")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateProgrammeEndpoint).ToEndpointName()) .WithName(typeof(CreateProgrammeEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -25,7 +25,6 @@ public class CreateProjectEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Create a new project (M04)") .WithDescription("Create a new project (M04)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(CreateProjectEndpoint).ToEndpointName()) .WithName(typeof(CreateProjectEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetActivitiesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of activities for a project") .WithDescription("Get a list of activities for a project")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetActivitiesEndpoint).ToEndpointName()) .WithName(typeof(GetActivitiesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Domain.Models.Activity[]>(StatusCodes.Status200OK) .Produces<Domain.Models.Activity[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetActivityEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Gets a specific activity by it's id") .WithDescription("Gets a specific activity by it's id")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetActivityEndpoint).ToEndpointName()) .WithName(typeof(GetActivityEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Domain.Models.Activity>(StatusCodes.Status200OK) .Produces<Domain.Models.Activity>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class GetMilestoneEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Gets a specific milestone") .WithDescription("Gets a specific milestone")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetMilestoneEndpoint).ToEndpointName()) .WithName(typeof(GetMilestoneEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Milestone>(StatusCodes.Status200OK) .Produces<Milestone>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetMilestonesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of all milestones") .WithDescription("Get a list of all milestones")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetMilestonesEndpoint).ToEndpointName()) .WithName(typeof(GetMilestonesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Milestone[]>(StatusCodes.Status200OK) .Produces<Milestone[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class GetProgrammeEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get specific programme") .WithDescription("Get specific programme")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProgrammeEndpoint).ToEndpointName()) .WithName(typeof(GetProgrammeEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Programme>(StatusCodes.Status200OK) .Produces<Programme>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class GetProgrammeProjectsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()), var r => Results.InternalServerError(r.Errors.ToProblems()),
}) })
.WithDescription("Get a list of all projects under a programme") .WithDescription("Get a list of all projects under a programme")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProgrammeProjectsEndpoint).ToEndpointName()) .WithName(typeof(GetProgrammeProjectsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Project[]>(StatusCodes.Status200OK) .Produces<Project[]>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public sealed class GetProgrammesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of all programmes") .WithDescription("Get a list of all programmes")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProgrammesEndpoint).ToEndpointName("Projects")) .WithName(typeof(GetProgrammesEndpoint).ToEndpointName("Projects"))
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Programme[]>(StatusCodes.Status200OK) .Produces<Programme[]>(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class GetProjectEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get project by ID") .WithDescription("Get project by ID")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProjectEndpoint).ToEndpointName()) .WithName(typeof(GetProjectEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Project[]>(StatusCodes.Status200OK) .Produces<Project[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetProjectIndicatorsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get get a detailed list of project indicators") .WithDescription("Get get a detailed list of project indicators")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProjectIndicatorsEndpoint).ToEndpointName()) .WithName(typeof(GetProjectIndicatorsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Indicator[]>(StatusCodes.Status200OK) .Produces<Indicator[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetProjectMilestonesEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of milestones for a project") .WithDescription("Get a list of milestones for a project")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProjectMilestonesEndpoint).ToEndpointName()) .WithName(typeof(GetProjectMilestonesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Milestone[]>(StatusCodes.Status200OK) .Produces<Milestone[]>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetProjectRisksEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of risks for a project") .WithDescription("Get a list of risks for a project")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProjectRisksEndpoint).ToEndpointName()) .WithName(typeof(GetProjectRisksEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Risk[]>(StatusCodes.Status200OK) .Produces<Risk[]>(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public class GetProjectsEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Get a list of projects") .WithDescription("Get a list of projects")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetProjectsEndpoint).ToEndpointName()) .WithName(typeof(GetProjectsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<Project[]>(StatusCodes.Status200OK) .Produces<Project[]>(StatusCodes.Status200OK)
@@ -21,7 +21,6 @@ public sealed class UpdateMilestoneEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update project milestone details") .WithDescription("Update project milestone details")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateMilestoneEndpoint).ToEndpointName()) .WithName(typeof(UpdateMilestoneEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public sealed class UpdateProgrammeEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update existing programme") .WithDescription("Update existing programme")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateProgrammeEndpoint).ToEndpointName()) .WithName(typeof(UpdateProgrammeEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class UpdateProjectEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update project details") .WithDescription("Update project details")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateProjectEndpoint).ToEndpointName()) .WithName(typeof(UpdateProjectEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -24,7 +24,6 @@ public class UpdateProjectStatusEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Update project status (M04)") .WithDescription("Update project status (M04)")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateProjectStatusEndpoint).ToEndpointName()) .WithName(typeof(UpdateProjectStatusEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -22,7 +22,6 @@ public sealed class EncodeIdEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Hashes an int64 identifier") .WithDescription("Hashes an int64 identifier")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(EncodeIdEndpoint).ToEndpointName()) .WithName(typeof(EncodeIdEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<string>(StatusCodes.Status200OK) .Produces<string>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class GetUserEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Gets the metadata of a single user.") .WithDescription("Gets the metadata of a single user.")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetUserEndpoint).ToEndpointName()) .WithName(typeof(GetUserEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<User>(StatusCodes.Status200OK) .Produces<User>(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public class GetUsersEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Paginated, searchable directory of system users. Supports filtering by ActivityStatus, searching by Email, and sorting") .WithDescription("Paginated, searchable directory of system users. Supports filtering by ActivityStatus, searching by Email, and sorting")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(GetUsersEndpoint).ToEndpointName()) .WithName(typeof(GetUsersEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces<User[]>(StatusCodes.Status200OK) .Produces<User[]>(StatusCodes.Status200OK)
@@ -30,7 +30,6 @@ public class SyncUserEndpoint : IEndpoint
}; };
}) })
.WithDescription("Trigger integration and data synchronization in the background") .WithDescription("Trigger integration and data synchronization in the background")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(SyncUserEndpoint).ToEndpointName()) .WithName(typeof(SyncUserEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -23,7 +23,6 @@ public sealed class UpdateUserStatusEndpoint : IEndpoint
var r => Results.InternalServerError(r.Errors.ToProblems()) var r => Results.InternalServerError(r.Errors.ToProblems())
}) })
.WithDescription("Changes the Activity status of the user in the system") .WithDescription("Changes the Activity status of the user in the system")
.RequireAuthorization(Constants.MainScope)
.WithName(typeof(UpdateUserStatusEndpoint).ToEndpointName()) .WithName(typeof(UpdateUserStatusEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1)) .MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status200OK)
@@ -25,8 +25,8 @@
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityModel" Version="6.2.0" /> <PackageReference Include="IdentityModel" Version="6.2.0" />
<PackageReference Include="KubernetesClient" Version="19.0.2" /> <PackageReference Include="KubernetesClient" Version="19.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Certificate" Version="10.0.12" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Certificate" Version="10.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.12" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.11" />
<Using Include="Microsoft.AspNetCore.Authentication" /> <Using Include="Microsoft.AspNetCore.Authentication" />
<Using Include="Microsoft.AspNetCore.Authentication.Cookies" /> <Using Include="Microsoft.AspNetCore.Authentication.Cookies" />
@@ -60,8 +60,8 @@
<!-- API Documentation --> <!-- API Documentation -->
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.12" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.11" />
<PackageReference Include="Scalar.AspNetCore" Version="2.17.4" /> <PackageReference Include="Scalar.AspNetCore" Version="2.17.2" />
<Using Include="Scalar.AspNetCore" /> <Using Include="Scalar.AspNetCore" />
<Using Include="Microsoft.OpenApi" /> <Using Include="Microsoft.OpenApi" />
+10 -47
View File
@@ -1,31 +1,16 @@
using Microsoft.FeatureManagement;
using PostFundManagement.Application.Extensions; using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Filters; using PostFundManagement.Application.Filters;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Health; using PostFundManagement.Domain.Health;
using PostFundManagement.Domain.Mediator; using PostFundManagement.Domain.Mediator;
using static PostFundManagement.Domain.Extensions.Constants; using static PostFundManagement.Domain.Extensions.Constants;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFeatureManagement(); builder.Services.AddEndpointsApiExplorer()
.AddApiVersioning(options => options.ApiVersionReader = new HeaderApiVersionReader());
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionReader = ApiVersionReader.Combine(
new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("version")
);
})
.AddApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
builder.Services.AddApiVersioning().AddApiExplorer();
builder.Services.AddScoped<ActiveUserFilter>(); builder.Services.AddScoped<ActiveUserFilter>();
builder.Services.AddEndpoints(Assembly.GetExecutingAssembly()); builder.Services.AddEndpoints(Assembly.GetExecutingAssembly());
@@ -106,33 +91,20 @@ builder.Services.AddOpenApi(options =>
}); });
}); });
var allowedOrigins = builder.Configuration.GetSection("CorsOrigins").Get<string[]>() ?? [];
builder.Services.AddCors(options =>
{
options.AddPolicy(CorsPolicy, policy =>
{
policy.WithOrigins(allowedOrigins)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
var app = builder.Build(); var app = builder.Build();
var schedulerFactory = app.Services.GetRequiredService<ISchedulerFactory>(); var schedulerFactory = app.Services.GetRequiredService<ISchedulerFactory>();
var scheduler = await schedulerFactory.GetScheduler(); var scheduler = await schedulerFactory.GetScheduler(DefaultSchedulerName);
if (scheduler!.Status != SchedulerStatus.Running) if (!scheduler!.IsStarted)
await scheduler.Start(); await scheduler.Start();
app.UseHsts(); app.UseHsts();
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(CorsPolicy);
app.UseOutputCache();
app.UseRouting();
app.UseOutputCache();
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
@@ -145,16 +117,7 @@ var versionGroups = new Dictionary<int, RouteGroupBuilder>
{ {
{ {
1, app.MapGroup("v{version:apiVersion}").WithApiVersionSet(versionSet) 1, app.MapGroup("v{version:apiVersion}").WithApiVersionSet(versionSet)
.RequireCors(CorsPolicy) .RequireAuthorization("ApiScope").AddEndpointFilter<ActiveUserFilter>()
.AddEndpointFilter(async (context, next) =>
{
if (HttpMethods.IsOptions(context.HttpContext.Request.Method))
return await next(context);
var filter = context.HttpContext.RequestServices.GetRequiredService<ActiveUserFilter>();
return await filter.InvokeAsync(context, next);
})
} }
}; };
-5
View File
@@ -1,9 +1,4 @@
{ {
"EnableServiceCaching": true,
"CorsOrigins": [
"https://console.ifri.khongisa.co.za",
"https://localhost:7208"
],
"GeneralS3Settings": { "GeneralS3Settings": {
"ServiceUrl": "https://s3.garage.khongisa.co.za", "ServiceUrl": "https://s3.garage.khongisa.co.za",
"Region": "garage", "Region": "garage",
@@ -2,7 +2,7 @@ using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Quartz; using PostFundManagement.Domain.Quartz;
using static PostFundManagement.Domain.Extensions.Constants; using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Extensions; namespace PostFundManagement.Domain.Extensions;
public static class Quartz public static class Quartz
{ {
@@ -10,33 +10,35 @@ public static class Quartz
{ {
var connectionString = configuration.GetConnectionString(DatabaseConfigName); var connectionString = configuration.GetConnectionString(DatabaseConfigName);
services.Configure<QuartzOptions>(options =>
{
options.Properties["quartz.scheduler.instanceName"] = schedulerName;
options.Properties["quartz.scheduler.instanceId"] = "AUTO";
});
services.ConfigureCommon(); services.ConfigureCommon();
services.AddQuartz(config => services.AddQuartz(config =>
{ {
config.SchedulerName = schedulerName;
config.SchedulerId = "AUTO";
config.UseSimpleTypeLoader(); config.UseSimpleTypeLoader();
config.UseDefaultThreadPool(options => options.MaxConcurrency = 0); config.UseDefaultThreadPool(options => options.MaxConcurrency = 0);
config.UseTimeZoneConverter(); config.UseTimeZoneConverter();
config.UsePersistentStore(storage => config.UsePersistentStore(storage =>
{ {
storage.ProvisionSchema(); storage.PerformSchemaValidation = false;
storage.UsePostgres(options => options.ConnectionString = connectionString!);
storage.UseSystemTextJsonSerializer(); storage.UseSystemTextJsonSerializer();
storage.SetProperty("quartz.jobStore.clustered", "true");
storage.UsePostgres(options =>
{
options.ConnectionString = connectionString!;
options.TablePrefix = "quartz.qrtz_";
});
storage.UseClustering(cluster => storage.UseClustering(cluster =>
{ {
cluster.CheckinInterval = TimeSpan.FromSeconds(30); cluster.CheckinInterval = TimeSpan.FromSeconds(30);
cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(90); cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(90);
}); });
}); });
}); });
return services; return services;
@@ -46,37 +48,36 @@ public static class Quartz
{ {
var connectionString = configuration.GetConnectionString(DatabaseConfigName); var connectionString = configuration.GetConnectionString(DatabaseConfigName);
services.Configure<QuartzOptions>(options =>
{
options.Properties["quartz.scheduler.instanceName"] = schedulerName;
options.Properties["quartz.scheduler.instanceId"] = "AUTO";
options.Properties["quartz.scheduler.batchTriggerAcquisitionMaxCount"] = "5";
options.Properties["quartz.jobStore.misfireThreshold"] = TimeSpan.FromMinutes(2).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
options.Properties["quartz.plugin.jobHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins";
options.Properties["quartz.plugin.triggerHistory.type"] = "Quartz.Plugin.History.LoggingTriggerHistoryPlugin, Quartz.Plugins";
});
services.ConfigureCommon(); services.ConfigureCommon();
services.AddQuartzHostedService(options => services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
{
options.WaitForJobsToComplete = true;
});
services.AddQuartz(config => services.AddQuartz(config =>
{ {
config.SchedulerName = schedulerName;
config.SchedulerId = "AUTO";
config.InterruptJobsOnShutdown = true;
config.InterruptJobsOnShutdownWithWait = true;
config.MaxBatchSize = 5;
config.UseSimpleTypeLoader(); config.UseSimpleTypeLoader();
config.UseDefaultThreadPool(options => options.MaxConcurrency = 5); config.UseDefaultThreadPool(options => options.MaxConcurrency = 1);
config.UseTimeZoneConverter(); config.UseTimeZoneConverter();
config.SetProperty("quartz.jobStore.misfireThreshold", TimeSpan.FromMinutes(2).TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
config.UsePersistentStore(storage => config.UsePersistentStore(storage =>
{ {
storage.ProvisionSchema(); storage.PerformSchemaValidation = false;
storage.UsePostgres(options => options.ConnectionString = connectionString!);
storage.UseSystemTextJsonSerializer(); storage.UseSystemTextJsonSerializer();
storage.SetProperty("quartz.jobStore.clustered", "true");
storage.UsePostgres(options =>
{
options.ConnectionString = connectionString!;
options.TablePrefix = "quartz.qrtz_";
});
storage.UseClustering(cluster => storage.UseClustering(cluster =>
{ {
cluster.CheckinInterval = TimeSpan.FromSeconds(30); cluster.CheckinInterval = TimeSpan.FromSeconds(30);
@@ -90,10 +91,18 @@ public static class Quartz
private static IServiceCollection ConfigureCommon(this IServiceCollection services) private static IServiceCollection ConfigureCommon(this IServiceCollection services)
{ {
services.Configure<QuartzOptions>(options => options.Scheduling.IgnoreDuplicates = true); services.Configure<QuartzOptions>(options =>
{
options.Scheduling.IgnoreDuplicates = true;
options.Scheduling.OverWriteExistingData = true;
options["quartz.plugin.jobHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins";
options["quartz.plugin.triggerHistory.type"] = "Quartz.Plugin.History.LoggingTriggerHistoryPlugin, Quartz.Plugins";
});
services.AddTransient<RetryJobListener>(); services.AddTransient<RetryJobListener>();
services.AddTransient<IJobOrchestrator, JobOrchestrator>(); services.AddTransient<IJobOrchestrator, JobOrchestrator>();
return services; return services;
} }
} }
@@ -1,6 +1,5 @@
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain.Security.Configuration; using PostFundManagement.Domain.Security.Configuration;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Security.Sdk; using PostFundManagement.Domain.Security.Sdk;
using PostFundManagement.Infrastructure.Database; using PostFundManagement.Infrastructure.Database;
@@ -139,7 +138,7 @@ public static class Security
{ {
options.MapInboundClaims = false; options.MapInboundClaims = false;
options.Authority = authOptions.Authority; options.Authority = authOptions.Authority;
options.Audience = authOptions.Audience; options.Audience = authOptions.Audience;
options.TokenValidationParameters = new TokenValidationParameters options.TokenValidationParameters = new TokenValidationParameters
{ {
@@ -151,7 +150,7 @@ public static class Security
}); });
services.AddAuthorizationBuilder() services.AddAuthorizationBuilder()
.AddPolicy(Constants.MainScope, policy => .AddPolicy("ApiScope", policy =>
{ {
policy.RequireAuthenticatedUser(); policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", authOptions.Audience!); policy.RequireClaim("scope", authOptions.Audience!);
@@ -24,9 +24,9 @@
<!-- API Documentation --> <!-- API Documentation -->
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.12" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.11" />
<PackageReference Include="Microsoft.Extensions.Validation" Version="10.0.12" /> <PackageReference Include="Microsoft.Extensions.Validation" Version="10.0.11" />
<PackageReference Include="Scalar.AspNetCore" Version="2.17.4" /> <PackageReference Include="Scalar.AspNetCore" Version="2.17.2" />
<Using Include="Scalar.AspNetCore" /> <Using Include="Scalar.AspNetCore" />
<Using Include="Microsoft.OpenApi" /> <Using Include="Microsoft.OpenApi" />
@@ -36,7 +36,6 @@
<!-- Shared Usings --> <!-- Shared Usings -->
<ItemGroup> <ItemGroup>
<Using Include="Humanizer" /> <Using Include="Humanizer" />
<Using Include="Microsoft.FeatureManagement" />
<Using Include="System.ComponentModel.DataAnnotations" /> <Using Include="System.ComponentModel.DataAnnotations" />
<Using Include="Microsoft.Extensions.Caching.Distributed" /> <Using Include="Microsoft.Extensions.Caching.Distributed" />
<Using Include="Microsoft.Extensions.Caching.Hybrid" /> <Using Include="Microsoft.Extensions.Caching.Hybrid" />
@@ -4,19 +4,14 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Communications; namespace PostFundManagement.Application.Services.Communications;
public sealed class CommunicationsCacheService(CommunicationsService service, IDistributedCache cache, public sealed class CommunicationsCacheService(CommunicationsService service, IDistributedCache cache) : ServiceCacheBase, ICommunicationsService
IFeatureManager featureManager) : ServiceCacheBase, ICommunicationsService
{ {
public async ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default) => public async ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () => await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetApplicantInviteAsync(applicantUserId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getapplicantinvite-{applicantUserId}").Value; var cacheKey = HashService.ToMd5Hash($"getapplicantinvite-{applicantUserId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -36,14 +31,11 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async ValueTask<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) => public async ValueTask<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getapplicantinvites-{applicantUserId}").Value; var cacheKey = HashService.ToMd5Hash($"getapplicantinvites-{applicantUserId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken); var result = await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken);
@@ -60,9 +52,6 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetInvitesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -4,12 +4,10 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Evidence; namespace PostFundManagement.Application.Services.Evidence;
public sealed class EvidenceCacheService(EvidenceService service, IDistributedCache cache, public sealed class EvidenceCacheService(EvidenceService service, IDistributedCache cache) : ServiceCacheBase, IEvidenceService
IFeatureManager featureManager) : ServiceCacheBase, IEvidenceService
{ {
public async ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default) => public async ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default) =>
await service.CreateEvidenceAsync(userId, form, file, cancellationToken); await service.CreateEvidenceAsync(userId, form, file, cancellationToken);
@@ -23,9 +21,6 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) => public async ValueTask<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence>>>)(async () => await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetEvidenceAsync(evidenceId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getevidence-{evidenceId}").Value; var cacheKey = HashService.ToMd5Hash($"getevidence-{evidenceId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -47,9 +42,6 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<Domain.Models.Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Domain.Models.Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetEvidenceFilesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -71,9 +63,6 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<string>> GetEvidenceUrlAsync(string evidenceIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<string>> GetEvidenceUrlAsync(string evidenceIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<string>>>)(async () => await Result.Try((Func<ValueTask<Result<string>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetEvidenceUrlAsync(evidenceIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getevidenceurl-{evidenceIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getevidenceurl-{evidenceIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -95,9 +84,6 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) => public async ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Indicator>>>)(async () => await Result.Try((Func<ValueTask<Result<Indicator>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetIndicatorAsync(indicatorId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getindicator-{indicatorId}").Value; var cacheKey = HashService.ToMd5Hash($"getindicator-{indicatorId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -119,9 +105,6 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetIndicatorsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -143,14 +126,11 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken); var result = await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken);
@@ -167,14 +147,11 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async ValueTask<Result<Domain.Models.Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Domain.Models.Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken); var result = await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken);
@@ -4,12 +4,10 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Execution; namespace PostFundManagement.Application.Services.Execution;
public sealed class ExecutionCacheService(ExecutionService service, IDistributedCache cache, public sealed class ExecutionCacheService(ExecutionService service, IDistributedCache cache) : ServiceCacheBase, IExecutionService
IFeatureManager featureManager) : ServiceCacheBase, IExecutionService
{ {
public async ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) => public async ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) =>
await service.ApproveDisbursementAsync(disbursementIdHash, userId, cancellationToken); await service.ApproveDisbursementAsync(disbursementIdHash, userId, cancellationToken);
@@ -23,9 +21,6 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Disbursement>>>)(async () => await Result.Try((Func<ValueTask<Result<Disbursement>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetDisbursementAsync(disbursementIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getdisbursement-{disbursementIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getdisbursement-{disbursementIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -47,9 +42,6 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async ValueTask<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Disbursement[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Disbursement[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetDisbursementsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getdisbursements-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getdisbursements-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -71,9 +63,6 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk>>>)(async () => await Result.Try((Func<ValueTask<Result<Risk>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetRiskAsync(riskIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getrisk-{riskIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getrisk-{riskIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -95,9 +84,6 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetRisksAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getrisks-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getrisks-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -4,12 +4,10 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Governance; namespace PostFundManagement.Application.Services.Governance;
public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache, public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache) : ServiceCacheBase, IGovernanceService
IFeatureManager featureManager) : ServiceCacheBase, IGovernanceService
{ {
public async ValueTask<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) => public async ValueTask<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateOrganisationAsync(request, userId, cancellationToken); await service.CreateOrganisationAsync(request, userId, cancellationToken);
@@ -20,9 +18,6 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default) => public async ValueTask<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Dashboard>>>)(async () => await Result.Try((Func<ValueTask<Result<Dashboard>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetDashboardAsync(cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getdashboard").Value; var cacheKey = HashService.ToMd5Hash($"getdashboard").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -44,9 +39,6 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Instrument[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Instrument[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetInstrumentsAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getinstruments").Value; var cacheKey = HashService.ToMd5Hash($"getinstruments").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -68,9 +60,6 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Organisation>>>)(async () => await Result.Try((Func<ValueTask<Result<Organisation>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetOrganisationAsync(organisationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getorganisation-{organisationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getorganisation-{organisationIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -92,9 +81,6 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Organisation[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Organisation[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetOrganisationsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getorganisations-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getorganisations-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -116,9 +102,6 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Portfolio[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Portfolio[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetPorfoliosAsync(organisationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfolios-{organisationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getportfolios-{organisationIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -140,14 +123,11 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Portfolio>>>)(async () => await Result.Try((Func<ValueTask<Result<Portfolio>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetPortfolioAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfolio-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getportfolio-{portfolioIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetPortfolioAsync(portfolioIdHash, cancellationToken); var result = await service.GetPortfolioAsync(portfolioIdHash, cancellationToken);
@@ -164,14 +144,11 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetPortfolioProgrammesAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfolioprogrammes-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getportfolioprogrammes-{portfolioIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetPortfolioProgrammesAsync(portfolioIdHash, cancellationToken); var result = await service.GetPortfolioProgrammesAsync(portfolioIdHash, cancellationToken);
@@ -188,9 +165,6 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProgrammesAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammes-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammes-{portfolioIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -4,12 +4,10 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Grants; namespace PostFundManagement.Application.Services.Grants;
public sealed class GrantsCacheService(GrantsService service, IDistributedCache cache, public sealed class GrantsCacheService(GrantsService service, IDistributedCache cache) : ServiceCacheBase, IGrantsService
IFeatureManager featureManager) : ServiceCacheBase, IGrantsService
{ {
public async ValueTask<Result> CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) => public async ValueTask<Result> CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateAwardAsync(request, userId, cancellationToken); await service.CreateAwardAsync(request, userId, cancellationToken);
@@ -26,9 +24,6 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Award>>>)(async () => await Result.Try((Func<ValueTask<Result<Award>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetAwardAsync(awardIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getaward-{awardIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getaward-{awardIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -50,9 +45,6 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Award[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Award[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetAwardsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getawards-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getawards-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -74,9 +66,6 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Budget>>>)(async () => await Result.Try((Func<ValueTask<Result<Budget>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetBudgetAsync(budgetIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getbudget-{budgetIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getbudget-{budgetIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -98,9 +87,6 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Budget[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Budget[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetBudgetsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getbudgets-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getbudgets-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -122,9 +108,6 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Contract>>>)(async () => await Result.Try((Func<ValueTask<Result<Contract>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetContractAsync(contractIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getctract-{contractIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getctract-{contractIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -146,9 +129,6 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Contract[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Contract[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetContractsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getcontracts-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cacheKey = HashService.ToMd5Hash($"getcontracts-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -170,18 +150,15 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async ValueTask<Result<string>> GetContractUrlAsync(string contractIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<string>> GetContractUrlAsync(string contractIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<string>>>)(async () => await Result.Try((Func<ValueTask<Result<string>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetContractUrlAsync(contractIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getcontracturl-{contractIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getcontracturl-{contractIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetContractUrlAsync(contractIdHash, cancellationToken); var result = await service.GetContractUrlAsync(contractIdHash, cancellationToken);
if (result.IsFailed) return result; if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value, cancellationToken); await cache.SetStringAsync(cacheKey, result.Value, cancellationToken);
@@ -4,12 +4,10 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Projects; namespace PostFundManagement.Application.Services.Projects;
public sealed class ProjectCacheService(ProjectService service, IDistributedCache cache, public sealed class ProjectCacheService(ProjectService service, IDistributedCache cache) : ServiceCacheBase, IProjectService
IFeatureManager featureManager) : ServiceCacheBase, IProjectService
{ {
public async ValueTask<Result> CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) => public async ValueTask<Result> CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateActivityAsync(request, userId, cancellationToken); await service.CreateActivityAsync(request, userId, cancellationToken);
@@ -23,9 +21,6 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Activity[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Domain.Models.Activity[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetActivitiesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getactivities-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getactivities-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -47,14 +42,11 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Activity>>>)(async () => await Result.Try((Func<ValueTask<Result<Domain.Models.Activity>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetActivityAsync(activityIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getactivity-{activityIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getactivity-{activityIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetActivityAsync(activityIdHash, cancellationToken); var result = await service.GetActivityAsync(activityIdHash, cancellationToken);
@@ -71,9 +63,6 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone>>>)(async () => await Result.Try((Func<ValueTask<Result<Milestone>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetMilestoneAsync(milestoneIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getmilestone-{milestoneIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getmilestone-{milestoneIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -95,14 +84,11 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Milestone[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetMilestonesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getmilestones-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cacheKey = HashService.ToMd5Hash($"getmilestones-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if (string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetMilestonesAsync(pagination, cancellationToken); var result = await service.GetMilestonesAsync(pagination, cancellationToken);
@@ -119,14 +105,11 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Programme>> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Programme>> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Programme>>>)(async () => await Result.Try((Func<ValueTask<Result<Programme>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProgrammeAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogramme-{programmeIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogramme-{programmeIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetProgrammeAsync(programmeIdHash, cancellationToken); var result = await service.GetProgrammeAsync(programmeIdHash, cancellationToken);
@@ -143,14 +126,11 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Project[]>> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Project[]>> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Project[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Project[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammeprojects-{programmeIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammeprojects-{programmeIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken); var result = await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken);
@@ -167,14 +147,11 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Programme[]>> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProgrammesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammes-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammes-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetProgrammesAsync(pagination, cancellationToken); var result = await service.GetProgrammesAsync(pagination, cancellationToken);
@@ -191,9 +168,6 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Project>>>)(async () => await Result.Try((Func<ValueTask<Result<Project>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProjectAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getproject-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getproject-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -215,9 +189,6 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectindicators-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectindicators-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -226,7 +197,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
{ {
var result = await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken); var result = await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken);
if (result.IsFailed) return result; if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
@@ -239,18 +210,15 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Milestone[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectmilestones-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectmilestones-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached)) if(string.IsNullOrWhiteSpace(cached))
{ {
var result = await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken); var result = await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken);
if (result.IsFailed) return result; if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
@@ -263,9 +231,6 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async ValueTask<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProjectRisksAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectrisks-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectrisks-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -274,7 +239,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
{ {
var result = await service.GetProjectRisksAsync(projectIdHash, cancellationToken); var result = await service.GetProjectRisksAsync(projectIdHash, cancellationToken);
if (result.IsFailed) return result; if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
@@ -287,9 +252,6 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async ValueTask<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async ValueTask<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Project[]>>>)(async () => await Result.Try((Func<ValueTask<Result<Project[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetProjectsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojects-{pagination.Index}-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getprojects-{pagination.Index}-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -298,7 +260,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
{ {
var result = await service.GetProjectsAsync(pagination, cancellationToken); var result = await service.GetProjectsAsync(pagination, cancellationToken);
if (result.IsFailed) return result; if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
@@ -1,19 +1,14 @@
using PostFundManagement.Application.Abstractions; using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services; using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Tools; namespace PostFundManagement.Application.Services.Tools;
public sealed class ToolCacheService(ToolService service, IDistributedCache cache, public sealed class ToolCacheService(ToolService service, IDistributedCache cache) : ServiceCacheBase, IToolService
IFeatureManager featureManager) : ServiceCacheBase, IToolService
{ {
public async ValueTask<Result<string>> EncodeLong(long id, CancellationToken cancellationToken) => public async ValueTask<Result<string>> EncodeLong(long id, CancellationToken cancellationToken) =>
await Result.Try((Func<ValueTask<Result<string>>>)(async () => await Result.Try((Func<ValueTask<Result<string>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.EncodeLong(id, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"encodelonghash-{id}").Value; var cacheKey = HashService.ToMd5Hash($"encodelonghash-{id}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -4,19 +4,14 @@ using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared; using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain; using PostFundManagement.Domain;
using PostFundManagement.Domain.Models; using PostFundManagement.Domain.Models;
using static PostFundManagement.Domain.Extensions.Constants;
namespace PostFundManagement.Application.Services.Users; namespace PostFundManagement.Application.Services.Users;
public sealed class UserCacheService(UserService service, IDistributedCache cache, public sealed class UserCacheService(UserService service, IDistributedCache cache) : ServiceCacheBase, IUserService
IFeatureManager featureManager) : ServiceCacheBase, IUserService
{ {
public async ValueTask<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken) => public async ValueTask<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken) =>
await Result.Try((Func<ValueTask<Result<User>>>)(async () => await Result.Try((Func<ValueTask<Result<User>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetUserAsync(userId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getuser-{userId}").Value; var cacheKey = HashService.ToMd5Hash($"getuser-{userId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken); var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
@@ -38,9 +33,6 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
public async ValueTask<Result<User[]>> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default) => public async ValueTask<Result<User[]>> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<User[]>>>)(async () => await Result.Try((Func<ValueTask<Result<User[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature))
return await service.GetUsersAsync(pagination, request, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getusers-{pagination.Page}-{pagination.PageSize}-" + var cacheKey = HashService.ToMd5Hash($"getusers-{pagination.Page}-{pagination.PageSize}-" +
$"{request.Email}-{request.Status}-{request.SortBy}-{request.SortDescending}").Value; $"{request.Email}-{request.Status}-{request.SortBy}-{request.SortDescending}").Value;
-10
View File
@@ -16,13 +16,3 @@ VITE_OIDC_CLIENT_SECRET="secret_71f88570a46eb22eb5270b47f69e3332c84d8db85d008f02
# PFM Backend API Base URL # PFM Backend API Base URL
VITE_API_BASE_URL="https://api.ifri.khongisa.co.za/" VITE_API_BASE_URL="https://api.ifri.khongisa.co.za/"
# Protocol / SSL Settings for local development
# HTTPS is enabled by default when running locally via @vitejs/plugin-basic-ssl.
# Set to 'false' if you ever need to run local dev over plain HTTP.
HTTPS="true"
VITE_ENABLE_HTTPS="true"
# HasherSettings for HashIds compatibility with backend pfm-api
VITE_HASHER_MIN_LENGTH="11"
VITE_HASHER_SALT="TGlnaHQgQ2hhcm1zLCBNaWRyYW5kQm9va3MgbWFrZSBsb3RzIG9mIG1vbmV5IGFuZCBhcmUgYSBzdWNjZXNzZnVsIHZpcmFsIHN0b3J5IGluIFNvdXRoIEFmcmljYQ=="
+5 -5
View File
@@ -6,14 +6,14 @@ WORKDIR /app
# Enable corepack to use Yarn # Enable corepack to use Yarn
RUN corepack enable RUN corepack enable
# Copy dependency definitions from the UI subdirectory into the container's /app folder # Copy dependency definitions from the subdirectory
COPY PostFundManagement.ConsoleUI/package*.json PostFundManagement.ConsoleUI/yarn.lock* ./ COPY package*.json yarn.lock* ./
# Install dependencies via Yarn # Install dependencies via Yarn
RUN yarn install --frozen-lockfile || yarn install RUN yarn install --frozen-lockfile || yarn install
# Copy application source from the UI subdirectory into the container's /app folder # Copy application source from the subdirectory
COPY PostFundManagement.ConsoleUI/ ./ COPY . .
# Build Vite application for production # Build Vite application for production
RUN yarn build RUN yarn build
@@ -38,4 +38,4 @@ EXPOSE 3000
# Set entrypoint and default command # Set entrypoint and default command
ENTRYPOINT ["/docker-entrypoint.sh"] ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"] CMD ["nginx", "-g", "daemon off;"]
-20
View File
@@ -1,20 +0,0 @@
<div align="center">
<img width="1200" height="475" alt="GHBanner" src="https://ai.google.dev/static/site-assets/images/share-ais-513315318.png" />
</div>
# Run and deploy your AI Studio app
This contains everything you need to run your app locally.
View your app in AI Studio: https://ai.studio/apps/b2519d4f-e797-44fe-be2e-0d30bec6814d
## Run Locally
**Prerequisites:** Node.js
1. Install dependencies:
`npm install`
2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
3. Run the app:
`npm run dev`
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,19 @@
version: '3.8'
services:
pfm-console:
build:
context: .
dockerfile: Dockerfile
container_name: pfm-console
ports:
- "8076:3000"
environment:
# OIDC Identity Provider Configuration
- OIDC_AUTHORITY=${OIDC_AUTHORITY}
- OIDC_AUDIENCE=${OIDC_AUDIENCE}
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
# Backend API Configuration
- API_BASE_URL=${API_BASE_URL}
restart: unless-stopped
@@ -1,102 +1,4 @@
#!/bin/sh #!/bin/sh
set -e set -e
# Target directory for Nginx static assets in container
TARGET_DIR="/usr/share/nginx/html"
# If not in standard nginx container, fallback to ./dist or ./public if present
if [ ! -d "$TARGET_DIR" ]; then
if [ -d "./dist" ]; then
TARGET_DIR="./dist"
elif [ -d "./public" ]; then
TARGET_DIR="./public"
fi
fi
# Prioritize deployment environment variables from all common naming patterns:
# 1. API Base URL
API_BASE_URL="${VITE_API_BASE_URL:-${API_BASE_URL:-${ApiSettings__BaseUrl:-${ApiSettings_BaseUrl:-${PFM_API_BASE_URL:-}}}}}"
# 2. OIDC Security Authority
OIDC_AUTHORITY="${VITE_OIDC_AUTHORITY:-${OIDC_AUTHORITY:-${SecuritySettings__Authority:-${SecuritySettings_Authority:-${AUTHORITY:-}}}}}"
# 3. OIDC Audience
OIDC_AUDIENCE="${VITE_OIDC_AUDIENCE:-${OIDC_AUDIENCE:-${SecuritySettings__Audience:-${SecuritySettings_Audience:-${AUDIENCE:-}}}}}"
# 4. OIDC Client ID
OIDC_CLIENT_ID="${VITE_OIDC_CLIENT_ID:-${OIDC_CLIENT_ID:-${SecuritySettings__ClientId:-${SecuritySettings_ClientId:-${CLIENT_ID:-}}}}}"
# 5. OIDC Client Secret
OIDC_CLIENT_SECRET="${VITE_OIDC_CLIENT_SECRET:-${OIDC_CLIENT_SECRET:-${SecuritySettings__ClientSecret:-${SecuritySettings_ClientSecret:-${CLIENT_SECRET:-}}}}}"
# 6. OIDC Scope
OIDC_SCOPE="${VITE_OIDC_SCOPE:-${OIDC_SCOPE:-${SecuritySettings__Scope:-${SecuritySettings_Scope:-${SCOPE:-}}}}}"
# 7. Hasher Settings
HASHER_SALT="${VITE_HASHER_SALT:-${HASHER_SALT:-${HasherSettings__Salt:-${HasherSettings_Salt:-}}}}}"
HASHER_MIN_LENGTH="${VITE_HASHER_MIN_LENGTH:-${HASHER_MIN_LENGTH:-${HasherSettings__MinLength:-${HasherSettings_MinLength:-}}}}}"
if [ -d "$TARGET_DIR" ]; then
echo "[docker-entrypoint] Generating runtime configuration files in $TARGET_DIR..."
# Generate env-config.js for instant, synchronous window.__RUNTIME_CONFIG__ initialization
cat <<EOF > "$TARGET_DIR/env-config.js"
// Generated dynamically at container startup from deployment environment variables
window.__RUNTIME_CONFIG__ = {
API_BASE_URL: "${API_BASE_URL}",
VITE_API_BASE_URL: "${API_BASE_URL}",
OIDC_AUTHORITY: "${OIDC_AUTHORITY}",
VITE_OIDC_AUTHORITY: "${OIDC_AUTHORITY}",
OIDC_AUDIENCE: "${OIDC_AUDIENCE}",
VITE_OIDC_AUDIENCE: "${OIDC_AUDIENCE}",
OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}",
VITE_OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}",
OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}",
VITE_OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}",
OIDC_SCOPE: "${OIDC_SCOPE}",
VITE_OIDC_SCOPE: "${OIDC_SCOPE}",
HASHER_SALT: "${HASHER_SALT}",
VITE_HASHER_SALT: "${HASHER_SALT}",
HASHER_MIN_LENGTH: "${HASHER_MIN_LENGTH}",
VITE_HASHER_MIN_LENGTH: "${HASHER_MIN_LENGTH}",
ApiSettings: {
BaseUrl: "${API_BASE_URL}"
},
SecuritySettings: {
Authority: "${OIDC_AUTHORITY}",
Audience: "${OIDC_AUDIENCE}",
ClientId: "${OIDC_CLIENT_ID}",
ClientSecret: "${OIDC_CLIENT_SECRET}",
Scope: "${OIDC_SCOPE}"
},
HasherSettings: {
Salt: "${HASHER_SALT}",
MinHashLength: "${HASHER_MIN_LENGTH}"
}
};
EOF
# Generate config.json for REST-based runtime retrieval
cat <<EOF > "$TARGET_DIR/config.json"
{
"ApiSettings": {
"BaseUrl": "${API_BASE_URL}"
},
"SecuritySettings": {
"Authority": "${OIDC_AUTHORITY}",
"Audience": "${OIDC_AUDIENCE}",
"ClientId": "${OIDC_CLIENT_ID}",
"ClientSecret": "${OIDC_CLIENT_SECRET}",
"Scope": "${OIDC_SCOPE}"
},
"HasherSettings": {
"Salt": "${HASHER_SALT}",
"MinHashLength": "${HASHER_MIN_LENGTH}"
}
}
EOF
echo "[docker-entrypoint] Successfully wrote $TARGET_DIR/env-config.js and $TARGET_DIR/config.json."
fi
exec "$@" exec "$@"
-106
View File
@@ -1,106 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
<defs>
<!-- Ambient Radial Glow -->
<radialGradient id="pfm-ambient-glow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#38bdf8" stop-opacity="0.4" />
<stop offset="70%" stop-color="#2563eb" stop-opacity="0.1" />
<stop offset="100%" stop-color="#1e1b4b" stop-opacity="0" />
</radialGradient>
<!-- Top facet: Governance & Portfolios (Indigo / Radiant Violet) -->
<linearGradient id="pfm-grad-top" x1="12" y1="8" x2="52" y2="26" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#a5b4fc" />
<stop offset="35%" stop-color="#6366f1" />
<stop offset="100%" stop-color="#4338ca" />
</linearGradient>
<!-- Left facet: Capital & Disbursement Vault (Electric Sapphire) -->
<linearGradient id="pfm-grad-left" x1="10" y1="22" x2="30" y2="56" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="45%" stop-color="#2563eb" />
<stop offset="100%" stop-color="#1e40af" />
</linearGradient>
<!-- Right facet: Milestones, Evidence & Impact Delivery (Cyan to Emerald) -->
<linearGradient id="pfm-grad-right" x1="34" y1="28" x2="54" y2="56" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#22d3ee" />
<stop offset="50%" stop-color="#06b6d4" />
<stop offset="100%" stop-color="#10b981" />
</linearGradient>
<!-- Center Radiant Diamond -->
<linearGradient id="pfm-grad-core" x1="27" y1="27" x2="37" y2="37" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#ffffff" />
<stop offset="40%" stop-color="#e0f2fe" />
<stop offset="100%" stop-color="#38bdf8" />
</linearGradient>
<!-- Soft outer glow filter -->
<filter id="pfm-glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="1.5" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Deep Contrast Foundation Disk for Dark & Light browser tabs -->
<circle cx="32" cy="32" r="31" fill="#090d16" />
<circle cx="32" cy="32" r="30" stroke="#1e293b" stroke-width="1" />
<circle cx="32" cy="32" r="28" fill="url(#pfm-ambient-glow)" />
<!-- Outer Hexagonal Structural Shield Outline -->
<path
d="M32 6.5 L53.5 19 C55 19.8 56 21.5 56 23.2 L56 40.8 C56 42.5 55 44.2 53.5 45 L32 57.5 C30.5 58.3 28.5 58.3 27 57.5 L5.5 45 C4 44.2 3 42.5 3 40.8 L3 23.2 C3 21.5 4 19.8 5.5 19 L27 6.5 C28.5 5.7 30.5 5.7 32 6.5 Z"
stroke="#3b82f6"
stroke-opacity="0.3"
stroke-width="1.2"
fill="none"
/>
<!-- Facet 1: Top Canopy (Governance / Oversight Architecture) -->
<path
d="M32 9 L51.5 20.2 L43 25.2 L32 18.8 L21 25.2 L12.5 20.2 Z"
fill="url(#pfm-grad-top)"
/>
<!-- Facet 2: Left Vault (Fund Management & Capital Allocation) -->
<path
d="M10 23 L19.2 28.4 L19.2 44.5 L30 50.8 L30 55.5 L10 43.8 Z"
fill="url(#pfm-grad-left)"
/>
<!-- Facet 3: Right Wing (Milestone Performance & Impact Assurance) -->
<path
d="M54 23 L54 43.8 L34 55.5 L34 50.8 L44.8 44.5 L44.8 28.4 Z"
fill="url(#pfm-grad-right)"
/>
<!-- Center Geometric Hub (The PFM Nexus Plate) -->
<path
d="M22 28.5 L32 22.8 L42 28.5 L42 35.5 L32 41.2 L22 35.5 Z"
fill="#0b1120"
stroke="#334155"
stroke-width="1"
/>
<!-- Kinetic Stepped Prisms -->
<path
d="M25 31.5 L32 27.5 L39 31.5 L32 35.5 Z"
fill="url(#pfm-grad-top)"
opacity="0.9"
/>
<path
d="M25 37 L32 41 L39 37 L32 33 L25 37 Z"
fill="url(#pfm-grad-right)"
opacity="0.9"
/>
<!-- Center Radiant Milestone Diamond -->
<polygon
points="32,27 36.5,32 32,37 27.5,32"
fill="url(#pfm-grad-core)"
filter="url(#pfm-glow)"
/>
<!-- Center Pure White Optical Star Point -->
<circle cx="32" cy="32" r="1.5" fill="#ffffff" />
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

+4 -12
View File
@@ -1,6 +1,6 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Post Fund Management Console</title> <title>Post Fund Management Console</title>
@@ -9,18 +9,10 @@
<meta property="og:description" content="Enterprise backoffice portal for Funders to manage portfolios, programmes, projects, grants, disbursements, and evidence workflows." /> <meta property="og:description" content="Enterprise backoffice portal for Funders to manage portfolios, programmes, projects, grants, disbursements, and evidence workflows." />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> </head>
<link rel="alternate icon" href="/favicon.svg" /> <body>
<link rel="mask-icon" href="/favicon.svg" color="#2563eb" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
</head>
<body>
<div id="root"></div> <div id="root"></div>
<!-- Runtime Environment Configuration (Populated dynamically during deployment) -->
<script src="/env-config.js"></script>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>
</html> </html>

Some files were not shown because too many files have changed in this diff Show More