Skip to content

🧹 Backend hygiene: bcrypt rounds, password validation, RRULE validation, 12-factor config, DB indexes #33

@fusion94

Description

@fusion94

Summary

Bundle of small, low-risk backend cleanups that close validation gaps and remove hardcoded values. Each is XS individually; bundling avoids issue spam.

Items

1. Bump bcrypt rounds

SALT_ROUNDS = 10 (server/index.js:9) → bump to 12. Existing hashes stay valid; new hashes use the higher cost.

2. Server-side password validation

Frontend enforces minLength: 4 (Register.jsx:44, Profile.jsx:179, ResetPassword.jsx:56); backend enforces nothing. Add an explicit length+complexity check on POST /api/register, POST /api/reset-password, and PUT /api/user/:username/password. Recommend min 8 chars.

3. Custom RRULE validation

POST /api/events and PUT /api/events/:id (server/index.js:1076, :1106) accept an arbitrary recurrence string. Validate with rrule.js before persisting.

4. Atomic file rename in username migration

server/index.js:369-376 renames a profile photo file as best-effort; if the rename fails the URL points at a missing path. Wrap rename + DB update in a single try/rollback.

5. Refactor duplicated ICS generation

GET /api/calendar/subscribe (server/index.js:716-794) and GET /api/events/export/ics (:797-874) share ~70% of their string-building logic. Extract buildIcsCalendar(events, opts).

6. 12-factor config

Move out of code into env vars (and add to .env.example):

7. DB indexes

Add to existing tables (cheap, eliminates full scans):

  • CREATE INDEX idx_users_reset_token ON users(resetToken);
  • CREATE INDEX idx_events_date_visibility ON calendar_events(event_date, visibility);
  • CREATE INDEX idx_invites_created_by ON invite_tokens(created_by);
  • CREATE INDEX idx_invites_used_by ON invite_tokens(used_by);

Acceptance Criteria

  • New password hashes use 12 rounds; existing logins still work.
  • Backend rejects passwords < 8 chars on all three endpoints.
  • Invalid RRULEs return a 400 with a useful message.
  • Username migration leaves no orphaned photo URLs even when the rename step fails.
  • ICS generation is one helper called from both places.
  • Backend honors all listed env vars and falls back to current defaults when unset.
  • All four indexes exist after server boot.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions