Store and publish annotations on the web, as described in the Web Annotation Discovery proposal.

web-annotation-discovery-se.../routes/ router.ts
102 lines
2.5 KiB

  1. // Copyright (c) 2020 Jan Kaßel
  2. // Copyright (c) 2022 Gerben
  3. //
  4. // SPDX-License-Identifier: MIT
  5. import express, { NextFunction, Request, Response } from 'express';
  6. import basicAuth from 'express-basic-auth';
  7. import users from '../config/users.json';
  8. import {
  9. createCollection,
  10. getCollection,
  11. deleteCollection,
  12. } from './handlers/collection.js';
  13. import {
  14. createAnnotation,
  15. getAnnotation,
  16. updateAnnotation,
  17. deleteAnnotation,
  18. } from './handlers/annotation.js';
  19. import { getUser } from './handlers/user.js';
  20. var router = express.Router();
  21. const authHandler = basicAuth({
  22. users,
  23. challenge: true,
  24. });
  25. // Require authentication only for write methods
  26. router.use((req, res, next) => {
  27. if (['POST', 'PUT', 'DELETE'].includes(req.method.toUpperCase()))
  28. authHandler(req, res, next);
  29. else next();
  30. });
  31. declare global {
  32. namespace Express {
  33. interface Request {
  34. auth?: {
  35. user: string;
  36. password: string;
  37. };
  38. }
  39. }
  40. }
  41. function checkIfAuthorised(req: Request, res: Response, next: NextFunction) {
  42. if (req.auth?.user === req.params.user) {
  43. next();
  44. } else {
  45. res.status(403).send('Forbidden');
  46. }
  47. }
  48. function ensureTrailingSlash(req: Request, res: Response, next: NextFunction) {
  49. const [originalPath, query] = req.originalUrl.split('?');
  50. if (originalPath.endsWith('/')) {
  51. next();
  52. } else {
  53. const newPath = `${originalPath}/${query ? `?${query}` : ''}`;
  54. res.redirect(301, newPath);
  55. }
  56. }
  57. router.get('/', ensureTrailingSlash, (req, res, next) => {
  58. res.render('index', {
  59. title: `Annonation server`,
  60. users: Object.keys(users),
  61. });
  62. });
  63. router.get('/login', authHandler, (req, res, next) => {
  64. if (req.auth?.user) {
  65. res.redirect(`${req.baseUrl}/${req.auth?.user}`);
  66. } else {
  67. res.status(500).send('Something wrong2.');
  68. }
  69. });
  70. router.get('/logout', (req, res, next) => {
  71. basicAuth({
  72. users: {},
  73. challenge: true,
  74. })(req, res, next);
  75. });
  76. router.get('/:user/', ensureTrailingSlash, getUser);
  77. router.post('/:user/', checkIfAuthorised, createCollection);
  78. router.get('/:user/:collection/', ensureTrailingSlash, getCollection);
  79. router.delete('/:user/:collection/', checkIfAuthorised, deleteCollection);
  80. router.post('/:user/:collection/', checkIfAuthorised, createAnnotation);
  81. router.get('/:user/:collection/:annotation', getAnnotation);
  82. router.put(
  83. '/:user/:collection/:annotation',
  84. checkIfAuthorised,
  85. updateAnnotation,
  86. );
  87. router.delete(
  88. '/:user/:collection/:annotation',
  89. checkIfAuthorised,
  90. deleteAnnotation,
  91. );
  92. export default router;