User Settings Management
Overviewβ
The /api/settings
endpoint manages user preferences, notification settings, privacy controls, and application configuration. This endpoint allows users to customize their Ring Platform experience according to their preferences.
Authenticationβ
Required: Valid session token Roles: All authenticated users Rate Limit: 60 requests per minute per user
Endpointsβ
Get User Settingsβ
GET /api/settings
Headers:
Authorization: Bearer <session-token>
Accept: application/json
Response (200):
{
"userId": "user_123",
"preferences": {
"language": "en",
"theme": "dark",
"timezone": "Europe/Kiev",
"dateFormat": "DD/MM/YYYY",
"timeFormat": "24h"
},
"notifications": {
"email": {
"enabled": true,
"frequency": "immediate",
"types": {
"news": true,
"opportunities": true,
"messages": true,
"systemUpdates": false,
"marketing": false
}
},
"push": {
"enabled": true,
"types": {
"messages": true,
"opportunities": true,
"news": false,
"systemUpdates": true
}
},
"sms": {
"enabled": false,
"types": {
"security": true,
"urgent": false
}
},
"inApp": {
"enabled": true,
"sound": true,
"badge": true
}
},
"privacy": {
"profileVisibility": "public",
"showEmail": false,
"showWalletAddress": false,
"showLocation": true,
"showCompany": true,
"showSocialLinks": true,
"allowDirectMessages": true,
"allowOpportunityInvites": true,
"searchableProfile": true
},
"security": {
"twoFactorEnabled": false,
"sessionTimeout": 30,
"loginNotifications": true,
"deviceTracking": true
},
"content": {
"autoplayVideos": false,
"showImages": true,
"contentLanguages": ["en", "uk"],
"hideNSFW": true
},
"accessibility": {
"highContrast": false,
"largeText": false,
"reducedMotion": false,
"screenReader": false
},
"updatedAt": "2024-12-14T15:45:00Z"
}
Update User Settingsβ
PUT /api/settings
Headers:
Authorization: Bearer <session-token>
Content-Type: application/json
Request Body (Partial Update):
{
"preferences": {
"language": "uk",
"theme": "light",
"timezone": "Europe/Kiev"
},
"notifications": {
"email": {
"enabled": true,
"frequency": "daily",
"types": {
"news": true,
"opportunities": true,
"marketing": false
}
},
"push": {
"enabled": false
}
},
"privacy": {
"profileVisibility": "private",
"showEmail": false,
"allowDirectMessages": false
}
}
Response (200):
{
"success": true,
"message": "Settings updated successfully",
"data": {
"userId": "user_123",
"updatedAt": "2024-12-14T16:00:00Z",
"changedFields": [
"preferences.language",
"preferences.theme",
"notifications.email.frequency",
"notifications.push.enabled",
"privacy.profileVisibility",
"privacy.allowDirectMessages"
]
}
}
Reset Settings to Defaultβ
POST /api/settings/reset
Headers:
Authorization: Bearer <session-token>
Content-Type: application/json
Request Body:
{
"sections": ["notifications", "privacy"],
"confirmReset": true
}
Response (200):
{
"success": true,
"message": "Settings reset to default values",
"data": {
"userId": "user_123",
"resetSections": ["notifications", "privacy"],
"resetAt": "2024-12-14T16:00:00Z"
}
}
Code Examplesβ
JavaScript/TypeScriptβ
// Settings management service
class SettingsService {
private baseUrl = '/api/settings'
async getSettings() {
try {
const response = await fetch(this.baseUrl, {
headers: {
'Authorization': `Bearer ${this.getSessionToken()}`,
'Accept': 'application/json'
}
})
if (!response.ok) {
throw new Error('Failed to fetch settings')
}
return await response.json()
} catch (error) {
console.error('Error fetching settings:', error)
throw error
}
}
async updateSettings(settings: Partial<UserSettings>) {
try {
const response = await fetch(this.baseUrl, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${this.getSessionToken()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(settings)
})
if (!response.ok) {
throw new Error('Failed to update settings')
}
return await response.json()
} catch (error) {
console.error('Error updating settings:', error)
throw error
}
}
async updateNotificationSettings(notifications: NotificationSettings) {
return this.updateSettings({ notifications })
}
async updatePrivacySettings(privacy: PrivacySettings) {
return this.updateSettings({ privacy })
}
async updatePreferences(preferences: UserPreferences) {
return this.updateSettings({ preferences })
}
async resetSettings(sections: string[] = []) {
try {
const response = await fetch(`${this.baseUrl}/reset`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.getSessionToken()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
sections,
confirmReset: true
})
})
if (!response.ok) {
throw new Error('Failed to reset settings')
}
return await response.json()
} catch (error) {
console.error('Error resetting settings:', error)
throw error
}
}
private getSessionToken(): string {
return localStorage.getItem('sessionToken') || ''
}
}
// Type definitions
interface UserSettings {
preferences: UserPreferences
notifications: NotificationSettings
privacy: PrivacySettings
security: SecuritySettings
content: ContentSettings
accessibility: AccessibilitySettings
}
interface UserPreferences {
language: string
theme: 'light' | 'dark' | 'auto'
timezone: string
dateFormat: string
timeFormat: '12h' | '24h'
}
interface NotificationSettings {
email: EmailNotifications
push: PushNotifications
sms: SMSNotifications
inApp: InAppNotifications
}
// Usage examples
const settingsService = new SettingsService()
// Get current settings
const settings = await settingsService.getSettings()
// Update theme preference
await settingsService.updatePreferences({
theme: 'dark',
language: 'uk'
})
// Disable email notifications
await settingsService.updateNotificationSettings({
email: { enabled: false }
})
// Update privacy settings
await settingsService.updatePrivacySettings({
profileVisibility: 'private',
showEmail: false
})
React Settings Componentβ
import { useState, useEffect } from 'react'
import { useSession } from 'next-auth/react'
interface SettingsPageProps {
section?: 'preferences' | 'notifications' | 'privacy' | 'security'
}
export function SettingsPage({ section = 'preferences' }: SettingsPageProps) {
const { data: session } = useSession()
const [settings, setSettings] = useState<UserSettings | null>(null)
const [loading, setLoading] = useState(true)
const [saving, setSaving] = useState(false)
const [message, setMessage] = useState('')
useEffect(() => {
if (session?.user) {
fetchSettings()
}
}, [session])
const fetchSettings = async () => {
try {
setLoading(true)
const response = await fetch('/api/settings')
if (!response.ok) {
throw new Error('Failed to fetch settings')
}
const settingsData = await response.json()
setSettings(settingsData)
} catch (error) {
setMessage(`Error: ${error.message}`)
} finally {
setLoading(false)
}
}
const updateSettings = async (updates: Partial<UserSettings>) => {
try {
setSaving(true)
setMessage('')
const response = await fetch('/api/settings', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates)
})
if (!response.ok) {
throw new Error('Failed to update settings')
}
await fetchSettings() // Refresh settings
setMessage('Settings updated successfully')
} catch (error) {
setMessage(`Error: ${error.message}`)
} finally {
setSaving(false)
}
}
const handlePreferenceChange = (key: string, value: any) => {
if (!settings) return
const updatedPreferences = {
...settings.preferences,
[key]: value
}
updateSettings({ preferences: updatedPreferences })
}
const handleNotificationChange = (category: string, key: string, value: any) => {
if (!settings) return
const updatedNotifications = {
...settings.notifications,
[category]: {
...settings.notifications[category],
[key]: value
}
}
updateSettings({ notifications: updatedNotifications })
}
if (!session?.user) {
return <div>Please sign in to access settings</div>
}
if (loading) return <div>Loading settings...</div>
if (!settings) return <div>Failed to load settings</div>
return (
<div className="settings-page">
<h1>Settings</h1>
{message && (
<div className={`message ${message.includes('Error') ? 'error' : 'success'}`}>
{message}
</div>
)}
<div className="settings-tabs">
<button
className={section === 'preferences' ? 'active' : ''}
onClick={() => setSection('preferences')}
>
Preferences
</button>
<button
className={section === 'notifications' ? 'active' : ''}
onClick={() => setSection('notifications')}
>
Notifications
</button>
<button
className={section === 'privacy' ? 'active' : ''}
onClick={() => setSection('privacy')}
>
Privacy
</button>
</div>
<div className="settings-content">
{section === 'preferences' && (
<PreferencesSection
preferences={settings.preferences}
onChange={handlePreferenceChange}
disabled={saving}
/>
)}
{section === 'notifications' && (
<NotificationsSection
notifications={settings.notifications}
onChange={handleNotificationChange}
disabled={saving}
/>
)}
{section === 'privacy' && (
<PrivacySection
privacy={settings.privacy}
onChange={(updates) => updateSettings({ privacy: updates })}
disabled={saving}
/>
)}
</div>
</div>
)
}
cURL Examplesβ
# Get user settings
curl -X GET "https://ring.ck.ua/api/settings" \
-H "Authorization: Bearer session-token" \
-H "Accept: application/json"
# Update preferences
curl -X PUT "https://ring.ck.ua/api/settings" \
-H "Authorization: Bearer session-token" \
-H "Content-Type: application/json" \
-d '{
"preferences": {
"language": "uk",
"theme": "dark"
}
}'
# Update notification settings
curl -X PUT "https://ring.ck.ua/api/settings" \
-H "Authorization: Bearer session-token" \
-H "Content-Type: application/json" \
-d '{
"notifications": {
"email": {
"enabled": false
},
"push": {
"enabled": true,
"types": {
"messages": true,
"opportunities": false
}
}
}
}'
# Reset settings
curl -X POST "https://ring.ck.ua/api/settings/reset" \
-H "Authorization: Bearer session-token" \
-H "Content-Type: application/json" \
-d '{
"sections": ["notifications"],
"confirmReset": true
}'
Settings Categoriesβ
Preferencesβ
- Language: Interface language (en, uk)
- Theme: Visual theme (light, dark, auto)
- Timezone: User timezone for date/time display
- Date Format: Date display format
- Time Format: 12-hour or 24-hour time
Notificationsβ
- Email: Email notification preferences and frequency
- Push: Browser/mobile push notifications
- SMS: SMS notifications for critical events
- In-App: Application notification settings
Privacyβ
- Profile Visibility: Public, private, or members-only
- Information Sharing: Control what information is visible
- Communication: Who can contact the user
- Search: Whether profile appears in search results
Securityβ
- Two-Factor Authentication: 2FA settings
- Session Management: Session timeout and device tracking
- Login Notifications: Alerts for new logins
- Device Management: Trusted devices
Contentβ
- Media Settings: Autoplay and image display preferences
- Language Filters: Content language preferences
- Content Filtering: NSFW and content type filters
Accessibilityβ
- Visual: High contrast, large text options
- Motion: Reduced motion preferences
- Screen Reader: Screen reader compatibility
Error Handlingβ
Validation Errors (400)β
{
"error": "VALIDATION_ERROR",
"message": "Invalid settings data",
"details": [
{
"field": "preferences.language",
"message": "Language must be 'en' or 'uk'"
},
{
"field": "notifications.email.frequency",
"message": "Frequency must be 'immediate', 'daily', or 'weekly'"
}
]
}
Unauthorized (401)β
{
"error": "UNAUTHORIZED",
"message": "Authentication required"
}
Settings Not Found (404)β
{
"error": "SETTINGS_NOT_FOUND",
"message": "User settings not found"
}
Default Settingsβ
New User Defaultsβ
{
"preferences": {
"language": "en",
"theme": "light",
"timezone": "UTC",
"dateFormat": "MM/DD/YYYY",
"timeFormat": "12h"
},
"notifications": {
"email": {
"enabled": true,
"frequency": "immediate",
"types": {
"news": true,
"opportunities": true,
"messages": true,
"systemUpdates": true,
"marketing": false
}
},
"push": {
"enabled": true,
"types": {
"messages": true,
"opportunities": true,
"news": false,
"systemUpdates": true
}
},
"sms": {
"enabled": false,
"types": {
"security": true,
"urgent": false
}
}
},
"privacy": {
"profileVisibility": "public",
"showEmail": false,
"showWalletAddress": false,
"showLocation": true,
"allowDirectMessages": true,
"searchableProfile": true
}
}
Related Endpointsβ
/api/profile
- User profile management/api/notifications/preferences
- Notification preferences/api/auth/[...nextauth]
- Authentication settings
Testingβ
Unit Testsβ
describe('Settings API', () => {
test('should get user settings', async () => {
const response = await request(app)
.get('/api/settings')
.set('Authorization', `Bearer ${validToken}`)
.expect(200)
expect(response.body).toHaveProperty('preferences')
expect(response.body).toHaveProperty('notifications')
expect(response.body).toHaveProperty('privacy')
})
test('should update settings', async () => {
const updates = {
preferences: { theme: 'dark' },
notifications: { email: { enabled: false } }
}
const response = await request(app)
.put('/api/settings')
.set('Authorization', `Bearer ${validToken}`)
.send(updates)
.expect(200)
expect(response.body.success).toBe(true)
})
test('should validate settings data', async () => {
const invalidData = {
preferences: { language: 'invalid' }
}
await request(app)
.put('/api/settings')
.set('Authorization', `Bearer ${validToken}`)
.send(invalidData)
.expect(400)
})
})
Troubleshootingβ
Common Issuesβ
Issue: "Settings not found" Solution: Settings are created automatically on first access
Issue: "Invalid language code" Solution: Use supported language codes (en, uk)
Issue: "Notification update failed" Solution: Check notification type and frequency values
Issue: "Privacy settings not saving" Solution: Ensure all privacy fields have valid boolean values