routeGen.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /**
  2. * @module mongoRouter
  3. *
  4. * Backend module to store React-Redux components in MongoDB.
  5. */
  6. import mongoose from 'mongoose'
  7. import { History } from './core/basicSchema'
  8. /**
  9. * Generates GET, POST, UPDATE and DELETE handlers which interact with
  10. * MongoDB.
  11. *
  12. * @param {object} Model - mongoose model to use
  13. * @param {boolean} versioned - use a revision control mechanism
  14. * @return {[type]}
  15. */
  16. function routeGen (Model, versioned = true) {
  17. /** GET handler (request one item or a list of items) */
  18. const get = (req, res) => {
  19. let { id } = req.params
  20. /** check whether an id was specified. */
  21. if (typeof id === 'string' && id.length > 1) {
  22. try {
  23. // try to convert the id string to a valid ObjectId
  24. id = mongoose.Types.ObjectId(id)
  25. } catch (err) {
  26. // If id couldn't be converted, return an error message.
  27. res.status(422)
  28. res.send({error: err.message})
  29. return
  30. }
  31. // if yes, return the one item
  32. Model.findOne({ _id: id }, function (err, item) {
  33. if (err) {
  34. res.status(404)
  35. res.send(err)
  36. return
  37. }
  38. res.json(item)
  39. })
  40. } else {
  41. // if not, return a list of items
  42. // limit the number of returned items and use an offset
  43. const limit = req.query.limit ? Math.min(Math.max(parseInt(req.query.limit), 1), 100) : 20
  44. const offset = req.query.offset ? Math.max(parseInt(req.query.offset), 0) : 0
  45. Model.find({}, {limit: limit, skip: offset}, function (err, items) {
  46. if (err) {
  47. res.status(404)
  48. res.send(err)
  49. return
  50. }
  51. res.json(items)
  52. })
  53. }
  54. }
  55. /** POST handler (insert a new item into the database) */
  56. const post = (req, res) => {
  57. // create the new item
  58. const item = new Model(req.body)
  59. // Check, if the model supports revision control
  60. if (typeof Model.schema.obj.__history !== 'undefined') {
  61. item.__history = new History({
  62. author: '',
  63. created: Date(),
  64. tag: '',
  65. reference: [],
  66. head: true
  67. })
  68. }
  69. // save the item
  70. item.save(function (err) {
  71. if (err) {
  72. res.status(422)
  73. res.send(err)
  74. return
  75. }
  76. res.send({ success: `${Model.modelName} added.` })
  77. })
  78. }
  79. /** PUT handler (update existing project) */
  80. const put = (req, res) => {
  81. let id = req.params['0']
  82. /** check whether an id was specified. */
  83. if (typeof id === 'string' && id.length > 1) {
  84. // remove leading slash
  85. id = id.substring(1)
  86. try {
  87. // try to convert the id string to a valid ObjectId
  88. id = mongoose.Types.ObjectId(req.params['1'].substring(1))
  89. } catch (err) {
  90. // If id couldn't be converted, return an error message.
  91. res.status(422)
  92. res.send({error: err.message})
  93. return
  94. }
  95. }
  96. // Find the object in the database
  97. Model.findOne({ _id: id }, function (err, item) {
  98. if (err) {
  99. res.status(404)
  100. res.send(err)
  101. }
  102. // Check, if the model supports revision control
  103. if (typeof Model.schema.obj.__history !== 'undefined') {
  104. // If yes, don't update the item, but create a new one based on the original
  105. const newItem = Model(item)
  106. // replace the requested elements
  107. for (let prop in req.body) {
  108. newItem[prop] = req.body[prop]
  109. }
  110. // give it a new history with updated reference array. Set the head-indicator to true
  111. newItem.__history = new History({
  112. author: '',
  113. created: Date(),
  114. tag: '',
  115. reference: [ ...item.__history.reference, item._id ],
  116. head: true
  117. })
  118. // set the original item's head indicator to false
  119. item.__history.head = false
  120. // save the documents
  121. newItem.save(function (err) {
  122. if (err) {
  123. res.status(422)
  124. res.send(err)
  125. }
  126. res.json({ message: `${Model.modelName} updated.` })
  127. })
  128. } else {
  129. for (let prop in req.body) {
  130. item[prop] = req.body[prop]
  131. }
  132. }
  133. item.save(function (err) {
  134. if (err) {
  135. res.status(422)
  136. res.send(err)
  137. }
  138. res.json({ message: `${Model.modelName} updated.` })
  139. })
  140. })
  141. }
  142. /** DELETE handler (delete project) */
  143. const del = (req, res) => {
  144. const id = mongoose.Types.ObjectId(req.params['0'])
  145. Model.remove({ _id: id }, function (err, project) {
  146. if (err) {
  147. res.send(err)
  148. }
  149. res.json({ message: 'Movie deleted.' })
  150. })
  151. }
  152. return {
  153. get,
  154. post,
  155. put,
  156. del
  157. }
  158. }
  159. export default routeGen