components/pages/routes.js

import { pageAllowedForClient, pageFilterHome } from './security.js';
import { requireHeader } from './../middleware.js';
import { backendInfo } from '../../server.js';
import { getAllPages, getPage } from './backend.js';

const pageAccess = () => {
  return async function (req, res, next) {
    const org = req.headers['x-openhab-org'] || '';
    const user = req.headers['x-openhab-user'];
    try {
      const allowed = await pageAllowedForClient(backendInfo.HOST, req, user, org, req.params.pageUid);
      if (allowed === true) {
        next();
      } else {
        res.status(403).send();
      }
    } catch {
      res.status(500).send();
    }
  };
};

/**
 * Provides required /pages routes.
 *
 * @memberof routes
 * @param {*} app expressjs app
 */
const pages = (app) => {
  /**
   * @swagger
   * /auth/pages:
   *   get:
   *     summary: Authorization endpoint for Page access.
   *     description: Used by NGINX auth_request.
   *     tags: [Auth]
   *     parameters:
   *       - in: header
   *         name: X-OPENHAB-USER
   *         required: true
   *         description: Name of user
   *         schema:
   *           type: string
   *         style: form
   *       - in: header
   *         name: X-OPENHAB-ORG
   *         required: false
   *         description: Organisations the user is member of
   *         schema:
   *           type: string
   *         style: form
   *       - in: header
   *         name: X-ORIGINAL-URI
   *         required: true
   *         description: Original request URI
   *         schema:
   *           type: string
   *         style: form
   *     responses:
   *       200:
   *         description: Allowed
   *       403:
   *         description: Forbidden
   */
  app.get('/auth/pages', requireHeader('X-OPENHAB-USER'), requireHeader('X-ORIGINAL-URI'), async (req, res) => {
    const org = req.headers['x-openhab-org'] || '';
    const user = req.headers['x-openhab-user'];
    const regex = /\/page\/([a-zA-Z_0-9]+)/;
    const pageUid = regex.exec(req.headers['x-original-uri']);
    if (pageUid == null) return res.status(403).send();
    try {
      const allowed = await pageAllowedForClient(backendInfo.HOST, req, user, org, pageUid[1]);
      if (allowed === true) {
        res.status(200).send();
      } else {
        res.status(403).send();
      }
    } catch {
      res.status(500).send();
    }
  });

  /**
   * @swagger
   * /rest/ui/components/ui:page:
   *   get:
   *     summary: Get all available Pages.
   *     tags: [Pages]
   *     parameters:
   *       - in: header
   *         name: X-OPENHAB-USER
   *         required: true
   *         description: Name of user
   *         schema:
   *           type: string
   *         style: form
   *       - in: header
   *         name: X-OPENHAB-ORG
   *         required: false
   *         description: Organisations the user is member of
   *         schema:
   *           type: string
   *         style: form
   *     responses:
   *       200:
   *         description: OK
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   */
  app.get('/rest/ui/components/ui[:]page', requireHeader('X-OPENHAB-USER'), async (req, res) => {
    const org = req.headers['x-openhab-org'] || '';
    const user = req.headers['x-openhab-user'];
    try {
      const allPages = await getAllPages(backendInfo.HOST, req);
      let filteredPages = [];
      for (const i in allPages) {
          if (await pageAllowedForClient(backendInfo.HOST, req, user, org, allPages[i].uid) === true) {
              if (allPages[i].uid === 'home') {
                  const filteredHome = await pageFilterHome(backendInfo.HOST, req, user, org, allPages[i]);
                  filteredPages.push(filteredHome);
              } else {
                  filteredPages.push(allPages[i]);
              }
          }
      }
      res.status(200).send(filteredPages);
    } catch (e) {
      console.info(e);
      res.status(500).send();
    }
  });

  /**
   * @swagger
   * /rest/ui/components/ui:page/{pageUid}:
   *   get:
   *     summary: Gets a single Page.
   *     tags: [Pages]
   *     parameters:
   *       - in: path
   *         name: pageUid
   *         required: true
   *         description: Page uid
   *         schema:
   *           type: string
   *         style: form
   *       - in: header
   *         name: X-OPENHAB-USER
   *         required: true
   *         description: Name of user
   *         schema:
   *           type: string
   *         style: form
   *       - in: header
   *         name: X-OPENHAB-ORG
   *         required: false
   *         description: Organisations the user is member of
   *         schema:
   *           type: string
   *         style: form
   *     responses:
   *       200:
   *         description: OK
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *       403:
   *         description: Page access forbidden
   *       404:
   *         description: Page not found
   */
  app.get('/rest/ui/components/ui[:]page/:pageUid', requireHeader('X-OPENHAB-USER'), pageAccess(), async (req, res) => {
    const org = req.headers['x-openhab-org'] || '';
    const user = req.headers['x-openhab-user'];
    try {
      const response = await getPage(backendInfo.HOST, req, req.params.pageUid);
      if(req.params.pageUid === 'home') {
        const filteredHome = await pageFilterHome(backendInfo.HOST, req, user, org, response.json);
        res.status(response.status).send(filteredHome);
      } else {
        res.status(response.status).send(response.json);
      }
    } catch (e) {
      console.info(e);
      res.status(500).send();
    }
  });
  
  /**
   * @swagger
   * /rest/ui/components/{namespace}/{componentUID}:
   *   get:
   *     summary: Gets other Main UI components. Requires nginx.
   *     tags: [Pages]
   *     parameters:
   *       - in: path
   *         name: namespace
   *         required: true
   *         description: Component namespace
   *         schema:
   *           type: string
   *         style: form
   *       - in: path
   *         name: componentUID
   *         required: false
   *         description: Component UID
   *         schema:
   *           type: string
   *         style: form
   *       - in: parameters
   *         name: parameters
   *         required: true
   *         description: Query parameters (e.g. summary)
   *         schema:
   *           type: string
   *         style: form   
   *     responses:
   *       200:
   *         description: OK
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *       404:
   *         description: Component not found
   */  
  
  /**
   * @swagger
   * /page/{pageUID}:
   *   get:
   *     summary: Gets Main UI page. Requires nginx.
   *     tags: [Pages]
   *     parameters:
   *       - in: path
   *         name: pageUID
   *         required: true
   *         description: Page UID
   *         schema:
   *           type: string
   *         style: form
   *     responses:
   *       200:
   *         description: OK
   */  

};


export default pages;