You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.6 KiB
TypeScript

import type { RequestHandler } from './$types';
import { getDb } from '$lib/server/db';
import { findActiveToken, createCalendarTokenUrl, buildCalendarIcsUrl } from '$lib/server/calendar-tokens';
export const GET: RequestHandler = async (event) => {
// Requiere sesión
const userId = event.locals.userId ?? null;
if (!userId) {
return new Response('Unauthorized', { status: 401 });
}
const db = await getDb();
// Listar solo grupos permitidos donde el usuario está activo (mismo gating que /api/me/groups)
const groups = db
.prepare(
`SELECT g.id, g.name
FROM groups g
INNER JOIN group_members gm
ON gm.group_id = g.id AND gm.user_id = ? AND gm.is_active = 1
INNER JOIN allowed_groups ag
ON ag.group_id = g.id AND ag.status = 'allowed'
WHERE COALESCE(g.active, 1) = 1
ORDER BY (g.name IS NULL) ASC, g.name ASC, g.id ASC`
)
.all(userId) as Array<{ id: string; name: string | null }>;
// Personal
const personalExisting = await findActiveToken('personal', userId, null);
const personal =
personalExisting
? { url: personalExisting.token_plain ? buildCalendarIcsUrl('personal', personalExisting.token_plain) : null }
: await (async () => {
const created = await createCalendarTokenUrl('personal', userId, null);
return { url: created.url };
})();
// Aggregate (multigrupo)
const aggregateExisting = await findActiveToken('aggregate', userId, null);
const aggregate =
aggregateExisting
? { url: aggregateExisting.token_plain ? buildCalendarIcsUrl('aggregate', aggregateExisting.token_plain) : null }
: await (async () => {
const created = await createCalendarTokenUrl('aggregate', userId, null);
return { url: created.url };
})();
// Por grupo (B): autogenerar si falta
const groupFeeds: Array<{ groupId: string; groupName: string | null; url: string | null }> = [];
for (const g of groups) {
const ex = await findActiveToken('group', userId, g.id);
if (ex) {
const url = ex.token_plain ? buildCalendarIcsUrl('group', ex.token_plain) : null;
groupFeeds.push({ groupId: g.id, groupName: g.name ?? null, url });
} else {
const created = await createCalendarTokenUrl('group', userId, g.id);
groupFeeds.push({ groupId: g.id, groupName: g.name ?? null, url: created.url });
}
}
const body = {
personal,
groups: groupFeeds,
aggregate
};
return new Response(JSON.stringify(body), {
status: 200,
headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
});
};