From 24833f479dde5195057addaad11cb7624bf206d6 Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Tue, 4 Aug 2020 08:28:57 -0700 Subject: [PATCH 01/11] Version 1.2.5 --- api/Hmcr.Api/appsettings.json | 2 +- api/Hmcr.Hangfire/appsettings.json | 2 +- openshift/configmaps/api-appsettings.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/Hmcr.Api/appsettings.json b/api/Hmcr.Api/appsettings.json index f081b003..92d3da75 100644 --- a/api/Hmcr.Api/appsettings.json +++ b/api/Hmcr.Api/appsettings.json @@ -1,7 +1,7 @@ { "AllowedHosts": "*", "Constants": { - "Version": "1.2.4.0", + "Version": "1.2.5.0", "SwaggerApiUrl": "/swagger/v1/swagger.json" }, "Serilog": { diff --git a/api/Hmcr.Hangfire/appsettings.json b/api/Hmcr.Hangfire/appsettings.json index b433d146..18258883 100644 --- a/api/Hmcr.Hangfire/appsettings.json +++ b/api/Hmcr.Hangfire/appsettings.json @@ -1,7 +1,7 @@ { "AllowedHosts": "*", "Constants": { - "Version": "1.2.2.0", + "Version": "1.2.5.0", "SwaggerApiUrl": "/swagger/v1/swagger.json" }, "Serilog": { diff --git a/openshift/configmaps/api-appsettings.yaml b/openshift/configmaps/api-appsettings.yaml index ce4b7682..57f1049b 100644 --- a/openshift/configmaps/api-appsettings.yaml +++ b/openshift/configmaps/api-appsettings.yaml @@ -9,7 +9,7 @@ objects: { "AllowedHosts": "*", "Constants": { - "Version": "1.2.4.0", + "Version": "1.2.5.0", "SwaggerApiUrl": "/swagger/v1/swagger.json" }, "Serilog": { From 4f1ad36dfd25447d74684c3471a63f9d10e6f5da Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Wed, 12 Aug 2020 11:23:13 -0700 Subject: [PATCH 02/11] Fix logging typo --- api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs index 9b13f63c..9e67919e 100644 --- a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs +++ b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs @@ -112,7 +112,7 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) if (!isApiClient && user.Username.ToUpperInvariant() != username || user.Email.ToUpperInvariant() != email) { - _logger.LogWarning($"Username/Email changed from {user.Username}/{user.Email} to {user.Email}/{email}."); + _logger.LogWarning($"Username/Email changed from {user.Username}/{user.Email} to {username}/{email}."); await _userService.UpdateUserFromBceidAsync(userGuid, username, user.UserType, user.ConcurrencyControlNumber); } From 2f2a4834f238614cdb23e862ab13240ad90f9524 Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Thu, 13 Aug 2020 09:15:41 -0700 Subject: [PATCH 03/11] Support for user name change in Api Client --- api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs index 9e67919e..bbfb912b 100644 --- a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs +++ b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs @@ -71,6 +71,7 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) var isApiClient = false; bool.TryParse(principal.FindFirstValue(HmcrClaimTypes.KcIsApiClient), out isApiClient); + //preferred_username token has a form of "{username}@{directory}". _curentUser.UserName = isApiClient ? principal.FindFirstValue(HmcrClaimTypes.KcApiUsername) : principal.FindFirstValue(HmcrClaimTypes.KcUsername); var usernames = _curentUser.UserName.Split("@"); var username = usernames[0].ToUpperInvariant(); @@ -88,6 +89,14 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) return false; } + //When it's an Api client, we don't want to use the username from the token because it's a hard-code value. + //This is to support the scenario where username has changed for the GUID. Note GUID never changes and unique but username can change. + if (isApiClient) + { + username = user.Username; + _curentUser.UserName = $"{username}@{directory}"; + } + if (directory == "IDIR") { _curentUser.UserGuid = userGuid; From 5e847569dbf25b9757f2e7f634ca82493a8472d1 Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Thu, 13 Aug 2020 09:48:03 -0700 Subject: [PATCH 04/11] Clean-up confusing properties from HmcrCurrentUser --- api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs | 10 ++++------ api/Hmcr.Data/Database/Entities/AppDbContextPartial.cs | 4 ++-- api/Hmcr.Domain/Hangfire/EmailJobService.cs | 2 +- api/Hmcr.Domain/Hangfire/SubmissionObjectJobService.cs | 2 +- api/Hmcr.Domain/Services/KeyCloakService.cs | 4 ++-- api/Hmcr.Model/HmcrCurrentUser.cs | 3 +-- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs index bbfb912b..acfe9a90 100644 --- a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs +++ b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs @@ -72,8 +72,8 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) bool.TryParse(principal.FindFirstValue(HmcrClaimTypes.KcIsApiClient), out isApiClient); //preferred_username token has a form of "{username}@{directory}". - _curentUser.UserName = isApiClient ? principal.FindFirstValue(HmcrClaimTypes.KcApiUsername) : principal.FindFirstValue(HmcrClaimTypes.KcUsername); - var usernames = _curentUser.UserName.Split("@"); + var preferredUsername = isApiClient ? principal.FindFirstValue(HmcrClaimTypes.KcApiUsername) : principal.FindFirstValue(HmcrClaimTypes.KcUsername); + var usernames = preferredUsername.Split("@"); var username = usernames[0].ToUpperInvariant(); var directory = usernames[1].ToUpperInvariant(); @@ -94,7 +94,6 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) if (isApiClient) { username = user.Username; - _curentUser.UserName = $"{username}@{directory}"; } if (directory == "IDIR") @@ -111,10 +110,9 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) _curentUser.UserType = UserTypeDto.BUSINESS; } - _curentUser.UniversalId = username; + _curentUser.Username = username; _curentUser.AuthDirName = directory; _curentUser.Email = email; - _curentUser.UserName = username; _curentUser.FirstName = user.FirstName; _curentUser.LastName = user.LastName; _curentUser.ApiClientId = user.ApiClientId; @@ -142,7 +140,7 @@ private void AddClaimsFromUserInfo(ClaimsPrincipal principal, UserCurrentDto use claims.Add(new Claim(HmcrClaimTypes.ServiceAreaNumber, serviceArea.ServiceAreaNumber.ToString())); } - claims.Add(new Claim(ClaimTypes.Name, _curentUser.UniversalId)); + claims.Add(new Claim(ClaimTypes.Name, _curentUser.Username)); principal.AddIdentity(new ClaimsIdentity(claims)); } diff --git a/api/Hmcr.Data/Database/Entities/AppDbContextPartial.cs b/api/Hmcr.Data/Database/Entities/AppDbContextPartial.cs index bbd6b09e..ddd6d666 100644 --- a/api/Hmcr.Data/Database/Entities/AppDbContextPartial.cs +++ b/api/Hmcr.Data/Database/Entities/AppDbContextPartial.cs @@ -65,14 +65,14 @@ private void PerformAudit() { if (entry.Members.Any(m => m.Metadata.Name == AppCreateUserGuid)) //auditable entity { - entry.Member(AppLastUpdateUserid).CurrentValue = _currentUser.UniversalId; + entry.Member(AppLastUpdateUserid).CurrentValue = _currentUser.Username; entry.Member(AppLastUpdateUserDirectory).CurrentValue = _currentUser.AuthDirName; entry.Member(AppLastUpdateUserGuid).CurrentValue = _currentUser.UserGuid; entry.Member(AppLastUpdateTimestamp).CurrentValue = currentTime; if (entry.State == EntityState.Added) { - entry.Member(AppCreateUserid).CurrentValue = _currentUser.UniversalId; + entry.Member(AppCreateUserid).CurrentValue = _currentUser.Username; entry.Member(AppCreateUserDirectory).CurrentValue = _currentUser.AuthDirName; entry.Member(AppCreateUserGuid).CurrentValue = _currentUser.UserGuid; entry.Member(AppCreateTimestamp).CurrentValue = currentTime; diff --git a/api/Hmcr.Domain/Hangfire/EmailJobService.cs b/api/Hmcr.Domain/Hangfire/EmailJobService.cs index e1cd025f..917b295f 100644 --- a/api/Hmcr.Domain/Hangfire/EmailJobService.cs +++ b/api/Hmcr.Domain/Hangfire/EmailJobService.cs @@ -37,7 +37,7 @@ public EmailJobService(IFeebackMessageRepository feedbackRepo, IEmailService ema public async Task ResendEmails() { _user.AuthDirName = UserTypeDto.IDIR; - _user.UniversalId = "hangfire"; + _user.Username = "hangfire"; _user.UserGuid = new Guid(); var feedbackMessages = await _feedbackRepo.GetFailedFeedbackMessagesAsync(); diff --git a/api/Hmcr.Domain/Hangfire/SubmissionObjectJobService.cs b/api/Hmcr.Domain/Hangfire/SubmissionObjectJobService.cs index f76f1639..f954f992 100644 --- a/api/Hmcr.Domain/Hangfire/SubmissionObjectJobService.cs +++ b/api/Hmcr.Domain/Hangfire/SubmissionObjectJobService.cs @@ -39,7 +39,7 @@ public SubmissionObjectJobService(ISubmissionObjectRepository submissionRepo, public async Task RunReportingJob(decimal serviceAreaNumber) { _user.AuthDirName = UserTypeDto.IDIR; - _user.UniversalId = "hangfire"; + _user.Username = "hangfire"; _user.UserGuid = new Guid(); var submissions = _submissionRepo.GetSubmissionObjecsForBackgroundJob(serviceAreaNumber); diff --git a/api/Hmcr.Domain/Services/KeyCloakService.cs b/api/Hmcr.Domain/Services/KeyCloakService.cs index 0595a536..afa357f1 100644 --- a/api/Hmcr.Domain/Services/KeyCloakService.cs +++ b/api/Hmcr.Domain/Services/KeyCloakService.cs @@ -118,12 +118,12 @@ public async Task GetUserClientAsync() var directoryType = _currentUser.UserType == UserTypeDto.INTERNAL ? "idir" : "bceid"; - var username = $"{_currentUser.UniversalId.ToLowerInvariant()}@{directoryType}"; + var username = $"{_currentUser.Username.ToLowerInvariant()}@{directoryType}"; var email = _currentUser.Email.ToLowerInvariant(); var guidClaimValue = _currentUser.UserGuid.ToString(); var createDto = new KeycloakClientCreateDto(_audience, username, email, $"{directoryType}_userid", guidClaimValue); - createDto.ClientId = $"api.{_currentUser.UserName.ToLowerInvariant()}.{GetUniqueToken(3)}"; + createDto.ClientId = $"api.{_currentUser.Username.ToLowerInvariant()}.{GetUniqueToken(3)}"; var payload = JsonSerializer.Serialize(createDto, _jsonOptions); var response = await _httpClient.PostAsync("clients", new StringContent(payload, Encoding.UTF8, "application/json")); diff --git a/api/Hmcr.Model/HmcrCurrentUser.cs b/api/Hmcr.Model/HmcrCurrentUser.cs index 8f55d52f..5a319cd8 100644 --- a/api/Hmcr.Model/HmcrCurrentUser.cs +++ b/api/Hmcr.Model/HmcrCurrentUser.cs @@ -7,11 +7,10 @@ public class HmcrCurrentUser { public Guid UserGuid { get; set; } public string UserType { get; set; } - public string UniversalId { get; set; } + public string Username { get; set; } public Guid? BusinessGuid { get; set; } public string AuthDirName { get; set; } public string Email { get; set; } - public string UserName { get; set; } public string BusinessLegalName { get; set; } public decimal BusinessNumber { get; set; } public string FirstName { get; set; } From 29b87a4bbffad10107aa511f08b0da10bbdc3882 Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Thu, 13 Aug 2020 12:16:58 -0700 Subject: [PATCH 05/11] Fix wrong title (Edit Role -> Edit User) --- client/src/js/components/UserAdmin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/js/components/UserAdmin.js b/client/src/js/components/UserAdmin.js index c68cbcc9..312b46bb 100644 --- a/client/src/js/components/UserAdmin.js +++ b/client/src/js/components/UserAdmin.js @@ -152,7 +152,7 @@ const UserAdmin = ({ serviceAreas, userStatuses, userTypes, showValidationErrorD }; const formModal = useFormModal( - 'Role', + 'User', , handleEditFormSubmit ); From b9ceed78d308ab70414747db9cacc94574bf8d4f Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Thu, 13 Aug 2020 14:57:46 -0700 Subject: [PATCH 06/11] bug fix - wrong if condition for update from BCeID web service. --- api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs index acfe9a90..7d3ec9ec 100644 --- a/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs +++ b/api/Hmcr.Api/Authentication/HmcrJwtBearerEvents.cs @@ -79,10 +79,9 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) var userGuidClaim = directory.ToUpperInvariant() == UserTypeDto.IDIR ? HmcrClaimTypes.KcIdirGuid : HmcrClaimTypes.KcBceidGuid; var userGuid = new Guid(principal.FindFirstValue(userGuidClaim)); - - var user = await _userService.GetActiveUserEntityAsync(userGuid); var email = principal.FindFirstValue(ClaimTypes.Email).ToUpperInvariant(); + var user = await _userService.GetActiveUserEntityAsync(userGuid); if (user == null) { _logger.LogWarning($"Access Denied - User[{username}/{userGuid}] does not exist"); @@ -94,6 +93,7 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) if (isApiClient) { username = user.Username; + email = user.Email; } if (directory == "IDIR") @@ -117,7 +117,13 @@ private async Task PopulateCurrentUserFromDb(ClaimsPrincipal principal) _curentUser.LastName = user.LastName; _curentUser.ApiClientId = user.ApiClientId; - if (!isApiClient && user.Username.ToUpperInvariant() != username || user.Email.ToUpperInvariant() != email) + if (isApiClient) //no db update, so everything's done. + { + _logger.LogInformation($"ApiClient Login - {preferredUsername}/{username}"); + return true; + } + + if (user.Username.ToUpperInvariant() != username || user.Email.ToUpperInvariant() != email) //when the info changed, update db with the latest info from bceid web service { _logger.LogWarning($"Username/Email changed from {user.Username}/{user.Email} to {username}/{email}."); await _userService.UpdateUserFromBceidAsync(userGuid, username, user.UserType, user.ConcurrencyControlNumber); From 216c56810ca0b178038c0dfd57eea583a40c1d4b Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Mon, 17 Aug 2020 08:06:55 -0700 Subject: [PATCH 07/11] Minor fix for logging text --- api/Hmcr.Api/Middlewares/ExceptionMiddleware.cs | 2 +- api/Hmcr.Domain/Services/UserService.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/Hmcr.Api/Middlewares/ExceptionMiddleware.cs b/api/Hmcr.Api/Middlewares/ExceptionMiddleware.cs index 566a9959..16f05c6d 100644 --- a/api/Hmcr.Api/Middlewares/ExceptionMiddleware.cs +++ b/api/Hmcr.Api/Middlewares/ExceptionMiddleware.cs @@ -31,7 +31,7 @@ public async Task InvokeAsync(HttpContext httpContext) return; var guid = Guid.NewGuid(); - _logger.LogError($"HMCR Exception{guid}: {ex}"); + _logger.LogError($"HMCR Exception {guid}: {ex}"); await HandleExceptionAsync(httpContext, guid); } } diff --git a/api/Hmcr.Domain/Services/UserService.cs b/api/Hmcr.Domain/Services/UserService.cs index 68f777b9..32f4e314 100644 --- a/api/Hmcr.Domain/Services/UserService.cs +++ b/api/Hmcr.Domain/Services/UserService.cs @@ -93,7 +93,7 @@ public async Task GetBceidAccountAsync(string username, str var (error, account) = await _bceid.GetBceidAccountCachedAsync(null, user.Username, user.UserType, _currentUser.UserGuid, _currentUser.UserType); if (error.IsNotEmpty()) { - throw new HmcrException($"Unable to retrieve User[{user.Username} ({user.UserType})] from BCeID Service."); + throw new HmcrException($"Unable to retrieve User[{user.Username}]-[{user.UserType}] from BCeID Service."); } user.Email = account.Email; @@ -102,7 +102,7 @@ public async Task GetBceidAccountAsync(string username, str if (await _userRepo.DoesUsernameExistAsync(user.Username, user.UserType)) { - errors.AddItem(Fields.Username, $"Username [{user.Username} ({user.UserType})] already exists."); + errors.AddItem(Fields.Username, $"Username [{user.Username}]-[{user.UserType}] already exists."); } if (errors.Count > 0) From e2fe89f441b91629c72dfaf73b57f2311cdb761a Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Tue, 25 Aug 2020 10:20:42 -0700 Subject: [PATCH 08/11] TH-65044, TH-65135 --- api/Hmcr.Domain/CsvHelpers/CsvHelperUtils.cs | 2 ++ api/Hmcr.Domain/Services/RockfallReportService.cs | 8 +++++++- api/Hmcr.Domain/Services/WorkReportService.cs | 8 +++++++- api/Hmcr.Model/Utils/DateUtils.cs | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/api/Hmcr.Domain/CsvHelpers/CsvHelperUtils.cs b/api/Hmcr.Domain/CsvHelpers/CsvHelperUtils.cs index 2165743c..48a5fd81 100644 --- a/api/Hmcr.Domain/CsvHelpers/CsvHelperUtils.cs +++ b/api/Hmcr.Domain/CsvHelpers/CsvHelperUtils.cs @@ -3,6 +3,7 @@ using Hmcr.Model.Utils; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text.RegularExpressions; namespace Hmcr.Domain.CsvHelpers @@ -32,6 +33,7 @@ public static void Config(Dictionary> errors, CsvReader csv } csv.Configuration.IgnoreBlankLines = true; + csv.Configuration.ShouldSkipRecord = (record) => record.All(field => field.IsEmpty()); } } } diff --git a/api/Hmcr.Domain/Services/RockfallReportService.cs b/api/Hmcr.Domain/Services/RockfallReportService.cs index b4643a28..b1bd610b 100644 --- a/api/Hmcr.Domain/Services/RockfallReportService.cs +++ b/api/Hmcr.Domain/Services/RockfallReportService.cs @@ -109,7 +109,13 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub if (!serviceAreastrings.Contains(row.ServiceArea)) { - errors.AddItem("ServiceArea", $"The file contains service area which is not {serviceAreastrings[0]}."); + errors.AddItem(Fields.ServiceArea, $"The file contains service area which is not {serviceAreastrings[0]}."); + return false; + } + + if (row.McrrIncidentNumber.IsEmpty()) + { + errors.AddItem(Fields.McrrIncidentNumber, $"MCRR Incident Number is missing for row [{csv.Context.Row}]."); return false; } diff --git a/api/Hmcr.Domain/Services/WorkReportService.cs b/api/Hmcr.Domain/Services/WorkReportService.cs index 17e457d4..61b594c6 100644 --- a/api/Hmcr.Domain/Services/WorkReportService.cs +++ b/api/Hmcr.Domain/Services/WorkReportService.cs @@ -109,7 +109,13 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub if (!serviceAreastrings.Contains(row.ServiceArea)) { - errors.AddItem("ServiceArea", $"The file contains service area which is not {serviceAreastrings[0]}."); + errors.AddItem(Fields.ServiceArea, $"The file contains service area which is not {serviceAreastrings[0]}."); + return false; + } + + if (row.RecordNumber.IsEmpty()) + { + errors.AddItem(Fields.RecordNumber, $"Record Number is missing for row [{csv.Context.Row}]."); return false; } diff --git a/api/Hmcr.Model/Utils/DateUtils.cs b/api/Hmcr.Model/Utils/DateUtils.cs index 64b319df..54d4976b 100644 --- a/api/Hmcr.Model/Utils/DateUtils.cs +++ b/api/Hmcr.Model/Utils/DateUtils.cs @@ -15,7 +15,7 @@ public static (bool parsed, DateTime? parsedDate) ParseDate(object val) return (true, (DateTime)val); } - var formats = new string[] { "yyyyMMdd", "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd" }; + var formats = new string[] { "yyyyMMdd", "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd", "yyyyMd", "yyyy-M-d", "yyyy/M/dd", "yyyy.M.d" }; var dateStr = val.ToString(); if (dateStr.IsEmpty()) From 5c8c03465891add2c8afeb610dc91c0205fb759d Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Wed, 26 Aug 2020 11:47:07 -0700 Subject: [PATCH 09/11] Fixed a typo --- client/src/js/components/ApiAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/js/components/ApiAccess.js b/client/src/js/components/ApiAccess.js index f6b906d8..c939416e 100644 --- a/client/src/js/components/ApiAccess.js +++ b/client/src/js/components/ApiAccess.js @@ -72,7 +72,7 @@ const ApiAccess = ({ hideErrorDialog }) => { `--header 'Content-Type: application/x-www-form-urlencoded' \\\n` + `--data-urlencode 'grant_type=client_credentials' \\\n` + `--data-urlencode 'client_id=${apiClient ? apiClient.clientId : ''}' \\\n` + - `--data-urlencode 'client_secret=''`; + `--data-urlencode 'client_secret='`; const accessTokenPowershell = `$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"\n` + From a9c1f77c3889548d956e0b1d203d6ff7453d713a Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Wed, 26 Aug 2020 14:33:40 -0700 Subject: [PATCH 10/11] HMCR-651 --- .../01_HMR_PDM-dml-CNT-PRTY-HMCR-651.sql | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 database/V23.2/01_HMR_PDM-dml-CNT-PRTY-HMCR-651.sql diff --git a/database/V23.2/01_HMR_PDM-dml-CNT-PRTY-HMCR-651.sql b/database/V23.2/01_HMR_PDM-dml-CNT-PRTY-HMCR-651.sql new file mode 100644 index 00000000..f49ff6e6 --- /dev/null +++ b/database/V23.2/01_HMR_PDM-dml-CNT-PRTY-HMCR-651.sql @@ -0,0 +1,78 @@ +-- ============================================= +-- Author: Ben Driver +-- Create date: 2020-08-25 +-- Updates: +-- 2020-08-25: data management for ticket HMCR-651 to addresss TH-65135, TH-64889 +-- Description: - Load CONTRACT_TERM PARTY association based on the business area specified users : +-- BCeID\BCORBACH from ARGO ROAD MAINTENANCE (SOUTH OKANAGAN) INC. for Service Area 21 +-- BCeID\SMONTEMURRO from EMIL ANDERSON MAINTENANCE CO. LTD., for Service Area 26 + +-- ============================================= + +--USE HMR_DEV; -- uncomment appropriate instance +--USE HMR_TST; +--USE HMR_UAT; +USE HMR_PRD; +GO + +/* Load user context variables. Redeclared further below for subsequent executions */ + +DECLARE @utcdate DATETIME = (SELECT getutcdate() AS utcdate) +DECLARE @app_guid UNIQUEIDENTIFIER = (SELECT CASE WHEN SUSER_SID() IS NOT NULL THEN SUSER_SID() ELSE (SELECT CONVERT(uniqueidentifier,STUFF(STUFF(STUFF(STUFF('B00D00A0AC0A0D0C00DD00F0D0C00000',9,0,'-'),14,0,'-'),19,0,'-'),24,0,'-'))) END AS app_guid) +DECLARE @app_user VARCHAR(30) = (SELECT CASE WHEN SUBSTRING(SUSER_NAME(),CHARINDEX('\',SUSER_NAME())+1,LEN(SUSER_NAME())) IS NOT NULL THEN SUBSTRING(SUSER_NAME(),CHARINDEX('\',SUSER_NAME())+1,LEN(SUSER_NAME())) ELSE CURRENT_USER END AS app_user) +DECLARE @app_user_dir VARCHAR(12) = (SELECT CASE WHEN LEN(SUBSTRING(SUSER_NAME(),0,CHARINDEX('\',SUSER_NAME(),0)))>1 THEN SUBSTRING(SUSER_NAME(),0,CHARINDEX('\',SUSER_NAME(),0)) ELSE 'WIN AUTH' END AS app_user_dir) + + +UPDATE CNRT_TRM + SET CNRT_TRM.[PARTY_ID] = prty_cnrt.PARTY_ID + ,CNRT_TRM.[CONCURRENCY_CONTROL_NUMBER] = CONCURRENCY_CONTROL_NUMBER+1 + ,CNRT_TRM.[APP_LAST_UPDATE_USERID] = @app_user + ,CNRT_TRM.[APP_LAST_UPDATE_TIMESTAMP] = @utcdate + ,CNRT_TRM.[APP_LAST_UPDATE_USER_GUID] = @app_guid + ,CNRT_TRM.[APP_LAST_UPDATE_USER_DIRECTORY] = @app_user_dir + ,CNRT_TRM.[DB_AUDIT_LAST_UPDATE_USERID] = @app_user + ,CNRT_TRM.[DB_AUDIT_LAST_UPDATE_TIMESTAMP] = @utcdate +FROM [dbo].[HMR_CONTRACT_TERM] CNRT_TRM +INNER JOIN ( +SELECT PARTY_ID, CONTRACT_NAME FROM ( + SELECT + PRTY.PARTY_ID, + RANK() OVER (PARTITION BY SRV_ARA.[SERVICE_AREA_NUMBER] + ORDER BY + SRV_ARA_USR.APP_LAST_UPDATE_TIMESTAMP DESC) AS Rank, + cnrt_trm.CONTRACT_NAME, + SYS_USR.USERNAME + FROM + [dbo].[HMR_SERVICE_AREA] SRV_ARA + INNER JOIN + [dbo].[HMR_SERVICE_AREA_USER] SRV_ARA_USR + ON SRV_ARA.SERVICE_AREA_NUMBER = SRV_ARA_USR.SERVICE_AREA_NUMBER + INNER JOIN + [dbo].[HMR_SYSTEM_USER] SYS_USR + ON SRV_ARA_USR.SYSTEM_USER_ID = SYS_USR.SYSTEM_USER_ID + INNER JOIN + [dbo].[HMR_PARTY] PRTY + ON SYS_USR.PARTY_ID = PRTY.PARTY_ID + INNER JOIN + [dbo].[HMR_CONTRACT_TERM] cnrt_trm + ON cnrt_trm.SERVICE_AREA_NUMBER = SRV_ARA_USR.SERVICE_AREA_NUMBER + WHERE + SYS_USR.USER_TYPE = 'BUSINESS' + AND SYS_USR.BUSINESS_GUID IS NOT NULL + AND PRTY.BUSINESS_GUID IS NOT NULL + -- business area specified the user names to associate with each service area + AND SYS_USR.USERNAME IN ('BCORBACH', 'SMONTEMURRO') AND cnrt_trm.SERVICE_AREA_NUMBER IN (21, 26) + -- only acceptable to overwrite an exiting party relationship without managing the contract term dates if there are no previous data submissions + AND SRV_ARA.SERVICE_AREA_NUMBER NOT IN ( + SELECT + SERVICE_AREA_NUMBER + FROM + [dbo].[HMR_SUBMISSION_ROW] SUBM_RW + INNER JOIN + [dbo].[HMR_SUBMISSION_OBJECT] SUBM_OBJ + ON SUBM_RW.SUBMISSION_OBJECT_ID = SUBM_OBJ.SUBMISSION_OBJECT_ID + WHERE + [SERVICE_AREA_NUMBER] IN (26, 21) + ) + ) PRTY_USR_SRV_ARA +) prty_cnrt ON CNRT_TRM.CONTRACT_NAME = prty_cnrt.CONTRACT_NAME \ No newline at end of file From 498f62d10eebd2ff6f126612afbbe971876984aa Mon Sep 17 00:00:00 2001 From: Young-Jin Chung Date: Thu, 27 Aug 2020 08:48:57 -0700 Subject: [PATCH 11/11] HMCR-650 Added support for blank line --- .../Hangfire/RockfallReportJobService.cs | 31 ++++++++++++++--- .../Hangfire/WildlifeReportJobService.cs | 31 ++++++++++++++--- .../Hangfire/WorkReportJobService.cs | 33 ++++++++++++++++--- .../Services/RockfallReportService.cs | 2 -- .../Services/WildlifeReportService.cs | 2 -- api/Hmcr.Domain/Services/WorkReportService.cs | 2 -- 6 files changed, 80 insertions(+), 21 deletions(-) diff --git a/api/Hmcr.Domain/Hangfire/RockfallReportJobService.cs b/api/Hmcr.Domain/Hangfire/RockfallReportJobService.cs index 00fa3458..85df8f7f 100644 --- a/api/Hmcr.Domain/Hangfire/RockfallReportJobService.cs +++ b/api/Hmcr.Domain/Hangfire/RockfallReportJobService.cs @@ -487,14 +487,35 @@ private string GetValidationEntityName(RockfallReportCsvDto untypedRow) CsvHelperUtils.Config(errors, csv, false); csv.Configuration.RegisterClassMap(); - var rows = csv.GetRecords().ToList(); - for (var i = 0; i < rows.Count; i++) + var rows = GetRecords(csv); + + return (rows, string.Join(',', csv.Context.HeaderRecord).Replace("\"", "")); + } + + private List GetRecords(CsvReader csv) + { + var rows = new List(); + + while (csv.Read()) { - rows[i].RowNum = i + 2; - rows[i].ServiceArea = _serviceArea.ConvertToServiceAreaString(rows[i].ServiceArea); + RockfallReportCsvDto row = null; + + try + { + row = csv.GetRecord(); + } + catch (Exception ex) + { + _logger.LogError(ex.ToString()); + throw; + } + + row.RowNum = csv.Context.Row; + row.ServiceArea = _serviceArea.ConvertToServiceAreaString(row.ServiceArea); + rows.Add(row); } - return (rows, string.Join(',', csv.Context.HeaderRecord).Replace("\"", "")); + return rows; } private (decimal rowNum, List rows) ParseRowsTyped(string text, Dictionary> errors) diff --git a/api/Hmcr.Domain/Hangfire/WildlifeReportJobService.cs b/api/Hmcr.Domain/Hangfire/WildlifeReportJobService.cs index f76e572f..820a22f1 100644 --- a/api/Hmcr.Domain/Hangfire/WildlifeReportJobService.cs +++ b/api/Hmcr.Domain/Hangfire/WildlifeReportJobService.cs @@ -326,14 +326,35 @@ private string GetValidationEntityName(WildlifeReportCsvDto untypedRow) CsvHelperUtils.Config(errors, csv, false); csv.Configuration.RegisterClassMap(); - var rows = csv.GetRecords().ToList(); - for (var i = 0; i < rows.Count; i++) + var rows = GetRecords(csv); + + return (rows, string.Join(',', csv.Context.HeaderRecord).Replace("\"", "")); + } + + private List GetRecords(CsvReader csv) + { + var rows = new List(); + + while (csv.Read()) { - rows[i].RowNum = i + 2; - rows[i].ServiceArea = _serviceArea.ConvertToServiceAreaString(rows[i].ServiceArea); + WildlifeReportCsvDto row = null; + + try + { + row = csv.GetRecord(); + } + catch (Exception ex) + { + _logger.LogError(ex.ToString()); + throw; + } + + row.RowNum = csv.Context.Row; + row.ServiceArea = _serviceArea.ConvertToServiceAreaString(row.ServiceArea); + rows.Add(row); } - return (rows, string.Join(',', csv.Context.HeaderRecord).Replace("\"", "")); + return rows; } private (decimal rowNum, List rows) ParseRowsTyped(string text, Dictionary> errors) diff --git a/api/Hmcr.Domain/Hangfire/WorkReportJobService.cs b/api/Hmcr.Domain/Hangfire/WorkReportJobService.cs index e4aafd54..f3d561bc 100644 --- a/api/Hmcr.Domain/Hangfire/WorkReportJobService.cs +++ b/api/Hmcr.Domain/Hangfire/WorkReportJobService.cs @@ -1,4 +1,5 @@ using CsvHelper; +using CsvHelper.TypeConversion; using Hmcr.Data.Database; using Hmcr.Data.Database.Entities; using Hmcr.Data.Repositories; @@ -19,6 +20,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Reflection.Metadata.Ecma335; using System.Text; using System.Threading.Tasks; @@ -648,14 +650,35 @@ private string GetValidationEntityName(WorkReportCsvDto untypedRow, ActivityCode CsvHelperUtils.Config(errors, csv, false); csv.Configuration.RegisterClassMap(); - var rows = csv.GetRecords().ToList(); - for (var i = 0; i < rows.Count; i++) + var rows = GetRecords(csv); + + return (rows, string.Join(',', csv.Context.HeaderRecord).Replace("\"", "")); + } + + private List GetRecords(CsvReader csv) + { + var rows = new List(); + + while (csv.Read()) { - rows[i].RowNum = i + 2; - rows[i].ServiceArea = _serviceArea.ConvertToServiceAreaString(rows[i].ServiceArea); + WorkReportCsvDto row = null; + + try + { + row = csv.GetRecord(); + } + catch (Exception ex) + { + _logger.LogError(ex.ToString()); + throw; + } + + row.RowNum = csv.Context.Row; + row.ServiceArea = _serviceArea.ConvertToServiceAreaString(row.ServiceArea); + rows.Add(row); } - return (rows, string.Join(',', csv.Context.HeaderRecord).Replace("\"", "")); + return rows; } private (decimal rowNum, List rows) ParseRowsTyped(string text, Dictionary> errors) diff --git a/api/Hmcr.Domain/Services/RockfallReportService.cs b/api/Hmcr.Domain/Services/RockfallReportService.cs index b1bd610b..de337d1b 100644 --- a/api/Hmcr.Domain/Services/RockfallReportService.cs +++ b/api/Hmcr.Domain/Services/RockfallReportService.cs @@ -55,7 +55,6 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub var headerValidated = false; var rows = new List(); - var rowNum = 1; while (csv.Read()) { @@ -77,7 +76,6 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub } } - row.RowNum = ++rowNum; row.ServiceArea = serviceArea.ConvertToServiceAreaString(row.ServiceArea); rows.Add(row); } diff --git a/api/Hmcr.Domain/Services/WildlifeReportService.cs b/api/Hmcr.Domain/Services/WildlifeReportService.cs index a99253d6..1903b685 100644 --- a/api/Hmcr.Domain/Services/WildlifeReportService.cs +++ b/api/Hmcr.Domain/Services/WildlifeReportService.cs @@ -53,7 +53,6 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub var headerValidated = false; var rows = new List(); - var rowNum = 1; while (csv.Read()) { @@ -75,7 +74,6 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub } } - row.RowNum = ++rowNum; row.ServiceArea = serviceArea.ConvertToServiceAreaString(row.ServiceArea); rows.Add(row); } diff --git a/api/Hmcr.Domain/Services/WorkReportService.cs b/api/Hmcr.Domain/Services/WorkReportService.cs index 61b594c6..292d5856 100644 --- a/api/Hmcr.Domain/Services/WorkReportService.cs +++ b/api/Hmcr.Domain/Services/WorkReportService.cs @@ -55,7 +55,6 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub var headerValidated = false; var rows = new List(); - var rowNum = 1; while (csv.Read()) { @@ -77,7 +76,6 @@ protected override async Task ParseRowsAsync(SubmissionObjectCreateDto sub } } - row.RowNum = ++rowNum; row.ServiceArea = serviceArea.ConvertToServiceAreaString(row.ServiceArea); rows.Add(row); }