WIP: new-activity notification #231
@@ -30,7 +30,6 @@ import {
|
||||
import {
|
||||
getNotificationApiHeaders,
|
||||
httpAuthErrorMessage,
|
||||
logNotificationRequestAuthenticated,
|
||||
logSkippingRefreshDueToMissingAuth,
|
||||
} from "./notificationApiAuth";
|
||||
import { logNotification } from "./NotificationDebugEvents";
|
||||
@@ -591,7 +590,7 @@ export async function refreshNotificationsWithDiagnostics(options?: {
|
||||
}
|
||||
|
||||
try {
|
||||
const auth = await getNotificationApiHeaders();
|
||||
const auth = await getNotificationApiHeaders("refresh");
|
||||
if (!auth.ok) {
|
||||
logSkippingRefreshDueToMissingAuth();
|
||||
logRefreshFailure(startedAt, auth.message);
|
||||
@@ -601,7 +600,6 @@ export async function refreshNotificationsWithDiagnostics(options?: {
|
||||
errorMessage: auth.message,
|
||||
};
|
||||
}
|
||||
logNotificationRequestAuthenticated("refresh");
|
||||
|
||||
const baseUrl = getNotificationApiBaseUrl();
|
||||
const res = await fetch(`${baseUrl}/notifications/refresh`, {
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
getNotificationApiHeaders,
|
||||
httpAuthErrorMessage,
|
||||
logNotificationAuthFailure,
|
||||
logNotificationRequestAuthenticated,
|
||||
} from "./notificationApiAuth";
|
||||
import {
|
||||
logTokenRegistrationFailure,
|
||||
@@ -42,12 +41,11 @@ export async function registerToken(fcmToken: string): Promise<void> {
|
||||
const deviceId = await getOrCreateDeviceId();
|
||||
const baseUrl = getNotificationApiBaseUrl();
|
||||
try {
|
||||
const auth = await getNotificationApiHeaders();
|
||||
const auth = await getNotificationApiHeaders("register");
|
||||
if (!auth.ok) {
|
||||
logNotificationAuthFailure("register", auth.message);
|
||||
throw new Error(`registerToken auth unavailable: ${auth.message}`);
|
||||
}
|
||||
logNotificationRequestAuthenticated("register");
|
||||
|
||||
const res = await fetch(`${baseUrl}/notifications/register`, {
|
||||
method: "POST",
|
||||
|
||||
@@ -54,7 +54,7 @@ async function registerRetrievedToken(
|
||||
return;
|
||||
}
|
||||
|
||||
const auth = await getNotificationApiHeaders();
|
||||
const auth = await getNotificationApiHeaders("register");
|
||||
if (!auth.ok) {
|
||||
if (options?.force) {
|
||||
throw new Error(`FCM registration auth unavailable: ${auth.message}`);
|
||||
|
||||
@@ -21,6 +21,7 @@ export {
|
||||
setBackendBaseUrl,
|
||||
setTestMode,
|
||||
} from "./NotificationDebugConfig";
|
||||
export { shouldBypassNotificationAuth } from "./notificationApiDebugMode";
|
||||
export {
|
||||
appendLog,
|
||||
clearNotificationDebugLogs,
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
/**
|
||||
* Authenticated headers for notification backend API calls (`/notifications/*`).
|
||||
* Uses the same `getHeaders` + active DID flow as the rest of the app.
|
||||
* Debug/local config can bypass auth for ngrok and panel testing.
|
||||
*/
|
||||
|
||||
import { getHeaders } from "@/libs/endorserServer";
|
||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||
import { logger } from "@/utils/logger";
|
||||
import { shouldBypassNotificationAuth } from "./notificationApiDebugMode";
|
||||
import { logNotification } from "./NotificationDebugEvents";
|
||||
|
||||
export type NotificationRequestKind = "register" | "refresh";
|
||||
|
||||
export type NotificationApiHeadersResult =
|
||||
| { ok: true; headers: { "Content-Type": string; Authorization: string } }
|
||||
| {
|
||||
ok: true;
|
||||
authenticated: boolean;
|
||||
headers: Record<string, string>;
|
||||
}
|
||||
| {
|
||||
ok: false;
|
||||
reason: "no_active_did" | "missing_token";
|
||||
message: string;
|
||||
};
|
||||
|
||||
const DEBUG_HEADERS: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
async function resolveActiveDid(): Promise<string | null> {
|
||||
try {
|
||||
const service = PlatformServiceFactory.getInstance();
|
||||
@@ -46,8 +56,33 @@ function hasBearerToken(headers: {
|
||||
);
|
||||
}
|
||||
|
||||
/** Resolve `Authorization: Bearer …` headers for notification API requests. */
|
||||
export async function getNotificationApiHeaders(): Promise<NotificationApiHeadersResult> {
|
||||
function logAuthBypassEnabled(): void {
|
||||
logNotification("Auth bypass enabled for debug/testing");
|
||||
}
|
||||
|
||||
function logAuthenticatedNotificationRequest(): void {
|
||||
logNotification("Using authenticated notification request");
|
||||
}
|
||||
|
||||
function logDebugUnauthenticatedNotificationRequest(): void {
|
||||
logNotification("Using debug unauthenticated notification request");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve headers for notification API requests.
|
||||
* @param kind Optional request kind for structured logs.
|
||||
*/
|
||||
export async function getNotificationApiHeaders(
|
||||
kind?: NotificationRequestKind,
|
||||
): Promise<NotificationApiHeadersResult> {
|
||||
if (shouldBypassNotificationAuth()) {
|
||||
logAuthBypassEnabled();
|
||||
if (kind) {
|
||||
logDebugUnauthenticatedNotificationRequest();
|
||||
}
|
||||
return { ok: true, authenticated: false, headers: { ...DEBUG_HEADERS } };
|
||||
}
|
||||
|
||||
const did = await resolveActiveDid();
|
||||
if (!did) {
|
||||
return {
|
||||
@@ -66,8 +101,13 @@ export async function getNotificationApiHeaders(): Promise<NotificationApiHeader
|
||||
};
|
||||
}
|
||||
|
||||
if (kind) {
|
||||
logAuthenticatedNotificationRequest();
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
authenticated: true,
|
||||
headers: {
|
||||
"Content-Type": headers["Content-Type"],
|
||||
Authorization: headers.Authorization,
|
||||
|
||||
11
src/services/notifications/notificationApiDebugMode.ts
Normal file
11
src/services/notifications/notificationApiDebugMode.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Debug/local notification API auth bypass (ngrok, Notification Debug Panel).
|
||||
* Production paths leave bypass off unless test mode or backend override is set.
|
||||
*/
|
||||
|
||||
import { getBackendBaseUrl, getTestMode } from "./NotificationDebugConfig";
|
||||
|
||||
/** True when local notification debug config allows unauthenticated API calls. */
|
||||
export function shouldBypassNotificationAuth(): boolean {
|
||||
return getTestMode() || getBackendBaseUrl() !== null;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ export async function flushDeferredFcmRegistration(
|
||||
return;
|
||||
}
|
||||
|
||||
const auth = await getNotificationApiHeaders();
|
||||
const auth = await getNotificationApiHeaders("register");
|
||||
if (!auth.ok) {
|
||||
scheduleDeferredRegistrationRetry();
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user