Manual Reference Source

app/modules/utils/router.js

  1. // @flow
  2.  
  3. const compose = require('koa-compose');
  4. const _ = require('lodash');
  5. const KoaBody = require('koa-body');
  6. const KoaRouter = require('koa-router');
  7. const Multer = require('koa-multer');
  8. const Config = require('../../config');
  9. const Access = require('../auth/access');
  10. const ApiAccess = require('../auth/api_access');
  11. const RateLimiter = require('../rate_limit/limit');
  12. const CrudController = require('../entities/crud/controllers');
  13. const Pipeline = require('./../pipeline/pipeline');
  14. const FS = require('fs');
  15. const Mime = require('mime');
  16. const Path = require('path');
  17. const Crypto = require('crypto');
  18.  
  19. /**
  20. * Generate default Koa middlewares
  21. * @param opts - Extra options:
  22. * - koa_body: object to pass to KoaBody middleware
  23. * @returns Array of middlewares
  24. */
  25. function koa_middlewares(opts: Object): Array<Function> {
  26. if ('koa_body' in opts) {
  27. return [KoaBody(opts.koa_body)];
  28. }
  29. return [KoaBody()];
  30. }
  31.  
  32. /**
  33. * Generate API middlewares
  34. * @param type - type of entity
  35. * @param access_type - one of c, r, u, d (for create, read, update, delete)
  36. * @param opts - extra options (notably with flag pass, to deactivate API authorization checks
  37. * @returns Array of middlewares
  38. */
  39. function api_middlewares(type: string,
  40. access_type: string, opts: Object): Array<Function> {
  41. const pass = 'pass' in opts ? opts.pass : false;
  42. return [ApiAccess.api_signature(pass),
  43. RateLimiter.limit(),
  44. Access.access(type, access_type, pass),
  45. Access.enforce_right,
  46. ];
  47. }
  48.  
  49. /**
  50. * Generate App middlewares
  51. * @param type - type of entity
  52. * @param opts - extra options:
  53. * - extra_middlewares: array of extra middlewares to be injected before validation
  54. * @returns Array of middlewares
  55. */
  56. function app_middlewares(type: string, opts: Object): Array<Function> {
  57. const emiddlewares = 'extra_middlewares' in opts ? opts.extra_middlewares : [];
  58. return [
  59. Pipeline.memoize_model(type),
  60. Pipeline.check(type),
  61. Pipeline.transform(type),
  62. Pipeline.merge(type),
  63. Pipeline.reset(type),
  64. Pipeline.defaults(type),
  65. Pipeline.format(type),
  66. Pipeline.complete(type),
  67. Pipeline.filter(type),
  68. // Pipeline.format(type),
  69. ...emiddlewares,
  70. Pipeline.validate(type),
  71. ];
  72. }
  73.  
  74. function get_middlewares(type: string) {
  75. return _.flatten([koa_middlewares({}),
  76. api_middlewares(type, 'r', { pass: true }),
  77. ]);
  78. }
  79.  
  80. function del_middlewares(type: string) {
  81. return _.flatten([koa_middlewares({}),
  82. api_middlewares(type, 'd', { pass: true }),
  83. ]);
  84. }
  85.  
  86. function put_middlewares(type: string, emid: Array<Function>, model: ?Object) {
  87. return _.flatten([
  88. koa_middlewares({}),
  89. api_middlewares(type, 'u', { pass: true }),
  90. app_middlewares(type, { extra_middlewares: emid || [], model }),
  91. ]);
  92. }
  93.  
  94. function post_middlewares(type: string, emid: Array<Function>, model: ?Object) {
  95. return _.flatten([
  96. koa_middlewares({}),
  97. api_middlewares(type, 'c', { pass: true }),
  98. app_middlewares(type, { extra_middlewares: emid || [], model }),
  99. ]);
  100. }
  101.  
  102. function upload_middlewares(type: string, dest: string, emid: Array<Function>, model: ?Object) {
  103. try {
  104. FS.mkdirSync(dest);
  105. } catch (err) {
  106. }
  107.  
  108. const storage = Multer.diskStorage({
  109. destination(req, file, cb) {
  110. cb(null, dest);
  111. },
  112. filename(req, file, cb) {
  113. const ext = Mime.getExtension(file.mimetype) || Path.extname(file.originalname);
  114. Crypto.pseudoRandomBytes(16, (err, raw) => {
  115. cb(null, `${raw.toString('hex') + Date.now()}.${ext}`);
  116. });
  117. },
  118. });
  119. const upload = Multer({ storage,
  120. /* limits: {
  121. fieldSize: 1024 * 1024 * 1024 * 1024 * 1024 * 10, // 10 Tb
  122. }*/ });
  123. return _.flatten([
  124. [upload.single('file'),
  125. async (ctx, next) => {
  126. ctx.request.body = ctx.req.body;
  127. ctx.request.file = ctx.req.file;
  128. return next();
  129. }],
  130. api_middlewares(type, 'c', { pass: true }),
  131. // app_middlewares(type, { extra_middlewares: emid || [], model }),
  132. ]);
  133. }
  134.  
  135. function generate_gets_routes(router: KoaRouter, prefix: string, type: string, emiddlewares: Array<Function>) {
  136. const get_mware = get_middlewares(type);
  137.  
  138. router.get(`${prefix}/${type}s/count`, compose([...get_mware, CrudController.count(type)]));
  139.  
  140. router.post(`${prefix}/${type}s/count`, compose([...get_mware, CrudController.count(type)]));
  141.  
  142. router.post(`${prefix}/${type}s/search`, compose([...get_mware, CrudController.search(type)]));
  143. router.post(`${prefix}/${type}s/search/:translatable/:lang`, compose([...get_mware, CrudController.search(type)]));
  144.  
  145. router.get(`${prefix}/${type}s/:projection/:population`, compose([...get_mware, CrudController.gets(type)]));
  146. router.get(`${prefix}/${type}s/:projection`, compose([...get_mware, CrudController.gets(type)]));
  147. router.get(`${prefix}/${type}s`, compose([...get_mware, CrudController.gets(type)]));
  148.  
  149. router.post(`${prefix}/${type}s/:projection/:population`, compose([...get_mware, CrudController.gets(type)]));
  150. router.post(`${prefix}/${type}s/:projection`, compose([...get_mware, CrudController.gets(type)]));
  151. router.post(`${prefix}/${type}s`, compose([...get_mware, CrudController.gets(type)]));
  152. }
  153.  
  154. function generate_get_routes(router: KoaRouter, prefix: string, type: string, emiddlewares: Array<Function>) {
  155. const get_mware = get_middlewares(type);
  156.  
  157. router.get(`${prefix}/${type}/exists/:id`, compose([...get_mware, CrudController.get(type, true)]));
  158.  
  159. router.get(`${prefix}/${type}/:id/:projection/:population`, compose([...get_mware, CrudController.get(type)]));
  160. router.get(`${prefix}/${type}/:id/:projection`, compose([...get_mware, CrudController.get(type)]));
  161. router.get(`${prefix}/${type}/:id`, compose([...get_mware, CrudController.get(type)]));
  162. }
  163.  
  164. function generate_del_routes(router: KoaRouter, prefix: string, type: string, emiddlewares: Array<Function>) {
  165. const del_mware = del_middlewares(type);
  166. router.del(`${prefix}/${type}/:id`, compose([...del_mware, CrudController.del(type)]));
  167. }
  168.  
  169. function generate_put_routes(router: KoaRouter, prefix: string,
  170. type: string, emiddlewares: Array<Function>,
  171. action: Function = async () => {}, action_options: Object = {}) {
  172. const put_mware = put_middlewares(type, emiddlewares);
  173. router.put(`${prefix}/${type}`, compose([...put_mware, CrudController.put_with_action(type, action, action_options)]));
  174. router.put(`${prefix}/${type}/validate`, compose([...put_mware, CrudController.validate]));
  175. router.put(`${prefix}/${type}/validate/:range`, compose([...put_mware, CrudController.validate]));
  176.  
  177. // router.put(`${prefix}/${type}/bulk`, compose([...put_mware, CrudController.put_with_action(type, action, action_options)]));
  178. }
  179.  
  180. function generate_post_routes(router: KoaRouter, prefix: string,
  181. type: string, emiddlewares: Array<Function>,
  182. action: Function = async () => {}, action_options: Object = {}) {
  183. const post_mware = post_middlewares(type, emiddlewares);
  184.  
  185. router.post(`${prefix}/${type}`, compose([...post_mware, CrudController.post_with_action(type, action, action_options)]));
  186. router.post(`${prefix}/${type}/validate`, compose([...post_mware, CrudController.validate]));
  187. router.post(`${prefix}/${type}/validate/:range`, compose([...post_mware, CrudController.validate]));
  188.  
  189. // router.post(`${prefix}/${type}/bulk`, compose([...post_mware, CrudController.post_with_action(type, action, action_options)]));
  190. }
  191.  
  192. function generate_entity_routes(router: KoaRouter,
  193. type: string, emiddlewares: Array<Function>) {
  194. const puprefix = `${Config.api.public.prefix}/${Config.api.public.version}`;
  195. generate_gets_routes(router, puprefix, type, emiddlewares);
  196. generate_get_routes(router, puprefix, type, emiddlewares);
  197. generate_del_routes(router, puprefix, type, emiddlewares);
  198. generate_post_routes(router, puprefix, type, emiddlewares);
  199. generate_put_routes(router, puprefix, type, emiddlewares);
  200. }
  201.  
  202. exports.generate_entity_routes = generate_entity_routes;
  203. exports.generate_gets_routes = generate_gets_routes;
  204. exports.generate_get_routes = generate_get_routes;
  205. exports.generate_del_routes = generate_del_routes;
  206. exports.generate_post_routes = generate_post_routes;
  207. exports.generate_put_routes = generate_put_routes;
  208. exports.koa_middlewares = koa_middlewares;
  209. exports.api_middlewares = api_middlewares;
  210. exports.app_middlewares = app_middlewares;
  211. exports.get_middlewares = get_middlewares;
  212. exports.del_middlewares = del_middlewares;
  213. exports.post_middlewares = post_middlewares;
  214. exports.put_middlewares = put_middlewares;
  215. exports.upload_middlewares = upload_middlewares;