Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa7e2772a7 |
@@ -65,6 +65,16 @@ export function getVapidPublicKey(): string | undefined {
|
|||||||
return process.env.VAPID_PUBLIC_KEY;
|
return process.env.VAPID_PUBLIC_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Najde login uživatele podle push subscription endpointu. */
|
||||||
|
export async function findLoginByEndpoint(endpoint: string): Promise<string | undefined> {
|
||||||
|
const registry = await getRegistry();
|
||||||
|
for (const [login, entry] of Object.entries(registry)) {
|
||||||
|
if (entry.subscription.endpoint === endpoint) {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/** Zkontroluje a odešle připomínky uživatelům, kteří si nezvolili oběd. */
|
/** Zkontroluje a odešle připomínky uživatelům, kteří si nezvolili oběd. */
|
||||||
async function checkAndSendReminders(): Promise<void> {
|
async function checkAndSendReminders(): Promise<void> {
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ router.post("/testPush", async (req, res, next) => {
|
|||||||
webpush.setVapidDetails(subject, publicKey, privateKey);
|
webpush.setVapidDetails(subject, publicKey, privateKey);
|
||||||
await webpush.sendNotification(
|
await webpush.sendNotification(
|
||||||
entry.subscription,
|
entry.subscription,
|
||||||
JSON.stringify({ title: 'Luncher test', body: 'Push notifikace fungují!', login })
|
JSON.stringify({ title: 'Luncher test', body: 'Push notifikace fungují!' })
|
||||||
);
|
);
|
||||||
res.status(200).json({ ok: true });
|
res.status(200).json({ ok: true });
|
||||||
} catch (e: any) { next(e) }
|
} catch (e: any) { next(e) }
|
||||||
|
|||||||
@@ -82,8 +82,7 @@ const router = express.Router();
|
|||||||
router.post("/addChoice", async (req: Request<{}, any, AddChoiceData["body"]>, res, next) => {
|
router.post("/addChoice", async (req: Request<{}, any, AddChoiceData["body"]>, res, next) => {
|
||||||
const login = getLogin(parseToken(req));
|
const login = getLogin(parseToken(req));
|
||||||
const trusted = getTrusted(parseToken(req));
|
const trusted = getTrusted(parseToken(req));
|
||||||
let slot: MealSlot | undefined;
|
const slot = parseSlot(req.body);
|
||||||
try { slot = parseSlot(req.body); } catch (e: any) { return res.status(400).json({ error: e.message }); }
|
|
||||||
let date = undefined;
|
let date = undefined;
|
||||||
if (req.body.dayIndex != null) {
|
if (req.body.dayIndex != null) {
|
||||||
let dayIndex;
|
let dayIndex;
|
||||||
@@ -104,8 +103,7 @@ router.post("/addChoice", async (req: Request<{}, any, AddChoiceData["body"]>, r
|
|||||||
router.post("/removeChoices", async (req: Request<{}, any, RemoveChoicesData["body"]>, res, next) => {
|
router.post("/removeChoices", async (req: Request<{}, any, RemoveChoicesData["body"]>, res, next) => {
|
||||||
const login = getLogin(parseToken(req));
|
const login = getLogin(parseToken(req));
|
||||||
const trusted = getTrusted(parseToken(req));
|
const trusted = getTrusted(parseToken(req));
|
||||||
let slot: MealSlot | undefined;
|
const slot = parseSlot(req.body);
|
||||||
try { slot = parseSlot(req.body); } catch (e: any) { return res.status(400).json({ error: e.message }); }
|
|
||||||
let date = undefined;
|
let date = undefined;
|
||||||
if (req.body.dayIndex != null) {
|
if (req.body.dayIndex != null) {
|
||||||
let dayIndex;
|
let dayIndex;
|
||||||
@@ -126,8 +124,7 @@ router.post("/removeChoices", async (req: Request<{}, any, RemoveChoicesData["bo
|
|||||||
router.post("/removeChoice", async (req: Request<{}, any, RemoveChoiceData["body"]>, res, next) => {
|
router.post("/removeChoice", async (req: Request<{}, any, RemoveChoiceData["body"]>, res, next) => {
|
||||||
const login = getLogin(parseToken(req));
|
const login = getLogin(parseToken(req));
|
||||||
const trusted = getTrusted(parseToken(req));
|
const trusted = getTrusted(parseToken(req));
|
||||||
let slot: MealSlot | undefined;
|
const slot = parseSlot(req.body);
|
||||||
try { slot = parseSlot(req.body); } catch (e: any) { return res.status(400).json({ error: e.message }); }
|
|
||||||
let date = undefined;
|
let date = undefined;
|
||||||
if (req.body.dayIndex != null) {
|
if (req.body.dayIndex != null) {
|
||||||
let dayIndex;
|
let dayIndex;
|
||||||
@@ -149,8 +146,7 @@ router.post("/updateNote", async (req: Request<{}, any, UpdateNoteData["body"]>,
|
|||||||
const login = getLogin(parseToken(req));
|
const login = getLogin(parseToken(req));
|
||||||
const trusted = getTrusted(parseToken(req));
|
const trusted = getTrusted(parseToken(req));
|
||||||
const note = req.body.note;
|
const note = req.body.note;
|
||||||
let slot: MealSlot | undefined;
|
const slot = parseSlot(req.body);
|
||||||
try { slot = parseSlot(req.body); } catch (e: any) { return res.status(400).json({ error: e.message }); }
|
|
||||||
try {
|
try {
|
||||||
if (note && note.length > 70) {
|
if (note && note.length > 70) {
|
||||||
throw Error("Poznámka může mít maximálně 70 znaků");
|
throw Error("Poznámka může mít maximálně 70 znaků");
|
||||||
@@ -200,8 +196,7 @@ router.post("/jdemeObed", async (req, res, next) => {
|
|||||||
|
|
||||||
router.post("/updateBuyer", async (req, res, next) => {
|
router.post("/updateBuyer", async (req, res, next) => {
|
||||||
const login = getLogin(parseToken(req));
|
const login = getLogin(parseToken(req));
|
||||||
let slot: MealSlot | undefined;
|
const slot = parseSlot(req.body ?? {});
|
||||||
try { slot = parseSlot(req.body ?? {}); } catch (e: any) { return res.status(400).json({ error: e.message }); }
|
|
||||||
try {
|
try {
|
||||||
const data = await updateBuyer(login, slot);
|
const data = await updateBuyer(login, slot);
|
||||||
getWebsocket().emit("message", data);
|
getWebsocket().emit("message", data);
|
||||||
|
|||||||
@@ -66,10 +66,13 @@ router.post("/push/unsubscribe", async (req, res, next) => {
|
|||||||
} catch (e: any) { next(e) }
|
} catch (e: any) { next(e) }
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Rychlá akce z push notifikace — nastaví volbu NEOBEDVAM pro přihlášeného uživatele. */
|
/** Rychlá akce z push notifikace — nastaví volbu bez JWT (identita přes login v payloadu). */
|
||||||
router.post("/push/quickChoice", async (req, res, next) => {
|
router.post("/push/quickChoice", async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const login = getLogin(parseToken(req));
|
const { login } = req.body;
|
||||||
|
if (!login) {
|
||||||
|
return res.status(400).json({ error: "Nebyl předán login" });
|
||||||
|
}
|
||||||
const data = await addChoice(login, false, 'NEOBEDVAM', undefined, undefined);
|
const data = await addChoice(login, false, 'NEOBEDVAM', undefined, undefined);
|
||||||
getWebsocket().emit("message", data);
|
getWebsocket().emit("message", data);
|
||||||
res.status(200).json({});
|
res.status(200).json({});
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export async function getData(date?: Date, slot?: MealSlot): Promise<ClientData>
|
|||||||
SENKSERIKOVA: await getRestaurantMenu('SENKSERIKOVA', date),
|
SENKSERIKOVA: await getRestaurantMenu('SENKSERIKOVA', date),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (slot === MealSlot.EXTRA) clientData.slot = MealSlot.EXTRA;
|
||||||
return clientData;
|
return clientData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,9 +531,9 @@ export async function updateNote(login: string, trusted: boolean, note?: string,
|
|||||||
* @param time preferovaný čas odchodu
|
* @param time preferovaný čas odchodu
|
||||||
* @param date datum, ke kterému se čas vztahuje
|
* @param date datum, ke kterému se čas vztahuje
|
||||||
*/
|
*/
|
||||||
export async function updateDepartureTime(login: string, time?: string, date?: Date) {
|
export async function updateDepartureTime(login: string, time?: string, date?: Date, slot?: MealSlot) {
|
||||||
const usedDate = date ?? getToday();
|
const usedDate = date ?? getToday();
|
||||||
let clientData = await getClientData(usedDate);
|
let clientData = await getClientData(usedDate, slot);
|
||||||
const found = Object.values(clientData.choices).find(location => login in location);
|
const found = Object.values(clientData.choices).find(location => login in location);
|
||||||
// TODO validace, že se jedná o restauraci
|
// TODO validace, že se jedná o restauraci
|
||||||
if (found) {
|
if (found) {
|
||||||
@@ -544,7 +545,7 @@ export async function updateDepartureTime(login: string, time?: string, date?: D
|
|||||||
}
|
}
|
||||||
found[login].departureTime = time;
|
found[login].departureTime = time;
|
||||||
}
|
}
|
||||||
await storage.setData(getDataKey(usedDate), clientData);
|
await storage.setData(getDataKey(usedDate, slot), clientData);
|
||||||
}
|
}
|
||||||
return clientData;
|
return clientData;
|
||||||
}
|
}
|
||||||
@@ -580,6 +581,5 @@ export async function getClientData(date?: Date, slot?: MealSlot): Promise<Clien
|
|||||||
return {
|
return {
|
||||||
...clientData,
|
...clientData,
|
||||||
todayDayIndex: getDayOfWeekIndex(getToday()),
|
todayDayIndex: getDayOfWeekIndex(getToday()),
|
||||||
...(slot === MealSlot.EXTRA ? { slot: MealSlot.EXTRA } : {}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,9 +27,8 @@ describe('MealSlot storage isolation', () => {
|
|||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('addChoice slot=extra writes only to _extra key, not to obed key, and returns slot=EXTRA', async () => {
|
test('addChoice slot=extra writes only to _extra key, not to obed key', async () => {
|
||||||
const result = await addChoice('user1', false, LunchChoice.OBJEDNAVAM, undefined, TODAY, MealSlot.EXTRA);
|
await addChoice('user1', false, LunchChoice.OBJEDNAVAM, undefined, TODAY, MealSlot.EXTRA);
|
||||||
expect(result.slot).toBe(MealSlot.EXTRA);
|
|
||||||
expect(mockStorageData.has(TODAY_EXTRA_STR)).toBe(true);
|
expect(mockStorageData.has(TODAY_EXTRA_STR)).toBe(true);
|
||||||
expect(mockStorageData.has(TODAY_STR)).toBe(false);
|
expect(mockStorageData.has(TODAY_STR)).toBe(false);
|
||||||
const extraData = mockStorageData.get(TODAY_EXTRA_STR);
|
const extraData = mockStorageData.get(TODAY_EXTRA_STR);
|
||||||
|
|||||||
Reference in New Issue
Block a user