Skip to content

Commit dbc3d70

Browse files
committed
BB-T43 PR#119 fixes
1 parent e0c8c1c commit dbc3d70

3 files changed

Lines changed: 28 additions & 20 deletions

File tree

src/lib/auth/api.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ authApi.interceptors.request.use((config) => {
2525
});
2626

2727
export const loginRequest = async (credentials: LoginCredentials): Promise<LoginResponse> => {
28+
// GDPR Art. 5(1)(c) data minimization: never log raw username PII.
29+
// Computed before the try block (with its own fallback) so the hash is
30+
// available in both success and error paths without an unguarded await
31+
// inside catch.
32+
let username_hash = 'unavailable';
33+
try {
34+
username_hash = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, credentials.username);
35+
} catch {
36+
// Hashing failed (e.g. crypto backend unavailable) — keep placeholder.
37+
}
38+
const gdpr = { purpose: 'auth', lawful_basis: 'contract' } as const;
39+
2840
try {
2941
const data = queryString.stringify({
3042
grant_type: 'password',
@@ -33,10 +45,6 @@ export const loginRequest = async (credentials: LoginCredentials): Promise<Login
3345
scope: Env.IS_MOBILE_APP ? 'openid profile offline_access mobile' : 'openid profile offline_access',
3446
});
3547

36-
// GDPR Art. 5(1)(c) data minimization: never log raw username PII.
37-
const username_hash = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, credentials.username);
38-
const gdpr = { purpose: 'auth', lawful_basis: 'contract' } as const;
39-
4048
logger.info({
4149
message: 'API: Sending login request',
4250
context: { username_hash, baseURL: authApi.defaults.baseURL, gdpr },
@@ -73,14 +81,13 @@ export const loginRequest = async (credentials: LoginCredentials): Promise<Login
7381
};
7482
}
7583
} catch (error) {
76-
const username_hash = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, credentials.username);
7784
logger.error({
7885
message: 'Login API call failed with exception',
7986
context: {
8087
error: error instanceof Error ? error.message : String(error),
8188
status: axios.isAxiosError(error) ? error.response?.status : undefined,
8289
username_hash,
83-
gdpr: { purpose: 'auth', lawful_basis: 'contract' },
90+
gdpr,
8491
},
8592
});
8693

src/services/signalr.service.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,7 @@ class SignalRService {
196196
// Set up event handlers
197197
connection.onclose((error) => {
198198
this.handleConnectionClose(config.name);
199-
if (error) {
200-
this.notifyConnectionStateCallbacks(config.name, 'onError', error);
201-
}
199+
this.notifyConnectionError(config.name, error);
202200
this.notifyConnectionStateCallbacks(config.name, 'onClose');
203201
});
204202

@@ -207,9 +205,7 @@ class SignalRService {
207205
message: `Reconnecting to hub: ${config.name}`,
208206
context: { error },
209207
});
210-
if (error) {
211-
this.notifyConnectionStateCallbacks(config.name, 'onError', error);
212-
}
208+
this.notifyConnectionError(config.name, error);
213209
this.notifyConnectionStateCallbacks(config.name, 'onReconnecting');
214210
});
215211

@@ -332,9 +328,7 @@ class SignalRService {
332328
// Set up event handlers
333329
connection.onclose((error) => {
334330
this.handleConnectionClose(config.name);
335-
if (error) {
336-
this.notifyConnectionStateCallbacks(config.name, 'onError', error);
337-
}
331+
this.notifyConnectionError(config.name, error);
338332
this.notifyConnectionStateCallbacks(config.name, 'onClose');
339333
});
340334

@@ -343,9 +337,7 @@ class SignalRService {
343337
message: `Reconnecting to hub: ${config.name}`,
344338
context: { error },
345339
});
346-
if (error) {
347-
this.notifyConnectionStateCallbacks(config.name, 'onError', error);
348-
}
340+
this.notifyConnectionError(config.name, error);
349341
this.notifyConnectionStateCallbacks(config.name, 'onReconnecting');
350342
});
351343

@@ -645,6 +637,12 @@ class SignalRService {
645637
}
646638
}
647639

640+
private notifyConnectionError(hubName: string, error?: Error): void {
641+
if (error) {
642+
this.notifyConnectionStateCallbacks(hubName, 'onError', error);
643+
}
644+
}
645+
648646
private notifyConnectionStateCallbacks(hubName: string, event: keyof SignalRConnectionStateCallbacks, error?: Error): void {
649647
this.connectionStateCallbacks.get(hubName)?.forEach((callbacks) => {
650648
try {

src/stores/signalr/signalr-store.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,12 @@ export const useSignalRStore = create<SignalRState>((set, get) => ({
223223
});
224224
set({ isUpdateHubConnected: true, error: null });
225225
});
226+
}
226227

227-
// Set up connection state monitoring via the service's public API
228-
// This ensures we properly track disconnections and reconnections
228+
// Connection state monitoring re-registers on each connect: disconnect
229+
// unregisters and nulls the handle, so guard on the handle rather than
230+
// the one-time listener flag above.
231+
if (!updateHubStateCallbackHandle) {
229232
updateHubStateCallbackHandle = signalRService.registerConnectionStateCallbacks(Env.CHANNEL_HUB_NAME, {
230233
onClose: () => {
231234
logger.info({

0 commit comments

Comments
 (0)