Files
Luncher/server/src/stores.ts
T
mates 88b9e20e2d
CI / Generate TypeScript types (push) Successful in 9s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 25s
CI / Build client (push) Successful in 37s
CI / Playwright E2E tests (push) Successful in 1m18s
CI / Build and push Docker image (push) Successful in 39s
CI / Notify (push) Successful in 2s
feat: proklik na stránky podniku ze stránky objednávek
2026-06-10 19:09:20 +02:00

74 lines
2.5 KiB
TypeScript

import { Store } from "../../types/gen/types.gen";
import getStorage from "./storage";
const storage = getStorage();
const STORES_KEY = 'stores';
/**
* Vrátí seznam povolených obchodů. Zachovává zpětnou kompatibilitu se starším
* formátem, kdy byly obchody uloženy jako pole řetězců (převede je na objekty).
*/
export async function getStores(): Promise<Store[]> {
const raw = await storage.getData<(string | Store)[]>(STORES_KEY);
if (!raw) {
return [];
}
return raw.map(s => (typeof s === 'string' ? { name: s } : s));
}
/**
* Přidá nový obchod do seznamu povolených.
*
* @param name název obchodu
* @param heslo admin heslo
* @param url volitelná URL na nabídku podniku
*/
export async function addStore(name: string, heslo: string, url?: string): Promise<Store[]> {
const adminPassword = process.env.ADMIN_PASSWORD;
if (!adminPassword || heslo !== adminPassword) {
throw new Error('UNAUTHORIZED');
}
const trimmed = name.trim();
if (!trimmed) {
throw new Error('Název obchodu nesmí být prázdný');
}
const stores = await getStores();
if (stores.some(s => s.name.toLowerCase() === trimmed.toLowerCase())) {
throw new Error('Obchod s tímto názvem již existuje');
}
const trimmedUrl = url?.trim();
if (trimmedUrl) {
// Povolíme pouze http(s), aby URL nemohla být zneužita (např. javascript: → XSS)
let parsed: URL;
try {
parsed = new URL(trimmedUrl);
} catch {
throw new Error('Neplatná URL obchodu');
}
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
throw new Error('URL musí začínat http:// nebo https://');
}
}
const store: Store = trimmedUrl ? { name: trimmed, url: trimmedUrl } : { name: trimmed };
const updated = [...stores, store];
await storage.setData(STORES_KEY, updated);
return updated;
}
/**
* Odebere obchod ze seznamu povolených (dle názvu).
*
* @param name název obchodu
* @param heslo admin heslo
*/
export async function removeStore(name: string, heslo: string): Promise<Store[]> {
const adminPassword = process.env.ADMIN_PASSWORD;
if (!adminPassword || heslo !== adminPassword) {
throw new Error('UNAUTHORIZED');
}
const stores = await getStores();
const updated = stores.filter(s => s.name.toLowerCase() !== name.trim().toLowerCase());
await storage.setData(STORES_KEY, updated);
return updated;
}