@newtonschool/react_proctoring_library 0.0.133-beta.2 → 0.0.135
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -77,6 +77,24 @@ const ProctorApp = _ref => {
|
|
|
77
77
|
return releaseWakeUpLock;
|
|
78
78
|
}, []);
|
|
79
79
|
const CustomPermissionView = customPermissionView;
|
|
80
|
+
const proctoringSessionId = (0, _react.useMemo)(() => {
|
|
81
|
+
const {
|
|
82
|
+
proctoredEntityType,
|
|
83
|
+
proctoredEntityHash
|
|
84
|
+
} = permissionPassedProps;
|
|
85
|
+
if (!proctoredEntityType || !proctoredEntityHash) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return "".concat(proctoredEntityType, "-").concat(proctoredEntityHash);
|
|
89
|
+
}, [permissionPassedProps]);
|
|
90
|
+
const sessionScopedFirebaseClient = (0, _react.useMemo)(() => {
|
|
91
|
+
if (!firebaseClient) {
|
|
92
|
+
return firebaseClient;
|
|
93
|
+
}
|
|
94
|
+
return _objectSpread(_objectSpread({}, firebaseClient), {}, {
|
|
95
|
+
proctoringSessionId
|
|
96
|
+
});
|
|
97
|
+
}, [firebaseClient, proctoringSessionId]);
|
|
80
98
|
const proctorParams = (0, _react.useMemo)(() => _objectSpread(_objectSpread({}, _defaults.defaultConfig), config.proctorParams), [config.proctorParams]);
|
|
81
99
|
const shouldShowProctoredComponent = (0, _react.useMemo)(() => (0, _breachUtils.showProctoredComponent)(proctorParams, permissions), [proctorParams, permissions, _breachUtils.showProctoredComponent]);
|
|
82
100
|
const allPermissionsGrantedCallback = () => {
|
|
@@ -133,7 +151,7 @@ const ProctorApp = _ref => {
|
|
|
133
151
|
permissions: permissions,
|
|
134
152
|
proctoredContext: proctoredContext,
|
|
135
153
|
isSecondaryDevice: isSecondaryDevice,
|
|
136
|
-
firebaseClient:
|
|
154
|
+
firebaseClient: sessionScopedFirebaseClient,
|
|
137
155
|
allPermissionGranted: allPermissionGrantedOnce.current
|
|
138
156
|
}), proctorParams.webcamSnapshots && /*#__PURE__*/(0, _jsxRuntime.jsx)(_webcamActivityTracker.default, {
|
|
139
157
|
logger: logger,
|
|
@@ -143,7 +161,7 @@ const ProctorApp = _ref => {
|
|
|
143
161
|
getWebcamSnapshot: getWebcamSnapshot,
|
|
144
162
|
proctoringIdentifier: proctoringIdentifier,
|
|
145
163
|
setAskPermissionAction: setAskPermissionAction,
|
|
146
|
-
firebaseClient:
|
|
164
|
+
firebaseClient: sessionScopedFirebaseClient,
|
|
147
165
|
isSecondaryDevice: isSecondaryDevice
|
|
148
166
|
}), proctorParams.screenshareSnapshots && /*#__PURE__*/(0, _jsxRuntime.jsx)(_screenshareActivityTracker.default, {
|
|
149
167
|
config: config,
|
|
@@ -10,7 +10,6 @@ var _proctoringStatusUtils = require("../../utils/proctoringStatusUtils");
|
|
|
10
10
|
var _permission = require("../../utils/permission");
|
|
11
11
|
var _breachUtils = require("../../utils/breachUtils");
|
|
12
12
|
var _usePageActivity = _interopRequireDefault(require("../../hooks/usePageActivity"));
|
|
13
|
-
var _proctoringDebugUtils = require("../../utils/proctoringDebugUtils");
|
|
14
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
14
|
const SecondaryDevice = _ref => {
|
|
16
15
|
let {
|
|
@@ -28,36 +27,10 @@ const SecondaryDevice = _ref => {
|
|
|
28
27
|
const [secondaryDeviceOnline, setSecondaryDeviceOnline] = (0, _react.useState)(true);
|
|
29
28
|
const [secondaryDeviceAllPermissionGranted, setSecondaryDeviceAllPermissionGranted] = (0, _react.useState)(true);
|
|
30
29
|
const {
|
|
31
|
-
isActive: isCurrentDeviceActive
|
|
32
|
-
isVisible,
|
|
33
|
-
isFocused,
|
|
34
|
-
isLifecycleActive
|
|
30
|
+
isActive: isCurrentDeviceActive
|
|
35
31
|
} = (0, _usePageActivity.default)();
|
|
36
32
|
const allPermissionGranted = (0, _permission.hasAllPermissions)((0, _breachUtils.getRequiredPermissionsFromProctorParams)(proctorParams), permissions);
|
|
37
33
|
const effectiveAllPermissionGranted = allPermissionGranted && isCurrentDeviceActive;
|
|
38
|
-
(0, _react.useEffect)(() => {
|
|
39
|
-
if (!isSecondaryDevice) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_session_started', {
|
|
43
|
-
deviceType: 'secondary',
|
|
44
|
-
userUuid: (firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid) || null,
|
|
45
|
-
requiredPermissions: (0, _breachUtils.getRequiredPermissionsFromProctorParams)(proctorParams),
|
|
46
|
-
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown'
|
|
47
|
-
}, firebaseClient);
|
|
48
|
-
}, [firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid, isSecondaryDevice, proctorParams]);
|
|
49
|
-
(0, _react.useEffect)(() => {
|
|
50
|
-
if (!isSecondaryDevice) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_page_activity_state_changed', {
|
|
54
|
-
deviceType: 'secondary',
|
|
55
|
-
isVisible,
|
|
56
|
-
isFocused,
|
|
57
|
-
isLifecycleActive,
|
|
58
|
-
isActive: isCurrentDeviceActive
|
|
59
|
-
}, firebaseClient);
|
|
60
|
-
}, [firebaseClient, isCurrentDeviceActive, isFocused, isLifecycleActive, isSecondaryDevice, isVisible]);
|
|
61
34
|
(0, _react.useEffect)(() => {
|
|
62
35
|
const cleanup = (0, _proctoringStatusUtils.setupDeviceStatusListeners)({
|
|
63
36
|
firebaseClient,
|
|
@@ -20,7 +20,6 @@ var _webcamMicrophoneUtils = require("../../utils/webcamMicrophoneUtils");
|
|
|
20
20
|
var _dom = require("../../constants/dom");
|
|
21
21
|
var _useBreachData = require("../../hooks/useBreachData");
|
|
22
22
|
var _proctoringStatusUtils = require("../../utils/proctoringStatusUtils");
|
|
23
|
-
var _proctoringDebugUtils = require("../../utils/proctoringDebugUtils");
|
|
24
23
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
24
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
26
25
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
@@ -47,7 +46,6 @@ const WebWebCam = _ref => {
|
|
|
47
46
|
references,
|
|
48
47
|
permissions
|
|
49
48
|
} = (0, _react.useContext)(proctoredContext);
|
|
50
|
-
const deviceType = isSecondaryDevice ? 'secondary' : 'primary';
|
|
51
49
|
const recurringFetchIntervalRef = (0, _react.useRef)(null);
|
|
52
50
|
const {
|
|
53
51
|
recurring = false,
|
|
@@ -110,13 +108,6 @@ const WebWebCam = _ref => {
|
|
|
110
108
|
screenshotFormat: "image/jpeg",
|
|
111
109
|
ref: webcamReference,
|
|
112
110
|
onUserMedia: () => {
|
|
113
|
-
if (isSecondaryDevice) {
|
|
114
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_webcam_user_media_succeeded', {
|
|
115
|
-
deviceType,
|
|
116
|
-
retryCount,
|
|
117
|
-
userUuid: (firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid) || null
|
|
118
|
-
}, firebaseClient);
|
|
119
|
-
}
|
|
120
111
|
setVideoPermission(true);
|
|
121
112
|
if (firebaseClient) {
|
|
122
113
|
if (isSecondaryDevice) {
|
|
@@ -127,17 +118,6 @@ const WebWebCam = _ref => {
|
|
|
127
118
|
}
|
|
128
119
|
},
|
|
129
120
|
onUserMediaError: err => {
|
|
130
|
-
if (isSecondaryDevice) {
|
|
131
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_webcam_user_media_failed', {
|
|
132
|
-
deviceType,
|
|
133
|
-
retryCount,
|
|
134
|
-
userUuid: (firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid) || null,
|
|
135
|
-
error: {
|
|
136
|
-
name: (err === null || err === void 0 ? void 0 : err.name) || null,
|
|
137
|
-
message: (err === null || err === void 0 ? void 0 : err.message) || String(err)
|
|
138
|
-
}
|
|
139
|
-
}, firebaseClient);
|
|
140
|
-
}
|
|
141
121
|
logger("Retry Count = ".concat(retryCount, " | Webcam error, onUserMediaError | ").concat(err.toString()));
|
|
142
122
|
if (retryCount === 0) {
|
|
143
123
|
setVideoPermission(false);
|
|
@@ -5,32 +5,24 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.updateCurrentDeviceStatus = exports.setupDeviceStatusListeners = exports.setSecondaryDeviceConnected = exports.setPrimaryDeviceConnected = void 0;
|
|
7
7
|
var _defaults = require("../constants/defaults");
|
|
8
|
-
var _proctoringDebugUtils = require("./proctoringDebugUtils");
|
|
9
8
|
const HEARTBEAT_INTERVAL_MS = 5000;
|
|
10
9
|
const OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS = 20000;
|
|
11
10
|
const SERVER_TIMESTAMP = {
|
|
12
11
|
'.sv': 'timestamp'
|
|
13
12
|
};
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
const hasRelevantObservedChange = (previousStatus, nextStatus) => {
|
|
29
|
-
const previous = getObservedStatusPayload(previousStatus);
|
|
30
|
-
const next = getObservedStatusPayload(nextStatus);
|
|
31
|
-
return previous.connected !== next.connected || previous.allPermissionGranted !== next.allPermissionGranted || previous.deviceId !== next.deviceId;
|
|
13
|
+
const getProctoringStatusBasePath = function getProctoringStatusBasePath() {
|
|
14
|
+
let {
|
|
15
|
+
userUuid,
|
|
16
|
+
proctoringSessionId
|
|
17
|
+
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
18
|
+
if (!userUuid) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (proctoringSessionId) {
|
|
22
|
+
return "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(userUuid, "/").concat(proctoringSessionId);
|
|
23
|
+
}
|
|
24
|
+
return "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(userUuid);
|
|
32
25
|
};
|
|
33
|
-
|
|
34
26
|
/**
|
|
35
27
|
* Marks the primary device as connected in Firebase. Call when desktop webcam
|
|
36
28
|
* connects successfully. No-op if firebaseClient is missing required fields.
|
|
@@ -46,7 +38,11 @@ const setPrimaryDeviceConnected = firebaseClient => {
|
|
|
46
38
|
updateValue: update,
|
|
47
39
|
getRef: ref
|
|
48
40
|
} = firebaseClient;
|
|
49
|
-
const
|
|
41
|
+
const statusBasePath = getProctoringStatusBasePath(firebaseClient);
|
|
42
|
+
if (!statusBasePath) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const primaryDeviceRef = ref(firebaseClient.myFirebaseDB, "".concat(statusBasePath, "/primaryDevice"));
|
|
50
46
|
const payload = {
|
|
51
47
|
connected: true
|
|
52
48
|
};
|
|
@@ -71,17 +67,15 @@ const setSecondaryDeviceConnected = firebaseClient => {
|
|
|
71
67
|
updateValue: update,
|
|
72
68
|
getRef: ref
|
|
73
69
|
} = firebaseClient;
|
|
74
|
-
const
|
|
70
|
+
const statusBasePath = getProctoringStatusBasePath(firebaseClient);
|
|
71
|
+
if (!statusBasePath) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const secondaryDeviceRef = ref(firebaseClient.myFirebaseDB, "".concat(statusBasePath, "/secondaryDevice"));
|
|
75
75
|
const payload = {
|
|
76
76
|
connected: true
|
|
77
77
|
};
|
|
78
78
|
return update(secondaryDeviceRef, payload).then(() => {}).catch(error => {
|
|
79
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
80
|
-
deviceType: 'secondary',
|
|
81
|
-
userUuid: firebaseClient.userUuid,
|
|
82
|
-
payload,
|
|
83
|
-
error: getErrorPayload(error)
|
|
84
|
-
}, firebaseClient);
|
|
85
79
|
console.error('::[proctoringStatusUtils] Failed to set secondary device status online:', error);
|
|
86
80
|
});
|
|
87
81
|
};
|
|
@@ -110,8 +104,12 @@ const updateCurrentDeviceStatus = _ref => {
|
|
|
110
104
|
updateValue: update,
|
|
111
105
|
getRef: ref
|
|
112
106
|
} = firebaseClient;
|
|
107
|
+
const statusBasePath = getProctoringStatusBasePath(firebaseClient);
|
|
108
|
+
if (!statusBasePath) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
113
111
|
const deviceKey = isSecondaryDevice ? 'secondaryDevice' : 'primaryDevice';
|
|
114
|
-
const deviceStatusRef = ref(firebaseClient.myFirebaseDB, "".concat(
|
|
112
|
+
const deviceStatusRef = ref(firebaseClient.myFirebaseDB, "".concat(statusBasePath, "/").concat(deviceKey));
|
|
115
113
|
const payload = {
|
|
116
114
|
allPermissionGranted
|
|
117
115
|
};
|
|
@@ -119,12 +117,6 @@ const updateCurrentDeviceStatus = _ref => {
|
|
|
119
117
|
if (!isSecondaryDevice) {
|
|
120
118
|
return;
|
|
121
119
|
}
|
|
122
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
123
|
-
deviceType: 'secondary',
|
|
124
|
-
userUuid: firebaseClient.userUuid,
|
|
125
|
-
payload,
|
|
126
|
-
error: getErrorPayload(error)
|
|
127
|
-
}, firebaseClient);
|
|
128
120
|
console.error('::[proctoringStatusUtils] Failed to update current device status:', error);
|
|
129
121
|
});
|
|
130
122
|
};
|
|
@@ -154,6 +146,7 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
154
146
|
const {
|
|
155
147
|
userUuid,
|
|
156
148
|
firestoreAuthStatus,
|
|
149
|
+
proctoringSessionId,
|
|
157
150
|
myFirebaseDB,
|
|
158
151
|
setValue: set,
|
|
159
152
|
getRef: ref,
|
|
@@ -161,12 +154,18 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
161
154
|
onDisconnect,
|
|
162
155
|
getValue: onValue
|
|
163
156
|
} = firebaseClient || {};
|
|
164
|
-
const deviceType = isSecondaryDevice ? 'secondary' : 'primary';
|
|
165
157
|
if (!userUuid || !firestoreAuthStatus || !ref || !set || !onDisconnect || !onValue) {
|
|
166
158
|
return () => {};
|
|
167
159
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
160
|
+
const statusBasePath = getProctoringStatusBasePath({
|
|
161
|
+
userUuid,
|
|
162
|
+
proctoringSessionId
|
|
163
|
+
});
|
|
164
|
+
if (!statusBasePath) {
|
|
165
|
+
return () => {};
|
|
166
|
+
}
|
|
167
|
+
const primaryDeviceStatusRef = ref(myFirebaseDB, "".concat(statusBasePath, "/primaryDevice"));
|
|
168
|
+
const secondaryDeviceStatusRef = ref(myFirebaseDB, "".concat(statusBasePath, "/secondaryDevice"));
|
|
170
169
|
const currentDeviceStatusRef = isSecondaryDevice ? secondaryDeviceStatusRef : primaryDeviceStatusRef;
|
|
171
170
|
const otherDeviceStatusRef = isSecondaryDevice ? primaryDeviceStatusRef : secondaryDeviceStatusRef;
|
|
172
171
|
const serverTimeOffsetRef = ref(myFirebaseDB, '.info/serverTimeOffset');
|
|
@@ -184,51 +183,27 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
184
183
|
onDisconnect(currentDeviceStatusRef).update({
|
|
185
184
|
connected: false
|
|
186
185
|
}).then(() => {}).catch(err => {
|
|
187
|
-
if (!isSecondaryDevice) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
191
|
-
deviceType,
|
|
192
|
-
userUuid,
|
|
193
|
-
payload: {
|
|
194
|
-
connected: false,
|
|
195
|
-
source: 'onDisconnect'
|
|
196
|
-
},
|
|
197
|
-
error: getErrorPayload(err)
|
|
198
|
-
}, firebaseClient);
|
|
199
186
|
console.error('::[proctoringStatusUtils] Failed to mark current device disconnected:', err);
|
|
200
187
|
});
|
|
201
188
|
|
|
202
189
|
// Get initial values and update callbacks immediately
|
|
203
|
-
const applyPrimarySnapshot =
|
|
190
|
+
const applyPrimarySnapshot = snapshot => {
|
|
204
191
|
var _snapshot$val, _snapshot$val2;
|
|
205
|
-
let source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'subscription';
|
|
206
|
-
const previousValue = latestPrimaryDeviceStatus;
|
|
207
192
|
const val = (_snapshot$val = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val2 = snapshot.val) === null || _snapshot$val2 === void 0 ? void 0 : _snapshot$val2.call(snapshot)) !== null && _snapshot$val !== void 0 ? _snapshot$val : snapshot;
|
|
208
193
|
latestPrimaryDeviceStatus = val;
|
|
209
194
|
onPrimaryDeviceStatusChange(Boolean(val === null || val === void 0 ? void 0 : val.connected));
|
|
210
195
|
};
|
|
211
|
-
const applySecondarySnapshot =
|
|
196
|
+
const applySecondarySnapshot = snapshot => {
|
|
212
197
|
var _snapshot$val3, _snapshot$val4;
|
|
213
|
-
let source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'subscription';
|
|
214
|
-
const previousValue = latestSecondaryDeviceStatus;
|
|
215
198
|
const val = (_snapshot$val3 = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val4 = snapshot.val) === null || _snapshot$val4 === void 0 ? void 0 : _snapshot$val4.call(snapshot)) !== null && _snapshot$val3 !== void 0 ? _snapshot$val3 : snapshot;
|
|
216
199
|
latestSecondaryDeviceStatus = val;
|
|
217
|
-
if (isSecondaryDevice && (source === 'initial_get' || hasRelevantObservedChange(previousValue, val))) {
|
|
218
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_observed', {
|
|
219
|
-
deviceType,
|
|
220
|
-
observedDeviceType: 'secondary',
|
|
221
|
-
source,
|
|
222
|
-
observedStatus: getObservedStatusPayload(val, getComparableNow())
|
|
223
|
-
}, firebaseClient);
|
|
224
|
-
}
|
|
225
200
|
onSecondaryDeviceStatusChange(Boolean(val === null || val === void 0 ? void 0 : val.connected), val === null || val === void 0 ? void 0 : val.allPermissionGranted);
|
|
226
201
|
};
|
|
227
202
|
if (typeof (primaryDeviceStatusRef === null || primaryDeviceStatusRef === void 0 ? void 0 : primaryDeviceStatusRef.get) === 'function') {
|
|
228
|
-
primaryDeviceStatusRef.get().then(snapshot => applyPrimarySnapshot(snapshot
|
|
203
|
+
primaryDeviceStatusRef.get().then(snapshot => applyPrimarySnapshot(snapshot)).catch(() => {});
|
|
229
204
|
}
|
|
230
205
|
if (typeof (secondaryDeviceStatusRef === null || secondaryDeviceStatusRef === void 0 ? void 0 : secondaryDeviceStatusRef.get) === 'function') {
|
|
231
|
-
secondaryDeviceStatusRef.get().then(snapshot => applySecondarySnapshot(snapshot
|
|
206
|
+
secondaryDeviceStatusRef.get().then(snapshot => applySecondarySnapshot(snapshot)).catch(() => {});
|
|
232
207
|
}
|
|
233
208
|
|
|
234
209
|
// Subscribe to updates
|
|
@@ -248,54 +223,19 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
248
223
|
let heartbeatIntervalId = null;
|
|
249
224
|
if (typeof window !== 'undefined' && typeof setInterval === 'function') {
|
|
250
225
|
heartbeatIntervalId = setInterval(() => {
|
|
251
|
-
const clientNow = Date.now();
|
|
252
226
|
const comparableNow = getComparableNow();
|
|
253
227
|
if (isCurrentDeviceActive) {
|
|
254
228
|
update(currentDeviceStatusRef, {
|
|
255
229
|
connected: true,
|
|
256
230
|
lastHeartbeatAt: SERVER_TIMESTAMP
|
|
257
231
|
}).then(() => {}).catch(error => {
|
|
258
|
-
if (!isSecondaryDevice) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_heartbeat_write_failed', {
|
|
262
|
-
deviceType,
|
|
263
|
-
userUuid,
|
|
264
|
-
isCurrentDeviceActive,
|
|
265
|
-
now: comparableNow !== null && comparableNow !== void 0 ? comparableNow : clientNow,
|
|
266
|
-
isSecondaryDevice,
|
|
267
|
-
error: getErrorPayload(error)
|
|
268
|
-
}, firebaseClient);
|
|
269
232
|
console.error('::[proctoringStatusUtils] Failed to send heartbeat for current device:', error);
|
|
270
233
|
});
|
|
271
234
|
}
|
|
272
235
|
if (!isCurrentDeviceActive) {
|
|
273
236
|
update(currentDeviceStatusRef, {
|
|
274
237
|
connected: false
|
|
275
|
-
}).then(() => {
|
|
276
|
-
if (!isSecondaryDevice) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_current_device_marked_inactive', {
|
|
280
|
-
deviceType,
|
|
281
|
-
userUuid,
|
|
282
|
-
now: comparableNow !== null && comparableNow !== void 0 ? comparableNow : clientNow,
|
|
283
|
-
isSecondaryDevice
|
|
284
|
-
}, firebaseClient);
|
|
285
|
-
}).catch(error => {
|
|
286
|
-
if (!isSecondaryDevice) {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
290
|
-
deviceType,
|
|
291
|
-
userUuid,
|
|
292
|
-
now: comparableNow !== null && comparableNow !== void 0 ? comparableNow : clientNow,
|
|
293
|
-
payload: {
|
|
294
|
-
connected: false,
|
|
295
|
-
source: 'inactive_page_state'
|
|
296
|
-
},
|
|
297
|
-
error: getErrorPayload(error)
|
|
298
|
-
}, firebaseClient);
|
|
238
|
+
}).then(() => {}).catch(error => {
|
|
299
239
|
console.error('::[proctoringStatusUtils] Failed to mark current device inactive:', error);
|
|
300
240
|
});
|
|
301
241
|
}
|
|
@@ -307,41 +247,7 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
307
247
|
if (typeof comparableNow === 'number' && isConnected && typeof lastBeat === 'number' && comparableNow - lastBeat > OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS) {
|
|
308
248
|
update(otherDeviceStatusRef, {
|
|
309
249
|
connected: false
|
|
310
|
-
}).then(() => {
|
|
311
|
-
const isMarkingSecondaryDeviceStale = !isSecondaryDevice;
|
|
312
|
-
if (!isMarkingSecondaryDeviceStale) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('primary_marked_secondary_inactive_due_to_stale_heartbeat', {
|
|
316
|
-
deviceType: 'primary',
|
|
317
|
-
userUuid,
|
|
318
|
-
now: comparableNow,
|
|
319
|
-
timeoutMs: OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS,
|
|
320
|
-
heartbeatDiffMs: comparableNow - lastBeat,
|
|
321
|
-
payload: {
|
|
322
|
-
connected: false,
|
|
323
|
-
source: 'stale_other_device',
|
|
324
|
-
otherDeviceType: 'secondary',
|
|
325
|
-
otherDeviceStatus: getObservedStatusPayload(otherDeviceStatus, comparableNow)
|
|
326
|
-
}
|
|
327
|
-
}, firebaseClient);
|
|
328
|
-
}).catch(otherErr => {
|
|
329
|
-
const isMarkingSecondaryDeviceStale = !isSecondaryDevice;
|
|
330
|
-
if (!isMarkingSecondaryDeviceStale) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
334
|
-
deviceType: 'secondary',
|
|
335
|
-
userUuid,
|
|
336
|
-
now: comparableNow,
|
|
337
|
-
payload: {
|
|
338
|
-
connected: false,
|
|
339
|
-
source: 'stale_other_device',
|
|
340
|
-
otherDeviceType: 'secondary',
|
|
341
|
-
otherDeviceStatus: getObservedStatusPayload(otherDeviceStatus, comparableNow)
|
|
342
|
-
},
|
|
343
|
-
error: getErrorPayload(otherErr)
|
|
344
|
-
}, firebaseClient);
|
|
250
|
+
}).then(() => {}).catch(otherErr => {
|
|
345
251
|
console.error('::[proctoringStatusUtils] Failed to mark other device disconnected due to stale heartbeat:', otherErr);
|
|
346
252
|
});
|
|
347
253
|
}
|
package/package.json
CHANGED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
require("core-js/modules/es.symbol.description.js");
|
|
4
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
5
|
-
require("core-js/modules/esnext.iterator.filter.js");
|
|
6
|
-
require("core-js/modules/esnext.iterator.for-each.js");
|
|
7
|
-
Object.defineProperty(exports, "__esModule", {
|
|
8
|
-
value: true
|
|
9
|
-
});
|
|
10
|
-
exports.emitProctoringDebugLog = void 0;
|
|
11
|
-
require("core-js/modules/es.json.stringify.js");
|
|
12
|
-
require("core-js/modules/es.promise.js");
|
|
13
|
-
var _defaults = require("../constants/defaults");
|
|
14
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
16
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
17
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
18
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
19
|
-
const DEBUG_LOG_PREFIX = '::[secondary-device-debug]';
|
|
20
|
-
const WEB_REPORT_LOG_ENDPOINT = '/api/v1/user/report/web/';
|
|
21
|
-
const safeJsonStringify = value => {
|
|
22
|
-
try {
|
|
23
|
-
return JSON.stringify(value);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
return JSON.stringify({
|
|
26
|
-
ts: Date.now(),
|
|
27
|
-
serializationError: (error === null || error === void 0 ? void 0 : error.message) || String(error)
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
const postDebugMessage = message => {
|
|
32
|
-
if (typeof window === 'undefined') {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
try {
|
|
36
|
-
if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {
|
|
37
|
-
const body = new Blob([safeJsonStringify({
|
|
38
|
-
message
|
|
39
|
-
})], {
|
|
40
|
-
type: 'application/json'
|
|
41
|
-
});
|
|
42
|
-
navigator.sendBeacon(WEB_REPORT_LOG_ENDPOINT, body);
|
|
43
|
-
} else if (typeof fetch === 'function') {
|
|
44
|
-
fetch(WEB_REPORT_LOG_ENDPOINT, {
|
|
45
|
-
method: 'POST',
|
|
46
|
-
headers: {
|
|
47
|
-
'Content-Type': 'application/json'
|
|
48
|
-
},
|
|
49
|
-
body: safeJsonStringify({
|
|
50
|
-
message
|
|
51
|
-
}),
|
|
52
|
-
keepalive: true
|
|
53
|
-
}).catch(() => {});
|
|
54
|
-
}
|
|
55
|
-
} catch (_) {}
|
|
56
|
-
};
|
|
57
|
-
const isDebugLogEnabled = async firebaseClient => {
|
|
58
|
-
if (!(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.userUuid) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.myFirebaseDB) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.getRef) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.getValue)) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
const {
|
|
62
|
-
getRef: ref,
|
|
63
|
-
getValue
|
|
64
|
-
} = firebaseClient;
|
|
65
|
-
const debugEnabledRef = ref(firebaseClient.myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(firebaseClient.userUuid, "/isDebugEnabled"));
|
|
66
|
-
try {
|
|
67
|
-
return await new Promise(resolve => {
|
|
68
|
-
getValue(debugEnabledRef, snapshot => {
|
|
69
|
-
var _snapshot$val, _snapshot$val2;
|
|
70
|
-
const value = (_snapshot$val = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val2 = snapshot.val) === null || _snapshot$val2 === void 0 ? void 0 : _snapshot$val2.call(snapshot)) !== null && _snapshot$val !== void 0 ? _snapshot$val : snapshot;
|
|
71
|
-
resolve(Boolean(value));
|
|
72
|
-
}, () => resolve(false), {
|
|
73
|
-
onlyOnce: true
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
} catch (_) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const emitProctoringDebugLog = exports.emitProctoringDebugLog = function emitProctoringDebugLog(event) {
|
|
81
|
-
let payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
82
|
-
let firebaseClient = arguments.length > 2 ? arguments[2] : undefined;
|
|
83
|
-
const message = "".concat(DEBUG_LOG_PREFIX, " ").concat(event, " ").concat(safeJsonStringify(_objectSpread({
|
|
84
|
-
ts: Date.now()
|
|
85
|
-
}, payload)));
|
|
86
|
-
isDebugLogEnabled(firebaseClient).then(enabled => {
|
|
87
|
-
if (!enabled) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
postDebugMessage(message);
|
|
91
|
-
});
|
|
92
|
-
};
|