← back to Watches

api/user/profile.js

192 lines

/**
 * User Profile API Routes
 * Get, update, and delete user profile
 */

import pool from '../../database/connection.js';

/**
 * GET /api/user/profile
 * Get current user's profile
 */
export async function getProfile(req, res) {
  if (!req.user) {
    return res.status(401).json({ success: false, error: 'Not authenticated' });
  }

  try {
    const result = await pool.query(
      `SELECT id, email, name, avatar_url, role, provider, email_verified,
              created_at, last_login_at, login_count
       FROM users WHERE id = $1`,
      [req.user.id]
    );

    if (result.rows.length === 0) {
      return res.status(404).json({ success: false, error: 'User not found' });
    }

    // Get user preferences
    const prefs = await pool.query(
      `SELECT currency, theme, language, email_notifications, push_notifications,
              alert_notifications, marketing_emails
       FROM user_preferences WHERE user_id = $1`,
      [req.user.id]
    );

    res.json({
      success: true,
      user: result.rows[0],
      preferences: prefs.rows[0] || {}
    });

  } catch (error) {
    console.error('Get profile error:', error);
    res.status(500).json({ success: false, error: 'Failed to get profile' });
  }
}

/**
 * PATCH /api/user/profile
 * Update user profile
 */
export async function updateProfile(req, res) {
  if (!req.user) {
    return res.status(401).json({ success: false, error: 'Not authenticated' });
  }

  const { name } = req.body;

  try {
    const result = await pool.query(
      `UPDATE users SET name = COALESCE($1, name), updated_at = NOW()
       WHERE id = $2
       RETURNING id, email, name, avatar_url`,
      [name, req.user.id]
    );

    res.json({
      success: true,
      user: result.rows[0]
    });

  } catch (error) {
    console.error('Update profile error:', error);
    res.status(500).json({ success: false, error: 'Failed to update profile' });
  }
}

/**
 * DELETE /api/user/profile
 * Delete user account
 */
export async function deleteProfile(req, res) {
  if (!req.user) {
    return res.status(401).json({ success: false, error: 'Not authenticated' });
  }

  try {
    // Soft delete by deactivating
    await pool.query(
      `UPDATE users SET is_active = false, email = email || '_deleted_' || id, updated_at = NOW()
       WHERE id = $1`,
      [req.user.id]
    );

    // Invalidate all sessions
    await pool.query(
      `UPDATE user_sessions SET is_valid = false, revoked_at = NOW(), revoke_reason = 'account_deleted'
       WHERE user_id = $1`,
      [req.user.id]
    );

    res.clearCookie('session_token');
    res.json({ success: true, message: 'Account deleted' });

  } catch (error) {
    console.error('Delete profile error:', error);
    res.status(500).json({ success: false, error: 'Failed to delete account' });
  }
}

/**
 * GET /api/user/preferences
 * Get user preferences
 */
export async function getPreferences(req, res) {
  if (!req.user) {
    return res.status(401).json({ success: false, error: 'Not authenticated' });
  }

  try {
    const result = await pool.query(
      `SELECT * FROM user_preferences WHERE user_id = $1`,
      [req.user.id]
    );

    res.json({
      success: true,
      preferences: result.rows[0] || {}
    });

  } catch (error) {
    console.error('Get preferences error:', error);
    res.status(500).json({ success: false, error: 'Failed to get preferences' });
  }
}

/**
 * PATCH /api/user/preferences
 * Update user preferences
 */
export async function updatePreferences(req, res) {
  if (!req.user) {
    return res.status(401).json({ success: false, error: 'Not authenticated' });
  }

  const {
    currency, theme, language,
    email_notifications, push_notifications, alert_notifications, marketing_emails,
    quiet_hours_start, quiet_hours_end, max_alerts_per_day
  } = req.body;

  try {
    const result = await pool.query(
      `UPDATE user_preferences
       SET currency = COALESCE($1, currency),
           theme = COALESCE($2, theme),
           language = COALESCE($3, language),
           email_notifications = COALESCE($4, email_notifications),
           push_notifications = COALESCE($5, push_notifications),
           alert_notifications = COALESCE($6, alert_notifications),
           marketing_emails = COALESCE($7, marketing_emails),
           quiet_hours_start = COALESCE($8, quiet_hours_start),
           quiet_hours_end = COALESCE($9, quiet_hours_end),
           max_alerts_per_day = COALESCE($10, max_alerts_per_day),
           updated_at = NOW()
       WHERE user_id = $11
       RETURNING *`,
      [currency, theme, language, email_notifications, push_notifications,
       alert_notifications, marketing_emails, quiet_hours_start, quiet_hours_end,
       max_alerts_per_day, req.user.id]
    );

    res.json({
      success: true,
      preferences: result.rows[0]
    });

  } catch (error) {
    console.error('Update preferences error:', error);
    res.status(500).json({ success: false, error: 'Failed to update preferences' });
  }
}

export default {
  getProfile,
  updateProfile,
  deleteProfile,
  getPreferences,
  updatePreferences
};