Improve centralized error handling
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { db } from '../config/database.js';
|
||||
import { users } from '../db/schema.js';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { users, userEmailAccounts, emailAccounts } from '../db/schema.js';
|
||||
import { eq, inArray } from 'drizzle-orm';
|
||||
import { hashPassword, generateTempPassword } from '../utils/password.js';
|
||||
import { logUserCreation, logRoleChange } from '../services/audit.service.js';
|
||||
import { formatErrorResponse, ConflictError, NotFoundError } from '../utils/errors.js';
|
||||
import { ConflictError, NotFoundError } from '../utils/errors.js';
|
||||
import * as emailAccountService from '../services/email-account.service.js';
|
||||
|
||||
/**
|
||||
@@ -11,7 +11,7 @@ import * as emailAccountService from '../services/email-account.service.js';
|
||||
* Ak je poskytnutý email a emailPassword, automaticky sa fetchne JMAP account ID
|
||||
* POST /api/admin/users
|
||||
*/
|
||||
export const createUser = async (req, res) => {
|
||||
export const createUser = async (req, res, next) => {
|
||||
const { username, email, emailPassword, firstName, lastName, role } = req.body;
|
||||
const adminId = req.userId;
|
||||
const ipAddress = req.ip || req.connection.remoteAddress;
|
||||
@@ -100,8 +100,7 @@ export const createUser = async (req, res) => {
|
||||
: 'Používateľ úspešne vytvorený. Email môže byť nastavený neskôr.',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,7 +108,7 @@ export const createUser = async (req, res) => {
|
||||
* Zoznam všetkých userov (admin only)
|
||||
* GET /api/admin/users
|
||||
*/
|
||||
export const getAllUsers = async (req, res) => {
|
||||
export const getAllUsers = async (req, res, next) => {
|
||||
try {
|
||||
const allUsers = await db
|
||||
.select({
|
||||
@@ -130,8 +129,7 @@ export const getAllUsers = async (req, res) => {
|
||||
data: allUsers,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,7 +137,7 @@ export const getAllUsers = async (req, res) => {
|
||||
* Získanie konkrétneho usera (admin only)
|
||||
* GET /api/admin/users/:userId
|
||||
*/
|
||||
export const getUser = async (req, res) => {
|
||||
export const getUser = async (req, res, next) => {
|
||||
const { userId } = req.params;
|
||||
|
||||
try {
|
||||
@@ -176,8 +174,7 @@ export const getUser = async (req, res) => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -185,7 +182,7 @@ export const getUser = async (req, res) => {
|
||||
* Zmena role usera (admin only)
|
||||
* PATCH /api/admin/users/:userId/role
|
||||
*/
|
||||
export const changeUserRole = async (req, res) => {
|
||||
export const changeUserRole = async (req, res, next) => {
|
||||
const { userId } = req.params;
|
||||
const { role } = req.body;
|
||||
const adminId = req.userId;
|
||||
@@ -228,8 +225,7 @@ export const changeUserRole = async (req, res) => {
|
||||
message: 'Rola používateľa bola zmenená',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -237,7 +233,7 @@ export const changeUserRole = async (req, res) => {
|
||||
* Zmazanie usera (admin only)
|
||||
* DELETE /api/admin/users/:userId
|
||||
*/
|
||||
export const deleteUser = async (req, res) => {
|
||||
export const deleteUser = async (req, res, next) => {
|
||||
const { userId } = req.params;
|
||||
|
||||
try {
|
||||
@@ -263,14 +259,38 @@ export const deleteUser = async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Get user's email account IDs before deletion
|
||||
const userEmailAccountLinks = await db
|
||||
.select({ emailAccountId: userEmailAccounts.emailAccountId })
|
||||
.from(userEmailAccounts)
|
||||
.where(eq(userEmailAccounts.userId, userId));
|
||||
|
||||
const emailAccountIds = userEmailAccountLinks.map(link => link.emailAccountId);
|
||||
|
||||
// Delete user (cascades userEmailAccounts links)
|
||||
await db.delete(users).where(eq(users.id, userId));
|
||||
|
||||
// Delete orphaned email accounts (no users linked)
|
||||
// This will cascade delete contacts and emails
|
||||
let deletedEmailAccounts = 0;
|
||||
for (const emailAccountId of emailAccountIds) {
|
||||
const [remainingLinks] = await db
|
||||
.select({ count: db.$count(userEmailAccounts) })
|
||||
.from(userEmailAccounts)
|
||||
.where(eq(userEmailAccounts.emailAccountId, emailAccountId));
|
||||
|
||||
if (remainingLinks.count === 0) {
|
||||
await db.delete(emailAccounts).where(eq(emailAccounts.id, emailAccountId));
|
||||
deletedEmailAccounts++;
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Používateľ bol zmazaný',
|
||||
deletedEmailAccounts,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,13 +4,12 @@ import {
|
||||
logPasswordChange,
|
||||
logEmailLink,
|
||||
} from '../services/audit.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* KROK 1: Login s temporary password
|
||||
* POST /api/auth/login
|
||||
*/
|
||||
export const login = async (req, res) => {
|
||||
export const login = async (req, res, next) => {
|
||||
const { username, password } = req.body;
|
||||
const ipAddress = req.ip || req.connection.remoteAddress;
|
||||
const userAgent = req.headers['user-agent'];
|
||||
@@ -55,8 +54,7 @@ export const login = async (req, res) => {
|
||||
// Log failed login
|
||||
await logLoginAttempt(username, false, ipAddress, userAgent, error.message);
|
||||
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,7 +63,7 @@ export const login = async (req, res) => {
|
||||
* POST /api/auth/set-password
|
||||
* Requires: authentication
|
||||
*/
|
||||
export const setPassword = async (req, res) => {
|
||||
export const setPassword = async (req, res, next) => {
|
||||
const { newPassword } = req.body;
|
||||
const userId = req.userId;
|
||||
const ipAddress = req.ip || req.connection.remoteAddress;
|
||||
@@ -83,8 +81,7 @@ export const setPassword = async (req, res) => {
|
||||
message: 'Heslo úspešne nastavené',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,7 +90,7 @@ export const setPassword = async (req, res) => {
|
||||
* POST /api/auth/link-email
|
||||
* Requires: authentication
|
||||
*/
|
||||
export const linkEmail = async (req, res) => {
|
||||
export const linkEmail = async (req, res, next) => {
|
||||
const { email, emailPassword } = req.body;
|
||||
const userId = req.userId;
|
||||
const ipAddress = req.ip || req.connection.remoteAddress;
|
||||
@@ -114,8 +111,7 @@ export const linkEmail = async (req, res) => {
|
||||
message: 'Email účet úspešne pripojený a overený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -124,7 +120,7 @@ export const linkEmail = async (req, res) => {
|
||||
* POST /api/auth/skip-email
|
||||
* Requires: authentication
|
||||
*/
|
||||
export const skipEmail = async (req, res) => {
|
||||
export const skipEmail = async (req, res, next) => {
|
||||
const userId = req.userId;
|
||||
|
||||
try {
|
||||
@@ -136,8 +132,7 @@ export const skipEmail = async (req, res) => {
|
||||
message: 'Email setup preskočený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -146,7 +141,7 @@ export const skipEmail = async (req, res) => {
|
||||
* POST /api/auth/logout
|
||||
* Requires: authentication
|
||||
*/
|
||||
export const logout = async (req, res) => {
|
||||
export const logout = async (req, res, next) => {
|
||||
try {
|
||||
const result = await authService.logout();
|
||||
|
||||
@@ -159,8 +154,7 @@ export const logout = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -169,7 +163,7 @@ export const logout = async (req, res) => {
|
||||
* GET /api/auth/session
|
||||
* Requires: authentication
|
||||
*/
|
||||
export const getSession = async (req, res) => {
|
||||
export const getSession = async (req, res, next) => {
|
||||
try {
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
@@ -179,8 +173,7 @@ export const getSession = async (req, res) => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -189,7 +182,7 @@ export const getSession = async (req, res) => {
|
||||
* GET /api/auth/me
|
||||
* Requires: authentication
|
||||
*/
|
||||
export const getMe = async (req, res) => {
|
||||
export const getMe = async (req, res, next) => {
|
||||
try {
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
@@ -198,7 +191,6 @@ export const getMe = async (req, res) => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,13 +2,12 @@ import * as companyService from '../services/company.service.js';
|
||||
import * as noteService from '../services/note.service.js';
|
||||
import * as companyReminderService from '../services/company-reminder.service.js';
|
||||
import * as companyEmailService from '../services/company-email.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Get all companies
|
||||
* GET /api/companies?search=query
|
||||
*/
|
||||
export const getAllCompanies = async (req, res) => {
|
||||
export const getAllCompanies = async (req, res, next) => {
|
||||
try {
|
||||
const { search } = req.query;
|
||||
|
||||
@@ -20,8 +19,7 @@ export const getAllCompanies = async (req, res) => {
|
||||
data: companies,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,7 +27,7 @@ export const getAllCompanies = async (req, res) => {
|
||||
* Get company by ID
|
||||
* GET /api/companies/:companyId
|
||||
*/
|
||||
export const getCompanyById = async (req, res) => {
|
||||
export const getCompanyById = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
|
||||
@@ -40,8 +38,7 @@ export const getCompanyById = async (req, res) => {
|
||||
data: company,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,7 +46,7 @@ export const getCompanyById = async (req, res) => {
|
||||
* Get company email threads aggregated across user's email accounts
|
||||
* GET /api/companies/:companyId/email-threads
|
||||
*/
|
||||
export const getCompanyEmailThreads = async (req, res) => {
|
||||
export const getCompanyEmailThreads = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { companyId } = req.params;
|
||||
@@ -64,8 +61,7 @@ export const getCompanyEmailThreads = async (req, res) => {
|
||||
data: result,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,7 +69,7 @@ export const getCompanyEmailThreads = async (req, res) => {
|
||||
* Get unread email counts grouped by company for current user
|
||||
* GET /api/companies/email-unread
|
||||
*/
|
||||
export const getCompanyUnreadCounts = async (req, res) => {
|
||||
export const getCompanyUnreadCounts = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const counts = await companyEmailService.getCompanyUnreadCounts(userId);
|
||||
@@ -83,8 +79,7 @@ export const getCompanyUnreadCounts = async (req, res) => {
|
||||
data: counts,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +87,7 @@ export const getCompanyUnreadCounts = async (req, res) => {
|
||||
* Get company with relations (projects, todos, notes)
|
||||
* GET /api/companies/:companyId/details
|
||||
*/
|
||||
export const getCompanyWithRelations = async (req, res) => {
|
||||
export const getCompanyWithRelations = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
|
||||
@@ -103,8 +98,7 @@ export const getCompanyWithRelations = async (req, res) => {
|
||||
data: company,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,7 +107,7 @@ export const getCompanyWithRelations = async (req, res) => {
|
||||
* POST /api/companies
|
||||
* Body: { name, description, address, city, country, phone, email, website }
|
||||
*/
|
||||
export const createCompany = async (req, res) => {
|
||||
export const createCompany = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const data = req.body;
|
||||
@@ -126,8 +120,7 @@ export const createCompany = async (req, res) => {
|
||||
message: 'Firma bola vytvorená',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -136,7 +129,7 @@ export const createCompany = async (req, res) => {
|
||||
* PATCH /api/companies/:companyId
|
||||
* Body: { name, description, address, city, country, phone, email, website }
|
||||
*/
|
||||
export const updateCompany = async (req, res) => {
|
||||
export const updateCompany = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
const data = req.body;
|
||||
@@ -149,8 +142,7 @@ export const updateCompany = async (req, res) => {
|
||||
message: 'Firma bola aktualizovaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,7 +150,7 @@ export const updateCompany = async (req, res) => {
|
||||
* Delete company
|
||||
* DELETE /api/companies/:companyId
|
||||
*/
|
||||
export const deleteCompany = async (req, res) => {
|
||||
export const deleteCompany = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
|
||||
@@ -169,8 +161,7 @@ export const deleteCompany = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,7 +169,7 @@ export const deleteCompany = async (req, res) => {
|
||||
* Get company notes
|
||||
* GET /api/companies/:companyId/notes
|
||||
*/
|
||||
export const getCompanyNotes = async (req, res) => {
|
||||
export const getCompanyNotes = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
|
||||
@@ -190,8 +181,7 @@ export const getCompanyNotes = async (req, res) => {
|
||||
data: notes,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -199,7 +189,7 @@ export const getCompanyNotes = async (req, res) => {
|
||||
* Add company note
|
||||
* POST /api/companies/:companyId/notes
|
||||
*/
|
||||
export const addCompanyNote = async (req, res) => {
|
||||
export const addCompanyNote = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { companyId } = req.params;
|
||||
@@ -216,8 +206,7 @@ export const addCompanyNote = async (req, res) => {
|
||||
message: 'Poznámka bola pridaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,7 +214,7 @@ export const addCompanyNote = async (req, res) => {
|
||||
* Update company note
|
||||
* PATCH /api/companies/:companyId/notes/:noteId
|
||||
*/
|
||||
export const updateCompanyNote = async (req, res) => {
|
||||
export const updateCompanyNote = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
const { content } = req.body;
|
||||
@@ -240,8 +229,7 @@ export const updateCompanyNote = async (req, res) => {
|
||||
message: 'Poznámka bola aktualizovaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -249,7 +237,7 @@ export const updateCompanyNote = async (req, res) => {
|
||||
* Delete company note
|
||||
* DELETE /api/companies/:companyId/notes/:noteId
|
||||
*/
|
||||
export const deleteCompanyNote = async (req, res) => {
|
||||
export const deleteCompanyNote = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
|
||||
@@ -260,8 +248,7 @@ export const deleteCompanyNote = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -269,7 +256,7 @@ export const deleteCompanyNote = async (req, res) => {
|
||||
* Company reminders
|
||||
* CRUD for /api/companies/:companyId/reminders
|
||||
*/
|
||||
export const getCompanyReminders = async (req, res) => {
|
||||
export const getCompanyReminders = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
|
||||
@@ -281,12 +268,11 @@ export const getCompanyReminders = async (req, res) => {
|
||||
data: reminders,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const createCompanyReminder = async (req, res) => {
|
||||
export const createCompanyReminder = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId } = req.params;
|
||||
const { description, dueDate, isChecked } = req.body;
|
||||
@@ -299,12 +285,11 @@ export const createCompanyReminder = async (req, res) => {
|
||||
message: 'Reminder bol pridaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const updateCompanyReminder = async (req, res) => {
|
||||
export const updateCompanyReminder = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId, reminderId } = req.params;
|
||||
const { description, dueDate, isChecked } = req.body;
|
||||
@@ -317,12 +302,11 @@ export const updateCompanyReminder = async (req, res) => {
|
||||
message: 'Reminder bol aktualizovaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteCompanyReminder = async (req, res) => {
|
||||
export const deleteCompanyReminder = async (req, res, next) => {
|
||||
try {
|
||||
const { companyId, reminderId } = req.params;
|
||||
|
||||
@@ -333,12 +317,11 @@ export const deleteCompanyReminder = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const getReminderSummary = async (_req, res) => {
|
||||
export const getReminderSummary = async (_req, res, next) => {
|
||||
try {
|
||||
const summary = await companyReminderService.getReminderSummary();
|
||||
res.status(200).json({
|
||||
@@ -346,12 +329,11 @@ export const getReminderSummary = async (_req, res) => {
|
||||
data: summary,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const getReminderCountsByCompany = async (_req, res) => {
|
||||
export const getReminderCountsByCompany = async (_req, res, next) => {
|
||||
try {
|
||||
const counts = await companyReminderService.getReminderCountsByCompany();
|
||||
res.status(200).json({
|
||||
@@ -359,12 +341,11 @@ export const getReminderCountsByCompany = async (_req, res) => {
|
||||
data: counts,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const getUpcomingReminders = async (_req, res) => {
|
||||
export const getUpcomingReminders = async (_req, res, next) => {
|
||||
try {
|
||||
const reminders = await companyReminderService.getUpcomingReminders();
|
||||
res.status(200).json({
|
||||
@@ -373,7 +354,6 @@ export const getUpcomingReminders = async (_req, res) => {
|
||||
data: reminders,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as contactService from '../services/contact.service.js';
|
||||
import { discoverContactsFromJMAP, getJmapConfigFromAccount } from '../services/jmap.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
import * as emailAccountService from '../services/email-account.service.js';
|
||||
import { logger } from '../utils/logger.js';
|
||||
|
||||
@@ -8,7 +7,7 @@ import { logger } from '../utils/logger.js';
|
||||
* Get all contacts for an email account
|
||||
* GET /api/contacts?accountId=xxx (required)
|
||||
*/
|
||||
export const getContacts = async (req, res) => {
|
||||
export const getContacts = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { accountId } = req.query;
|
||||
@@ -35,8 +34,7 @@ export const getContacts = async (req, res) => {
|
||||
data: contacts,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +42,7 @@ export const getContacts = async (req, res) => {
|
||||
* Discover potential contacts from JMAP (email senders)
|
||||
* GET /api/contacts/discover?accountId=xxx&search=query&limit=50
|
||||
*/
|
||||
export const discoverContacts = async (req, res) => {
|
||||
export const discoverContacts = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { accountId, search = '', limit = 50 } = req.query;
|
||||
@@ -96,8 +94,7 @@ export const discoverContacts = async (req, res) => {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('ERROR in discoverContacts', { error: error.message, stack: error.stack });
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,7 +103,7 @@ export const discoverContacts = async (req, res) => {
|
||||
* POST /api/contacts
|
||||
* Body: { email, name, notes, accountId }
|
||||
*/
|
||||
export const addContact = async (req, res) => {
|
||||
export const addContact = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
logger.debug('Full req.body', { body: req.body });
|
||||
@@ -162,8 +159,7 @@ export const addContact = async (req, res) => {
|
||||
message: 'Kontakt pridaný a emaily synchronizované',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -171,7 +167,7 @@ export const addContact = async (req, res) => {
|
||||
* Remove a contact
|
||||
* DELETE /api/contacts/:contactId?accountId=xxx
|
||||
*/
|
||||
export const removeContact = async (req, res) => {
|
||||
export const removeContact = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -197,8 +193,7 @@ export const removeContact = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -206,7 +201,7 @@ export const removeContact = async (req, res) => {
|
||||
* Update a contact
|
||||
* PATCH /api/contacts/:contactId?accountId=xxx
|
||||
*/
|
||||
export const updateContact = async (req, res) => {
|
||||
export const updateContact = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -234,8 +229,7 @@ export const updateContact = async (req, res) => {
|
||||
message: 'Kontakt aktualizovaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -244,7 +238,7 @@ export const updateContact = async (req, res) => {
|
||||
* POST /api/contacts/:contactId/link-company?accountId=xxx
|
||||
* Body: { companyId }
|
||||
*/
|
||||
export const linkCompanyToContact = async (req, res) => {
|
||||
export const linkCompanyToContact = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -282,8 +276,7 @@ export const linkCompanyToContact = async (req, res) => {
|
||||
message: 'Firma bola linknutá ku kontaktu',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -291,7 +284,7 @@ export const linkCompanyToContact = async (req, res) => {
|
||||
* Unlink company from contact
|
||||
* POST /api/contacts/:contactId/unlink-company?accountId=xxx
|
||||
*/
|
||||
export const unlinkCompanyFromContact = async (req, res) => {
|
||||
export const unlinkCompanyFromContact = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -318,8 +311,7 @@ export const unlinkCompanyFromContact = async (req, res) => {
|
||||
message: 'Firma bola odlinknutá od kontaktu',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -328,7 +320,7 @@ export const unlinkCompanyFromContact = async (req, res) => {
|
||||
* POST /api/contacts/:contactId/create-company?accountId=xxx
|
||||
* Body: { name, email, phone, address, city, country, website, description } (all optional, uses contact data as defaults)
|
||||
*/
|
||||
export const createCompanyFromContact = async (req, res) => {
|
||||
export const createCompanyFromContact = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -356,7 +348,6 @@ export const createCompanyFromContact = async (req, res) => {
|
||||
message: 'Firma bola vytvorená z kontaktu',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ import * as crmEmailService from '../services/crm-email.service.js';
|
||||
import * as contactService from '../services/contact.service.js';
|
||||
import * as emailAccountService from '../services/email-account.service.js';
|
||||
import { markEmailAsRead, sendEmail, getJmapConfig, getJmapConfigFromAccount, syncEmailsFromSender, searchEmailsJMAP as searchEmailsJMAPService } from '../services/jmap.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
import { getUserById } from '../services/auth.service.js';
|
||||
import { logger } from '../utils/logger.js';
|
||||
|
||||
@@ -10,7 +9,7 @@ import { logger } from '../utils/logger.js';
|
||||
* Get all emails for authenticated user
|
||||
* GET /api/emails?accountId=xxx (REQUIRED)
|
||||
*/
|
||||
export const getEmails = async (req, res) => {
|
||||
export const getEmails = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { accountId } = req.query;
|
||||
@@ -36,8 +35,7 @@ export const getEmails = async (req, res) => {
|
||||
data: emails,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,7 +43,7 @@ export const getEmails = async (req, res) => {
|
||||
* Get emails by thread (conversation)
|
||||
* GET /api/emails/thread/:threadId?accountId=xxx (accountId required)
|
||||
*/
|
||||
export const getThread = async (req, res) => {
|
||||
export const getThread = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { threadId } = req.params;
|
||||
@@ -72,8 +70,7 @@ export const getThread = async (req, res) => {
|
||||
data: thread,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -81,7 +78,7 @@ export const getThread = async (req, res) => {
|
||||
* Search emails
|
||||
* GET /api/emails/search?q=query&accountId=xxx (accountId required)
|
||||
*/
|
||||
export const searchEmails = async (req, res) => {
|
||||
export const searchEmails = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { q, accountId } = req.query;
|
||||
@@ -107,8 +104,7 @@ export const searchEmails = async (req, res) => {
|
||||
data: results,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,7 +113,7 @@ export const searchEmails = async (req, res) => {
|
||||
* GET /api/emails/unread-count
|
||||
* Returns total unread count and per-account counts
|
||||
*/
|
||||
export const getUnreadCount = async (req, res) => {
|
||||
export const getUnreadCount = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
|
||||
@@ -139,8 +135,7 @@ export const getUnreadCount = async (req, res) => {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('ERROR in getUnreadCount', { error: error.message });
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,7 +144,7 @@ export const getUnreadCount = async (req, res) => {
|
||||
* POST /api/emails/sync
|
||||
* Body: { accountId } (optional - defaults to primary account)
|
||||
*/
|
||||
export const syncEmails = async (req, res) => {
|
||||
export const syncEmails = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { accountId } = req.body;
|
||||
@@ -213,8 +208,7 @@ export const syncEmails = async (req, res) => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -222,7 +216,7 @@ export const syncEmails = async (req, res) => {
|
||||
* Mark email as read/unread
|
||||
* PATCH /api/emails/:jmapId/read?accountId=xxx
|
||||
*/
|
||||
export const markAsRead = async (req, res) => {
|
||||
export const markAsRead = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { jmapId } = req.params;
|
||||
@@ -249,8 +243,7 @@ export const markAsRead = async (req, res) => {
|
||||
message: `Email označený ako ${isRead ? 'prečítaný' : 'neprečítaný'}`,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -258,7 +251,7 @@ export const markAsRead = async (req, res) => {
|
||||
* Mark all emails from contact as read
|
||||
* POST /api/emails/contact/:contactId/read?accountId=xxx
|
||||
*/
|
||||
export const markContactEmailsRead = async (req, res) => {
|
||||
export const markContactEmailsRead = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -308,8 +301,7 @@ export const markContactEmailsRead = async (req, res) => {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('ERROR in markContactEmailsRead', { error: error.message });
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -317,7 +309,7 @@ export const markContactEmailsRead = async (req, res) => {
|
||||
* Mark entire thread as read
|
||||
* POST /api/emails/thread/:threadId/read?accountId=xxx
|
||||
*/
|
||||
export const markThreadRead = async (req, res) => {
|
||||
export const markThreadRead = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { threadId } = req.params;
|
||||
@@ -361,8 +353,7 @@ export const markThreadRead = async (req, res) => {
|
||||
count,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -371,7 +362,7 @@ export const markThreadRead = async (req, res) => {
|
||||
* POST /api/emails/reply
|
||||
* Body: { to, subject, body, inReplyTo, threadId, accountId }
|
||||
*/
|
||||
export const replyToEmail = async (req, res) => {
|
||||
export const replyToEmail = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { to, subject, body, inReplyTo = null, threadId = null, accountId } = req.body;
|
||||
@@ -414,8 +405,7 @@ export const replyToEmail = async (req, res) => {
|
||||
data: result,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -423,7 +413,7 @@ export const replyToEmail = async (req, res) => {
|
||||
* Get emails for a specific contact
|
||||
* GET /api/emails/contact/:contactId?accountId=xxx
|
||||
*/
|
||||
export const getContactEmails = async (req, res) => {
|
||||
export const getContactEmails = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { contactId } = req.params;
|
||||
@@ -450,8 +440,7 @@ export const getContactEmails = async (req, res) => {
|
||||
data: emails,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -460,7 +449,7 @@ export const getContactEmails = async (req, res) => {
|
||||
* GET /api/emails/search-jmap?query=text&limit=50&offset=0&accountId=xxx
|
||||
* Searches in: from, to, subject, and email body
|
||||
*/
|
||||
export const searchEmailsJMAP = async (req, res) => {
|
||||
export const searchEmailsJMAP = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { query = '', limit = 50, offset = 0, accountId } = req.query;
|
||||
@@ -505,7 +494,6 @@ export const searchEmailsJMAP = async (req, res) => {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('ERROR in searchEmailsJMAP', { error: error.message });
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,13 +2,12 @@ import * as emailAccountService from '../services/email-account.service.js';
|
||||
import {
|
||||
logEmailLink,
|
||||
} from '../services/audit.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Get all email accounts for logged-in user
|
||||
* GET /api/email-accounts
|
||||
*/
|
||||
export const getEmailAccounts = async (req, res) => {
|
||||
export const getEmailAccounts = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const accounts = await emailAccountService.getUserEmailAccounts(userId);
|
||||
@@ -18,8 +17,7 @@ export const getEmailAccounts = async (req, res) => {
|
||||
data: accounts,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,7 +25,7 @@ export const getEmailAccounts = async (req, res) => {
|
||||
* Get a specific email account
|
||||
* GET /api/email-accounts/:id
|
||||
*/
|
||||
export const getEmailAccount = async (req, res) => {
|
||||
export const getEmailAccount = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { id } = req.params;
|
||||
@@ -39,8 +37,7 @@ export const getEmailAccount = async (req, res) => {
|
||||
data: account,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,7 +45,7 @@ export const getEmailAccount = async (req, res) => {
|
||||
* Create a new email account
|
||||
* POST /api/email-accounts
|
||||
*/
|
||||
export const createEmailAccount = async (req, res) => {
|
||||
export const createEmailAccount = async (req, res, next) => {
|
||||
const { email, emailPassword } = req.body;
|
||||
const userId = req.userId;
|
||||
const ipAddress = req.ip || req.connection.remoteAddress;
|
||||
@@ -70,8 +67,7 @@ export const createEmailAccount = async (req, res) => {
|
||||
message: 'Email účet úspešne pripojený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -79,7 +75,7 @@ export const createEmailAccount = async (req, res) => {
|
||||
* Update email account password
|
||||
* PATCH /api/email-accounts/:id/password
|
||||
*/
|
||||
export const updateEmailAccountPassword = async (req, res) => {
|
||||
export const updateEmailAccountPassword = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { id } = req.params;
|
||||
@@ -97,8 +93,7 @@ export const updateEmailAccountPassword = async (req, res) => {
|
||||
message: 'Heslo k emailovému účtu bolo aktualizované',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,7 +101,7 @@ export const updateEmailAccountPassword = async (req, res) => {
|
||||
* Toggle email account active status
|
||||
* PATCH /api/email-accounts/:id/status
|
||||
*/
|
||||
export const toggleEmailAccountStatus = async (req, res) => {
|
||||
export const toggleEmailAccountStatus = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { id } = req.params;
|
||||
@@ -124,8 +119,7 @@ export const toggleEmailAccountStatus = async (req, res) => {
|
||||
message: `Email účet ${isActive ? 'aktivovaný' : 'deaktivovaný'}`,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -133,7 +127,7 @@ export const toggleEmailAccountStatus = async (req, res) => {
|
||||
* Set email account as primary
|
||||
* POST /api/email-accounts/:id/set-primary
|
||||
*/
|
||||
export const setPrimaryEmailAccount = async (req, res) => {
|
||||
export const setPrimaryEmailAccount = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { id } = req.params;
|
||||
@@ -146,8 +140,7 @@ export const setPrimaryEmailAccount = async (req, res) => {
|
||||
message: 'Primárny email účet bol nastavený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -155,7 +148,7 @@ export const setPrimaryEmailAccount = async (req, res) => {
|
||||
* Delete email account
|
||||
* DELETE /api/email-accounts/:id
|
||||
*/
|
||||
export const deleteEmailAccount = async (req, res) => {
|
||||
export const deleteEmailAccount = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { id } = req.params;
|
||||
@@ -168,7 +161,6 @@ export const deleteEmailAccount = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as noteService from '../services/note.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Get all notes
|
||||
* GET /api/notes?search=query&companyId=xxx&projectId=xxx&todoId=xxx&contactId=xxx
|
||||
*/
|
||||
export const getAllNotes = async (req, res) => {
|
||||
export const getAllNotes = async (req, res, next) => {
|
||||
try {
|
||||
const { search, companyId, projectId, todoId, contactId } = req.query;
|
||||
|
||||
@@ -25,8 +24,7 @@ export const getAllNotes = async (req, res) => {
|
||||
data: notes,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +32,7 @@ export const getAllNotes = async (req, res) => {
|
||||
* Get note by ID
|
||||
* GET /api/notes/:noteId
|
||||
*/
|
||||
export const getNoteById = async (req, res) => {
|
||||
export const getNoteById = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
|
||||
@@ -45,8 +43,7 @@ export const getNoteById = async (req, res) => {
|
||||
data: note,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,7 +52,7 @@ export const getNoteById = async (req, res) => {
|
||||
* POST /api/notes
|
||||
* Body: { title, content, companyId, projectId, todoId, contactId }
|
||||
*/
|
||||
export const createNote = async (req, res) => {
|
||||
export const createNote = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const data = req.body;
|
||||
@@ -68,8 +65,7 @@ export const createNote = async (req, res) => {
|
||||
message: 'Poznámka bola vytvorená',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,7 +74,7 @@ export const createNote = async (req, res) => {
|
||||
* PATCH /api/notes/:noteId
|
||||
* Body: { title, content, companyId, projectId, todoId, contactId }
|
||||
*/
|
||||
export const updateNote = async (req, res) => {
|
||||
export const updateNote = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
const data = req.body;
|
||||
@@ -91,8 +87,7 @@ export const updateNote = async (req, res) => {
|
||||
message: 'Poznámka bola aktualizovaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,7 +95,7 @@ export const updateNote = async (req, res) => {
|
||||
* Delete note
|
||||
* DELETE /api/notes/:noteId
|
||||
*/
|
||||
export const deleteNote = async (req, res) => {
|
||||
export const deleteNote = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
|
||||
@@ -111,8 +106,7 @@ export const deleteNote = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,7 +114,7 @@ export const deleteNote = async (req, res) => {
|
||||
* Get upcoming reminders for current user
|
||||
* GET /api/notes/my-reminders
|
||||
*/
|
||||
export const getMyReminders = async (req, res) => {
|
||||
export const getMyReminders = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
|
||||
@@ -132,8 +126,7 @@ export const getMyReminders = async (req, res) => {
|
||||
data: reminders,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,7 +134,7 @@ export const getMyReminders = async (req, res) => {
|
||||
* Mark reminder as sent
|
||||
* POST /api/notes/:noteId/mark-reminder-sent
|
||||
*/
|
||||
export const markReminderSent = async (req, res) => {
|
||||
export const markReminderSent = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
|
||||
@@ -153,7 +146,6 @@ export const markReminderSent = async (req, res) => {
|
||||
message: 'Reminder označený ako odoslaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import * as projectService from '../services/project.service.js';
|
||||
import * as noteService from '../services/note.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Get all projects
|
||||
* GET /api/projects?search=query&companyId=xxx
|
||||
*/
|
||||
export const getAllProjects = async (req, res) => {
|
||||
export const getAllProjects = async (req, res, next) => {
|
||||
try {
|
||||
const { search, companyId } = req.query;
|
||||
|
||||
@@ -18,8 +17,7 @@ export const getAllProjects = async (req, res) => {
|
||||
data: projects,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,7 +25,7 @@ export const getAllProjects = async (req, res) => {
|
||||
* Get project by ID
|
||||
* GET /api/projects/:projectId
|
||||
*/
|
||||
export const getProjectById = async (req, res) => {
|
||||
export const getProjectById = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
|
||||
@@ -38,8 +36,7 @@ export const getProjectById = async (req, res) => {
|
||||
data: project,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,7 +44,7 @@ export const getProjectById = async (req, res) => {
|
||||
* Get project with relations (company, todos, notes, timesheets)
|
||||
* GET /api/projects/:projectId/details
|
||||
*/
|
||||
export const getProjectWithRelations = async (req, res) => {
|
||||
export const getProjectWithRelations = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
|
||||
@@ -58,8 +55,7 @@ export const getProjectWithRelations = async (req, res) => {
|
||||
data: project,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +64,7 @@ export const getProjectWithRelations = async (req, res) => {
|
||||
* POST /api/projects
|
||||
* Body: { name, description, companyId, status, startDate, endDate }
|
||||
*/
|
||||
export const createProject = async (req, res) => {
|
||||
export const createProject = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const data = req.body;
|
||||
@@ -81,8 +77,7 @@ export const createProject = async (req, res) => {
|
||||
message: 'Projekt bol vytvorený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +86,7 @@ export const createProject = async (req, res) => {
|
||||
* PATCH /api/projects/:projectId
|
||||
* Body: { name, description, companyId, status, startDate, endDate }
|
||||
*/
|
||||
export const updateProject = async (req, res) => {
|
||||
export const updateProject = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
const data = req.body;
|
||||
@@ -104,8 +99,7 @@ export const updateProject = async (req, res) => {
|
||||
message: 'Projekt bol aktualizovaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,7 +107,7 @@ export const updateProject = async (req, res) => {
|
||||
* Delete project
|
||||
* DELETE /api/projects/:projectId
|
||||
*/
|
||||
export const deleteProject = async (req, res) => {
|
||||
export const deleteProject = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
|
||||
@@ -124,8 +118,7 @@ export const deleteProject = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -133,7 +126,7 @@ export const deleteProject = async (req, res) => {
|
||||
* Get project notes
|
||||
* GET /api/projects/:projectId/notes
|
||||
*/
|
||||
export const getProjectNotes = async (req, res) => {
|
||||
export const getProjectNotes = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
|
||||
@@ -145,8 +138,7 @@ export const getProjectNotes = async (req, res) => {
|
||||
data: notes,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -154,7 +146,7 @@ export const getProjectNotes = async (req, res) => {
|
||||
* Add project note
|
||||
* POST /api/projects/:projectId/notes
|
||||
*/
|
||||
export const addProjectNote = async (req, res) => {
|
||||
export const addProjectNote = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { projectId } = req.params;
|
||||
@@ -172,8 +164,7 @@ export const addProjectNote = async (req, res) => {
|
||||
message: 'Poznámka bola pridaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -181,7 +172,7 @@ export const addProjectNote = async (req, res) => {
|
||||
* Update project note
|
||||
* PATCH /api/projects/:projectId/notes/:noteId
|
||||
*/
|
||||
export const updateProjectNote = async (req, res) => {
|
||||
export const updateProjectNote = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
const { content, reminderAt } = req.body;
|
||||
@@ -197,8 +188,7 @@ export const updateProjectNote = async (req, res) => {
|
||||
message: 'Poznámka bola aktualizovaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -206,7 +196,7 @@ export const updateProjectNote = async (req, res) => {
|
||||
* Delete project note
|
||||
* DELETE /api/projects/:projectId/notes/:noteId
|
||||
*/
|
||||
export const deleteProjectNote = async (req, res) => {
|
||||
export const deleteProjectNote = async (req, res, next) => {
|
||||
try {
|
||||
const { noteId } = req.params;
|
||||
|
||||
@@ -217,8 +207,7 @@ export const deleteProjectNote = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -226,7 +215,7 @@ export const deleteProjectNote = async (req, res) => {
|
||||
* Get project users (team members)
|
||||
* GET /api/projects/:projectId/users
|
||||
*/
|
||||
export const getProjectUsers = async (req, res) => {
|
||||
export const getProjectUsers = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId } = req.params;
|
||||
|
||||
@@ -238,8 +227,7 @@ export const getProjectUsers = async (req, res) => {
|
||||
data: users,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -248,7 +236,7 @@ export const getProjectUsers = async (req, res) => {
|
||||
* POST /api/projects/:projectId/users
|
||||
* Body: { userId, role }
|
||||
*/
|
||||
export const assignUserToProject = async (req, res) => {
|
||||
export const assignUserToProject = async (req, res, next) => {
|
||||
try {
|
||||
const currentUserId = req.userId;
|
||||
const { projectId } = req.params;
|
||||
@@ -267,8 +255,7 @@ export const assignUserToProject = async (req, res) => {
|
||||
message: 'Používateľ bol priradený k projektu',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -276,7 +263,7 @@ export const assignUserToProject = async (req, res) => {
|
||||
* Remove user from project
|
||||
* DELETE /api/projects/:projectId/users/:userId
|
||||
*/
|
||||
export const removeUserFromProject = async (req, res) => {
|
||||
export const removeUserFromProject = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId, userId } = req.params;
|
||||
|
||||
@@ -287,8 +274,7 @@ export const removeUserFromProject = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -297,7 +283,7 @@ export const removeUserFromProject = async (req, res) => {
|
||||
* PATCH /api/projects/:projectId/users/:userId
|
||||
* Body: { role }
|
||||
*/
|
||||
export const updateUserRoleOnProject = async (req, res) => {
|
||||
export const updateUserRoleOnProject = async (req, res, next) => {
|
||||
try {
|
||||
const { projectId, userId } = req.params;
|
||||
const { role } = req.body;
|
||||
@@ -310,7 +296,6 @@ export const updateUserRoleOnProject = async (req, res) => {
|
||||
message: 'Rola používateľa bola aktualizovaná',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as timeTrackingService from '../services/time-tracking.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Start a new time entry
|
||||
* POST /api/time-tracking/start
|
||||
*/
|
||||
export const startTimeEntry = async (req, res) => {
|
||||
export const startTimeEntry = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { projectId, todoId, companyId, description } = req.body;
|
||||
@@ -23,8 +22,7 @@ export const startTimeEntry = async (req, res) => {
|
||||
message: 'Časovač bol spustený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,7 +30,7 @@ export const startTimeEntry = async (req, res) => {
|
||||
* Stop a running time entry
|
||||
* POST /api/time-tracking/:entryId/stop
|
||||
*/
|
||||
export const stopTimeEntry = async (req, res) => {
|
||||
export const stopTimeEntry = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { entryId } = req.params;
|
||||
@@ -51,8 +49,7 @@ export const stopTimeEntry = async (req, res) => {
|
||||
message: 'Časovač bol zastavený',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,7 +57,7 @@ export const stopTimeEntry = async (req, res) => {
|
||||
* Get running time entry for current user
|
||||
* GET /api/time-tracking/running
|
||||
*/
|
||||
export const getRunningTimeEntry = async (req, res) => {
|
||||
export const getRunningTimeEntry = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
|
||||
@@ -71,8 +68,24 @@ export const getRunningTimeEntry = async (req, res) => {
|
||||
data: entry,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all running time entries (for dashboard)
|
||||
* GET /api/time-tracking/running-all
|
||||
*/
|
||||
export const getAllRunningTimeEntries = async (req, res, next) => {
|
||||
try {
|
||||
const entries = await timeTrackingService.getAllRunningTimeEntries();
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: entries,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -80,7 +93,7 @@ export const getRunningTimeEntry = async (req, res) => {
|
||||
* Get all time entries for current user with filters
|
||||
* GET /api/time-tracking?projectId=xxx&todoId=xxx&companyId=xxx&startDate=xxx&endDate=xxx
|
||||
*/
|
||||
export const getAllTimeEntries = async (req, res) => {
|
||||
export const getAllTimeEntries = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { projectId, todoId, companyId, startDate, endDate } = req.query;
|
||||
@@ -101,8 +114,7 @@ export const getAllTimeEntries = async (req, res) => {
|
||||
data: entries,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -110,7 +122,7 @@ export const getAllTimeEntries = async (req, res) => {
|
||||
* Get time entries for a specific month
|
||||
* GET /api/time-tracking/month/:year/:month
|
||||
*/
|
||||
export const getMonthlyTimeEntries = async (req, res) => {
|
||||
export const getMonthlyTimeEntries = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const userRole = req.user.role;
|
||||
@@ -129,8 +141,7 @@ export const getMonthlyTimeEntries = async (req, res) => {
|
||||
data: entries,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,7 +149,7 @@ export const getMonthlyTimeEntries = async (req, res) => {
|
||||
* Generate timesheet file for a month
|
||||
* POST /api/time-tracking/month/:year/:month/generate
|
||||
*/
|
||||
export const generateMonthlyTimesheet = async (req, res) => {
|
||||
export const generateMonthlyTimesheet = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const userRole = req.user.role;
|
||||
@@ -157,8 +168,7 @@ export const generateMonthlyTimesheet = async (req, res) => {
|
||||
message: 'Timesheet bol vygenerovaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -166,7 +176,7 @@ export const generateMonthlyTimesheet = async (req, res) => {
|
||||
* Get time entry by ID
|
||||
* GET /api/time-tracking/:entryId
|
||||
*/
|
||||
export const getTimeEntryById = async (req, res) => {
|
||||
export const getTimeEntryById = async (req, res, next) => {
|
||||
try {
|
||||
const { entryId } = req.params;
|
||||
|
||||
@@ -177,8 +187,7 @@ export const getTimeEntryById = async (req, res) => {
|
||||
data: entry,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,7 +195,7 @@ export const getTimeEntryById = async (req, res) => {
|
||||
* Get time entry with related data
|
||||
* GET /api/time-tracking/:entryId/details
|
||||
*/
|
||||
export const getTimeEntryWithRelations = async (req, res) => {
|
||||
export const getTimeEntryWithRelations = async (req, res, next) => {
|
||||
try {
|
||||
const { entryId } = req.params;
|
||||
|
||||
@@ -197,8 +206,7 @@ export const getTimeEntryWithRelations = async (req, res) => {
|
||||
data: entry,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -206,7 +214,7 @@ export const getTimeEntryWithRelations = async (req, res) => {
|
||||
* Update time entry
|
||||
* PATCH /api/time-tracking/:entryId
|
||||
*/
|
||||
export const updateTimeEntry = async (req, res) => {
|
||||
export const updateTimeEntry = async (req, res, next) => {
|
||||
try {
|
||||
const { entryId } = req.params;
|
||||
const { startTime, endTime, projectId, todoId, companyId, description } = req.body;
|
||||
@@ -229,8 +237,7 @@ export const updateTimeEntry = async (req, res) => {
|
||||
message: 'Záznam bol aktualizovaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -238,7 +245,7 @@ export const updateTimeEntry = async (req, res) => {
|
||||
* Delete time entry
|
||||
* DELETE /api/time-tracking/:entryId
|
||||
*/
|
||||
export const deleteTimeEntry = async (req, res) => {
|
||||
export const deleteTimeEntry = async (req, res, next) => {
|
||||
try {
|
||||
const { entryId } = req.params;
|
||||
|
||||
@@ -249,8 +256,7 @@ export const deleteTimeEntry = async (req, res) => {
|
||||
|
||||
res.status(200).json(result);
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -258,7 +264,7 @@ export const deleteTimeEntry = async (req, res) => {
|
||||
* Get monthly statistics
|
||||
* GET /api/time-tracking/stats/monthly/:year/:month
|
||||
*/
|
||||
export const getMonthlyStats = async (req, res) => {
|
||||
export const getMonthlyStats = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const userRole = req.user.role;
|
||||
@@ -276,7 +282,6 @@ export const getMonthlyStats = async (req, res) => {
|
||||
data: stats,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as timesheetService from '../services/timesheet.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
import { ForbiddenError } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Upload timesheet
|
||||
* POST /api/timesheets/upload
|
||||
*/
|
||||
export const uploadTimesheet = async (req, res) => {
|
||||
export const uploadTimesheet = async (req, res, next) => {
|
||||
try {
|
||||
const { year, month, userId: requestUserId } = req.body;
|
||||
|
||||
@@ -15,11 +15,7 @@ export const uploadTimesheet = async (req, res) => {
|
||||
let targetUserId = req.userId;
|
||||
if (requestUserId) {
|
||||
if (req.user.role !== 'admin') {
|
||||
const errorResponse = formatErrorResponse(
|
||||
new Error('Iba admin môže nahrávať timesheets za iných používateľov'),
|
||||
process.env.NODE_ENV === 'development'
|
||||
);
|
||||
return res.status(403).json(errorResponse);
|
||||
throw new ForbiddenError('Iba admin môže nahrávať timesheets za iných používateľov');
|
||||
}
|
||||
targetUserId = requestUserId;
|
||||
}
|
||||
@@ -37,8 +33,7 @@ export const uploadTimesheet = async (req, res) => {
|
||||
message: 'Timesheet bol úspešne nahraný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,7 +41,7 @@ export const uploadTimesheet = async (req, res) => {
|
||||
* Get user's timesheets (with optional filters)
|
||||
* GET /api/timesheets/my
|
||||
*/
|
||||
export const getMyTimesheets = async (req, res) => {
|
||||
export const getMyTimesheets = async (req, res, next) => {
|
||||
try {
|
||||
const { year, month } = req.query;
|
||||
|
||||
@@ -60,8 +55,7 @@ export const getMyTimesheets = async (req, res) => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,7 +63,7 @@ export const getMyTimesheets = async (req, res) => {
|
||||
* Get all users' timesheets (admin only) - grouped by user
|
||||
* GET /api/timesheets/all
|
||||
*/
|
||||
export const getAllTimesheets = async (req, res) => {
|
||||
export const getAllTimesheets = async (req, res, next) => {
|
||||
try {
|
||||
const { userId, year, month } = req.query;
|
||||
|
||||
@@ -83,8 +77,7 @@ export const getAllTimesheets = async (req, res) => {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +85,7 @@ export const getAllTimesheets = async (req, res) => {
|
||||
* Download timesheet file
|
||||
* GET /api/timesheets/:timesheetId/download
|
||||
*/
|
||||
export const downloadTimesheet = async (req, res) => {
|
||||
export const downloadTimesheet = async (req, res, next) => {
|
||||
try {
|
||||
const { timesheetId } = req.params;
|
||||
const { filePath, fileName } = await timesheetService.getDownloadInfo(timesheetId, {
|
||||
@@ -102,8 +95,7 @@ export const downloadTimesheet = async (req, res) => {
|
||||
|
||||
res.download(filePath, fileName);
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -111,7 +103,7 @@ export const downloadTimesheet = async (req, res) => {
|
||||
* Delete timesheet
|
||||
* DELETE /api/timesheets/:timesheetId
|
||||
*/
|
||||
export const deleteTimesheet = async (req, res) => {
|
||||
export const deleteTimesheet = async (req, res, next) => {
|
||||
try {
|
||||
const { timesheetId } = req.params;
|
||||
|
||||
@@ -125,7 +117,6 @@ export const deleteTimesheet = async (req, res) => {
|
||||
message: 'Timesheet bol zmazaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as todoService from '../services/todo.service.js';
|
||||
import { formatErrorResponse } from '../utils/errors.js';
|
||||
|
||||
/**
|
||||
* Get all todos
|
||||
* GET /api/todos?search=query&projectId=xxx&companyId=xxx&assignedTo=xxx&status=xxx
|
||||
*/
|
||||
export const getAllTodos = async (req, res) => {
|
||||
export const getAllTodos = async (req, res, next) => {
|
||||
try {
|
||||
const { search, projectId, companyId, assignedTo, status, completed, priority } = req.query;
|
||||
|
||||
@@ -32,8 +31,7 @@ export const getAllTodos = async (req, res) => {
|
||||
data: todos,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,7 +39,7 @@ export const getAllTodos = async (req, res) => {
|
||||
* Get my todos (assigned to current user)
|
||||
* GET /api/todos/my?status=xxx
|
||||
*/
|
||||
export const getMyTodos = async (req, res) => {
|
||||
export const getMyTodos = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const { status } = req.query;
|
||||
@@ -59,8 +57,7 @@ export const getMyTodos = async (req, res) => {
|
||||
data: todos,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +65,7 @@ export const getMyTodos = async (req, res) => {
|
||||
* Get todo by ID
|
||||
* GET /api/todos/:todoId
|
||||
*/
|
||||
export const getTodoById = async (req, res) => {
|
||||
export const getTodoById = async (req, res, next) => {
|
||||
try {
|
||||
const { todoId } = req.params;
|
||||
|
||||
@@ -79,8 +76,7 @@ export const getTodoById = async (req, res) => {
|
||||
data: todo,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,7 +84,7 @@ export const getTodoById = async (req, res) => {
|
||||
* Get todo with relations (project, company, assigned user, notes)
|
||||
* GET /api/todos/:todoId/details
|
||||
*/
|
||||
export const getTodoWithRelations = async (req, res) => {
|
||||
export const getTodoWithRelations = async (req, res, next) => {
|
||||
try {
|
||||
const { todoId } = req.params;
|
||||
|
||||
@@ -99,8 +95,7 @@ export const getTodoWithRelations = async (req, res) => {
|
||||
data: todo,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,7 +104,7 @@ export const getTodoWithRelations = async (req, res) => {
|
||||
* POST /api/todos
|
||||
* Body: { title, description, projectId, companyId, assignedUserIds, status, priority, dueDate }
|
||||
*/
|
||||
export const createTodo = async (req, res) => {
|
||||
export const createTodo = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.userId;
|
||||
const data = req.body;
|
||||
@@ -123,8 +118,7 @@ export const createTodo = async (req, res) => {
|
||||
message: 'Todo bolo vytvorené',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -133,7 +127,7 @@ export const createTodo = async (req, res) => {
|
||||
* PATCH /api/todos/:todoId
|
||||
* Body: { title, description, projectId, companyId, assignedUserIds, status, priority, dueDate }
|
||||
*/
|
||||
export const updateTodo = async (req, res) => {
|
||||
export const updateTodo = async (req, res, next) => {
|
||||
try {
|
||||
const { todoId } = req.params;
|
||||
const data = req.body;
|
||||
@@ -147,8 +141,7 @@ export const updateTodo = async (req, res) => {
|
||||
message: 'Todo bolo aktualizované',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,7 +149,7 @@ export const updateTodo = async (req, res) => {
|
||||
* Delete todo
|
||||
* DELETE /api/todos/:todoId
|
||||
*/
|
||||
export const deleteTodo = async (req, res) => {
|
||||
export const deleteTodo = async (req, res, next) => {
|
||||
try {
|
||||
const { todoId } = req.params;
|
||||
|
||||
@@ -167,8 +160,7 @@ export const deleteTodo = async (req, res) => {
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,7 +168,7 @@ export const deleteTodo = async (req, res) => {
|
||||
* Toggle todo completion status
|
||||
* PATCH /api/todos/:todoId/toggle
|
||||
*/
|
||||
export const toggleTodo = async (req, res) => {
|
||||
export const toggleTodo = async (req, res, next) => {
|
||||
try {
|
||||
const { todoId } = req.params;
|
||||
|
||||
@@ -194,7 +186,6 @@ export const toggleTodo = async (req, res) => {
|
||||
message: 'Todo status aktualizovaný',
|
||||
});
|
||||
} catch (error) {
|
||||
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
|
||||
res.status(error.statusCode || 500).json(errorResponse);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,12 +48,6 @@ export const authenticate = async (req, res, next) => {
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Neplatný alebo expirovaný token',
|
||||
statusCode: 401,
|
||||
},
|
||||
});
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,11 +2,19 @@ import { formatErrorResponse } from '../../utils/errors.js';
|
||||
import { logger } from '../../utils/logger.js';
|
||||
|
||||
export function errorHandler(err, req, res, next) {
|
||||
if (res.headersSent) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
// Log error
|
||||
logger.error('Unhandled error', err);
|
||||
|
||||
// Get status code
|
||||
const statusCode = err.statusCode || res.statusCode !== 200 ? res.statusCode : 500;
|
||||
const statusCode = typeof err.statusCode === 'number'
|
||||
? err.statusCode
|
||||
: res.statusCode >= 400
|
||||
? res.statusCode
|
||||
: 500;
|
||||
|
||||
// Format error response
|
||||
const errorResponse = formatErrorResponse(err, process.env.NODE_ENV === 'development');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { AuthenticationError } from './errors.js';
|
||||
|
||||
/**
|
||||
* Generuje access JWT token
|
||||
@@ -33,10 +34,10 @@ export const verifyAccessToken = (token) => {
|
||||
return jwt.verify(token, process.env.JWT_SECRET);
|
||||
} catch (error) {
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
throw new Error('Token expiroval');
|
||||
throw new AuthenticationError('Token expiroval');
|
||||
}
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
throw new Error('Neplatný token');
|
||||
throw new AuthenticationError('Neplatný token');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
@@ -53,10 +54,10 @@ export const verifyRefreshToken = (token) => {
|
||||
return jwt.verify(token, process.env.JWT_REFRESH_SECRET);
|
||||
} catch (error) {
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
throw new Error('Refresh token expiroval');
|
||||
throw new AuthenticationError('Refresh token expiroval');
|
||||
}
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
throw new Error('Neplatný refresh token');
|
||||
throw new AuthenticationError('Neplatný refresh token');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user