- ForgotPasswordPage: email input, sends reset request, shows success
- ResetPasswordPage: reads token from ?token= query param, password
+ confirm inputs, validates min length, shows success with login link
- LoginForm: added [FORGOT PASSWORD?] link below the form
- App.tsx: /forgot-password and /reset-password routes (public, no auth)
- auth store: requestPasswordReset + resetPassword actions
- Backend routes already existed at POST /auth/request-password-reset
and POST /auth/reset-password
Single script: git pull, make build, systemctl restart.
Nvm is sourced inside the script (server now has node v22.23.1 installed).
Run via: ssh dumpsterchat /opt/dumpsterChat/deploy.sh
The token column was dropped in a previous migration step
(ALTER TABLE webhooks DROP COLUMN IF EXISTS token), but the
CREATE INDEX referencing it still ran, causing migration failure
on databases where the column was already removed.
Phase 7.1 — Per-channel notification settings
- New notification_settings table (user_id, channel_id, level)
- GET/PUT/DELETE handlers under /channels/{channelID}/notifications
- Push dispatch and @mention loops filtered by notification level
- Frontend: bell icon per channel cycling all/mentions/none
Phase 7.4 — Read receipts
- New read_states table (user_id, channel_id, last_read_message_id)
- PUT /channels/{channelID}/read and GET /users/me/read-states
- Auto-mark-read when messages load in ChatArea
- Unread dot for channels never opened
Also: favicon/icon refresh in index.html
- New VideoGrid component: live camera feeds (local + remote) in VoicePanel
- Camera toggle in VoiceControls: enable/disable video per participant
- Noise suppression toggle in VoiceControls + voice store
- VOICE_WHISPER WS event: backend routes whisper to target user only
- Whisper UI: per-participant whisper button, notification toasts with dismiss
- Fix circular import between voice.ts and ws.ts (use lazy accessor)
Backend:
- Login handler accepts username OR email via the same field
- New PUT /auth/me/password endpoint (verifies current password,
requires min 8 chars for new password)
Frontend:
- Login form shows EMAIL OR USERNAME field (single field for both)
- Auth store updated with changePassword function
- UserSettings has new CHANGE PASSWORD section
Backend:
- Add GET /api/v1/servers/{serverID}/members endpoint
- Wire MemberHandler routes in main.go
Frontend:
- Create member store (fetchMembers by server ID)
- MemberList now fetches members from API instead of empty props
- ChatArea: show channel name instead of ID, add error display,
add flex-1 + min-w-0 to input for proper sizing, error handling
on sendMessage
The channel Create handler was expecting server_id in the JSON body,
but the frontend sends it in the URL path (/servers/{serverID}/channels).
Now reads serverID from chi.URLParam and only requires name in the body.
The CSRF middleware was rejecting requests from LAN IPs because
cfg.Host defaults to 'localhost' which doesn't match the LAN IP.
Now supports DUMPSTER_CSRF_ORIGINS env var (comma-separated list of
full origins) for additional trusted origins beyond cfg.Host.
Removed debug logging from CSRF middleware.