1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.user.social
21 
22 import akka.http.scaladsl.model._
23 import akka.http.scaladsl.model.headers.{Authorization, OAuth2BearerToken}
24 import akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller
25 import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller}
26 import akka.http.scaladsl.{Http, HttpExt}
27 import grizzled.slf4j.Logging
28 import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport
29 import org.make.api.technical.ActorSystemComponent
30 import org.make.api.user.social.models.google.PeopleInfo
31 
32 import scala.concurrent.ExecutionContext.Implicits.global
33 import scala.concurrent.Future
34 
35 trait GoogleApiComponent {
36   def googleApi: GoogleApi
37 }
38 
39 trait GoogleApi {
40   def peopleInfo(userToken: String): Future[PeopleInfo]
41 }
42 
43 trait DefaultGoogleApiComponent extends GoogleApiComponent with ErrorAccumulatingCirceSupport {
44   self: ActorSystemComponent with SocialProvidersConfigurationComponent =>
45 
46   override lazy val googleApi: GoogleApi = new DefaultGoogleApi
47 
48   class DefaultGoogleApi extends GoogleApi with Logging {
49     private val http: HttpExt = Http()
50 
51     override def peopleInfo(userToken: String): Future[PeopleInfo] = {
52       val apiKey = socialProvidersConfiguration.google.apiKey
53       val url =
54         s"https://people.googleapis.com/v1/people/me?key=$apiKey&personFields=metadata,names,birthdays,photos,emailAddresses"
55 
56       http
57         .singleRequest(
58           HttpRequest(method = HttpMethods.GET, uri = url, headers = Seq(Authorization(OAuth2BearerToken(userToken))))
59         )
60         .flatMap(unmarshal[PeopleInfo](_))
61     }
62 
63     private def unmarshal[Entity](response: HttpResponse, expectedCode: StatusCode = StatusCodes.OK)(
64       implicit unmarshaller: Unmarshaller[ResponseEntity, Entity]
65     ): Future[Entity] = {
66       logger.debug(s"Server answered $response")
67       response match {
68         case HttpResponse(`expectedCode`, _, entity, _) =>
69           Unmarshal(entity).to[Entity]
70         case HttpResponse(code, _, entity, _) =>
71           Unmarshal(entity).to[String].flatMap { error =>
72             Future.failed(SocialProviderException(s"Got unexpected response code: $code, with body: $error"))
73           }
74       }
75     }
76   }
77 }
Line Stmt Id Pos Tree Symbol Tests Code
49 42256 1852 - 1852 Select org.make.api.technical.ActorSystemComponent.actorSystem DefaultGoogleApiComponent.this.actorSystem
49 34389 1848 - 1854 ApplyToImplicitArgs akka.http.scaladsl.Http.apply akka.http.scaladsl.Http.apply()(DefaultGoogleApiComponent.this.actorSystem)
52 47129 1946 - 1988 Select org.make.api.user.social.GoogleConfiguration.apiKey DefaultGoogleApiComponent.this.socialProvidersConfiguration.google.apiKey
57 39318 2152 - 2152 Select akka.http.scaladsl.HttpExt.singleRequest$default$3 DefaultGoogleApi.this.http.singleRequest$default$3
57 31172 2152 - 2152 Select akka.http.scaladsl.HttpExt.singleRequest$default$4 DefaultGoogleApi.this.http.singleRequest$default$4
57 47174 2152 - 2152 Select akka.http.scaladsl.HttpExt.singleRequest$default$2 DefaultGoogleApi.this.http.singleRequest$default$2
58 33889 2177 - 2285 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.GET, model.this.Uri.apply(url), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](akka.http.scaladsl.model.headers.Authorization.apply(akka.http.scaladsl.model.headers.OAuth2BearerToken.apply(userToken))), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5)
58 38300 2177 - 2177 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
58 32773 2236 - 2284 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](akka.http.scaladsl.model.headers.Authorization.apply(akka.http.scaladsl.model.headers.OAuth2BearerToken.apply(userToken)))
58 39568 2198 - 2213 Select akka.http.scaladsl.model.HttpMethods.GET akka.http.scaladsl.model.HttpMethods.GET
58 47474 2254 - 2282 Apply akka.http.scaladsl.model.headers.OAuth2BearerToken.apply akka.http.scaladsl.model.headers.OAuth2BearerToken.apply(userToken)
58 45554 2177 - 2177 Select akka.http.scaladsl.model.HttpRequest.apply$default$4 akka.http.scaladsl.model.HttpRequest.apply$default$4
58 40368 2240 - 2283 Apply akka.http.scaladsl.model.headers.Authorization.apply akka.http.scaladsl.model.headers.Authorization.apply(akka.http.scaladsl.model.headers.OAuth2BearerToken.apply(userToken))
58 31751 2221 - 2224 ApplyImplicitView akka.http.scaladsl.model.Uri.apply model.this.Uri.apply(url)
60 33928 2138 - 2338 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultGoogleApi.this.http.singleRequest(akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.GET, model.this.Uri.apply(url), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](akka.http.scaladsl.model.headers.Authorization.apply(akka.http.scaladsl.model.headers.OAuth2BearerToken.apply(userToken))), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5), DefaultGoogleApi.this.http.singleRequest$default$2, DefaultGoogleApi.this.http.singleRequest$default$3, DefaultGoogleApi.this.http.singleRequest$default$4).flatMap[org.make.api.user.social.models.google.PeopleInfo](((x$1: akka.http.scaladsl.model.HttpResponse) => DefaultGoogleApi.this.unmarshal[org.make.api.user.social.models.google.PeopleInfo](x$1, DefaultGoogleApi.this.unmarshal$default$2[org.make.api.user.social.models.google.PeopleInfo])(DefaultGoogleApiComponent.this.unmarshaller[org.make.api.user.social.models.google.PeopleInfo](google.this.PeopleInfo.decoder))))(scala.concurrent.ExecutionContext.Implicits.global)
60 48537 2322 - 2322 TypeApply org.make.api.user.social.DefaultGoogleApiComponent.DefaultGoogleApi.unmarshal$default$2 DefaultGoogleApi.this.unmarshal$default$2[org.make.api.user.social.models.google.PeopleInfo]
60 32814 2334 - 2334 ApplyToImplicitArgs de.heikoseeberger.akkahttpcirce.ErrorAccumulatingUnmarshaller.unmarshaller DefaultGoogleApiComponent.this.unmarshaller[org.make.api.user.social.models.google.PeopleInfo](google.this.PeopleInfo.decoder)
60 37727 2312 - 2312 Select scala.concurrent.ExecutionContext.Implicits.global scala.concurrent.ExecutionContext.Implicits.global
60 45302 2313 - 2337 ApplyToImplicitArgs org.make.api.user.social.DefaultGoogleApiComponent.DefaultGoogleApi.unmarshal DefaultGoogleApi.this.unmarshal[org.make.api.user.social.models.google.PeopleInfo](x$1, DefaultGoogleApi.this.unmarshal$default$2[org.make.api.user.social.models.google.PeopleInfo])(DefaultGoogleApiComponent.this.unmarshaller[org.make.api.user.social.models.google.PeopleInfo](google.this.PeopleInfo.decoder))
60 40406 2334 - 2334 Select org.make.api.user.social.models.google.PeopleInfo.decoder google.this.PeopleInfo.decoder
66 46919 2546 - 2588 Apply grizzled.slf4j.Logger.debug DefaultGoogleApi.this.logger.debug(("Server answered ".+(response): String))
69 30924 2701 - 2701 Select org.make.api.technical.ActorSystemComponent.actorSystem DefaultGoogleApiComponent.this.actorSystem
69 38813 2701 - 2701 Select scala.concurrent.ExecutionContext.Implicits.global scala.concurrent.ExecutionContext.Implicits.global
69 40446 2681 - 2709 ApplyToImplicitArgs akka.http.scaladsl.unmarshalling.Unmarshal.to akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](entity).to[Entity](unmarshaller, scala.concurrent.ExecutionContext.Implicits.global, stream.this.Materializer.matFromSystem(DefaultGoogleApiComponent.this.actorSystem))
69 47988 2701 - 2701 ApplyToImplicitArgs akka.stream.Materializer.matFromSystem stream.this.Materializer.matFromSystem(DefaultGoogleApiComponent.this.actorSystem)
71 30964 2806 - 2806 Select scala.concurrent.ExecutionContext.Implicits.global scala.concurrent.ExecutionContext.Implicits.global
71 43751 2769 - 2938 ApplyToImplicitArgs scala.concurrent.Future.flatMap akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](entity).to[String](akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller, scala.concurrent.ExecutionContext.Implicits.global, stream.this.Materializer.matFromSystem(DefaultGoogleApiComponent.this.actorSystem)).flatMap[Nothing](((error: String) => scala.concurrent.Future.failed[Nothing](SocialProviderException.apply(("Got unexpected response code: ".+(code).+(", with body: ").+(error): String)))))(scala.concurrent.ExecutionContext.Implicits.global)
71 37485 2789 - 2789 Select org.make.api.technical.ActorSystemComponent.actorSystem DefaultGoogleApiComponent.this.actorSystem
71 32559 2789 - 2789 Select akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller
71 34383 2789 - 2789 ApplyToImplicitArgs akka.stream.Materializer.matFromSystem stream.this.Materializer.matFromSystem(DefaultGoogleApiComponent.this.actorSystem)
71 45338 2789 - 2789 Select scala.concurrent.ExecutionContext.Implicits.global scala.concurrent.ExecutionContext.Implicits.global
72 46958 2843 - 2925 Apply org.make.api.user.social.SocialProviderException.apply SocialProviderException.apply(("Got unexpected response code: ".+(code).+(", with body: ").+(error): String))
72 38570 2829 - 2926 Apply scala.concurrent.Future.failed scala.concurrent.Future.failed[Nothing](SocialProviderException.apply(("Got unexpected response code: ".+(code).+(", with body: ").+(error): String)))