diff --git a/backend-services/feed-service/app/controllers/DailyController.scala b/backend-services/feed-service/app/controllers/DailyController.scala index d75dc30de56d292fb6e449d2692798c3251890c3..a63fcf3a1d107f8d99c6abda5a07586094311108 100644 --- a/backend-services/feed-service/app/controllers/DailyController.scala +++ b/backend-services/feed-service/app/controllers/DailyController.scala @@ -60,13 +60,13 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents, * * @param userId The ID of the user to get the feed for. */ - def getUserFeed(userId: String) = authenticatedUserAction { + def getUserFeed(userId: String) = authenticatedUserAction { implicit request: AuthenticationRequest[AnyContent] => println("DailyController:getUserFeed") try { if (!ObjectId.isValid(userId)) throw new InvalidRequestBodyException("Invalid query parameter ID format: userId") - val result: Seq[Daily] = Daily.getUserFeedAsync(new ObjectId(userId)) + val result: Seq[Daily] = Daily.getUserFeedAsync(new ObjectId(userId), request.jwt) val jsonResult: JsValue = Daily.toJson(result) Ok(jsonResult) } catch { @@ -104,7 +104,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents, try { val (dailyId, likerId) = fetchLikeRequestBody(request.body) - Daily.likeAsync(dailyId, likerId) + Daily.likeAsync(dailyId, likerId, request.jwt) Ok("Daily liked.") } catch { case _: TimeoutException => BadRequest("Request timed out") @@ -124,7 +124,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents, try { val (dailyId, likerId) = fetchLikeRequestBody(request.body) - Daily.unlikeAsync(dailyId, likerId) + Daily.unlikeAsync(dailyId, likerId, request.jwt) Ok("Daily unliked.") } catch { case _: TimeoutException => BadRequest("Request timed out") diff --git a/backend-services/feed-service/app/controllers/TestController.scala b/backend-services/feed-service/app/controllers/TestController.scala index eb197e7324eb88a68b22f416d37ffb7dd729a69f..123a9d0ebcd253ce5edbce811c69a9d8cc6e3b9d 100644 --- a/backend-services/feed-service/app/controllers/TestController.scala +++ b/backend-services/feed-service/app/controllers/TestController.scala @@ -1,5 +1,7 @@ package controllers +import models.actions.AuthenticatedUserAction + import javax.inject._ import play.api.mvc._ import play.api.libs.json.{JsString, JsArray} @@ -10,9 +12,10 @@ import play.api.libs.json.JsBoolean * application's test page. */ @Singleton -class TestController @Inject()(val controllerComponents: ControllerComponents) extends BaseController { +class TestController @Inject()(val controllerComponents: ControllerComponents, authenticatedUserAction: AuthenticatedUserAction) + extends BaseController { - def getFriends(userId: String) = Action { + def getFriends(userId: String) = authenticatedUserAction { println("TestController:getFriends") println(s"Fetching friends for User with ID {$userId}") @@ -27,7 +30,7 @@ class TestController @Inject()(val controllerComponents: ControllerComponents) e Ok(response) } - def verifyUser(userId: String) = Action { + def verifyUser(userId: String) = authenticatedUserAction { println("TestController:verifyUser") println(s"Verifying User with ID {$userId}") diff --git a/backend-services/feed-service/app/models/Daily.scala b/backend-services/feed-service/app/models/Daily.scala index 59b41f1aef75f6a481770ed4d719c71e530e47f8..b4eda23e7fdcc1ffeb790a951e133087066f2f9d 100644 --- a/backend-services/feed-service/app/models/Daily.scala +++ b/backend-services/feed-service/app/models/Daily.scala @@ -54,17 +54,17 @@ object Daily { Await.result[Seq[Daily]](future, timeout.seconds) } - def getUserFeedAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = { + def getUserFeedAsync(userId: ObjectId, jwt: String, timeout: Int = 4): Seq[Daily] = { // Sequentially waits for Future objects to complete before calling next method val result: Future[Seq[Daily]] = for { - friends: Seq[ObjectId] <- User.getUserFriends(userId) + friends: Seq[ObjectId] <- User.getUserFriends(userId, jwt) feed: Seq[Daily] <- dailyRepo.getByValues[ObjectId]("user_id", friends) } yield feed Await.result[Seq[Daily]](result, timeout.seconds) } - def likeAsync(dailyId: ObjectId, likerId: ObjectId, timeout: Int = 4): Unit = { + def likeAsync(dailyId: ObjectId, likerId: ObjectId, jwt: String, timeout: Int = 4): Unit = { val result: Future[Unit] = for { // Fetch Daily from given ID daily: Daily <- { @@ -80,7 +80,7 @@ object Daily { _ = if (daily.usersLiked.contains(likerId)) throw new ConflictException("User has already liked this Daily.") // Check user with given ID exists - _ <- User.userExists(likerId).map((exists: Boolean) => if (!exists) throw new NotFoundException("No user with given ID.")) + _ <- User.userExists(likerId, jwt).map((exists: Boolean) => if (!exists) throw new NotFoundException("No user with given ID.")) like: Unit <- { val updatedUsersLiked: Seq[ObjectId] = daily.usersLiked :+ likerId @@ -93,7 +93,7 @@ object Daily { Await.result[Unit](result, timeout.seconds) } - def unlikeAsync(dailyId: ObjectId, likerId: ObjectId, timeout: Int = 4): Unit = { + def unlikeAsync(dailyId: ObjectId, likerId: ObjectId, jwt: String, timeout: Int = 4): Unit = { val result: Future[Unit] = for { // Fetch Daily from given ID daily: Daily <- { @@ -106,7 +106,7 @@ object Daily { } // Check user with given ID exists - _ <- User.userExists(likerId).map((exists: Boolean) => if (!exists) throw new NotFoundException("No user with given ID.")) + _ <- User.userExists(likerId, jwt).map((exists: Boolean) => if (!exists) throw new NotFoundException("No user with given ID.")) // Check user has liked the Daily _ = if (!daily.usersLiked.contains(likerId)) throw new ConflictException("User has not liked this Daily.") diff --git a/backend-services/feed-service/app/models/HttpCall.scala b/backend-services/feed-service/app/models/HttpCall.scala index 7a35b888f0252f69107f5935f0946902e93667bd..cef4e4294d427aa8fe5e0b3f9937fae214ebbc69 100644 --- a/backend-services/feed-service/app/models/HttpCall.scala +++ b/backend-services/feed-service/app/models/HttpCall.scala @@ -3,6 +3,7 @@ package models import akka.actor.ActorSystem import akka.stream.{Materializer, SystemMaterializer} import play.api.libs.ws.ahc.{StandaloneAhcWSClient} +import play.api.libs.ws.StandaloneWSRequest import play.api.libs.json.JsValue import scala.concurrent.Future @@ -18,7 +19,11 @@ object HttpCall { * * @return a Future containing the response body as a JSON. */ - def get(url: String, queryStringParameters: (String, String)*): Future[JsValue] = { + def get( + url: String, + queryStringParameters: Seq[(String, String)] = Seq.empty[(String, String)], + jwt: String = "" + ): Future[JsValue] = { // Create ActorSystem for thread and streaming management implicit val system: ActorSystem = ActorSystem() @@ -28,14 +33,23 @@ object HttpCall { // Create the standalone WS client val wsClient: StandaloneAhcWSClient = StandaloneAhcWSClient() + // Create base request + var request: StandaloneWSRequest = wsClient.url(url) + + // Add query parameters to request + request = request.addQueryStringParameters(queryStringParameters: _*) + + // Add JWT header to request, if supplied + request = if (!jwt.isEmpty()) request.addHttpHeaders(("Authorization", s"Bearer $jwt")) else request + // Call API and fetch response - val response: Future[JsValue] = wsClient.url(url).addQueryStringParameters(queryStringParameters: _*).get().map { response => - if (response.status > 399) throw new RuntimeException() + val response: Future[JsValue] = request.get().map(response => { + if (response.status > 399) throw new RuntimeException() - val statusText: String = response.statusText - println(s"Got a response: $statusText") - response.body[JsValue] - } + val statusText: String = response.statusText + println(s"Got a response: $statusText") + response.body[JsValue] + }) // Close WSClient and terminate ActorSystem response diff --git a/backend-services/feed-service/app/models/User.scala b/backend-services/feed-service/app/models/User.scala index ecd569c3199de89148509895ad7e78681341e599..8556770ce2776d6ad9ca035ecba745f325d51bb7 100644 --- a/backend-services/feed-service/app/models/User.scala +++ b/backend-services/feed-service/app/models/User.scala @@ -9,18 +9,20 @@ import scala.concurrent.ExecutionContext.Implicits.global object User { - def getUserFriends(userId: ObjectId): Future[Seq[ObjectId]] = { - println(s"Fetching friends for user with ID {$userId}") + def getUserFriends(userId: ObjectId, jwt: String): Future[Seq[ObjectId]] = { + val url: String = "http://localhost:9000/test/getFriends" + val queryStringParameters: Seq[(String, String)] = Seq(("userId", userId.toString())) - HttpCall.get("http://localhost:9000/test/getFriends", ("userId", userId.toString())).map[Seq[ObjectId]]((json: JsValue) => { + HttpCall.get(url, queryStringParameters, jwt).map[Seq[ObjectId]]((json: JsValue) => { val sequence: Seq[String] = json.as[Seq[String]] sequence.map[ObjectId](new ObjectId(_)) }) } - def userExists(userId: ObjectId): Future[Boolean] = { - println(s"Verifying user with ID {$userId} exists") + def userExists(userId: ObjectId, jwt: String): Future[Boolean] = { + val url: String = "http://localhost:9000/test/verifyUser" + val queryStringParameters: Seq[(String, String)] = Seq(("userId", userId.toString())) - HttpCall.get("http://localhost:9000/test/verifyUser", ("userId", userId.toString())).map[Boolean](_.as[Boolean]) + HttpCall.get(url, queryStringParameters, jwt).map[Boolean](_.as[Boolean]) } }