WIP: new-activity notification #231

Draft
trentlarson wants to merge 80 commits from notify-api into master
5 changed files with 61 additions and 4 deletions
Showing only changes of commit 82380b3d35 - Show all commits

View File

@@ -39,6 +39,22 @@
<span>Test Mode</span>
</label>
<label class="flex items-center gap-2 text-sm mb-1 cursor-pointer">
<input
v-model="bypassAuthEnabled"
type="checkbox"
class="rounded border-slate-300"
:disabled="busy"
@change="onBypassAuthChange"
/>
<span>Skip JWT Authentication (Local Development Only)</span>
</label>
<p class="text-xs text-slate-500 mb-4">
Enable only when using a local development server (for example localhost
or ngrok) that intentionally accepts unauthenticated notification
requests.
</p>
<div class="flex flex-col gap-2 mb-4">
<button
class="w-full text-md bg-gradient-to-b from-emerald-400 to-emerald-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
@@ -129,6 +145,10 @@
<dt class="text-slate-500 shrink-0">testMode</dt>
<dd>{{ testModeEnabled ? "true" : "false" }}</dd>
</div>
<div class="flex gap-2">
<dt class="text-slate-500 shrink-0">bypassAuth</dt>
<dd>{{ bypassAuthEnabled ? "true" : "false" }}</dd>
</div>
</dl>
</div>
</div>
@@ -327,6 +347,7 @@ const pending = ref<PendingInfo[]>([]);
const pendingInspectorMessage = ref<string | null>(null);
const backendUrlDraft = ref("");
const testModeEnabled = ref(NotificationDebugService.isTestModeEnabled());
const bypassAuthEnabled = ref(NotificationDebugService.isBypassAuthEnabled());
const fcmToken = ref<string | null>(NotificationDebugService.getFcmToken());
const activeBackendUrl = ref(NotificationDebugService.getActiveBackendUrl());
@@ -406,6 +427,7 @@ function syncBackendState(): void {
backendUrlDraft.value =
NotificationDebugService.getBackendUrlOverride() ?? "";
testModeEnabled.value = NotificationDebugService.isTestModeEnabled();
bypassAuthEnabled.value = NotificationDebugService.isBypassAuthEnabled();
fcmToken.value = NotificationDebugService.getFcmToken();
activeBackendUrl.value = NotificationDebugService.getActiveBackendUrl();
}
@@ -419,6 +441,10 @@ function onTestModeChange(): void {
NotificationDebugService.setTestModeEnabled(testModeEnabled.value);
}
function onBypassAuthChange(): void {
NotificationDebugService.setBypassAuthEnabled(bypassAuthEnabled.value);
}
async function onRegisterToken(): Promise<void> {
await withBusy(async () => {
try {

View File

@@ -8,6 +8,7 @@ import { APP_SERVER } from "@/constants/app";
const LOG = "[NotificationDebug]";
const STORAGE_KEY_BACKEND_URL = "notificationDebug.backendBaseUrl";
const STORAGE_KEY_TEST_MODE = "notificationDebug.testMode";
const STORAGE_KEY_BYPASS_AUTH = "notificationDebug.bypassAuth";
/** Trim whitespace, drop trailing slash; empty input becomes null. */
export function normalizeNotificationBackendUrl(url: string): string | null {
@@ -83,6 +84,21 @@ export function setTestMode(enabled: boolean): void {
console.log(`${LOG} test mode ${enabled ? "enabled" : "disabled"}`);
}
/** When never configured via debug UI/console, auth bypass is off (JWT used). */
export function getBypassAuth(): boolean {
const raw = readStorage(STORAGE_KEY_BYPASS_AUTH);
if (raw === null) {
return false;
}
return raw === "true";
}
export function setBypassAuth(enabled: boolean): void {
writeStorage(STORAGE_KEY_BYPASS_AUTH, enabled ? "true" : "false");
// eslint-disable-next-line no-console
console.log(`${LOG} auth bypass ${enabled ? "enabled" : "disabled"}`);
}
/**
* Base URL for `/notifications/*` API calls.
* Uses debug override when set; otherwise the built-in app server (production default).

View File

@@ -18,9 +18,11 @@ import {
import { logNotificationClearing } from "./notificationLog";
import {
getBackendBaseUrl,
getBypassAuth,
getNotificationApiBaseUrl,
getTestMode,
setBackendBaseUrl,
setBypassAuth,
setTestMode,
} from "./NotificationDebugConfig";
import {
@@ -143,6 +145,17 @@ export const NotificationDebugService = {
return getTestMode();
},
setBypassAuthEnabled(enabled: boolean): void {
setBypassAuth(enabled);
logNotification(
`Auth bypass ${enabled ? "enabled" : "disabled"} (local dev only)`,
);
},
isBypassAuthEnabled(): boolean {
return getBypassAuth();
},
getFcmToken(): string | null {
return getLastKnownFcmToken();
},

View File

@@ -15,10 +15,12 @@
export {
getBackendBaseUrl,
getBypassAuth,
getNotificationApiBaseUrl,
getTestMode,
normalizeNotificationBackendUrl,
setBackendBaseUrl,
setBypassAuth,
setTestMode,
} from "./NotificationDebugConfig";
export { shouldBypassNotificationAuth } from "./notificationApiDebugMode";

View File

@@ -1,11 +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.
* Controlled explicitly via `notificationDebug.bypassAuth`; off by default.
*/
import { getBackendBaseUrl, getTestMode } from "./NotificationDebugConfig";
import { getBypassAuth } from "./NotificationDebugConfig";
/** True when local notification debug config allows unauthenticated API calls. */
/** True when debug panel explicitly allows unauthenticated API calls. */
export function shouldBypassNotificationAuth(): boolean {
return getTestMode() || getBackendBaseUrl() !== null;
return getBypassAuth();
}