-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathpropose-action-handler.ts
97 lines (96 loc) · 3.19 KB
/
propose-action-handler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import type { ExerciseAction } from 'digital-fuesim-manv-shared';
import {
ReducerError,
ExpectedReducerError,
validateExerciseAction,
validatePermissions,
} from 'digital-fuesim-manv-shared';
import type { ExerciseServer, ExerciseSocket } from '../../exercise-server';
import { clientMap } from '../client-map';
import { secureOn } from './secure-on';
export const registerProposeActionHandler = (
io: ExerciseServer,
client: ExerciseSocket
) => {
secureOn(
client,
'proposeAction',
(action: ExerciseAction, callback): void => {
const clientWrapper = clientMap.get(client);
if (!clientWrapper) {
// There is no client. Skip.
console.error('Got an action from missing client');
return;
}
// 1. validate json
const errors = validateExerciseAction(action);
if (errors.length > 0) {
callback({
success: false,
message: `Invalid payload: ${errors}`,
expected: false,
});
return;
}
// 2. Get matching exercise wrapper & client wrapper
const exerciseWrapper = clientWrapper.exercise;
if (!exerciseWrapper) {
callback({
success: false,
message: 'No exercise selected',
expected: false,
});
return;
}
if (!clientWrapper.client) {
callback({
success: false,
message: 'No client selected',
expected: false,
});
return;
}
// 3. validate user permissions
if (
!validatePermissions(
clientWrapper.client,
action,
exerciseWrapper.getStateSnapshot()
)
) {
callback({
success: false,
message: 'No sufficient rights',
expected: false,
});
return;
}
// 4. apply & broadcast action (+ save to timeline)
try {
exerciseWrapper.applyAction(action, clientWrapper.client.id);
} catch (error: any) {
if (error instanceof ReducerError) {
if (error instanceof ExpectedReducerError) {
callback({
success: false,
message: error.message,
expected: true,
});
} else {
callback({
success: false,
message: error.message,
expected: false,
});
}
return;
}
throw error;
}
// 5. send success response to emitting client
callback({
success: true,
});
}
);
};