v1.6.5: fix attendance unique constraint, schema sync, seed script
- Change attendance idx_attendance_user_date from unique to index (allow multiple shifts per day) - Reset migrations to single baseline init migration - Add seed script with admin user (admin/admin) - Update CLAUDE.md with migration workflow documentation - Various frontend fixes (queries, pages, hooks) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- action=balances: leave balance overview for all users ---
|
||||
if (action === "balances") {
|
||||
if (!authData.permissions.includes("attendance.admin")) {
|
||||
if (!authData.permissions.includes("attendance.balances")) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
const yr = Number(query.year) || new Date().getFullYear();
|
||||
@@ -110,7 +110,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- action=workfund: monthly work fund overview ---
|
||||
if (action === "workfund") {
|
||||
if (!authData.permissions.includes("attendance.admin")) {
|
||||
if (!authData.permissions.includes("attendance.manage")) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
const yr = Number(query.year) || new Date().getFullYear();
|
||||
@@ -120,7 +120,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- action=project_report: monthly project hours ---
|
||||
if (action === "project_report") {
|
||||
if (!authData.permissions.includes("attendance.admin")) {
|
||||
if (!authData.permissions.includes("attendance.manage")) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
const yr = Number(query.year) || new Date().getFullYear();
|
||||
@@ -130,7 +130,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- action=print: attendance print data for admin ---
|
||||
if (action === "print") {
|
||||
if (!authData.permissions.includes("attendance.admin")) {
|
||||
if (!authData.permissions.includes("attendance.manage")) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
|
||||
@@ -145,8 +145,7 @@ export default async function attendanceRoutes(
|
||||
// --- action=attendance_users: users with attendance.record permission ---
|
||||
if (action === "attendance_users") {
|
||||
if (
|
||||
!authData.permissions.includes("attendance.admin") &&
|
||||
!authData.permissions.includes("attendance.view") &&
|
||||
!authData.permissions.includes("attendance.manage") &&
|
||||
!authData.permissions.includes("attendance.record")
|
||||
) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
@@ -182,10 +181,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- action=project_logs: get project logs for a specific attendance record ---
|
||||
if (action === "project_logs") {
|
||||
if (
|
||||
!authData.permissions.includes("attendance.view") &&
|
||||
!authData.permissions.includes("attendance.record")
|
||||
) {
|
||||
if (!authData.permissions.includes("attendance.record")) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
const attendanceId = Number(query.attendance_id);
|
||||
@@ -200,7 +196,7 @@ export default async function attendanceRoutes(
|
||||
if (!id) return error(reply, "Missing id", 400);
|
||||
const record = await attendanceService.getLocationRecord(id);
|
||||
if (!record) return error(reply, "Záznam nenalezen", 404);
|
||||
const isAdmin = authData.permissions.includes("attendance.admin");
|
||||
const isAdmin = authData.permissions.includes("attendance.manage");
|
||||
if (record.user_id !== authData.userId && !isAdmin) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
@@ -209,7 +205,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- Default: paginated records list ---
|
||||
const { page, limit, skip, order } = parsePagination(query);
|
||||
const isAdmin = authData.permissions.includes("attendance.admin");
|
||||
const isAdmin = authData.permissions.includes("attendance.manage");
|
||||
const userId = query.user_id ? Number(query.user_id) : undefined;
|
||||
|
||||
const result = await attendanceService.listAttendance({
|
||||
@@ -285,7 +281,7 @@ export default async function attendanceRoutes(
|
||||
|
||||
// --- action=bulk_attendance: bulk fill month ---
|
||||
if (postQuery.action === "bulk_attendance") {
|
||||
if (!authData.permissions.includes("attendance.admin")) {
|
||||
if (!authData.permissions.includes("attendance.manage")) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
|
||||
@@ -328,7 +324,7 @@ export default async function attendanceRoutes(
|
||||
if (
|
||||
leaveBody.user_id != null &&
|
||||
leaveBody.user_id !== authData.userId &&
|
||||
!authData.permissions.includes("attendance.admin")
|
||||
!authData.permissions.includes("attendance.manage")
|
||||
) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
@@ -384,7 +380,7 @@ export default async function attendanceRoutes(
|
||||
if (
|
||||
body.user_id != null &&
|
||||
body.user_id !== authData.userId &&
|
||||
!authData.permissions.includes("attendance.admin")
|
||||
!authData.permissions.includes("attendance.manage")
|
||||
) {
|
||||
return error(reply, "Nedostatečná oprávnění", 403);
|
||||
}
|
||||
@@ -429,7 +425,7 @@ export default async function attendanceRoutes(
|
||||
// PUT /api/admin/attendance/:id
|
||||
fastify.put<{ Params: { id: string } }>(
|
||||
"/:id",
|
||||
{ preHandler: requirePermission("attendance.edit") },
|
||||
{ preHandler: requirePermission("attendance.manage") },
|
||||
async (request, reply) => {
|
||||
const id = parseId(request.params.id, reply);
|
||||
if (id === null) return;
|
||||
@@ -438,7 +434,7 @@ export default async function attendanceRoutes(
|
||||
const body = parsed.data;
|
||||
|
||||
const authData = request.authData!;
|
||||
const isAdmin = authData.permissions.includes("attendance.admin");
|
||||
const isAdmin = authData.permissions.includes("attendance.manage");
|
||||
|
||||
const result = await attendanceService.updateAttendance(
|
||||
id,
|
||||
@@ -481,7 +477,7 @@ export default async function attendanceRoutes(
|
||||
// DELETE /api/admin/attendance/:id
|
||||
fastify.delete<{ Params: { id: string } }>(
|
||||
"/:id",
|
||||
{ preHandler: requirePermission("attendance.admin") },
|
||||
{ preHandler: requirePermission("attendance.manage") },
|
||||
async (request, reply) => {
|
||||
const id = parseId(request.params.id, reply);
|
||||
if (id === null) return;
|
||||
|
||||
Reference in New Issue
Block a user