tududi/backend/modules/users/controller.js
Chris 542be2c1e9
Fix bug 366 (#764)
* Optimize DB

* Clean up names

* fixup! Clean up names

* fixup! fixup! Clean up names
2026-01-07 18:18:07 +02:00

291 lines
7.2 KiB
JavaScript

'use strict';
const usersService = require('./service');
const { UnauthorizedError } = require('../../shared/errors');
const { getAuthenticatedUserId } = require('../../utils/request-utils');
const { logError } = require('../../services/logService');
const fs = require('fs').promises;
/**
* Get authenticated user ID or throw UnauthorizedError.
*/
function requireUserId(req) {
const userId = getAuthenticatedUserId(req);
if (!userId) {
throw new UnauthorizedError('Authentication required');
}
return userId;
}
/**
* Users controller - handles HTTP requests/responses.
*/
const usersController = {
/**
* GET /api/users
* List all users.
*/
async list(req, res, next) {
try {
const users = await usersService.listUsers();
res.json(users);
} catch (error) {
next(error);
}
},
/**
* GET /api/profile
* Get current user profile.
*/
async getProfile(req, res, next) {
try {
const userId = requireUserId(req);
const profile = await usersService.getProfile(userId);
res.json(profile);
} catch (error) {
next(error);
}
},
/**
* PATCH /api/profile
* Update current user profile.
*/
async updateProfile(req, res, next) {
try {
const userId = requireUserId(req);
const profile = await usersService.updateProfile(userId, req.body);
res.json(profile);
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/avatar
* Upload avatar.
*/
async uploadAvatar(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.uploadAvatar(userId, req.file);
res.json(result);
} catch (error) {
if (req.file) {
await fs.unlink(req.file.path).catch(() => {});
}
next(error);
}
},
/**
* DELETE /api/profile/avatar
* Delete avatar.
*/
async deleteAvatar(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.deleteAvatar(userId);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/change-password
* Change password.
*/
async changePassword(req, res, next) {
try {
const userId = requireUserId(req);
const { currentPassword, newPassword } = req.body;
const result = await usersService.changePassword(
userId,
currentPassword,
newPassword
);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* GET /api/profile/api-keys
* List API keys.
*/
async listApiKeys(req, res, next) {
try {
const userId = requireUserId(req);
const keys = await usersService.listApiKeys(userId);
res.json(keys);
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/api-keys
* Create API key.
*/
async createApiKey(req, res, next) {
try {
const userId = requireUserId(req);
const { name, expires_at } = req.body || {};
const result = await usersService.createApiKey(
userId,
name,
expires_at
);
res.status(201).json(result);
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/api-keys/:id/revoke
* Revoke API key.
*/
async revokeApiKey(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.revokeApiKey(
userId,
req.params.id
);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* DELETE /api/profile/api-keys/:id
* Delete API key.
*/
async deleteApiKey(req, res, next) {
try {
const userId = requireUserId(req);
await usersService.deleteApiKey(userId, req.params.id);
res.status(204).send();
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/task-summary/toggle
* Toggle task summary.
*/
async toggleTaskSummary(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.toggleTaskSummary(userId);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/task-summary/frequency
* Update task summary frequency.
*/
async updateTaskSummaryFrequency(req, res, next) {
try {
const userId = requireUserId(req);
const { frequency } = req.body;
const result = await usersService.updateTaskSummaryFrequency(
userId,
frequency
);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* POST /api/profile/task-summary/send-now
* Send task summary now.
*/
async sendTaskSummaryNow(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.sendTaskSummaryNow(userId);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* GET /api/profile/task-summary/status
* Get task summary status.
*/
async getTaskSummaryStatus(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.getTaskSummaryStatus(userId);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* PUT /api/profile/today-settings
* Update today settings.
*/
async updateTodaySettings(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.updateTodaySettings(
userId,
req.body
);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* PUT /api/profile/sidebar-settings
* Update sidebar settings.
*/
async updateSidebarSettings(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.updateSidebarSettings(
userId,
req.body
);
res.json(result);
} catch (error) {
next(error);
}
},
/**
* PUT /api/profile/ui-settings
* Update UI settings.
*/
async updateUiSettings(req, res, next) {
try {
const userId = requireUserId(req);
const result = await usersService.updateUiSettings(
userId,
req.body
);
res.json(result);
} catch (error) {
next(error);
}
},
};
module.exports = usersController;