Skip to content

Commit 9eb4704

Browse files
authored
Merge branch 'main' into cleanup_test_noise
2 parents a54a0bb + f9096e2 commit 9eb4704

File tree

14 files changed

+208
-57
lines changed

14 files changed

+208
-57
lines changed

src/queries/super-users/construct-view-model.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,34 @@ import {
88
failureWithStatus,
99
} from '../../types/failure-with-status';
1010
import {StatusCodes} from 'http-status-codes';
11-
import {readModels} from '../../read-models';
11+
import {membersTable} from '../../read-models/shared-state/state';
12+
import {eq} from 'drizzle-orm';
1213

1314
export const constructViewModel =
14-
(deps: Dependencies) =>
15+
(sharedReadModel: Dependencies['sharedReadModel']) =>
1516
(user: User): TE.TaskEither<FailureWithStatus, ViewModel> =>
1617
pipe(
17-
deps.getAllEvents(),
18-
TE.filterOrElse(
19-
readModels.superUsers.is(user.memberNumber),
18+
sharedReadModel.members.get(user.memberNumber),
19+
TE.fromOption(
2020
failureWithStatus(
21-
'Only super-users can see this page',
22-
StatusCodes.FORBIDDEN
21+
'Cannot find sufficent information about you to determine if you can access this page',
22+
StatusCodes.UNAUTHORIZED
2323
)
2424
),
25-
TE.map(events => ({
25+
TE.filterOrElse(
26+
loggedInMember => loggedInMember.isSuperUser,
27+
() =>
28+
failureWithStatus(
29+
'Only super-users can see this page',
30+
StatusCodes.FORBIDDEN
31+
)()
32+
),
33+
TE.map(() => ({
2634
user: user,
27-
superUsers: readModels.superUsers.getAll()(events),
35+
superUsers: sharedReadModel.db
36+
.select()
37+
.from(membersTable)
38+
.where(eq(membersTable.isSuperUser, true))
39+
.all(),
2840
}))
2941
);

src/queries/super-users/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {safe, toLoggedInContent} from '../../types/html';
88
export const superUsers: Query = deps => user =>
99
pipe(
1010
user,
11-
constructViewModel(deps),
11+
constructViewModel(deps.sharedReadModel),
1212
TE.map(render),
1313
TE.map(toLoggedInContent(safe('Super Users')))
1414
);

src/queries/super-users/render.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
import {pipe} from 'fp-ts/lib/function';
2-
import {html, joinHtml} from '../../types/html';
2+
import {html, joinHtml, safe, sanitizeString} from '../../types/html';
33
import * as RA from 'fp-ts/ReadonlyArray';
44
import {ViewModel} from './view-model';
55
import {displayDate} from '../../templates/display-date';
66
import {renderMemberNumber} from '../../templates/member-number';
77
import {DateTime} from 'luxon';
8+
import * as O from 'fp-ts/Option';
89

910
const renderSuperUsers = (superUsers: ViewModel['superUsers']) =>
1011
pipe(
1112
superUsers,
1213
RA.map(
13-
user => html`
14+
member => html`
1415
<tr>
15-
<td>${renderMemberNumber(user.memberNumber)}</td>
16-
<td>${displayDate(DateTime.fromJSDate(user.since))}</td>
16+
<td>${renderMemberNumber(member.memberNumber)}</td>
17+
<td>${sanitizeString(O.getOrElse(() => '-')(member.name))}</td>
18+
<td>${safe(member.emailAddress)}</td>
1719
<td>
18-
<a href="/super-users/revoke?memberNumber=${user.memberNumber}">
20+
${member.superUserSince
21+
? displayDate(DateTime.fromJSDate(member.superUserSince))
22+
: safe('-')}
23+
</td>
24+
<td>
25+
<a href="/super-users/revoke?memberNumber=${member.memberNumber}">
1926
Revoke
2027
</a>
2128
</td>
@@ -28,6 +35,8 @@ const renderSuperUsers = (superUsers: ViewModel['superUsers']) =>
2835
<table>
2936
<tr>
3037
<th>Member Number</th>
38+
<th>Name</th>
39+
<th>Email</th>
3140
<th>SU since</th>
3241
<th></th>
3342
</tr>
@@ -38,8 +47,7 @@ const renderSuperUsers = (superUsers: ViewModel['superUsers']) =>
3847
);
3948

4049
export const render = (viewModel: ViewModel) => html`
41-
<h1>Super-users</h1>
42-
<a href="/super-users/declare">Declare a member to be a super-user</a>
43-
</table>
44-
${renderSuperUsers(viewModel.superUsers)}
45-
`;
50+
<h1>Super-users</h1>
51+
<a href="/super-users/declare">Declare a member to be a super-user</a>
52+
${renderSuperUsers(viewModel.superUsers)}
53+
`;
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import {User} from '../../types';
2+
import * as O from 'fp-ts/Option';
23

34
export type ViewModel = {
45
user: User;
56
superUsers: ReadonlyArray<{
67
memberNumber: number;
7-
since: Date;
8+
name: O.Option<string>;
9+
emailAddress: string;
10+
superUserSince: Date | null;
811
}>;
912
};

src/read-models/shared-state/area/expand.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const expandOwners =
2525
RA.map(ownerDetails => ({
2626
...ownerDetails.members,
2727
agreementSigned: O.fromNullable(ownerDetails.members.agreementSigned),
28+
superUserSince: O.fromNullable(ownerDetails.members.superUserSince),
2829
ownershipRecordedAt: ownerDetails.owners.ownershipRecordedAt,
2930
markedOwnerBy: O.fromEither(
3031
Actor.decode(ownerDetails.owners.markedOwnerByActor)

src/read-models/shared-state/equipment/expand.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const expandTrainers =
4242
RA.map(member => ({
4343
...member.members,
4444
agreementSigned: O.fromNullable(member.members.agreementSigned),
45+
superUserSince: O.fromNullable(member.members.superUserSince),
4546
markedTrainerByActor: O.fromEither(
4647
Actor.decode(member.trainers.markedTrainerByActor)
4748
),
@@ -84,6 +85,7 @@ const expandTrainedMembers =
8485
),
8586
trainedSince: result.trainedMembers.trainedAt,
8687
agreementSigned: O.fromNullable(result.members.agreementSigned),
88+
superUserSince: O.fromNullable(result.members.superUserSince),
8789
trainedByMemberNumber,
8890
trainedByEmail: pipe(
8991
trainedByMemberNumber,
@@ -143,6 +145,7 @@ const expandMembersAwaitingTraining =
143145
...q.members,
144146
quizId: q.trainingQuizResults.quizId as UUID,
145147
agreementSigned: O.fromNullable(q.members.agreementSigned),
148+
superUserSince: O.fromNullable(q.members.superUserSince),
146149
waitingSince: q.trainingQuizResults.timestamp,
147150
})),
148151
membersAwaitingTraining => ({
@@ -176,6 +179,7 @@ const expandFailedQuizAttempts =
176179
RA.map(q => ({
177180
...q.members,
178181
agreementSigned: O.fromNullable(q.members.agreementSigned),
182+
superUserSince: O.fromNullable(q.members.superUserSince),
179183
quizId: q.trainingQuizResults.quizId as UUID,
180184
score: q.trainingQuizResults.score,
181185
maxScore: q.trainingQuizResults.maxScore,

src/read-models/shared-state/member/get.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import {membersTable} from '../state';
99
const transformRow = <
1010
R extends {
1111
agreementSigned: Date | null | undefined;
12+
superUserSince: Date | null | undefined;
1213
},
1314
>(
1415
row: R
1516
) => ({
1617
...row,
1718
agreementSigned: O.fromNullable(row.agreementSigned),
19+
superUserSince: O.fromNullable(row.superUserSince),
1820
});
1921

2022
export const getMemberCore =

src/read-models/shared-state/return-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export type MemberCoreInfo = {
8585
pronouns: O.Option<string>;
8686
agreementSigned: O.Option<Date>;
8787
isSuperUser: boolean;
88+
superUserSince: O.Option<Date>;
8889
gravatarHash: GravatarHash;
8990
};
9091

src/read-models/shared-state/state.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const membersTable = sqliteTable('members', {
2020
.notNull()
2121
.$type<ReadonlyArray<EmailAddress>>(),
2222
isSuperUser: integer('isSuperUser', {mode: 'boolean'}).notNull(),
23+
superUserSince: integer('superUserSince', {mode: 'timestamp_ms'}),
2324
agreementSigned: integer('agreementSigned', {mode: 'timestamp_ms'}),
2425
});
2526

@@ -32,6 +33,7 @@ const createMembersTable = sql`
3233
pronouns BLOB,
3334
prevEmails BLOB,
3435
isSuperUser INTEGER,
36+
superUserSince INTEGER,
3537
agreementSigned INTEGER
3638
);`;
3739

src/read-models/shared-state/update-state.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const updateState =
3030
prevEmails: [],
3131
isSuperUser: false,
3232
agreementSigned: undefined,
33+
superUserSince: undefined,
3334
})
3435
.run();
3536
break;
@@ -67,13 +68,13 @@ export const updateState =
6768
}
6869
case 'SuperUserDeclared':
6970
db.update(membersTable)
70-
.set({isSuperUser: true})
71+
.set({isSuperUser: true, superUserSince: event.recordedAt})
7172
.where(eq(membersTable.memberNumber, event.memberNumber))
7273
.run();
7374
break;
7475
case 'SuperUserRevoked':
7576
db.update(membersTable)
76-
.set({isSuperUser: false})
77+
.set({isSuperUser: false, superUserSince: null})
7778
.where(eq(membersTable.memberNumber, event.memberNumber))
7879
.run();
7980
break;

0 commit comments

Comments
 (0)