12 KiB
Users API
Endpoints for user management, profile settings, and preferences.
List Users
Get a paginated list of all users.
Endpoint: GET /api/users
Authentication: Required
Permissions: users.read
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer | 1 |
Page number |
limit |
integer | 50 |
Items per page |
Response: 200 OK
{
"users": [
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"roleId": 2,
"roleName": "user",
"isActive": true,
"createdAt": "2024-01-15T10:30:00Z",
"lastLoginAt": "2024-03-20T14:25:00Z"
},
{
"id": 2,
"username": "jane_admin",
"email": "jane@example.com",
"roleId": 1,
"roleName": "admin",
"isActive": true,
"createdAt": "2024-01-10T08:00:00Z",
"lastLoginAt": "2024-03-21T09:15:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 2,
"totalPages": 1
}
}
Examples:
curl http://localhost:3100/api/users \
-H "Authorization: Bearer <token>"
const { data } = await axios.get('http://localhost:3100/api/users', {
headers: { Authorization: `Bearer ${token}` },
params: { page: 1, limit: 20 }
});
Get User
Get details of a specific user by ID.
Endpoint: GET /api/users/:id
Authentication: Required
Permissions: users.read
URL Parameters:
id(integer, required) - User ID
Response: 200 OK
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"roleId": 2,
"roleName": "user",
"isActive": true,
"createdAt": "2024-01-15T10:30:00Z",
"lastLoginAt": "2024-03-20T14:25:00Z",
"permissions": [
"games.play",
"games.read",
"playlists.create",
"playlists.update",
"playlists.delete"
]
}
Error Responses:
404 Not Found- User not found
Examples:
curl http://localhost:3100/api/users/1 \
-H "Authorization: Bearer <token>"
const userId = 1;
const { data: user } = await axios.get(
`http://localhost:3100/api/users/${userId}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
Create User
Create a new user account (admin only).
Endpoint: POST /api/users
Authentication: Required
Permissions: users.create
Request Body:
{
"username": "string (min: 3, max: 50)",
"email": "string (valid email)",
"password": "string (min: 6)",
"roleId": "integer (positive)",
"isActive": "boolean (optional, default: true)"
}
Response: 201 Created
{
"id": 3,
"username": "new_user",
"email": "newuser@example.com",
"roleId": 2,
"roleName": "user",
"isActive": true,
"createdAt": "2024-03-21T10:00:00Z",
"lastLoginAt": null
}
Error Responses:
400 Bad Request- Validation error409 Conflict- Username or email already exists
Examples:
curl -X POST http://localhost:3100/api/users \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"username": "new_user",
"email": "newuser@example.com",
"password": "securepass123",
"roleId": 2,
"isActive": true
}'
const newUser = await axios.post(
'http://localhost:3100/api/users',
{
username: 'new_user',
email: 'newuser@example.com',
password: 'securepass123',
roleId: 2,
isActive: true
},
{ headers: { Authorization: `Bearer ${token}` } }
);
Update User
Update an existing user's information.
Endpoint: PATCH /api/users/:id
Authentication: Required
Permissions: users.update
URL Parameters:
id(integer, required) - User ID
Request Body:
All fields are optional:
{
"email": "string (valid email, optional)",
"roleId": "integer (positive, optional)",
"isActive": "boolean (optional)"
}
Response: 200 OK
{
"id": 1,
"username": "john_doe",
"email": "newemail@example.com",
"roleId": 3,
"roleName": "moderator",
"isActive": true,
"createdAt": "2024-01-15T10:30:00Z",
"lastLoginAt": "2024-03-20T14:25:00Z"
}
Error Responses:
400 Bad Request- Validation error404 Not Found- User not found409 Conflict- Email already exists
Examples:
curl -X PATCH http://localhost:3100/api/users/1 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"email": "newemail@example.com",
"roleId": 3
}'
const userId = 1;
const { data: updatedUser } = await axios.patch(
`http://localhost:3100/api/users/${userId}`,
{
email: 'newemail@example.com',
roleId: 3
},
{ headers: { Authorization: `Bearer ${token}` } }
);
Delete User
Delete a user account. Cannot delete the last admin user.
Endpoint: DELETE /api/users/:id
Authentication: Required
Permissions: users.delete
URL Parameters:
id(integer, required) - User ID
Response: 200 OK
{
"success": true,
"message": "User deleted successfully"
}
Error Responses:
400 Bad Request- Cannot delete last admin404 Not Found- User not found
Examples:
curl -X DELETE http://localhost:3100/api/users/3 \
-H "Authorization: Bearer <token>"
const userId = 3;
await axios.delete(
`http://localhost:3100/api/users/${userId}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
Change Password
Change a user's password. Users can change their own password, or admins can change any password.
Endpoint: POST /api/users/:id/change-password
Authentication: Required
Permissions: Own password (any user) or users.update (admin)
URL Parameters:
id(integer, required) - User ID
Request Body:
{
"currentPassword": "string (min: 6)",
"newPassword": "string (min: 6)"
}
Response: 200 OK
{
"success": true,
"message": "Password changed successfully"
}
Error Responses:
400 Bad Request- Validation error401 Unauthorized- Current password incorrect403 Forbidden- Insufficient permissions (not own account or admin)404 Not Found- User not found
Examples:
curl -X POST http://localhost:3100/api/users/1/change-password \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"currentPassword": "oldpassword123",
"newPassword": "newpassword456"
}'
const userId = 1;
await axios.post(
`http://localhost:3100/api/users/${userId}/change-password`,
{
currentPassword: 'oldpassword123',
newPassword: 'newpassword456'
},
{ headers: { Authorization: `Bearer ${token}` } }
);
Get User Settings
Get all settings for the current user.
Endpoint: GET /api/users/me/settings
Authentication: Required
Response: 200 OK
{
"theme_mode": "dark",
"primary_color": "blue",
"game_view_mode": "grid",
"games_per_page": "50",
"auto_play_next": "false",
"show_extreme_content": "false"
}
Note: Settings are stored as key-value pairs (string values). Convert as needed in your application.
Examples:
curl http://localhost:3100/api/users/me/settings \
-H "Authorization: Bearer <token>"
const { data: settings } = await axios.get(
'http://localhost:3100/api/users/me/settings',
{ headers: { Authorization: `Bearer ${token}` } }
);
// Convert to typed values
const userSettings = {
themeMode: settings.theme_mode,
primaryColor: settings.primary_color,
gamesPerPage: parseInt(settings.games_per_page),
autoPlayNext: settings.auto_play_next === 'true'
};
Update User Settings
Update multiple settings for the current user.
Endpoint: PATCH /api/users/me/settings
Authentication: Required
Request Body:
Key-value pairs of settings to update:
{
"theme_mode": "dark",
"primary_color": "purple",
"games_per_page": "100",
"show_extreme_content": "true"
}
Response: 200 OK
{
"theme_mode": "dark",
"primary_color": "purple",
"game_view_mode": "grid",
"games_per_page": "100",
"auto_play_next": "false",
"show_extreme_content": "true"
}
Examples:
curl -X PATCH http://localhost:3100/api/users/me/settings \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"theme_mode": "dark",
"primary_color": "purple",
"games_per_page": "100"
}'
await axios.patch(
'http://localhost:3100/api/users/me/settings',
{
theme_mode: 'dark',
primary_color: 'purple',
games_per_page: '100',
show_extreme_content: 'true'
},
{ headers: { Authorization: `Bearer ${token}` } }
);
Common User Settings
| Setting Key | Type | Default | Description |
|---|---|---|---|
theme_mode |
enum | dark |
Theme mode: "light", "dark", "system" |
primary_color |
string | blue |
Primary color name |
game_view_mode |
enum | grid |
View mode: "grid", "list" |
games_per_page |
string | 50 |
Games per page (store as string) |
auto_play_next |
boolean | false |
Auto-play next game in playlist |
show_extreme_content |
boolean | false |
Show extreme content in search |
show_broken_games |
boolean | false |
Show broken games in search |
default_library |
enum | - | Default library: "arcade", "theatre" |
player_scale_mode |
enum | showall |
Ruffle scale mode |
enable_sound |
boolean | true |
Enable game sound |
All setting values are stored as strings in the database. Convert to appropriate types in your application.
Deprecated Endpoints
The following endpoints are deprecated but still functional for backward compatibility:
GET /api/users/me/theme
Deprecated: Use GET /api/users/me/settings instead.
Returns theme settings in legacy format:
{
"themeColor": "blue-500",
"surfaceColor": "slate-700"
}
PATCH /api/users/me/theme
Deprecated: Use PATCH /api/users/me/settings with theme_mode and primary_color keys.
GET /api/users/me/settings/theme
Deprecated: Use GET /api/users/me/settings instead.
PATCH /api/users/me/settings/theme
Deprecated: Use PATCH /api/users/me/settings instead.
User Management Best Practices
Password Security
- Enforce minimum password length (6+ characters, recommend 12+)
- Hash passwords with bcrypt (automatically handled by backend)
- Never log or display passwords
- Use HTTPS for all password-related requests
Role Assignment
- Use role IDs from
GET /api/rolesendpoint - Default new users to "user" role (ID: 2)
- Assign "admin" role carefully (ID: 1)
- Check permissions before allowing actions
Account Lifecycle
- Create: Use
POST /api/userswith strong initial password - Update: Use
PATCH /api/users/:idfor metadata changes - Password: Use
POST /api/users/:id/change-passwordseparately - Deactivate: Set
isActive: falseinstead of deleting - Delete: Use
DELETE /api/users/:idonly when necessary
Settings Management
- Store all settings as strings (convert types in application)
- Update multiple settings in single request for efficiency
- Provide sensible defaults for missing settings
- Validate setting values on client-side before sending
Self-Service vs Admin Actions
Users can:
- View own profile (
GET /api/auth/me) - Change own password (
POST /api/users/:id/change-password) - Update own settings (
PATCH /api/users/me/settings)
Admins can:
- View all users (
GET /api/users) - Create users (
POST /api/users) - Update any user (
PATCH /api/users/:id) - Delete users (
DELETE /api/users/:id) - Change any password (with admin
users.updatepermission)