router.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. const fs = require('fs');
  2. const crypto = require('crypto');
  3. const auth = require('./auth');
  4. const db = require('./db');
  5. const doc = require('../data/documentation.json');
  6. // Constante d'erreur
  7. const ERR_REQUEST = 1;
  8. const ERR_AUTH = 2;
  9. const ERR_UNKNOW = 3;
  10. const ERR_TOKEN = 4;
  11. const ERR_SERV = 5;
  12. const ERR_FILE = 6;
  13. const ERR_REGISTER = 7;
  14. const ERR_NOTFOUND = 404;
  15. // Fonctions reponses
  16. function error(code) {
  17. let answer = {
  18. success: false,
  19. code: code
  20. };
  21. switch (code) {
  22. case ERR_REQUEST:
  23. answer.message = 'Bad request';
  24. break;
  25. case ERR_AUTH:
  26. answer.message = 'Bad authentication';
  27. break;
  28. case ERR_UNKNOW:
  29. answer.message = 'Unknow user';
  30. break;
  31. case ERR_TOKEN:
  32. answer.message = 'Invalid token';
  33. break;
  34. case ERR_SERV:
  35. answer.message = 'Server error';
  36. break;
  37. case ERR_FILE:
  38. answer.message = 'File not found';
  39. break;
  40. case ERR_REGISTER:
  41. answer.message = 'User already exist';
  42. break;
  43. case ERR_NOTFOUND:
  44. answer.message = 'Page not found';
  45. break;
  46. default:
  47. answer.message = 'Unknow error';
  48. }
  49. return answer;
  50. }
  51. function success(data) {
  52. if (data === undefined || data === null) {
  53. return {success: true};
  54. } else if (typeof data !== 'object') {
  55. return {success: true, data: data};
  56. } else {
  57. data.success = true;
  58. return data;
  59. }
  60. }
  61. const router = class Router {
  62. constructor(app) {
  63. this.app = app;
  64. }
  65. /* --- Fonctions pre traitement --- */
  66. verifyAuth(req, res, next) {
  67. if (req.body.user === undefined || req.body.token === undefined) {
  68. res.json(error(ERR_REQUEST));
  69. return;
  70. }
  71. if (auth.isActivated() && !auth.verify(req.body.user, req.body.token)) {
  72. res.json(error(ERR_TOKEN));
  73. return;
  74. }
  75. let promise = db.userExist(req.body.user);
  76. if (promise === false) {
  77. res.json(error(ERR_REQUEST));
  78. return;
  79. }
  80. promise.then((exist) => {
  81. if (exist) {
  82. next();
  83. } else {
  84. res.json(error(ERR_UNKNOW));
  85. }
  86. });
  87. }
  88. verbose(req, res, next) {
  89. if (global.verbose) {
  90. const nbProp = Object.keys(req.body);
  91. console.info(`\nCall ${req.method} ${req.route.path} with ${nbProp.length} parameter(s)`);
  92. if (nbProp.length > 0) {
  93. for (let prop in req.body) {
  94. console.info(` ${prop}: ${req.body[prop]}`);
  95. }
  96. }
  97. }
  98. next();
  99. }
  100. /* --- Definitions des routes --- */
  101. route() {
  102. this.app.get('/', [this.verbose, this.getDocumentation]);
  103. this.app.get('/authentication', [this.verbose, this.authenticationActivated]);
  104. this.app.post('/register', [this.verbose, this.register]);
  105. this.app.post('/login', [this.verbose, this.login]);
  106. this.app.get('/token', [this.verbose, this.testToken]);
  107. this.app.get('/list', [this.verbose, this.verifyAuth, this.listFile]);
  108. this.app.get('/:file', [this.verbose, this.verifyAuth, this.getFile]);
  109. this.app.post('/save', [this.verbose, this.verifyAuth, this.newFile]);
  110. this.app.put('/save/:file', [this.verbose, this.verifyAuth, this.updateFile]);
  111. this.app.put('/rename/:file', [this.verbose, this.verifyAuth, this.renameFile]);
  112. this.app.delete('/:file', [this.verbose, this.verifyAuth, this.deleteFile]);
  113. this.app.use(this.notFound);
  114. }
  115. getDocumentation(req, res) {
  116. res.json(doc);
  117. }
  118. authenticationActivated(req, res) {
  119. res.json(success({authentication: auth.isActivated()}));
  120. }
  121. register(req, res) {
  122. if (req.body.user === undefined || req.body.password === undefined) {
  123. res.json(error(ERR_REQUEST));
  124. return;
  125. }
  126. const passHash = auth.passwordHash(req.body.password);
  127. let promise = db.addUser(req.body.user, passHash);
  128. if (promise === false) {
  129. res.json(error(ERR_SERV));
  130. return;
  131. }
  132. promise.then((result) => {
  133. if (result) {
  134. return res.json(success());
  135. } else {
  136. return res.json(error(ERR_REGISTER));
  137. }
  138. });
  139. }
  140. login(req, res) {
  141. if (req.body.user === undefined || req.body.password === undefined) {
  142. res.json(error(ERR_REQUEST));
  143. return;
  144. }
  145. const promise = db.getUser(req.body.user);
  146. if (promise === false) {
  147. res.json(error(ERR_REQUEST));
  148. return;
  149. }
  150. promise.then((user) => {
  151. if (user === undefined) {
  152. res.json(error(ERR_UNKNOW));
  153. } else {
  154. if (auth.passwordVerify(req.body.password, user.pass)) {
  155. res.json(success({token: auth.generateToken(req.body.user)}));
  156. } else {
  157. res.json(error(ERR_AUTH));
  158. }
  159. }
  160. });
  161. }
  162. testToken(req, res) {
  163. if (req.body.user === undefined || req.body.token === undefined) {
  164. res.json(error(ERR_REQUEST));
  165. return;
  166. }
  167. res.json(success({valid: auth.verify(req.body.user, req.body.token)}));
  168. }
  169. listFile(req, res) {
  170. const promise = db.listFile(req.body.user);
  171. if (promise === false) {
  172. res.json(error(ERR_REQUEST));
  173. return;
  174. }
  175. promise.then((list) => {
  176. if (list === false) {
  177. res.json(error(ERR_SERV));
  178. } else {
  179. res.json(success({
  180. total: list.length,
  181. list: list
  182. }));
  183. }
  184. });
  185. }
  186. newFile(req, res) {
  187. if (req.body.file === undefined || req.body.data === undefined) {
  188. res.json(error(ERR_REQUEST));
  189. return;
  190. }
  191. let promise, filename;
  192. // Si on sauvegarde les données dans des fichiers, generation du chemin
  193. if (global.storage === 'file') {
  194. let hash = Date.now() + '-' + req.body.user + '-' + req.params.file;
  195. hash = crypto.createHash('md5').update(hash).digest('base64');
  196. hash = hash.replace(/=/g, '').replace(/\//g, '');
  197. filename = './data/' + hash + '.fdata';
  198. promise = db.addFile(req.body.user, req.body.file, filename);
  199. }
  200. // Sinon om met directement en base
  201. else {
  202. promise = db.addFile(req.body.user, req.body.file, req.body.data);
  203. }
  204. if (promise === false) {
  205. res.json(error(ERR_REQUEST));
  206. return;
  207. }
  208. promise.then((fileId) => {
  209. if (fileId === false) {
  210. res.json(ERR_SERV);
  211. } else {
  212. // Si en mode fichier stockage dans un fichier
  213. if ((global.storage === 'file')) {
  214. fs.writeFile(filename, req.body.data, (err) => {
  215. if (err) {
  216. if (global.verbose) {
  217. console.error(err);
  218. }
  219. res.json(error(ERR_SERV));
  220. } else {
  221. res.json(success({fileId: fileId, fileName: req.body.file}));
  222. }
  223. });
  224. }
  225. // Le fichier est directement sauvegarder en base
  226. else {
  227. res.json(success({fileId: fileId, fileName: req.body.file}));
  228. }
  229. }
  230. });
  231. }
  232. getFile(req, res) {
  233. const promise = db.getFile(req.body.user, req.params.file);
  234. if (promise === false) {
  235. res.json(error(ERR_REQUEST));
  236. return;
  237. }
  238. promise.then((file) => {
  239. // Erreur
  240. if (file === false) {
  241. res.json(error(ERR_SERV));
  242. } else // Le fichier n'existe pas
  243. if (file === null) {
  244. res.json(error(ERR_FILE));
  245. }
  246. // Création reponse commune
  247. else {
  248. let result = {
  249. fileid: file.fi_hash,
  250. filename: file.fi_name
  251. };
  252. // Recupération données fichier
  253. if (global.storage === 'database') {
  254. result.data = file.data;
  255. res.json(success(result));
  256. } else {
  257. if (!fs.existsSync(file.data)) {
  258. res.json(error(ERR_FILE));
  259. }
  260. fs.readFile(file.data, (err, data) => {
  261. result.data = data.toString();
  262. res.json(success(result));
  263. });
  264. }
  265. }
  266. });
  267. }
  268. updateFile(req, res) {
  269. if (req.body.data === undefined || req.params.file === undefined) {
  270. res.json(error(ERR_REQUEST));
  271. return;
  272. }
  273. // Si les données sont dans un fichier
  274. if (global.storage === 'file') {
  275. let promise = db.getFile(req.body.user, req.params.file);
  276. if (promise === false) {
  277. res.json(error(ERR_SERV));
  278. return;
  279. }
  280. promise.then((file) => {
  281. if (file === false) {
  282. res.json(error(ERR_FILE));
  283. } else if (!fs.existsSync(file.data)) {
  284. res.json(error(ERR_FILE));
  285. } else {
  286. fs.writeFile(file.data, req.body.data, (err) => {
  287. if (err) {
  288. if (global.verbose) {
  289. console.error(err);
  290. }
  291. res.json(error(ERR_SERV));
  292. } else {
  293. res.json(success({fileId: req.params.file}));
  294. }
  295. });
  296. }
  297. });
  298. }
  299. // Sinon on modifie la base
  300. else {
  301. let promise = db.updateFile(req.body.user, req.params.file, req.body.data);
  302. if (promise === false) {
  303. res.json(error(ERR_REQUEST));
  304. return;
  305. }
  306. promise.then((result) => {
  307. if (result) {
  308. res.json(success({fileId: req.params.file}));
  309. } else {
  310. res.json(error(ERR_FILE));
  311. }
  312. });
  313. }
  314. }
  315. renameFile(req, res) {
  316. if (req.body.name === undefined || req.params.file === undefined) {
  317. res.json(error(ERR_REQUEST));
  318. return;
  319. }
  320. let promise = db.renameFile(req.body.user, req.params.file, req.body.name);
  321. if (promise === false) {
  322. res.json(error(ERR_REQUEST));
  323. return;
  324. }
  325. promise.then((result) => {
  326. if (result) {
  327. res.json(success({fileId: req.params.file, filename: req.body.name}));
  328. } else {
  329. res.json(error(ERR_FILE));
  330. }
  331. });
  332. }
  333. deleteFile(req, res) {
  334. if (req.params.file === undefined) {
  335. res.json(error(ERR_REQUEST));
  336. return;
  337. }
  338. let promise = db.deleteFile(req.body.user, req.params.file);
  339. if (promise === false) {
  340. res.json(error(ERR_REQUEST));
  341. return;
  342. }
  343. promise.then((result) => {
  344. if (result) {
  345. res.json(success());
  346. } else {
  347. res.json(error(ERR_FILE));
  348. }
  349. });
  350. }
  351. notFound(req, res) {
  352. if (global.verbose) {
  353. const nbProp = Object.keys(req.body);
  354. console.info(`\nCall unknown page ${req.method} ${req.url} with ${nbProp.length} parameter(s)`);
  355. if (nbProp.length > 0) {
  356. for (let prop in req.body) {
  357. console.info(` ${prop}: ${req.body[prop]}`);
  358. }
  359. }
  360. }
  361. res.json(error(ERR_NOTFOUND));
  362. }
  363. };
  364. module.exports = router;