Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

251 lignes
10 KiB

  1. const fs = require('fs-extra');
  2. const debug = require('debug')('server-connect:setup:routes');
  3. const config = require('./config');
  4. const { map } = require('../core/async');
  5. const { posix, extname } = require('path');
  6. const { cache, serverConnect, templateView } = require('../core/middleware');
  7. const database = require('./database');
  8. const webhooks = require('./webhooks');
  9. module.exports = async function (app) {
  10. app.use((req, res, next) => {
  11. req.fragment = (req.headers['accept'] || '*/*').includes('fragment');
  12. next();
  13. });
  14. if (fs.existsSync('extensions/server_connect/routes')) {
  15. const entries = fs.readdirSync('extensions/server_connect/routes', { withFileTypes: true });
  16. for (let entry of entries) {
  17. if (entry.isFile() && extname(entry.name) == '.js') {
  18. let hook = require(`../../extensions/server_connect/routes/${entry.name}`);
  19. if (hook.before) hook.before(app);
  20. if (hook.handler) hook.handler(app);
  21. debug(`Custom router ${entry.name} loaded`);
  22. }
  23. }
  24. }
  25. database(app);
  26. webhooks(app);
  27. if (config.createApiRoutes) {
  28. fs.ensureDirSync('app/api');
  29. createApiRoutes('app/api');
  30. }
  31. if (fs.existsSync('app/config/routes.json')) {
  32. const { routes, layouts } = fs.readJSONSync('app/config/routes.json');
  33. parseRoutes(routes, null);
  34. function parseRoutes(routes, parent) {
  35. for (let route of routes) {
  36. if (!route.path) continue;
  37. createRoute(route, parent);
  38. if (Array.isArray(route.routes)) {
  39. parseRoutes(route.routes, route);
  40. }
  41. }
  42. }
  43. function createRoute({ auth, path, method, redirect, url, page, layout, exec, data, ttl, status, proxy }, parent) {
  44. method = method || 'all';
  45. data = data || {};
  46. if (page) page = page.replace(/^\//, '');
  47. if (layout) layout = layout.replace(/^\//, '');
  48. if (parent && parent.path) path = parent.path + path;
  49. if (auth) {
  50. app.use(path, (req, res, next) => {
  51. if (typeof auth == 'string' && req.session && req.session[auth + 'Id']) {
  52. next();
  53. } else if (typeof auth == 'object' && auth.user) {
  54. const b64auth = (req.headers.authorization || '').split(' ')[1] || '';
  55. const [user, password] = Buffer.from(b64auth, 'base64').toString().split(':');
  56. if (user && password && user === auth.user && password === auth.password) {
  57. next();
  58. } else {
  59. res.set('WWW-Authenticate', 'Basic realm="401"');
  60. res.status(401).json({ error: 'Unauthorized' });
  61. }
  62. } else {
  63. res.status(401).json({ error: 'Unauthorized' });
  64. }
  65. });
  66. }
  67. if (proxy) {
  68. const httpProxy = require('http-proxy');
  69. const proxyServer = httpProxy.createProxyServer(proxy);
  70. app.use(path, (req, res) => {
  71. proxyServer.web(req, res);
  72. });
  73. } else if (redirect) {
  74. app.get(path, (req, res) => res.redirect(status == 302 ? 302 : 301, redirect));
  75. } else if (url) {
  76. app[method](path, (req, res, next) => {
  77. next(parent && !req.fragment ? 'route' : null);
  78. }, (req, res) => {
  79. res.sendFile(url, { root: 'public' })
  80. });
  81. if (parent) {
  82. createRoute({
  83. path,
  84. method: parent.method,
  85. redirect: parent.redirect,
  86. url: parent.url,
  87. page: parent.page,
  88. layout: parent.layout,
  89. exec: parent.exec,
  90. data: parent.data
  91. });
  92. }
  93. } else if (page) {
  94. if (exec) {
  95. if (fs.existsSync(`app/${exec}.json`)) {
  96. let json = fs.readJSONSync(`app/${exec}.json`);
  97. if (json.exec && json.exec.steps) {
  98. json = json.exec.steps;
  99. } else if (json.steps) {
  100. json = json.steps;
  101. }
  102. if (!Array.isArray(json)) {
  103. json = [json];
  104. }
  105. if (layout && layouts && layouts[layout]) {
  106. if (layouts[layout].data) {
  107. data = Object.assign({}, layouts[layout].data, data);
  108. }
  109. if (layouts[layout].exec) {
  110. if (fs.existsSync(`app/${layouts[layout].exec}.json`)) {
  111. let _json = fs.readJSONSync(`app/${layouts[layout].exec}.json`);
  112. if (_json.exec && _json.exec.steps) {
  113. _json = _json.exec.steps;
  114. } else if (_json.steps) {
  115. _json = _json.steps;
  116. }
  117. if (!Array.isArray(_json)) {
  118. _json = [_json];
  119. }
  120. json = _json.concat(json);
  121. } else {
  122. debug(`Route ${path} skipped, "app/${exec}.json" not found`);
  123. return;
  124. }
  125. }
  126. }
  127. app[method](path, (req, res, next) => {
  128. next(parent && !req.fragment ? 'route' : null);
  129. }, cache({ttl}), templateView(layout, page, data, json));
  130. } else {
  131. debug(`Route ${path} skipped, "app/${exec}.json" not found`);
  132. return;
  133. }
  134. } else {
  135. let json = [];
  136. if (layout && layouts && layouts[layout]) {
  137. if (layouts[layout].data) {
  138. data = Object.assign({}, layouts[layout].data, data);
  139. }
  140. if (layouts[layout].exec) {
  141. if (fs.existsSync(`app/${layouts[layout].exec}.json`)) {
  142. let _json = fs.readJSONSync(`app/${layouts[layout].exec}.json`);
  143. if (_json.exec && _json.exec.steps) {
  144. _json = _json.exec.steps;
  145. } else if (_json.steps) {
  146. _json = _json.steps;
  147. }
  148. if (!Array.isArray(_json)) {
  149. _json = [_json];
  150. }
  151. json = _json.concat(json);
  152. } else {
  153. debug(`Route ${path} skipped, "app/${exec}.json" not found`);
  154. return;
  155. }
  156. }
  157. }
  158. app[method](path, (req, res, next) => {
  159. next(parent && !req.fragment ? 'route' : null);
  160. }, cache({ttl}), templateView(layout, page, data, json));
  161. }
  162. if (parent) {
  163. createRoute({
  164. path,
  165. method: parent.method,
  166. redirect: parent.redirect,
  167. url: parent.url,
  168. page: parent.page,
  169. layout: parent.layout,
  170. exec: parent.exec,
  171. data: parent.data
  172. });
  173. }
  174. } else if (exec) {
  175. if (fs.existsSync(`app/${exec}.json`)) {
  176. let json = fs.readJSONSync(`app/${exec}.json`);
  177. app[method](path, cache({ttl}), serverConnect(json));
  178. return;
  179. }
  180. }
  181. }
  182. }
  183. if (fs.existsSync('extensions/server_connect/routes')) {
  184. const entries = fs.readdirSync('extensions/server_connect/routes', { withFileTypes: true });
  185. for (let entry of entries) {
  186. if (entry.isFile() && extname(entry.name) == '.js') {
  187. let hook = require(`../../extensions/server_connect/routes/${entry.name}`);
  188. if (hook.after) hook.after(app);
  189. debug(`Custom router ${entry.name} loaded`);
  190. }
  191. }
  192. }
  193. function createApiRoutes(dir) {
  194. const entries = fs.readdirSync(dir, { withFileTypes: true });
  195. return map(entries, async (entry) => {
  196. let path = posix.join(dir, entry.name);
  197. if (entry.isFile() && extname(path) == '.json') {
  198. let json = fs.readJSONSync(path);
  199. let routePath = (json.settings && json.settings.options && json.settings.options.path) ? json.settings.options.path : path.replace(/^app/i, '').replace(/.json$/, '(.json)?');
  200. let routeMethod = (json.settings && json.settings.options && json.settings.options.method) ? json.settings.options.method : 'all';
  201. let ttl = (json.settings && json.settings.options && json.settings.options.ttl) ? json.settings.options.ttl : 0;
  202. app[routeMethod](routePath, cache({ttl}), serverConnect(json));
  203. debug(`Api route ${routePath} created`);
  204. }
  205. if (entry.isDirectory()) {
  206. return createApiRoutes(path);
  207. }
  208. });
  209. }
  210. };