fix: hardening pass — permissions, socket reconnect, canvas setup, arrangements

- Fix 403 on save for public collection viewers (return role in GET board response)
- Add read-only status indicator (StatusBar + StatusIndicator)
- Fix beforeunload save to use fetch+keepalive with auth header
- Socket reconnect now rejoins board room automatically
- Canvas setup uses polling instead of brittle 200ms timer
- Fix double user:left on disconnect (use disconnecting event, snapshot rooms)
- Thread + comment creation wrapped in db.transaction
- Prevent owner downgrade via addCollectionMember (check existing member)
- Bound redirect depth in downloadImage to 5
- Arrangement operations anchor to bounding box top-left (no drift)
- Distribute H/V also anchor to top-left
- Fix annotations fetch to use axios api instance (401 interceptor)
- Replace require() with static import in shortcut-definitions
This commit is contained in:
Hiren Kangad
2026-03-11 08:08:21 +05:30
parent fc2d9df741
commit 6518ed6763
13 changed files with 141 additions and 84 deletions
+3 -2
View File
@@ -1,6 +1,6 @@
import React from 'react';
export type SaveStatus = 'saved' | 'saving' | 'unsaved';
export type SaveStatus = 'saved' | 'saving' | 'unsaved' | 'readonly';
interface StatusBarProps {
boardName: string;
@@ -47,10 +47,11 @@ const statusConfig: Record<SaveStatus, { label: string; color: string }> = {
saved: { label: 'Saved', color: '#69db7c' },
saving: { label: 'Saving...', color: '#ffd43b' },
unsaved: { label: 'Unsaved changes', color: '#ff6b6b' },
readonly: { label: 'Read-only', color: '#4dabf7' },
};
export default function StatusBar({ boardName, imageCount, saveStatus }: StatusBarProps) {
const status = statusConfig[saveStatus];
const status = statusConfig[saveStatus] || statusConfig.saved;
return (
<div style={styles.bar}>