Compare commits
22
Commits
92d481f75d
...
garages3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d0f2b494a | ||
|
|
d428f6e17c | ||
|
|
5829bffaa0 | ||
|
|
b703b0c64d | ||
|
|
6d554d19a7 | ||
|
|
ec777fabf8 | ||
|
|
41bf9b63bf | ||
|
|
940630f0ed | ||
|
|
6de3d30a8b | ||
|
|
831d57a8a0 | ||
|
|
2d74f7f1bd | ||
|
|
ebf35d7f12 | ||
|
|
77307f4bf0 | ||
|
|
464c21e41d | ||
|
|
364fe65e0d | ||
|
|
b239c402fa | ||
|
|
f4a1064003 | ||
|
|
5f18478675 | ||
|
|
e71ba99f9c | ||
|
|
8de761e4e6 | ||
|
|
ca6d04d528 | ||
|
|
f607eaf152 |
+11
-2
@@ -11,6 +11,7 @@
|
|||||||
*.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
|
||||||
@@ -51,6 +52,8 @@ 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
|
||||||
@@ -58,8 +61,7 @@ bld/
|
|||||||
# 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/
|
||||||
|
|
||||||
@@ -347,6 +349,7 @@ _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
|
||||||
@@ -432,3 +435,9 @@ FodyWeavers.xsd
|
|||||||
*.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
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
|
# Stage 1: Runtime base
|
||||||
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
|
|
||||||
|
|
||||||
ARG BUILD_CONFIGURATION=Release
|
# Stage 2: Build & Restore
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy csproj files for layer caching
|
||||||
|
COPY ["PostFundManagement.Api/PostFundManagement.Api.csproj", "PostFundManagement.Api/"]
|
||||||
|
COPY ["PostFundManagement.Application/PostFundManagement.Application.csproj", "PostFundManagement.Application/"]
|
||||||
|
COPY ["PostFundManagement.Domain/PostFundManagement.Domain.csproj", "PostFundManagement.Domain/"]
|
||||||
|
COPY ["PostFundManagement.Infrastructure/PostFundManagement.Infrastructure.csproj", "PostFundManagement.Infrastructure/"]
|
||||||
|
|
||||||
|
# Restore packages
|
||||||
|
RUN dotnet restore "PostFundManagement.Api/PostFundManagement.Api.csproj"
|
||||||
|
|
||||||
|
# Copy full source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN dotnet restore PostFundManagement.slnx
|
# Build from the project folder using relative filename
|
||||||
|
WORKDIR "/src/PostFundManagement.Api"
|
||||||
|
RUN dotnet build "PostFundManagement.Api.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
WORKDIR ./PostFundManagement.Api
|
# Stage 3: Publish
|
||||||
RUN ls -lth
|
FROM build AS publish
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
RUN dotnet build PostFundManagement.Api.csproj -c $BUILD_CONFIGURATION -o /app/build
|
RUN dotnet publish "PostFundManagement.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
RUN dotnet publish PostFundManagement.Api.csproj -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
|
||||||
|
|
||||||
|
# Stage 4: Final Runtime
|
||||||
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
ENTRYPOINT ["dotnet", "PostFundManagement.Api.dll"]
|
ENTRYPOINT ["dotnet", "PostFundManagement.Api.dll"]
|
||||||
@@ -23,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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())
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.RequireAuthorization()
|
|
||||||
.DisableAntiforgery()
|
|
||||||
.WithDescription("Upload supporting evidence file to S3 and register metadata (M14)")
|
.WithDescription("Upload supporting evidence file to S3 and register metadata (M14)")
|
||||||
|
.DisableAntiforgery()
|
||||||
|
.RequireAuthorization(Constants.MainScope)
|
||||||
.WithName(typeof(CreateEvidenceEndpoint).ToEndpointName())
|
.WithName(typeof(CreateEvidenceEndpoint).ToEndpointName())
|
||||||
.MapToApiVersion(new ApiVersion(1))
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
.Produces(StatusCodes.Status200OK)
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ 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,6 +24,7 @@ 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,6 +23,7 @@ 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,6 +21,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +22,7 @@ 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,6 +22,7 @@ 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,6 +23,7 @@ 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,6 +24,8 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +24,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +24,7 @@ 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,6 +21,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +25,7 @@ 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,6 +21,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +25,7 @@ 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,6 +25,7 @@ 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,6 +25,7 @@ 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,6 +24,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +24,7 @@ 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,6 +23,7 @@ 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,6 +22,7 @@ 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,6 +25,7 @@ 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,6 +33,8 @@ 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,6 +23,7 @@ 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,6 +25,7 @@ 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,6 +25,7 @@ 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,6 +22,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +24,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +24,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +22,7 @@ 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,6 +21,7 @@ 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,6 +24,7 @@ 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,6 +23,7 @@ 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,6 +24,7 @@ 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,6 +22,7 @@ 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,6 +23,7 @@ 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,6 +23,7 @@ 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,6 +30,7 @@ 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,6 +23,7 @@ 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.11" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.Certificate" Version="10.0.12" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.12" />
|
||||||
|
|
||||||
<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.11" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.12" />
|
||||||
<PackageReference Include="Scalar.AspNetCore" Version="2.17.2" />
|
<PackageReference Include="Scalar.AspNetCore" Version="2.17.4" />
|
||||||
|
|
||||||
<Using Include="Scalar.AspNetCore" />
|
<Using Include="Scalar.AspNetCore" />
|
||||||
<Using Include="Microsoft.OpenApi" />
|
<Using Include="Microsoft.OpenApi" />
|
||||||
|
|||||||
@@ -1,16 +1,31 @@
|
|||||||
|
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.AddEndpointsApiExplorer()
|
builder.Services.AddFeatureManagement();
|
||||||
.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());
|
||||||
@@ -91,20 +106,33 @@ 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(DefaultSchedulerName);
|
var scheduler = await schedulerFactory.GetScheduler();
|
||||||
|
|
||||||
if (!scheduler!.IsStarted)
|
if (scheduler!.Status != SchedulerStatus.Running)
|
||||||
await scheduler.Start();
|
await scheduler.Start();
|
||||||
|
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
app.UseCors(CorsPolicy);
|
||||||
app.UseOutputCache();
|
app.UseOutputCache();
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
@@ -117,7 +145,16 @@ var versionGroups = new Dictionary<int, RouteGroupBuilder>
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
1, app.MapGroup("v{version:apiVersion}").WithApiVersionSet(versionSet)
|
1, app.MapGroup("v{version:apiVersion}").WithApiVersionSet(versionSet)
|
||||||
.RequireAuthorization("ApiScope").AddEndpointFilter<ActiveUserFilter>()
|
.RequireCors(CorsPolicy)
|
||||||
|
.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);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
{
|
{
|
||||||
|
"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.Domain.Extensions;
|
namespace PostFundManagement.Application.Extensions;
|
||||||
|
|
||||||
public static class Quartz
|
public static class Quartz
|
||||||
{
|
{
|
||||||
@@ -10,29 +10,27 @@ 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.PerformSchemaValidation = false;
|
storage.ProvisionSchema();
|
||||||
|
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);
|
||||||
@@ -48,36 +46,37 @@ 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 => options.WaitForJobsToComplete = true);
|
services.AddQuartzHostedService(options =>
|
||||||
|
{
|
||||||
|
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 = 1);
|
config.UseDefaultThreadPool(options => options.MaxConcurrency = 5);
|
||||||
config.UseTimeZoneConverter();
|
config.UseTimeZoneConverter();
|
||||||
|
|
||||||
config.SetProperty("quartz.jobStore.misfireThreshold", TimeSpan.FromMinutes(2).TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
|
|
||||||
|
|
||||||
config.UsePersistentStore(storage =>
|
config.UsePersistentStore(storage =>
|
||||||
{
|
{
|
||||||
storage.PerformSchemaValidation = false;
|
storage.ProvisionSchema();
|
||||||
|
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);
|
||||||
@@ -91,15 +90,7 @@ public static class Quartz
|
|||||||
|
|
||||||
private static IServiceCollection ConfigureCommon(this IServiceCollection services)
|
private static IServiceCollection ConfigureCommon(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.Configure<QuartzOptions>(options =>
|
services.Configure<QuartzOptions>(options => options.Scheduling.IgnoreDuplicates = true);
|
||||||
{
|
|
||||||
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>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
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;
|
||||||
|
|
||||||
@@ -150,7 +151,7 @@ public static class Security
|
|||||||
});
|
});
|
||||||
|
|
||||||
services.AddAuthorizationBuilder()
|
services.AddAuthorizationBuilder()
|
||||||
.AddPolicy("ApiScope", policy =>
|
.AddPolicy(Constants.MainScope, 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.11" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.12" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Validation" Version="10.0.11" />
|
<PackageReference Include="Microsoft.Extensions.Validation" Version="10.0.12" />
|
||||||
<PackageReference Include="Scalar.AspNetCore" Version="2.17.2" />
|
<PackageReference Include="Scalar.AspNetCore" Version="2.17.4" />
|
||||||
|
|
||||||
<Using Include="Scalar.AspNetCore" />
|
<Using Include="Scalar.AspNetCore" />
|
||||||
<Using Include="Microsoft.OpenApi" />
|
<Using Include="Microsoft.OpenApi" />
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
<!-- 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" />
|
||||||
|
|||||||
+12
-1
@@ -4,14 +4,19 @@ 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) : ServiceCacheBase, ICommunicationsService
|
public sealed class CommunicationsCacheService(CommunicationsService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -31,6 +36,9 @@ 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);
|
||||||
@@ -52,6 +60,9 @@ 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,10 +4,12 @@ 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) : ServiceCacheBase, IEvidenceService
|
public sealed class EvidenceCacheService(EvidenceService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -21,6 +23,9 @@ 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);
|
||||||
@@ -42,6 +47,9 @@ 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);
|
||||||
@@ -63,6 +71,9 @@ 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);
|
||||||
@@ -84,6 +95,9 @@ 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);
|
||||||
@@ -105,6 +119,9 @@ 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);
|
||||||
@@ -126,6 +143,9 @@ 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);
|
||||||
@@ -147,6 +167,9 @@ 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);
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ 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) : ServiceCacheBase, IExecutionService
|
public sealed class ExecutionCacheService(ExecutionService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -21,6 +23,9 @@ 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);
|
||||||
@@ -42,6 +47,9 @@ 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);
|
||||||
@@ -63,6 +71,9 @@ 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);
|
||||||
@@ -84,6 +95,9 @@ 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,10 +4,12 @@ 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) : ServiceCacheBase, IGovernanceService
|
public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -18,6 +20,9 @@ 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);
|
||||||
@@ -39,6 +44,9 @@ 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);
|
||||||
@@ -60,6 +68,9 @@ 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);
|
||||||
@@ -81,6 +92,9 @@ 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);
|
||||||
@@ -102,6 +116,9 @@ 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);
|
||||||
@@ -123,6 +140,9 @@ 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);
|
||||||
@@ -144,6 +164,9 @@ 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);
|
||||||
@@ -165,6 +188,9 @@ 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,10 +4,12 @@ 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) : ServiceCacheBase, IGrantsService
|
public sealed class GrantsCacheService(GrantsService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -24,6 +26,9 @@ 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);
|
||||||
@@ -45,6 +50,9 @@ 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);
|
||||||
@@ -66,6 +74,9 @@ 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);
|
||||||
@@ -87,6 +98,9 @@ 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);
|
||||||
@@ -108,6 +122,9 @@ 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);
|
||||||
@@ -129,6 +146,9 @@ 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);
|
||||||
@@ -150,6 +170,9 @@ 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);
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ 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) : ServiceCacheBase, IProjectService
|
public sealed class ProjectCacheService(ProjectService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -21,6 +23,9 @@ 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);
|
||||||
@@ -42,6 +47,9 @@ 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);
|
||||||
@@ -63,6 +71,9 @@ 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);
|
||||||
@@ -84,6 +95,9 @@ 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);
|
||||||
@@ -105,6 +119,9 @@ 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);
|
||||||
@@ -126,6 +143,9 @@ 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);
|
||||||
@@ -147,6 +167,9 @@ 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);
|
||||||
@@ -168,6 +191,9 @@ 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);
|
||||||
@@ -189,6 +215,9 @@ 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);
|
||||||
@@ -210,6 +239,9 @@ 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);
|
||||||
@@ -231,6 +263,9 @@ 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);
|
||||||
@@ -252,6 +287,9 @@ 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);
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
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) : ServiceCacheBase, IToolService
|
public sealed class ToolCacheService(ToolService service, IDistributedCache cache,
|
||||||
|
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,14 +4,19 @@ 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) : ServiceCacheBase, IUserService
|
public sealed class UserCacheService(UserService service, IDistributedCache cache,
|
||||||
|
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);
|
||||||
@@ -33,6 +38,9 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -16,3 +16,13 @@ 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=="
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<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
+717
-3573
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
|||||||
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,4 +1,102 @@
|
|||||||
#!/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 "$@"
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<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>
|
||||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -9,9 +9,17 @@
|
|||||||
<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" />
|
||||||
|
<link rel="alternate icon" href="/favicon.svg" />
|
||||||
|
<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>
|
</head>
|
||||||
<body>
|
<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>
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ server {
|
|||||||
gzip_proxied expired no-cache no-store private auth;
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/json image/svg+xml;
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/json image/svg+xml;
|
||||||
|
|
||||||
# Cache control for static assets
|
# Never cache dynamic runtime configuration files or index.html
|
||||||
location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
location ~* ^/(?:config\.json|env-config\.js|index\.html)$ {
|
||||||
expires 1y;
|
expires -1;
|
||||||
access_log off;
|
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Disable caching for appsettings.json so changes take effect immediately
|
# Cache control for static assets (CSS, JS, fonts, images)
|
||||||
location = /appsettings.json {
|
location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff|woff2|ttf|eot)$ {
|
||||||
expires -1;
|
expires 1y;
|
||||||
add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
|
access_log off;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTML5 SPA History Mode Support
|
# HTML5 SPA History Mode Support
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user