FoodController.scala 6.2 KB

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