feat(plan): assertNotPastDate guard for write paths
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
|||||||
resolveCell,
|
resolveCell,
|
||||||
resolveGrid,
|
resolveGrid,
|
||||||
listPlanUsers,
|
listPlanUsers,
|
||||||
|
assertNotPastDate,
|
||||||
} from "../services/plan.service";
|
} from "../services/plan.service";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -187,3 +188,28 @@ describe("plan.service.listPlanUsers", () => {
|
|||||||
expect(found?.has_attendance_record).toBe(true);
|
expect(found?.has_attendance_record).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// assertNotPastDate
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe("plan.service.assertNotPastDate", () => {
|
||||||
|
it("returns error for a past date", () => {
|
||||||
|
const result = assertNotPastDate("2000-01-01", false);
|
||||||
|
expect(result).toEqual({
|
||||||
|
error:
|
||||||
|
"Nelze upravovat plán pro datum v minulosti. Pro nouzovou opravu použijte ?force=1.",
|
||||||
|
status: 403,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns null for a future date", () => {
|
||||||
|
const result = assertNotPastDate("2099-01-01", false);
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns null for a past date with force=true", () => {
|
||||||
|
const result = assertNotPastDate("2000-01-01", true);
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -245,3 +245,29 @@ export async function listPlanUsers(): Promise<PlanUser[]> {
|
|||||||
has_attendance_record: true,
|
has_attendance_record: true,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guard helper: returns { error, status } if `dateStr` is in the past
|
||||||
|
* and `force` is not set. Returns null if the date is editable.
|
||||||
|
*
|
||||||
|
* The comparison uses ISO date string equality. For past-date guard purposes
|
||||||
|
* any date strictly before today (in the local timezone per the project's
|
||||||
|
* TZ=Europe/Prague setting) is locked.
|
||||||
|
*/
|
||||||
|
export function assertNotPastDate(
|
||||||
|
dateStr: string,
|
||||||
|
force: boolean,
|
||||||
|
): { error: string; status: number } | null {
|
||||||
|
if (force) return null;
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
const todayStr = today.toISOString().slice(0, 10);
|
||||||
|
if (dateStr < todayStr) {
|
||||||
|
return {
|
||||||
|
error:
|
||||||
|
"Nelze upravovat plán pro datum v minulosti. Pro nouzovou opravu použijte ?force=1.",
|
||||||
|
status: 403,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user