index_BACK.js 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. //Dedicated router for retrieving 'tool'
  2. var logger = require('../../../utils/logger');
  3. var ip = require('ip');
  4. var router = require('express').Router();
  5. var Tool = require('../../../models/Tool');
  6. //Middleware to use for every request
  7. router.use(function (req, res, next) {
  8. next();
  9. });
  10. /* ================================================================================================================== */
  11. /**
  12. * ROUTE: /api/tool/
  13. * METHOD(S): POST
  14. */
  15. /* ================================================================================================================== */
  16. router.route('/')
  17. /**
  18. * Request: POST /api/tool/
  19. * Returns: JSON Object
  20. * Logged: YES
  21. *
  22. * Description:
  23. * Creates a new (empty) tool in the DB.
  24. * Requires that an id and name be supplied for the new tool in the body of the request.
  25. *
  26. * Body (Required):
  27. * toolId [Number] The id of the tool to be added.
  28. * toolName [String] The name of the tool to be added.
  29. *
  30. * Responses:
  31. * HTTP 200 [Success] Returned if tool was created.
  32. * { created: true }
  33. *
  34. * HTTP 400 [Error] Returned if there was a missing parameter. Response -> 'errors' will contain the missing field
  35. * {
  36. * created: false,
  37. * errors: "Missing parameter 'XXXXXX'"
  38. * }
  39. * HTTP 422 [Error] Returned if the request went through successfully, but there was an issue creating the tool.
  40. * {
  41. * created: false,
  42. * errors: "New tool creation failed. Duplicate tool id. Please check all inputs."
  43. * }
  44. */
  45. .post(function (req, res) {
  46. //Get the toolId and toolName from the body of the request
  47. var toolId = req.body.toolId;
  48. var toolName = req.body.toolName;
  49. //Check that the request body contains the required data
  50. if (toolId && toolName) {
  51. //Parse the int just to make sure it is actually an integer before we create the tool
  52. var _id = parseInt(toolId);
  53. //Declare a new Tool object using the model
  54. var newTool = new Tool({
  55. _id: _id,
  56. id: _id,
  57. name: toolName,
  58. about: [],
  59. training: [],
  60. links: []
  61. });
  62. //Save to MongoDB
  63. newTool.save(function (err) {
  64. //If there was an error while saving, send it back to the client
  65. if (err) {
  66. var message = "";
  67. //In this case, 11000 is the error code for a duplicate key
  68. if (err.code == 11000)
  69. message = "New tool creation failed. Duplicate tool id. Please check all inputs.";
  70. //Otherwise, just set the message = error message from mongoose
  71. else
  72. message = err.errmsg;
  73. //Send an HTTP 422 (Unprocessable Entity) with the error message.
  74. //Why HTTP 422: HTTP 400 is bad syntax. Correct syntax was supplied, but something went wrong during the request
  75. res.status(422).send({created: false, errors: message});
  76. //Log this request
  77. logger.info("[" + ip.address() + "] New tool creation failed. Tool id=" + toolId + " Reason: " + message);
  78. }
  79. //Otherwise, the addition was successful
  80. else {
  81. //Send an HTTP 201 (Created)
  82. res.status(201).send({created: true});
  83. //Log this request
  84. logger.info("[" + ip.address() + "] New tool creation succeeded. toolId=" + toolId);
  85. }
  86. });
  87. }
  88. //Otherwise, the required data was not supplied in the request. DO NOT attempt to access the DB in this case.
  89. else {
  90. var message = "";
  91. //If-else block to determine which parameter was missing. Sets the message text = missing param
  92. if (!req.body.toolId)
  93. message = "Missing body parameter 'toolId'.";
  94. else
  95. message = "Missing body parameter 'toolName'.";
  96. //Send an HTTP 400 (Bad Request) back with the error message
  97. res.status(400).send({created: false, errors: message});
  98. }
  99. });
  100. /* ================================================================================================================== */
  101. /**
  102. * ROUTE: /api/tool/:tool_id
  103. * METHOD(S): GET
  104. */
  105. /* ================================================================================================================== */
  106. router.route('/:toolId')
  107. /**
  108. * Request: GET /api/tool/:toolId
  109. * Returns: JSON Object
  110. * Logged: NO
  111. *
  112. * Description:
  113. * Retrieves a single tool from the DB in its entirety.
  114. *
  115. * Body (Required):
  116. * toolId [Number] The id of the tool to retrieve.
  117. *
  118. * Responses:
  119. * HTTP 200 [Success] Returned if a tool was found with a matching id.
  120. * {
  121. * _id: 01234,
  122. * id: 01234,
  123. * name: "Test Tool",
  124. * about: [],
  125. * training: [],
  126. * links: []
  127. * }
  128. *
  129. * HTTP 400 [Error] Returned if the 'toolId' param was not supplied.
  130. * { errors: ""Missing parameter 'toolId'" }
  131. *
  132. * HTTP 404 [Error] Returned if a tool could not be found with the given id.
  133. * { errors: "Could not find a tool with id=12345" }
  134. */
  135. .get(function (req, res) {
  136. //Get the toolId from the request params
  137. var toolId = req.params.toolId;
  138. //Check that a toolId was given
  139. if (toolId) {
  140. //Query the DB for a matching document
  141. Tool.findOne({'id': toolId}, function (err, tool) {
  142. //If there was an error while querying, send it as an error back to the client
  143. if (err)
  144. res.status(404).send({errors: err});
  145. //If the tool retrieved is null, a matching tool was not found
  146. else if (tool == null)
  147. res.status(404).send({errors: "Could not find a tool with id=" + toolId});
  148. //Otherwise, a matching tool was found
  149. else
  150. res.status(200).send(tool);
  151. });
  152. }
  153. //Otherwise, the toolId is missing
  154. else {
  155. //Send an HTTP 400 (Bad Request) back with the error message
  156. res.status(400).send({errors: "Missing parameter 'toolId'"});
  157. }
  158. });
  159. /* ================================================================================================================== */
  160. /**
  161. * ROUTE: /api/tool/:toolId/:sectionName
  162. * METHOD(S): GET / POST
  163. */
  164. /* ================================================================================================================== */
  165. router.route('/:toolId/:sectionName')
  166. /**
  167. * Request: GET /api/tool/:toolId/:sectionName
  168. * Returns: JSON Array
  169. * Logged: NO
  170. *
  171. * Description:
  172. * Retrieves a single tool section for a particular tool from the DB.
  173. *
  174. * Params (Required):
  175. * toolId [Number] The id of the tool to retrieve.
  176. * sectionName [String] The name of the section (i.e. 'About') to retrieve.
  177. *
  178. * Responses:
  179. * HTTP 200 [Success] Returned if the matching toolId and sectionName combo was found.
  180. * [
  181. * {
  182. * "heading": "What is JIRA?",
  183. * "contents": "JIRA is the name of our new Change Management System that will replace ClearQuest, CDG and CEM. JIRA is a proprietary issue tracking product, developed by [Atlassian](https://atlassian.com). It provides bug and issue tracking, and project management functions. It also provides the capability to manage Agile Backlog records."
  184. * }
  185. *
  186. * ...
  187. * ]
  188. *
  189. * HTTP 400 [Failure] Returned if there was a missing param in the request body
  190. * { errors: "Missing body parameter 'toolId'" }
  191. *
  192. * HTTP 404 [Failure] Returned if the matching toolId and sectionName combo was NOT found.
  193. * { errors: "Could not find matching toolId and sectionName combo." }
  194. */
  195. .get(function (req, res) {
  196. //Get the tool id and section name from the params of the request
  197. var toolId = req.params.toolId;
  198. var sectionName = req.params.sectionName.toLowerCase();
  199. //Check that the params were actually supplied in the request
  200. if (toolId && sectionName) {
  201. //Look for a matching document in the DB
  202. Tool.findOne({'id': toolId}, function (err, tool) {
  203. //Catch any general errors and send them back to the client
  204. if (err)
  205. res.status(404).send({errors: err});
  206. //Otherwise, there was (or was not) a matching document
  207. else
  208. //If the matching toolId + sectionName combo was not found, send back a 404
  209. if (tool[sectionName] == undefined || tool[sectionName] == null)
  210. res.status(404).send({errors: "Could not find matching toolId and sectionName combo."});
  211. //Otherwise, send back the matching JSON Array
  212. else
  213. res.status(200).send(tool[sectionName]);
  214. });
  215. }
  216. //Otherwise, the required data was not supplied in the request. DO NOT attempt to access the DB in this case.
  217. else {
  218. var message = "";
  219. //If-else block to determine which parameter was missing. Sets the message text = missing param
  220. if (!toolId)
  221. message = "Missing parameter 'toolId'.";
  222. else
  223. message = "Missing parameter 'sectionName'.";
  224. //Send an HTTP 400 (Bad Request) back with the error message
  225. res.status(400).send({errors: message});
  226. }
  227. })
  228. /**
  229. * Request: POST /api/tool/:toolId/:sectionName
  230. * Returns: JSON Object
  231. * Logged: YES
  232. *
  233. * Description:
  234. * Adds a new item to the tool/section name list (i.e. a new card)
  235. *
  236. * Body (Required):
  237. * toolId [Number] The id of the tool to retrieve.
  238. * sectionName [String] The name of the section (i.e. 'About') to retrieve.
  239. *
  240. * Responses:
  241. * HTTP 201 [Success] Returned if the new item was successfully added.
  242. * { added: true }
  243. *
  244. * HTTP 400 [Failure] Returned if there was a missing param.
  245. * { errors: "Missing parameter 'toolId'" }
  246. *
  247. * HTTP 404 [Failure] Returned if the matching toolId and sectionName combo was NOT found.
  248. * { errors: "Could not find matching toolId and sectionName combo." }
  249. *
  250. * HTTP 422 [Failure] Returned if there was an error while saving the document.
  251. * { added: false, errors: err }
  252. */
  253. .post(function (req, res) {
  254. //Get the tool id and section name from the params of the request
  255. var toolId = req.params.toolId;
  256. var sectionName = req.params.sectionName.toLowerCase();
  257. //Check that the params were actually supplied in the request
  258. if (toolId && sectionName) {
  259. var heading = req.body.heading;
  260. var contents = req.body.contents;
  261. //Check that the heading and contents were supplied in the body of the request
  262. if (heading && contents) {
  263. Tool.findOne({'id': toolId}, function (err, tool) {
  264. //Catch any general errors and send them back to the client
  265. if (err)
  266. res.status(404).send({errors: err});
  267. else {
  268. //If the matching toolId + sectionName combo was not found, send back a 404
  269. if (tool[sectionName] == undefined || tool[sectionName] == null)
  270. res.status(404).send({errors: "Could not find matching toolId and sectionName combo."});
  271. //Otherwise, a matching toolId and sectionName combo was found
  272. else {
  273. //Push a new document with the request body supplied to the sectionName array
  274. tool[sectionName].push({"heading": heading, "contents": contents});
  275. //Attempt to save the document (tool)
  276. tool.save(function (err) {
  277. //If there was an error while saving, send back a 422 (Unprocessable Entity)
  278. if (err) {
  279. logger.info("[" + ip.address() + "] New item addition failed. Tool ID / Section Name=" + toolId + " " + sectionName + " | Reason= " + err);
  280. res.status(422).send({added: false, errors: err});
  281. }
  282. //Otherwise, the document was saved successfully
  283. else {
  284. logger.info("[" + ip.address() + "] New item addition succeeded. Tool ID / Section Name=" + toolId + " " + sectionName);
  285. res.status(201).send({added: true});
  286. }
  287. });
  288. }
  289. }
  290. });
  291. }
  292. else {
  293. var errorMessage = "";
  294. //If-else block to determine which parameter was missing. Sets the message text = missing param
  295. if (!toolId)
  296. errorMessage = "Missing parameter 'heading'.";
  297. else
  298. errorMessage = "Missing parameter 'contents'.";
  299. //Send an HTTP 400 (Bad Request) back with the error message
  300. res.status(400).send({errors: errorMessage});
  301. }
  302. }
  303. //Otherwise, the required data was not supplied in the request. DO NOT attempt to access the DB in this case.
  304. else {
  305. var message = "";
  306. //If-else block to determine which parameter was missing. Sets the message text = missing param
  307. if (!toolId)
  308. message = "Missing parameter 'toolId'.";
  309. else
  310. message = "Missing parameter 'sectionName'.";
  311. //Send an HTTP 400 (Bad Request) back with the error message
  312. res.status(400).send({errors: message});
  313. }
  314. });
  315. /* ================================================================================================================== */
  316. /**
  317. * ROUTE: /api/tool/:toolId/:sectionName/count
  318. * METHOD(S): GET / POST
  319. */
  320. /* ================================================================================================================== */
  321. router.route('/:toolId/:sectionName/count')
  322. /**
  323. * Request: GET /api/tool/:toolId/:sectionName/count
  324. * Returns: JSON Object
  325. * Logged: NO
  326. *
  327. * Description:
  328. * Retrieves the count of items in a tool & section combo.
  329. *
  330. * Params (Required):
  331. * toolId [Number] The id of the tool to retrieve.
  332. * sectionName [String] The name of the section (i.e. 'About') to retrieve.
  333. *
  334. * Responses:
  335. * HTTP 200 [Success] Returned if a matching tool and section combo was found.
  336. * { count: 10 }
  337. *
  338. * HTTP 400 [Failure] Returned if there was a missing param.
  339. * { errors: "Missing parameter 'toolId'" }
  340. *
  341. * HTTP 404 [Failure] Returned if the matching toolId and sectionName combo was NOT found.
  342. * { errors: "Could not find matching toolId and sectionName combo." }
  343. */
  344. .get(function (req, res) {
  345. var toolId = req.params.toolId;
  346. var sectionName = req.params.sectionName.toLowerCase();
  347. //Check that the params were actually supplied in the request
  348. if (toolId && sectionName) {
  349. Tool.findOne({'id': toolId}, function (err, tool) {
  350. //Catch any general errors and send them back to the client
  351. if (err)
  352. res.status(404).send({errors: err});
  353. //Otherwise, there was (or was not) a matching document
  354. else
  355. //If the matching toolId + sectionName combo was not found, send back a 404
  356. if (tool[sectionName] == undefined || tool[sectionName] == null)
  357. res.status(404).send({errors: "Could not find matching toolId and sectionName combo."});
  358. //Otherwise, send back the count
  359. else
  360. res.status(200).send({count: tool[sectionName].length});
  361. });
  362. }
  363. //Otherwise, the required data was not supplied in the request. DO NOT attempt to access the DB in this case.
  364. else {
  365. var message = "";
  366. //If-else block to determine which parameter was missing. Sets the message text = missing param
  367. if (!toolId)
  368. message = "Missing parameter 'toolId'.";
  369. else
  370. message = "Missing parameter 'sectionName'.";
  371. //Send an HTTP 400 (Bad Request) back with the error message
  372. res.status(400).send({errors: message});
  373. }
  374. });
  375. /* ================================================================================================================== */
  376. /**
  377. * ROUTE: /api/tool/:toolId/:sectionName/:itemNum
  378. * METHOD(S): GET / DELETE
  379. */
  380. /* ================================================================================================================== */
  381. router.route('/:toolId/:sectionName/:itemNum')
  382. /**
  383. * Request: GET /api/tool/:toolId/:sectionName/:itemNum
  384. * Returns: JSON Object
  385. * Logged: NO
  386. *
  387. * Description:
  388. * Retrieves the particular item (i.e. card) from the given section name list for the given tool
  389. *
  390. * Params (Required):
  391. * toolId [Number] The id of the tool to retrieve.
  392. * sectionName [String] The name of the section (i.e. 'About') to retrieve.
  393. * itemNum [Number] The position of the item in the list (ex: 0 = 1st item).
  394. *
  395. * Responses:
  396. * HTTP 200 [Success] Returned if a matching item was found
  397. * { heading: "What is JIRA?", contents: "..." }
  398. *
  399. * HTTP 400 [Failure] Returned if there was a missing param.
  400. * { errors: "Missing parameter 'toolId'" }
  401. *
  402. * HTTP 404 [Failure] Returned if the matching toolId and sectionName combo was NOT found. ALSO returned if the matching item was NOT found.
  403. * { errors: "Could not find matching toolId and sectionName combo." }
  404. */
  405. .get(function (req, res) {
  406. var toolId = req.params.toolId;
  407. var sectionName = req.params.sectionName.toLowerCase();
  408. var itemNum = req.params.itemNum;
  409. //Check that the params were actually supplied in the request
  410. if (toolId && sectionName && itemNum) {
  411. Tool.findOne({'id': toolId}, function (err, tool) {
  412. //Catch any general errors and send them back to the client
  413. if (err)
  414. res.status(404).send({errors: err});
  415. //Otherwise, there was (or was not) a matching document
  416. else {
  417. //If the matching toolId + sectionName combo was not found, send back a 404
  418. if (tool[sectionName] == undefined || tool[sectionName] == null)
  419. res.status(404).send({errors: "Could not find matching toolId and sectionName combo."});
  420. //Otherwise, send back the item
  421. else {
  422. if (tool[sectionName][itemNum] == undefined || tool[sectionName][itemNum] == null)
  423. res.status(404).send({errors: "Could not find given item."});
  424. else
  425. res.status(200).send(tool[sectionName][itemNum]);
  426. }
  427. }
  428. });
  429. }
  430. //Otherwise, the required data was not supplied in the request. DO NOT attempt to access the DB in this case.
  431. else {
  432. var message = "";
  433. //If-else block to determine which parameter was missing. Sets the message text = missing param
  434. if (!toolId)
  435. message = "Missing parameter 'toolId'.";
  436. else if (!sectionName)
  437. message = "Missing parameter 'sectionName'.";
  438. else
  439. message = "Missing parameter 'itemNum'.";
  440. //Send an HTTP 400 (Bad Request) back with the error message
  441. res.status(400).send({errors: message});
  442. }
  443. })
  444. /**
  445. * Request: DELETE /api/tool/:toolId/:sectionName/:itemNum
  446. * Returns: JSON Object
  447. * Logged: YES
  448. *
  449. * Description:
  450. * Deletes a particular item (i.e. card) from the given section name list for the given tool.
  451. *
  452. * Params (Required):
  453. * toolId [Number] The id of the tool to retrieve.
  454. * sectionName [String] The name of the section (i.e. 'About') to retrieve.
  455. * itemNum [Number] The position of the item in the list (ex: 0 = 1st item).
  456. *
  457. * Responses:
  458. * HTTP 200 [Success] Returned if a matching item was found
  459. * { heading: "What is JIRA?", contents: "..." }
  460. *
  461. * HTTP 400 [Failure] Returned if there was a missing param.
  462. * { errors: "Missing parameter 'toolId'" }
  463. *
  464. * HTTP 404 [Failure] Returned if the matching toolId and sectionName combo was NOT found. ALSO returned if the matching item was NOT found.
  465. * { errors: "Could not find matching toolId and sectionName combo." }
  466. *
  467. * HTTP 422 [Failure] Returned if there was an error while saving the updated document.
  468. * { deleted: false, errors: "..."}
  469. */
  470. .delete(function (req, res) {
  471. var toolId = req.params.toolId;
  472. var sectionName = req.params.sectionName.toLowerCase();
  473. var itemNum = req.params.itemNum;
  474. //Check that the params were actually supplied in the request
  475. if (toolId && sectionName && itemNum) {
  476. Tool.findOne({'id': toolId}, function (err, tool) {
  477. //Catch any general errors and send them back to the client
  478. if (err)
  479. res.status(404).send({errors: err});
  480. //Get the item that the user wants to delete
  481. var itemToDel = tool[sectionName][itemNum];
  482. //If the item doesn't exist, send an error back to the client
  483. if (!itemToDel) {
  484. res.status(404).send({deleted: false, errors: "Item to delete was not found."})
  485. }
  486. //Otherwise, the deletion step can be executed
  487. else {
  488. //Remove the first indexed item
  489. tool[sectionName].splice(itemNum, 1);
  490. //Attempt to save the tool now that item was removed
  491. tool.save(function (err) {
  492. //If there was an error while saving, send the error back to the client
  493. if (err) {
  494. logger.info("[" + ip.address() + "] Item deletion failed. Tool/Section/Item = " + toolId + "/" + sectionName + "/" + itemNum);
  495. res.status(422).send({deleted: false, errors: err});
  496. }
  497. //Otherwise, the save was successful
  498. else {
  499. logger.info("[" + ip.address() + "] Item deletion succeeded. Tool/Section/Item = " + toolId + "/" + sectionName + "/" + itemNum);
  500. res.status(200).send({deleted: true});
  501. }
  502. });
  503. }
  504. });
  505. }
  506. //Otherwise, the required data was not supplied in the request. DO NOT attempt to access the DB in this case.
  507. else {
  508. var message = "";
  509. //If-else block to determine which parameter was missing. Sets the message text = missing param
  510. if (!toolId)
  511. message = "Missing parameter 'toolId'.";
  512. else if (!sectionName)
  513. message = "Missing parameter 'sectionName'.";
  514. else
  515. message = "Missing parameter 'itemNum'.";
  516. //Send an HTTP 400 (Bad Request) back with the error message
  517. res.status(400).send({errors: message});
  518. }
  519. });
  520. module.exports = router;