mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-03 14:09:42 +02:00
Merge pull request #501 from aakhter/pr/webview-sse-owner
fix(webview): route webview:changed only to its owner in multi-user mode
This commit is contained in:
@@ -165,7 +165,11 @@ function registerCrudRoutes(app: FastifyInstance, ctx: EventPort & TabLayoutPort
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
ctx.broadcast(SseEvent.WebviewChanged, { action: 'created', id: created.id });
|
||||
ctx.broadcast(SseEvent.WebviewChanged, {
|
||||
action: 'created',
|
||||
id: created.id,
|
||||
owner: ownerLayoutKey(created.owner),
|
||||
});
|
||||
return { success: true, data: created };
|
||||
});
|
||||
|
||||
@@ -195,7 +199,11 @@ function registerCrudRoutes(app: FastifyInstance, ctx: EventPort & TabLayoutPort
|
||||
// Any edit invalidates the outstanding capability. Otherwise a token minted
|
||||
// against the OLD url keeps proxying to it after the user repointed the tab.
|
||||
webviewCapabilities.revokeWebview(id);
|
||||
ctx.broadcast(SseEvent.WebviewChanged, { action: 'updated', id });
|
||||
ctx.broadcast(SseEvent.WebviewChanged, {
|
||||
action: 'updated',
|
||||
id,
|
||||
owner: ownerLayoutKey(updated.owner),
|
||||
});
|
||||
return { success: true, data: updated };
|
||||
});
|
||||
|
||||
@@ -231,7 +239,11 @@ function registerCrudRoutes(app: FastifyInstance, ctx: EventPort & TabLayoutPort
|
||||
|
||||
webviewCapabilities.revokeWebview(id);
|
||||
socketCounts.delete(id);
|
||||
ctx.broadcast(SseEvent.WebviewChanged, { action: 'deleted', id });
|
||||
ctx.broadcast(SseEvent.WebviewChanged, {
|
||||
action: 'deleted',
|
||||
id,
|
||||
owner: ownerLayoutKey(result.owner),
|
||||
});
|
||||
return { success: true, data: { id } };
|
||||
});
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ import { PushSubscriptionStore } from '../push-store.js';
|
||||
import webpush from 'web-push';
|
||||
import { SseStreamManager } from './sse-stream-manager.js';
|
||||
import { deriveTabLayoutSseHint } from './tab-layout-sse.js';
|
||||
import { deriveWebviewSseHint } from './webview-sse.js';
|
||||
import {
|
||||
type SessionListenerRefs,
|
||||
createSessionListeners,
|
||||
@@ -2461,6 +2462,12 @@ export class WebServer extends EventEmitter {
|
||||
if (event.startsWith('tab:')) {
|
||||
return deriveTabLayoutSseHint(data);
|
||||
}
|
||||
// Saved-webview invalidations carry the trusted resource owner. Route them to
|
||||
// that owner (plus admins), so an admin editing a user's web tab notifies the
|
||||
// user, and no other user learns the ids of someone else's web tabs.
|
||||
if (event.startsWith('webview:')) {
|
||||
return deriveWebviewSseHint(data);
|
||||
}
|
||||
// Session-scoped families: resolve the owner from the payload's session id.
|
||||
const SESSION_PREFIXES = [
|
||||
'session:',
|
||||
|
||||
@@ -481,8 +481,10 @@ export const AuthPasswordChangeRequired = 'auth:passwordChangeRequired' as const
|
||||
export const SessionOrderChanged = 'session:orderChanged' as const;
|
||||
|
||||
/** A saved web tab (dashboard URL) was created, updated or deleted.
|
||||
* Payload: `{ action: 'created' | 'updated' | 'deleted', id }`. The client
|
||||
* re-fetches the list rather than patching from the payload. */
|
||||
* Payload: `{ action: 'created' | 'updated' | 'deleted', id, owner }`. The client
|
||||
* re-fetches the list rather than patching from the payload. `owner` is the web
|
||||
* tab's owner (`'@single'` when multi-user mode is off); in multi-user mode the
|
||||
* event is delivered only to that owner and admins (`deriveWebviewSseHint`). */
|
||||
export const WebviewChanged = 'webview:changed' as const;
|
||||
/** Owner-scoped layout invalidation. Payload contains only `{ owner, version }`. */
|
||||
export const TabLayoutChanged = 'tab:layoutChanged' as const;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/** @fileoverview Trusted owner routing metadata for saved-webview invalidations. */
|
||||
import type { SseRoutingHint } from './sse-stream-manager.js';
|
||||
|
||||
export function deriveWebviewSseHint(data: unknown): SseRoutingHint {
|
||||
return { username: (data as { owner?: string }).owner, sessionScoped: true };
|
||||
}
|
||||
Reference in New Issue
Block a user