|
- // Copyright (c) 2020 Jan Kaßel
- // Copyright (c) 2022 Gerben
- //
- // SPDX-License-Identifier: MIT
-
- import { v4 as uuid } from 'uuid';
- // import validateAnnotation from 'validate-web-annotation';
- import db from '../db.js';
- import { Container, sendAnnotation, extractAnnotationIdFromUrl } from '../ldp.js';
- import type { Request, Response } from 'express';
- import { asArray } from 'web-annotation-utils';
-
- export async function createAnnotation(req: Request, res: Response) {
- const collectionKey = `${req.params.user}/${req.params.collection}`;
- try {
- await db.get(collectionKey);
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
- if (!req.body) {
- res.status(400).send('Bad request: Missing request body');
- return;
- }
-
- const annotation = req.body;
- // TODO Improve validator; it appears to disagree about the date format.
- // if (!validateAnnotation(annotation, { optionalId: true })) {
- // res.status(400).send('Bad request: Invalid body schema');
- // return;
- // }
-
- const id = uuid();
- const annotationKey = `${collectionKey}/${id}`;
- if (annotation.id) {
- annotation.via = [...asArray(annotation.via), annotation.id];
- }
- annotation.id = id;
-
- try {
- await db.get(annotationKey);
- res.status(409).send('Conflict');
- } catch (err: any) {
- if (!err.notFound) {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- return;
- }
-
- annotation.creator ??= {
- type: 'Person',
- nickname: req.params.user,
- };
-
- await db.put(annotationKey, annotation);
-
- const collectionInfo = await db.get(collectionKey);
- const containerInfo = new Container(req, collectionKey, collectionInfo);
- res
- .status(201)
- .header('Location', `/${annotationKey}`)
- .header('Content-Location', `/${annotationKey}`);
- sendAnnotation(req, res, annotation, containerInfo);
- }
- }
-
- export async function getAnnotation(req: Request, res: Response) {
- const collectionKey = `${req.params.user}/${req.params.collection}`;
-
- try {
- await db.get(collectionKey);
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
-
- const annotationKey = `${collectionKey}/${req.params.annotation}`;
- try {
- const annotation = await db.get(annotationKey);
- const collectionInfo = await db.get(collectionKey);
- const containerInfo = new Container(req, collectionKey, collectionInfo);
- sendAnnotation(req, res, annotation, containerInfo);
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
- }
-
- export async function updateAnnotation(req: Request, res: Response) {
- const collectionKey = `${req.params.user}/${req.params.collection}`;
- try {
- await db.get(collectionKey);
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
-
- const annotation = req.body;
- if (
- !annotation ||
- // TODO Improve validator; it appears to disagree about the date format.
- // || !validateAnnotation(annotation)
- !annotation.id
- ) {
- res.status(400).send('Bad request: Invalid body schema');
- return;
- }
-
- const collectionInfo = await db.get(collectionKey);
- const containerInfo = new Container(req, collectionKey, collectionInfo);
- const normalizedId = extractAnnotationIdFromUrl(
- annotation.id,
- containerInfo.url,
- );
- if (!normalizedId) {
- res
- .status(400)
- .send(
- `Bad Request: Annotation ID did not match the expected container IRI: ${containerInfo.url}`,
- );
- return;
- }
- const contractedAnnotation = {
- ...annotation,
- id: normalizedId,
- };
- const annotationKey = `${collectionKey}/${contractedAnnotation.id}`;
- try {
- await db.get(annotationKey);
- await db.put(annotationKey, contractedAnnotation);
-
- const collectionInfo = await db.get(collectionKey);
- const containerInfo = new Container(req, collectionKey, collectionInfo);
- sendAnnotation(req, res, contractedAnnotation, containerInfo);
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
- }
-
- export async function deleteAnnotation(req: Request, res: Response) {
- const collectionKey = `${req.params.user}/${req.params.collection}`;
- try {
- await db.get(collectionKey);
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
-
- const annotationKey = `${collectionKey}/${req.params.annotation}`;
- try {
- await db.get(annotationKey);
- await db.del(annotationKey);
- res.status(204).send();
- } catch (err: any) {
- if (err.notFound) {
- res.status(404).send('Not found');
- } else {
- console.error(req.method, req.path, err);
- res.status(500).send('Internal server error');
- }
- return;
- }
- }
|