feat(debug): allow local testMode auth on send-wakeup
Move requireAuthOrNotificationLocalTest into shared auth middleware and apply it only to POST /debug/send-wakeup so local testing matches register/refresh without changing JWT-authenticated behavior.
This commit is contained in:
@@ -13,6 +13,21 @@ type ClientErrorBody = {
|
||||
};
|
||||
};
|
||||
|
||||
/** Synthetic userId for unauthenticated local debug registrations (testMode). */
|
||||
const LOCAL_TEST_USER_ID = "__notification_local_test__";
|
||||
|
||||
function isNotificationLocalTestBypass(req: Request): boolean {
|
||||
if (req.headers.authorization?.startsWith("Bearer ")) {
|
||||
return false;
|
||||
}
|
||||
const body = req.body;
|
||||
return (
|
||||
body !== null &&
|
||||
typeof body === "object" &&
|
||||
(body as { testMode?: unknown }).testMode === true
|
||||
);
|
||||
}
|
||||
|
||||
function clientErrorMessage(err: unknown): string | undefined {
|
||||
if (err && typeof err === "object" && "clientError" in err) {
|
||||
const message = (err as ClientErrorBody).clientError?.message;
|
||||
@@ -86,3 +101,17 @@ export async function requireAuth(
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function requireAuthOrNotificationLocalTest(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> {
|
||||
if (isNotificationLocalTestBypass(req)) {
|
||||
req.did = LOCAL_TEST_USER_ID;
|
||||
console.log("[Auth] Local notification test bypass");
|
||||
next();
|
||||
return;
|
||||
}
|
||||
return requireAuth(req, res, next);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Router } from "express";
|
||||
import { db } from "../db/fcmTokens.js";
|
||||
import { requireAuth } from "../middleware/auth.js";
|
||||
import {
|
||||
requireAuth,
|
||||
requireAuthOrNotificationLocalTest,
|
||||
} from "../middleware/auth.js";
|
||||
import {
|
||||
computeNextEligibleAt,
|
||||
sendPushToDevice,
|
||||
@@ -11,8 +14,6 @@ import { maskToken } from "../util/maskToken.js";
|
||||
// TODO: Protect this endpoint before production deployment
|
||||
export const debugRouter = Router();
|
||||
|
||||
debugRouter.use(requireAuth);
|
||||
|
||||
function deviceDebugPayload(row: {
|
||||
id: string;
|
||||
deviceId: string;
|
||||
@@ -47,7 +48,7 @@ function sendWakeupFailureReason(
|
||||
}
|
||||
|
||||
// TODO: Protect this endpoint before production deployment
|
||||
debugRouter.get("/device/:token", async (req, res) => {
|
||||
debugRouter.get("/device/:token", requireAuth, async (req, res) => {
|
||||
const started = Date.now();
|
||||
const userId = req.did;
|
||||
if (userId === undefined) {
|
||||
@@ -81,7 +82,7 @@ debugRouter.get("/device/:token", async (req, res) => {
|
||||
});
|
||||
|
||||
// TODO: Protect this endpoint before production deployment
|
||||
debugRouter.post("/send-wakeup", async (req, res) => {
|
||||
debugRouter.post("/send-wakeup", requireAuthOrNotificationLocalTest, async (req, res) => {
|
||||
const started = Date.now();
|
||||
const userId = req.did;
|
||||
if (userId === undefined) {
|
||||
|
||||
@@ -1,39 +1,9 @@
|
||||
import type { NextFunction, Request, Response } from "express";
|
||||
import { Router } from "express";
|
||||
import { db } from "../db/fcmTokens.js";
|
||||
import { requireAuth } from "../middleware/auth.js";
|
||||
import { requireAuthOrNotificationLocalTest } from "../middleware/auth.js";
|
||||
import { errorMessage, formatElapsedMs } from "../util/formatElapsed.js";
|
||||
import { maskToken } from "../util/maskToken.js";
|
||||
|
||||
/** Synthetic userId for unauthenticated local debug registrations (testMode). */
|
||||
const LOCAL_TEST_USER_ID = "__notification_local_test__";
|
||||
|
||||
function isNotificationLocalTestBypass(req: Request): boolean {
|
||||
if (req.headers.authorization?.startsWith("Bearer ")) {
|
||||
return false;
|
||||
}
|
||||
const body = req.body;
|
||||
return (
|
||||
body !== null &&
|
||||
typeof body === "object" &&
|
||||
(body as { testMode?: unknown }).testMode === true
|
||||
);
|
||||
}
|
||||
|
||||
async function requireAuthOrNotificationLocalTest(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> {
|
||||
if (isNotificationLocalTestBypass(req)) {
|
||||
req.did = LOCAL_TEST_USER_ID;
|
||||
console.log("[Auth] Local notification test bypass");
|
||||
next();
|
||||
return;
|
||||
}
|
||||
return requireAuth(req, res, next);
|
||||
}
|
||||
|
||||
export const notificationsRouter = Router();
|
||||
|
||||
notificationsRouter.get("/", (_req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user