diff --git a/COMPLIANCE.yaml b/COMPLIANCE.yaml index c40bea9a..105eeda8 100644 --- a/COMPLIANCE.yaml +++ b/COMPLIANCE.yaml @@ -4,8 +4,8 @@ description: | compliance. spec: - name: PIA - status: in-progress - last-updated: '2020-01-29T00:04:31.849Z' + status: Completed - TRAN19022 + last-updated: '2019-12-10T00:00:00.000Z' - name: STRA - status: in-progress - last-updated: '2020-01-29T00:04:31.849Z' + status: Completed - STAR2019013 + last-updated: '2020-04-09T00:00:00.000Z' diff --git a/README.md b/README.md index 380ec73b..4ed67f6b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![img](https://img.shields.io/badge/Lifecycle-Stable-97ca00) + # HMCR As part of the Highway Maintenance Contract Renewal (HMCR) process the business area defined the reporting requirements for the Maintenance Contractors (MCs). The contracts outlined the fields that have to be reported on and the format that it needs to be reported in. diff --git a/api/Hmcr.Api/Extensions/IApplicationBuilderExtensions.cs b/api/Hmcr.Api/Extensions/IApplicationBuilderExtensions.cs index d3a98b8a..7b37016d 100644 --- a/api/Hmcr.Api/Extensions/IApplicationBuilderExtensions.cs +++ b/api/Hmcr.Api/Extensions/IApplicationBuilderExtensions.cs @@ -14,15 +14,6 @@ namespace Hmcr.Api.Extensions { public static class IApplicationBuilderExtensions { - public static void UseHmcrCors(this IApplicationBuilder app) - { - app.UseCors(builder => builder - .AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader() - .WithExposedHeaders("Content-Disposition")); - } - public static void UseExceptionMiddleware(this IApplicationBuilder app) { app.UseMiddleware(); diff --git a/api/Hmcr.Api/Extensions/IServiceCollectionExtensions.cs b/api/Hmcr.Api/Extensions/IServiceCollectionExtensions.cs index d5216016..8dc68c71 100644 --- a/api/Hmcr.Api/Extensions/IServiceCollectionExtensions.cs +++ b/api/Hmcr.Api/Extensions/IServiceCollectionExtensions.cs @@ -216,5 +216,20 @@ public static void AddHmcrHealthCheck(this IServiceCollection services, string c services.AddHealthChecks() .AddSqlServer(connectionString, name: "HMCR-DB-Check", failureStatus: HealthStatus.Degraded, tags: new string[] { "sql", "db" }); } + + public static void AddHmcrCors(this IServiceCollection services) + { + services.AddCors(options => + { + options.AddPolicy(name: Constants.HmcrOrigins, + builder => + { + builder.WithOrigins("https://dev-hmcr.th.gov.bc.ca", "https://tst-hmcr.th.gov.bc.ca", "https://uat-hmcr.th.gov.bc.ca", "https://hmcr.th.gov.bc.ca") + .AllowAnyHeader() + .AllowAnyMethod() + .WithExposedHeaders("Content-Disposition"); + }); + }); + } } } diff --git a/api/Hmcr.Api/Startup.cs b/api/Hmcr.Api/Startup.cs index e7ec5a31..3047267a 100644 --- a/api/Hmcr.Api/Startup.cs +++ b/api/Hmcr.Api/Startup.cs @@ -4,6 +4,7 @@ using Hmcr.Data.Repositories; using Hmcr.Domain.Hangfire; using Hmcr.Domain.Services; +using Hmcr.Model; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -31,7 +32,7 @@ public void ConfigureServices(IServiceCollection services) services.AddHttpContextAccessor(); services.AddHmcrAuthentication(Configuration); services.AddHmcrDbContext(connectionString); - services.AddCors(); + services.AddHmcrCors(); services.AddHmcrControllers(); services.AddHmcrAutoMapper(); services.AddHmcrApiVersioning(); @@ -51,9 +52,10 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISubmiss app.UseExceptionMiddleware(); app.UseHmcrHealthCheck(); - app.UseAuthorization(); - app.UseAuthentication(); app.UseRouting(); + app.UseCors(Constants.HmcrOrigins); + app.UseAuthentication(); + app.UseAuthorization(); app.UseHmcrEndpoints(); app.UseHmcrSwagger(env, Configuration.GetSection("Constants:SwaggerApiUrl").Value); diff --git a/api/Hmcr.Api/appsettings.json b/api/Hmcr.Api/appsettings.json index 92d3da75..c2b6c846 100644 --- a/api/Hmcr.Api/appsettings.json +++ b/api/Hmcr.Api/appsettings.json @@ -1,7 +1,7 @@ { "AllowedHosts": "*", "Constants": { - "Version": "1.2.5.0", + "Version": "1.2.7.0", "SwaggerApiUrl": "/swagger/v1/swagger.json" }, "Serilog": { diff --git a/api/Hmcr.Domain/Services/Base/ReportServiceBase.cs b/api/Hmcr.Domain/Services/Base/ReportServiceBase.cs index c70163cf..40f9d665 100644 --- a/api/Hmcr.Domain/Services/Base/ReportServiceBase.cs +++ b/api/Hmcr.Domain/Services/Base/ReportServiceBase.cs @@ -6,6 +6,7 @@ using Hmcr.Model.Dtos.SubmissionRow; using Hmcr.Model.Dtos.SubmissionStream; using Hmcr.Model.Utils; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; @@ -20,6 +21,7 @@ public abstract class ReportServiceBase protected IUnitOfWork _unitOfWork; protected IFieldValidatorService _validator; protected IServiceAreaService _saService; + private ILogger _logger; protected ISubmissionStreamService _streamService; protected ISubmissionObjectRepository _submissionRepo; protected ISumbissionRowRepository _rowRepo; @@ -46,7 +48,7 @@ public abstract class ReportServiceBase public ReportServiceBase(IUnitOfWork unitOfWork, ISubmissionStreamService streamService, ISubmissionObjectRepository submissionRepo, ISumbissionRowRepository rowRepo, IContractTermRepository contractRepo, ISubmissionStatusService statusService, IFieldValidatorService validator, - IServiceAreaService saService) + IServiceAreaService saService, ILogger logger) { _unitOfWork = unitOfWork; _streamService = streamService; @@ -56,14 +58,21 @@ public ReportServiceBase(IUnitOfWork unitOfWork, _statusService = statusService; _validator = validator; _saService = saService; + _logger = logger; } public async Task<(Dictionary> errors, List resubmittedRecordNumbers)> CheckResubmitAsync(FileUploadDto upload) { if (!HasRowIdentifier) return (new Dictionary>(), null); + var instance = Guid.NewGuid(); + + _logger.LogInformation($"[Api] {instance} Checking resubmit started."); + var (errors, submission) = await ValidateAndLogReportErrorAsync(upload); + _logger.LogInformation($"[Api] {instance} Checking resubmit finished."); + //if there are any errors, just log it and report them to the user. if (errors.Count > 0) return (errors, null); @@ -75,16 +84,23 @@ public ReportServiceBase(IUnitOfWork unitOfWork, public async Task<(decimal submissionObjectId, Dictionary> errors)> CreateReportAsync(FileUploadDto upload) { + var instance = Guid.NewGuid(); + + _logger.LogInformation($"[Api] {instance} Creating report started."); + var (errors, submission) = await ValidateAndLogReportErrorAsync(upload); if (errors.Count > 0) { + _logger.LogInformation($"[Api] {instance} Creating report finished with errors."); return (0, errors); } var submissionEntity = await _submissionRepo.CreateSubmissionObjectAsync(submission); _unitOfWork.Commit(); + _logger.LogInformation($"[Api] {instance} Creating report finished - submission #: {submissionEntity.SubmissionObjectId}"); + return (submissionEntity.SubmissionObjectId, errors); } diff --git a/api/Hmcr.Domain/Services/RockfallReportService.cs b/api/Hmcr.Domain/Services/RockfallReportService.cs index de337d1b..aa143afb 100644 --- a/api/Hmcr.Domain/Services/RockfallReportService.cs +++ b/api/Hmcr.Domain/Services/RockfallReportService.cs @@ -33,7 +33,7 @@ public RockfallReportService(IUnitOfWork unitOfWork, ISubmissionStreamService streamService, ISubmissionObjectRepository submissionRepo, ISumbissionRowRepository rowRepo, IContractTermRepository contractRepo, ISubmissionStatusService statusService, IRockfallReportRepository rockfallRepo, IFieldValidatorService validator, ILogger logger, IServiceAreaService saService) - : base(unitOfWork, streamService, submissionRepo, rowRepo, contractRepo, statusService, validator, saService) + : base(unitOfWork, streamService, submissionRepo, rowRepo, contractRepo, statusService, validator, saService, logger) { TableName = TableNames.RockfallReport; HasRowIdentifier = true; diff --git a/api/Hmcr.Domain/Services/WildlifeReportService.cs b/api/Hmcr.Domain/Services/WildlifeReportService.cs index 1903b685..3bb099d6 100644 --- a/api/Hmcr.Domain/Services/WildlifeReportService.cs +++ b/api/Hmcr.Domain/Services/WildlifeReportService.cs @@ -33,7 +33,7 @@ public WildlifeReportService(IUnitOfWork unitOfWork, ISubmissionStreamService streamService, ISubmissionObjectRepository submissionRepo, ISumbissionRowRepository rowRepo, IContractTermRepository contractRepo, ISubmissionStatusService statusService, IWildlifeReportRepository wildlifeRepo, IFieldValidatorService validator, ILogger logger, IServiceAreaService saService) - : base(unitOfWork, streamService, submissionRepo, rowRepo, contractRepo, statusService, validator, saService) + : base(unitOfWork, streamService, submissionRepo, rowRepo, contractRepo, statusService, validator, saService, logger) { TableName = TableNames.WildlifeReport; HasRowIdentifier = false; diff --git a/api/Hmcr.Domain/Services/WorkReportService.cs b/api/Hmcr.Domain/Services/WorkReportService.cs index 292d5856..e8060ad1 100644 --- a/api/Hmcr.Domain/Services/WorkReportService.cs +++ b/api/Hmcr.Domain/Services/WorkReportService.cs @@ -33,7 +33,7 @@ public WorkReportService(IUnitOfWork unitOfWork, ISubmissionStreamService streamService, ISubmissionObjectRepository submissionRepo, ISumbissionRowRepository rowRepo, IContractTermRepository contractRepo, ISubmissionStatusService statusService, IWorkReportRepository workRptRepo, IFieldValidatorService validator, ILogger logger, IServiceAreaService saService) - : base(unitOfWork, streamService, submissionRepo, rowRepo, contractRepo, statusService, validator, saService) + : base(unitOfWork, streamService, submissionRepo, rowRepo, contractRepo, statusService, validator, saService, logger) { TableName = TableNames.WorkReport; HasRowIdentifier = true; diff --git a/api/Hmcr.Model/Constants.cs b/api/Hmcr.Model/Constants.cs index 3627133f..1a4e3eb2 100644 --- a/api/Hmcr.Model/Constants.cs +++ b/api/Hmcr.Model/Constants.cs @@ -12,6 +12,7 @@ public static class Constants public const string VancouverTimeZone = "America/Vancouver"; public const string PacificTimeZone = "Pacific Standard Time"; public const string SystemAdmin = "SYSTEM_ADMIN"; + public const string HmcrOrigins = "HmcrOrigins"; } public static class Reports diff --git a/client/.env.development b/client/.env.development index e2add909..ecd6b073 100644 --- a/client/.env.development +++ b/client/.env.development @@ -1,7 +1,8 @@ BROWSER=none -REACT_APP_API_HOST=http://localhost:27238 +REACT_APP_API_HOST=localhost:27238 +REACT_APP_CLIENT_ORIGIN=localhost:3000 REACT_APP_SSO_CLIENT=hmcr-public-dev REACT_APP_SSO_REALM=fygf50pt -REACT_APP_SSO_HOST=https://sso-dev.pathfinder.gov.bc.ca/auth +REACT_APP_SSO_HOST=https://dev.oidc.gov.bc.ca/auth REACT_APP_DEFAULT_PAGE_SIZE_OPTIONS=25,50,100,200 -REACT_APP_DEFAULT_PAGE_SIZE=25 \ No newline at end of file +REACT_APP_DEFAULT_PAGE_SIZE=25 diff --git a/client/src/js/Api.js b/client/src/js/Api.js index 7da618d0..fa0e1279 100644 --- a/client/src/js/Api.js +++ b/client/src/js/Api.js @@ -7,8 +7,10 @@ import { buildApiErrorObject } from './utils'; import * as Constants from './Constants'; export const instance = axios.create({ - baseURL: '/api', - headers: { 'Access-Control-Allow-Origin': '*', Pragma: 'no-cache' }, + baseURL: `${Constants.API_URL}`, + headers: { + Pragma: 'no-cache', + }, }); instance.interceptors.response.use( diff --git a/client/src/js/Constants.js b/client/src/js/Constants.js index 61e59429..9b03084d 100644 --- a/client/src/js/Constants.js +++ b/client/src/js/Constants.js @@ -1,6 +1,6 @@ -export const API_URL = window.RUNTIME_REACT_APP_API_HOST - ? `${window.location.protocol}//${window.RUNTIME_REACT_APP_API_HOST}/api` - : process.env.REACT_APP_API_HOST; +export const API_URL = window.RUNTIME_REACT_APP_API_HOST //In non-dev environments, start.sh makes sure the runtime variables are popluated using host environment variables. + ? `${window.location.protocol}//${window.RUNTIME_REACT_APP_API_HOST}/api` //For non-dev environments, CORS is enabled to HMCR urls. + : `${window.location.protocol}//${process.env.REACT_APP_CLIENT_ORIGIN}/api`; //For dev environment, proxy (setupProxy.js) is set up to avoid the same origin policy const CODE_LOOKUP = '/codelookup'; const ACTIVITY_RULE = '/activityrule'; diff --git a/client/src/setupProxy.js b/client/src/setupProxy.js index c493816f..3e2cb50b 100644 --- a/client/src/setupProxy.js +++ b/client/src/setupProxy.js @@ -4,14 +4,14 @@ module.exports = function (app) { app.use( '/api', createProxyMiddleware({ - target: process.env.REACT_APP_API_HOST || 'http://localhost:27238', + target: 'http://' + process.env.REACT_APP_API_HOST, changeOrigin: true, }) ), app.use( '/swagger', createProxyMiddleware({ - target: process.env.REACT_APP_API_HOST || 'http://localhost:27238', + target: 'http://' + process.env.REACT_APP_API_HOST, changeOrigin: true, }) ); diff --git a/openshift/api-deploy-config.yaml b/openshift/api-deploy-config.yaml index 1668dcd1..21453b15 100644 --- a/openshift/api-deploy-config.yaml +++ b/openshift/api-deploy-config.yaml @@ -154,6 +154,25 @@ objects: targetPort: 8080 selector: deploymentconfig: ${NAME}${SUFFIX} + - apiVersion: route.openshift.io/v1 + kind: Route + metadata: + annotations: + haproxy.router.openshift.io/timeout: 1h + creationTimestamp: null + name: ${NAME}${SUFFIX} + spec: + host: api-${HOST} + path: "/" + port: + targetPort: web + tls: + termination: edge + to: + kind: Service + name: ${NAME}${SUFFIX} + weight: 100 + wildcardPolicy: None parameters: - description: Name of the project (HMCR) displayName: PROJECT_NAME diff --git a/openshift/client-deploy-config.yaml b/openshift/client-deploy-config.yaml index 9f99183b..84c7a6d0 100644 --- a/openshift/client-deploy-config.yaml +++ b/openshift/client-deploy-config.yaml @@ -62,7 +62,7 @@ objects: name: sso-configs-${ENV} key: CLIENT_SSO_CLIENTID - name: REACT_APP_API_HOST - value: ${HOST} + value: api-${HOST} - name: HMCR_DEPLOY_SUFFIX value: ${SUFFIX} test: false