Skip to content

feat(profile): Implement user profile persistence for logged-in users #312

@arunderwood

Description

@arunderwood

Summary

Add database persistence for user profiles, enabling cross-device sync for logged-in users.

Parent Epic

Part of #309 (User Profiles & Personalization)

Dependencies

  • Depends on: LocalStorage preferences issue

Deliverables

Database Schema

  • Create Liquibase migration for user_profiles table:
    CREATE TABLE user_profiles (
      id BIGSERIAL PRIMARY KEY,
      user_id BIGINT NOT NULL REFERENCES app_users(id) UNIQUE,
      callsign VARCHAR(10),
      grid_square VARCHAR(8),
      preferred_bands TEXT[],
      preferred_modes TEXT[],
      created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
      updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
    );
    
    CREATE INDEX idx_user_profiles_user_id ON user_profiles(user_id);

Backend

  • Create UserProfileEntity.java
  • Create UserProfileRepository.java
  • Create ProfileEndpoint.java with @BrowserCallable:
    @BrowserCallable
    public class ProfileEndpoint {
        @PermitAll  // Any authenticated user
        public Optional<UserProfile> getProfile() { ... }
    
        @PermitAll
        public UserProfile updateProfile(ProfileUpdateRequest request) { ... }
    }

Sync Strategy

  • On login: Merge LocalStorage → DB (DB wins for conflicts, or use "last modified" timestamp)
  • On login: Populate LocalStorage from DB if LocalStorage is empty
  • Update usePreferences hook to detect auth state and sync

Testing

  • Unit tests for ProfileEndpoint
  • Integration tests for sync behavior
  • Test conflict resolution

Sync Flow

Login detected
    │
    ├─► LocalStorage empty?
    │   └─► YES: Fetch from DB → populate LocalStorage
    │   └─► NO: Compare timestamps
    │           └─► DB newer: Update LocalStorage
    │           └─► Local newer: Update DB
    │
    └─► Subscribe to preference changes → sync to DB

Acceptance Criteria

  • Logged-in user's preferences sync to database
  • Preferences restored on login from different device
  • LocalStorage acts as cache for logged-in users
  • Logout does NOT clear LocalStorage (anonymous persistence)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions