Skip to content

Commit

Permalink
Improve email redaction
Browse files Browse the repository at this point in the history
  • Loading branch information
chromy committed Jul 22, 2024
1 parent 58fa478 commit 80206f8
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 23 deletions.
50 changes: 30 additions & 20 deletions src/read-models/members/get-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,33 +95,43 @@ export const liftActorOrUser = (actorOrUser: Actor | User) =>
const redactEmail = (member: MemberDetails): MemberDetails =>
Object.assign({}, member, {emailAddress: '******'});

const redactEmails = (details: MultipleMemberDetails) => {
const redactedDetails = new Map();
for (const [k, v] of details.entries()) {
redactedDetails.set(k, redactEmail(v));
}
return redactedDetails;
};

const redactDetailsForActor =
(actor: Actor) => (details: MultipleMemberDetails) => {
// If a given |actor|, with the context of |details| is viewing |member|
// should sensitive details (email) about that member be redacted.
const shouldRedact =
(actor: Actor) =>
(details: MultipleMemberDetails) =>
(member: MemberDetails) => {
switch (actor.tag) {
case 'token':
return details;
return false;
case 'system':
return details;
return false;
case 'user': {
for (const member of details.values()) {
if (
member.emailAddress === actor.user.emailAddress &&
member.isSuperUser
) {
return details;
}
const viewingUser = actor.user;
const viewingMember = details.get(viewingUser.memberNumber);
if (viewingMember !== undefined && viewingMember.isSuperUser) {
return false;
}
if (viewingUser.memberNumber === member.memberNumber) {
return false;
}
return redactEmails(details);
return true;
}
}
};

const redactDetailsForActor =
(actor: Actor) => (details: MultipleMemberDetails) => {
const needsRedaction = shouldRedact(actor)(details);
const redactedDetails = new Map();
for (const [memberNumber, member] of details.entries()) {
if (needsRedaction(member)) {
redactedDetails.set(memberNumber, redactEmail(member));
} else {
redactedDetails.set(memberNumber, member);
}
}
return redactedDetails;
};

export const getAllDetailsAsActor =
Expand Down
18 changes: 16 additions & 2 deletions src/read-models/members/get.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import {pipe} from 'fp-ts/lib/function';
import * as RA from 'fp-ts/ReadonlyArray';
import * as O from 'fp-ts/Option';
import {MemberDetails, DomainEvent, filterByName} from '../../types';
import {getAllDetails, pertinentEvents} from './get-all';
import {
MemberDetails,
DomainEvent,
filterByName,
Actor,
User,
} from '../../types';
import {getAllDetails, getAllDetailsAsActor, pertinentEvents} from './get-all';

export const getDetails =
(memberNumber: number) =>
Expand All @@ -14,3 +20,11 @@ export const getDetails =
getAllDetails,
allDetails => O.fromNullable(allDetails.get(memberNumber))
);

export const getDetailsAsActor =
(actorOrUser: Actor | User) =>
(memberNumber: number) =>
(events: ReadonlyArray<DomainEvent>) =>
pipe(events, getAllDetailsAsActor(actorOrUser), allDetails =>
O.fromNullable(allDetails.get(memberNumber))
);
3 changes: 2 additions & 1 deletion src/read-models/members/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {getAll, getAllDetails, getAllDetailsAsActor} from './get-all';
import {getDetails} from './get';
import {getDetails, getDetailsAsActor} from './get';
import {lookupByEmail} from './lookup-by-email';
import {getPotentialOwners} from './get-potential-owners';
import {getFailedImports} from './get-failed-imports';
Expand All @@ -10,6 +10,7 @@ export const members = {
getAllDetails,
getAllDetailsAsActor,
getDetails,
getDetailsAsActor,
getFailedImports,
getPotentialOwners,
};
Expand Down

0 comments on commit 80206f8

Please sign in to comment.