// Identity. Store your memories and mental belongings // Copyright (C) 2024 SofĂa Aritz // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. import { randomUUID } from "node:crypto"; import list from "./list.js"; import type { AppInterface } from "../../app.js"; import type { AuthInterface } from "../../auth.js"; import { toDBList, type DatabaseInterface } from "../../database.js"; import { Static, Type } from "@sinclair/typebox"; const EntryIDQuery = Type.Object({ entry_id: Type.String(), }); type EntryIDQueryType = Static<typeof EntryIDQuery>; const PutEntryBody = Type.Object({ entry: Type.Object({ title: Type.Optional(Type.String()), description: Type.Optional(Type.String()), creationDate: Type.String(), assets: Type.Array(Type.String()), feelings: Type.Array( Type.Union([ Type.String(), Type.Object({ identifier: Type.String(), description: Type.String(), backgroundColor: Type.String(), textColor: Type.String(), }), ]), ), base: Type.Union([ Type.Object({ kind: Type.String(), }), Type.Object({ kind: Type.String(), artist: Type.String(), title: Type.String(), link: Type.Array(Type.String()), id: Type.Array( Type.Object({ provider: Type.String(), id: Type.String(), }), ), }), Type.Object({ kind: Type.String(), location: Type.Union([ Type.String(), Type.Object({ latitude: Type.Number(), longitude: Type.Number(), }), ]), }), Type.Object({ kind: Type.String(), referencedDate: Type.String(), }), ]), }), }); type PutEntryBodyType = Static<typeof PutEntryBody>; export default function registerRoutes(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) { list(app, auth, database); app.delete<{ Querystring: EntryIDQueryType }>("/entry", { async handler(request) { let jwt = request.headers["authorization"].replace("Bearer", "").trim(); let { payload } = await auth.verifyJwt(jwt); let user = await auth.user(payload.uid); database.removeEntry(request.query.entry_id); }, schema: { headers: { $ref: "schema://identity/authorization" }, querystring: EntryIDQuery, }, }); app.put<{ Body: PutEntryBodyType }>("/entry", { async handler(request) { let jwt = request.headers["authorization"].replace("Bearer", "").trim(); let { payload } = await auth.verifyJwt(jwt); let entry = request.body.entry; let musicEntry, locationEntry, dateEntry; if ((entry.base.kind === "album" || entry.base.kind === "song") && "artist" in entry.base) { musicEntry = { id: randomUUID(), title: entry.base.title, artist: entry.base.artist, links: toDBList(entry.base.link), universalIDs: toDBList(entry.base.id), }; } else if (entry.base.kind === "environment" && "location" in entry.base) { locationEntry = { id: randomUUID(), locationText: typeof entry.base.location === "string" ? entry.base.location : undefined, locationCoordinates: typeof entry.base.location === "string" ? undefined : JSON.stringify(entry.base.location), }; } else if (entry.base.kind === "date" && "referencedDate" in entry.base) { dateEntry = { id: randomUUID(), referencedDate: Date.parse(entry.base.referencedDate), }; } await database.insertEntry( { id: randomUUID(), userID: payload.uid, feelings: toDBList(entry.feelings), assets: toDBList(entry.assets), title: entry.title, description: entry.description, kind: entry.base.kind, createdAt: Date.now(), }, musicEntry, locationEntry, dateEntry, ); }, schema: { headers: { $ref: "schema://identity/authorization" }, body: PutEntryBody, }, }); }