Skip to content

Commit cd724f4

Browse files
mominzafarTWVeena-tw
authored andcommitted
HIP | Zafar, Veena | Adds masking of PII information
1 parent fe64db3 commit cd724f4

File tree

9 files changed

+128
-61
lines changed

9 files changed

+128
-61
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using In.ProjectEKA.HipLibrary.Patient;
4+
5+
namespace In.ProjectEKA.DefaultHip.Patient
6+
{
7+
public class MaskingUtility : IMaskUtility
8+
{
9+
private static Dictionary<string,string> maskedDataMap = new Dictionary<string, string>();
10+
public string MaskReference(string referenceNumber)
11+
{
12+
var maskedPatientReferenceNumber = "";
13+
if (referenceNumber.Length > 2)
14+
{
15+
maskedPatientReferenceNumber = string.Concat(
16+
"".PadLeft(referenceNumber.Length - 2, 'X'),
17+
referenceNumber.Substring(referenceNumber.Length - 2));
18+
}
19+
else {
20+
maskedPatientReferenceNumber = "XXX" + referenceNumber;
21+
}
22+
23+
if (!maskedDataMap.ContainsKey(referenceNumber))
24+
{
25+
maskedDataMap.Add(referenceNumber,maskedPatientReferenceNumber);
26+
}
27+
return maskedPatientReferenceNumber;
28+
}
29+
public string MaskMobileNumber(string mobileNumber)
30+
{
31+
var number = mobileNumber;
32+
var paddingBit = "".PadLeft(mobileNumber.Length - 8, 'X');
33+
return string.Concat(
34+
number.Substring(0,6)+
35+
paddingBit,
36+
number.Substring(mobileNumber.Length - 2));
37+
}
38+
public string MaskCareContextDisplay(string referenceNumber)
39+
{
40+
return string.Concat(
41+
"".PadLeft(referenceNumber.Length - 4, 'X'),
42+
referenceNumber.Substring(referenceNumber.Length - 2));
43+
}
44+
45+
public string UnmaskData(string maskedData)
46+
{
47+
var keysWithMatchingValues = maskedDataMap.Where(p => p.Value == maskedData).Select(p => p.Key);
48+
return keysWithMatchingValues.First();
49+
}
50+
51+
public string MaskPatientName(string patientName)
52+
{
53+
if (patientName.Length >= 5)
54+
{
55+
return string.Concat(
56+
patientName.Substring(0,2)+
57+
"".PadLeft(patientName.Length - 4, 'X'),
58+
patientName.Substring(patientName.Length - 2));
59+
}
60+
return "XXX"+patientName;
61+
}
62+
}
63+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace In.ProjectEKA.HipLibrary.Patient
2+
{
3+
public interface IMaskUtility
4+
{
5+
string MaskReference(string referenceNumber);
6+
string MaskCareContextDisplay(string referenceNumber);
7+
string UnmaskData(string maskedData);
8+
string MaskMobileNumber(string mobileNumber);
9+
10+
}
11+
}

src/In.ProjectEKA.HipLibrary/Patient/Model/LinkEnquiryRepresentation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class LinkEnquiryRepresentation
99

1010
public string AuthenticationType { get; }
1111

12-
public LinkReferenceMeta Meta { get; }
12+
public LinkReferenceMeta Meta { get; set; }
1313

1414
public LinkEnquiryRepresentation()
1515
{

src/In.ProjectEKA.HipLibrary/Patient/Model/LinkReferenceMeta.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ namespace In.ProjectEKA.HipLibrary.Patient.Model
22
{
33
public class LinkReferenceMeta
44
{
5-
public string CommunicationMedium { get; }
5+
public string CommunicationMedium { get; set; }
6+
7+
public string CommunicationHint { get; set; }
68

7-
public string CommunicationHint { get; }
8-
99
public string CommunicationExpiry { get; }
1010

1111

src/In.ProjectEKA.HipLibrary/Patient/Model/PatientEnquiryRepresentation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public class PatientEnquiryRepresentation
66
{
77
public string ReferenceNumber { get; set; }
88

9-
public string Display { get; }
9+
public string Display { get; set; }
1010

1111
public IEnumerable<CareContextRepresentation> CareContexts { get; }
1212

src/In.ProjectEKA.HipService/Common/MaskingUtility.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/In.ProjectEKA.HipService/Discovery/PatientDiscovery.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using In.ProjectEKA.HipLibrary.Matcher;
66
using In.ProjectEKA.HipLibrary.Patient;
77
using In.ProjectEKA.HipLibrary.Patient.Model;
8-
using In.ProjectEKA.HipService.Common;
98
using In.ProjectEKA.HipService.Link;
109
using In.ProjectEKA.HipService.Link.Model;
1110
using In.ProjectEKA.HipService.Logger;
@@ -61,7 +60,7 @@ await discoveryRequestRepository.Add(new Model.DiscoveryRequest(request.Transact
6160
request.Patient.Id, patient.Identifier));
6261

6362
var careContextRepresentations = GetUnlinkedCareContexts(linkedCareContexts, patient).ToList();
64-
var maskedPatientEnquiryRepresentation = MaskingUtility.GetMaskedPatientEnquiryRepresentation(
63+
var maskedPatientEnquiryRepresentation = GetMaskedPatientEnquiryRepresentation(
6564
patient.ToPatientEnquiryRepresentation(
6665
careContextRepresentations));
6766

@@ -83,7 +82,7 @@ await discoveryRequestRepository.Add(new Model.DiscoveryRequest(request.Transact
8382

8483
await discoveryRequestRepository.Add(new Model.DiscoveryRequest(request.TransactionId,
8584
request.Patient.Id, patientEnquiryRepresentation.ReferenceNumber));
86-
var representation = MaskingUtility.GetMaskedPatientEnquiryRepresentation(patientEnquiryRepresentation);
85+
var representation =GetMaskedPatientEnquiryRepresentation(patientEnquiryRepresentation);
8786

8887
return (new DiscoveryRepresentation(representation), null);
8988
}
@@ -111,5 +110,22 @@ private static IEnumerable<CareContextRepresentation> GetUnlinkedCareContexts(
111110
allLinkedCareContexts.Find(linkedCareContext =>
112111
linkedCareContext == careContext.ReferenceNumber) == null);
113112
}
113+
114+
private PatientEnquiryRepresentation GetMaskedPatientEnquiryRepresentation(
115+
PatientEnquiryRepresentation patient)
116+
{
117+
var maskingUtility = new DefaultHip.Patient.MaskingUtility();
118+
patient.ReferenceNumber = maskingUtility.MaskReference(patient.ReferenceNumber);
119+
patient.Display = maskingUtility.MaskPatientName(patient.Display);
120+
foreach (var careContextRepresentation in patient.CareContexts.AsEnumerable())
121+
{
122+
careContextRepresentation.ReferenceNumber =
123+
new DefaultHip.Patient.MaskingUtility().MaskReference(careContextRepresentation.ReferenceNumber);
124+
careContextRepresentation.Display =
125+
new DefaultHip.Patient.MaskingUtility().MaskCareContextDisplay(careContextRepresentation.Display);
126+
}
127+
128+
return patient;
129+
}
114130
}
115131
}

src/In.ProjectEKA.HipService/Link/LinkController.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
33
using Hangfire;
4+
using In.ProjectEKA.DefaultHip.Patient;
45
using In.ProjectEKA.HipLibrary.Patient.Model;
56
using In.ProjectEKA.HipService.Common;
67
using In.ProjectEKA.HipService.Discovery;
@@ -62,7 +63,7 @@ public async Task LinkPatient(LinkReferenceRequest request)
6263
cmUserId,
6364
request.Patient.ReferenceNumber,
6465
request.Patient.CareContexts);
65-
patient = MaskingUtility.GetUnmaskedLinkEnquiry(patient);
66+
patient = GetUnmaskedLinkEnquiry(patient);
6667
try
6768
{
6869
var doesRequestExists = await discoveryRequestRepository.RequestExistsFor(
@@ -89,7 +90,8 @@ public async Task LinkPatient(LinkReferenceRequest request)
8990
{
9091
linkedPatientRepresentation = linkReferenceResponse.Link;
9192
}
92-
93+
linkedPatientRepresentation.Meta.CommunicationHint =
94+
new MaskingUtility().MaskMobileNumber(linkedPatientRepresentation.Meta.CommunicationHint);
9395
var response = new GatewayLinkResponse(
9496
linkedPatientRepresentation,
9597
error?.Error,
@@ -133,5 +135,16 @@ public async Task LinkPatientCareContextFor(LinkPatientRequest request)
133135
Log.Error(exception, exception.StackTrace);
134136
}
135137
}
138+
private LinkEnquiry GetUnmaskedLinkEnquiry(LinkEnquiry linkEnquiry)
139+
{
140+
var maskingUtility = new MaskingUtility();
141+
foreach (var careContextEnquiry in linkEnquiry.CareContexts)
142+
{
143+
careContextEnquiry.ReferenceNumber = maskingUtility.UnmaskData(careContextEnquiry.ReferenceNumber);
144+
}
145+
return linkEnquiry;
146+
}
147+
148+
136149
}
137150
}

test/In.ProjectEKA.HipServiceTest/Discovery/PatientDiscoveryTest.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ private async void ShouldReturnPatientForAlreadyLinkedPatient()
4040
var verifiedIdentifiers = new[] {new Identifier(IdentifierType.MOBILE, phoneNumber)};
4141
var unverifiedIdentifiers = new[] {new Identifier(IdentifierType.MR, Faker().Random.String())};
4242
var patientId = "pat";
43-
var name = Faker().Name.FullName();
43+
var name = "Hina Patel";
4444
var display = "display";
4545
var alreadyLinked =
4646
new CareContextRepresentation(Faker().Random.String(), display);
4747
var expectedPatient = new PatientEnquiryRepresentation(
48-
"tap",
49-
name,
48+
"Xat",
49+
"HiXXXXXXel",
5050
Array.Empty<CareContextRepresentation>(),
5151
new[] {Match.ConsentManagerUserId.ToString()});
5252
var transactionId = Faker().Random.String();
@@ -102,21 +102,22 @@ private async void ShouldReturnAPatientWhichIsNotLinkedAtAll()
102102
linkPatientRepository.Object,
103103
patientRepository.Object);
104104
var referenceNumber = "abc";
105-
var name = Faker().Random.String();
106-
var phoneNumber = Faker().Phone.PhoneNumber();
105+
var name = "Hina Patel";
106+
var phoneNumber = "+91-8888888888";
107107
var consentManagerUserId = Faker().Random.String();
108108
var transactionId = Faker().Random.String();
109109
const ushort yearOfBirth = 2019;
110-
var MaskedReferenceNumber = "cba";
111-
var MaskedCareContextReferenceNumber1 = "xyz";
112-
var MaskedCareContextReferenceNumber2 = "def";
110+
var MaskedReferenceNumber = "Xbc";
111+
var MaskedCareContextReferenceNumber1 = "Xyx";
112+
var MaskedCareContextReferenceNumber2 = "Xed";
113113
var display = "display";
114+
var maskedDisplay = "XXXay";
114115
var careContextRepresentationsExpected = new[]
115116
{
116117
new CareContextRepresentation(MaskedCareContextReferenceNumber1,
117-
display),
118+
maskedDisplay),
118119
new CareContextRepresentation(MaskedCareContextReferenceNumber2,
119-
display)
120+
maskedDisplay)
120121
};
121122
var careContextRepresentationsActual = new[]
122123
{
@@ -126,7 +127,7 @@ private async void ShouldReturnAPatientWhichIsNotLinkedAtAll()
126127
display)
127128
};
128129
var expectedPatient = new PatientEnquiryRepresentation(MaskedReferenceNumber,
129-
name,
130+
"HiXXXXXXel",
130131
careContextRepresentationsExpected,
131132
new List<string>
132133
{
@@ -186,15 +187,15 @@ private async void ShouldReturnAPatientWhenUnverifiedIdentifierIsNull()
186187
linkPatientRepository.Object,
187188
patientRepository.Object);
188189
var referenceNumber = "abc";
189-
var MaskedReferenceNumber = "cba";
190+
var MaskedReferenceNumber = "Xbc";
190191
var consentManagerUserId = Faker().Random.String();
191192
var transactionId = Faker().Random.String();
192-
var name = Faker().Name.FullName();
193+
var name = "Hina patel";
193194
const ushort yearOfBirth = 2019;
194195
var phoneNumber = Faker().Phone.PhoneNumber();
195196
var expectedPatient = new PatientEnquiryRepresentation(
196197
MaskedReferenceNumber,
197-
name,
198+
"HiXXXXXXel",
198199
Array.Empty<CareContextRepresentation>(),
199200
new List<string>
200201
{

0 commit comments

Comments
 (0)