FoodController.scala 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package com.weEat.controllers
  2. import com.weEat.models.{FoodNode => FoodNodeCollection}
  3. import com.weEat.services.MongoDBService
  4. import com.weEat.shared.models._
  5. import javax.inject.{Inject,Singleton}
  6. import play.api.libs.json._
  7. import play.api.mvc._
  8. import org.bson.types.ObjectId
  9. import org.mongodb.scala.model.Filters._
  10. import scala.concurrent.Future
  11. import scala.util.{Success,Failure}
  12. import com.weEat.models.Authorization
  13. import scalaoauth2.provider.{AuthInfoRequest,OAuth2ProviderActionBuilders}
  14. import com.weEat.services.OAuth2Service
  15. import org.mongodb.scala.model.Filters._
  16. @Singleton
  17. class FoodController @Inject()(
  18. val controllerComponents: ControllerComponents,
  19. oauth: OAuth2Service,
  20. db: MongoDBService
  21. ) extends BaseController
  22. with OAuth2ProviderActionBuilders {
  23. implicit val ec = scala.concurrent.ExecutionContext.global
  24. import db.withCollection
  25. def get(id: String) = Action.async
  26. { implicit request: Request[AnyContent] =>
  27. withCollection(FoodNodeCollection) { (collection) =>
  28. collection.find(equal("_id", new ObjectId(id)))
  29. .first()
  30. .toFuture()
  31. .transform({
  32. case Success(null) => Success(NotFound(id))
  33. case Success(x) => Success(Ok(Json.toJson(x)))
  34. case Failure(x) => throw x
  35. })
  36. }.flatten
  37. }
  38. def all() = Action.async
  39. { implicit request: Request[AnyContent] =>
  40. withCollection(FoodNodeCollection) { (collection) =>
  41. collection.find()
  42. .toFuture()
  43. .transform({
  44. case Success(x) => Success(Ok(Json.toJson(x)))
  45. case Failure(x) => throw x
  46. })
  47. }.flatten
  48. }
  49. def query(q: String) = Action.async
  50. { implicit request: Request[AnyContent] =>
  51. withCollection(FoodNodeCollection) { (collection) =>
  52. collection.find(regex("name", q, "i"))
  53. .toFuture()
  54. .transform({
  55. case Success(x) => Success(Ok(Json.toJson(x)))
  56. case Failure(x) => throw x
  57. })
  58. }.flatten
  59. }
  60. // def getImage(foodId: String, idx: Int) = Action.async
  61. // { implicit request: Request[AnyContent] =>
  62. // withCollection(FoodImages) {collection =>
  63. // collection.find(and(equal("food", foodId), equal("index", idx)))
  64. // .first()
  65. // .toFuture()
  66. // .transform({
  67. // case Success(img) =>
  68. // Success(Ok.streamed(img.data, img.data.length, img.mime))
  69. // case Failure(x) => throw x
  70. // })
  71. // }.flatten
  72. // ???
  73. // }
  74. // def addImageTo(id: String) = Action.async(parse.byteString)
  75. // { implicit request: Request[ByteString] =>
  76. // withCollection(FoodImages) { images =>
  77. // images.insertOne(FoodImage(None, id, , request.body, request.contentType.get))
  78. // .head().transformWith({
  79. // case Success(img) => withCollection(FoodNode) { foods =>
  80. // foods.findOneAndUpdate(
  81. // equal("id", id),
  82. // push("imageIds", img._id.get)
  83. // ).head().transform({
  84. // case Success(x) => Success(Ok(x))
  85. // case Failure(x) =>
  86. // images.deleteOne(eq("_id", img._id.get))
  87. // throw x
  88. // })
  89. // }
  90. // case Failure(x) => throw x
  91. // })
  92. // }.flatten
  93. // ???
  94. // }
  95. // def deleteImage(foodId: String, imageId: String) = Action.async
  96. // { implicit request: Request[AnyContent] =>
  97. // withCollection(FoodNode) { foods =>
  98. // foods.findOneAndUpdate(
  99. // equal("id", foodId),
  100. // pull("imageIds", imageId)
  101. // ).head().transformWith({
  102. // case Success(x) => images.deleteOne(eq("_id", img._id.get))
  103. // .head().transform({
  104. // case Success(x) => Success(Ok(x))
  105. // case Failure(x) => throw x
  106. // })
  107. // case Failure(x) => throw x
  108. // })
  109. // }.flatten
  110. // ???
  111. // }
  112. def add(uid: Option[String]) = AuthorizedAction[Authorization](oauth)
  113. .async(parse.json)
  114. { implicit request: AuthInfoRequest[JsValue, Authorization] =>
  115. try {
  116. val food = request.body.as[FoodNode].withId(
  117. new ObjectId,
  118. uid.flatMap({ (id) =>
  119. if (request.authInfo.user.hasAdminPermissions) Some(new ObjectId(id))
  120. else None
  121. }).getOrElse(request.authInfo.user.userId)
  122. )
  123. withCollection(FoodNodeCollection) { (collection) =>
  124. collection.insertOne(food).map({ (res) =>
  125. val id = res.getInsertedId().asObjectId().getValue()
  126. Ok(Json.toJson(food.withId(id)))
  127. }).head()
  128. }.flatten
  129. }
  130. catch {
  131. case _: JsResultException => Future.successful(
  132. BadRequest(s"Could not parse json into a Food node.")
  133. )
  134. }
  135. }
  136. def update(id: String, uid: Option[String]) =
  137. AuthorizedAction[Authorization](oauth)
  138. .async(parse.json)
  139. { implicit request: AuthInfoRequest[JsValue, Authorization] =>
  140. try {
  141. val refFood = if (request.authInfo.user.hasAdminPermissions)
  142. request.body.as[FoodNode]
  143. else
  144. request.body.as[FoodNode]
  145. .withId(new ObjectId(id), request.authInfo.user.userId)
  146. val food = refFood.withId(
  147. new ObjectId(id),
  148. uid.flatMap({ (id) =>
  149. if (request.authInfo.user.hasAdminPermissions) Some(new ObjectId(id))
  150. else None
  151. // tflucke@[2023-10-07] Should this query for the current uid instead?
  152. }).getOrElse(request.authInfo.user.userId)
  153. )
  154. withCollection(FoodNodeCollection) { (collection) =>
  155. collection.replaceOne(refFood match {
  156. case fni: FoodNodeId => and(
  157. equal("_id", new ObjectId(id)),
  158. equal("uid", fni.uid)
  159. )
  160. case _ => equal("_id", new ObjectId(id))
  161. }, food)
  162. .map({ (res) => if (res.getModifiedCount > 0)
  163. Ok(Json.toJson(food))
  164. else
  165. NotFound(s"User ${request.authInfo.user.userId} does not have a food node $id")
  166. })
  167. .head()
  168. }.flatten
  169. }
  170. catch {
  171. case _: JsResultException => Future.successful(
  172. BadRequest(s"Could not parse json into a Food node.")
  173. )
  174. }
  175. }
  176. }