Revert "Merge pull request #5686 from veloce/firebase"

This reverts commit c98edc1ee1, reversing
changes made to 6eb97bd27b.
pull/5692/head
Thibault Duplessis 2019-11-26 17:14:31 -06:00
parent aead8ac6ee
commit 88bffaa938
8 changed files with 16 additions and 151 deletions

View File

@ -303,7 +303,7 @@ lazy val playban = module("playban", Seq(common, db, game, message, chat)).setti
)
lazy val push = module("push", Seq(common, db, user, game, challenge, message)).settings(
libraryDependencies ++= Seq(googleOAuth) ++ provided(play.api, reactivemongo.driver)
libraryDependencies ++= provided(play.api, reactivemongo.driver)
)
lazy val slack = module("slack", Seq(common, hub, user)).settings(

View File

@ -289,10 +289,6 @@ push {
app_id = ""
key = ""
}
firebase {
service_account_file = "firebase-service-account.json"
url = "https://fcm.googleapis.com/v1/projects/lichess-1366/messages:send"
}
}
mod {
collection {

View File

@ -1,50 +0,0 @@
package lila.push
import java.util.concurrent.{ Executors, SynchronousQueue, ThreadPoolExecutor, ThreadFactory, TimeUnit }
import java.util.concurrent.atomic.AtomicInteger
import scala.concurrent.{ Promise, Future }
import scala.util.control.NonFatal
object BlockingIO {
/**
* Current google oauth client (v0.18.0) doesn't support timeout setting
* (default is 60s).
* To avoid any problem, let's use a thread pool with direct handoff (no
* queuing), and bounded at the number of processors, so it can handle a few
* concurrent requests.
* Uses the default AbortPolicy, so if there is no more thread available
* it will reject the task and throw a RejectedExecutionException
*/
private val threadPool = new ThreadPoolExecutor(
1,
Runtime.getRuntime.availableProcessors,
60,
TimeUnit.SECONDS,
new SynchronousQueue[Runnable](),
new ThreadFactory {
private val count = new AtomicInteger()
override def newThread(r: Runnable) = {
val thread = new Thread(r)
thread.setName(s"push-blocking-io-thread-${count.incrementAndGet}")
thread.setDaemon(true)
thread
}
}
)
def apply[T](cb: => T): Future[T] = {
val p = Promise[T]()
threadPool.execute(new Runnable {
def run() = try {
p.success(cb)
} catch {
case NonFatal(ex) => p.failure(ex)
}
})
p.future
}
}

View File

@ -3,7 +3,7 @@ package lila.push
import org.joda.time.DateTime
private final case class Device(
_id: String, // Firebase token or OneSignal playerId
_id: String, // google device ID or Apple token or OneSignal playerId
platform: String, // cordova platform (android, ios)
userId: String,
seenAt: DateTime

View File

@ -1,11 +1,7 @@
package lila.push
import akka.actor._
import collection.JavaConverters._
import com.typesafe.config.Config
import com.google.auth.oauth2.ServiceAccountCredentials
import play.api.Play
import Play.current
import lila.game.Game
@ -25,8 +21,6 @@ final class Env(
private val OneSignalAppId = config getString "onesignal.app_id"
private val OneSignalKey = config getString "onesignal.key"
private val FirebaseUrl = config getString "firebase.url"
private val WebUrl = config getString "web.url"
val WebVapidPublicKey = config getString "web.vapid_public_key"
@ -43,20 +37,6 @@ final class Env(
key = OneSignalKey
)
val serviceAccountFile = config getString "firebase.service_account_file"
val googleCredentials = Play.resourceAsStream(serviceAccountFile).map { file =>
ServiceAccountCredentials
.fromStream(file)
.createScoped(Set("https://www.googleapis.com/auth/firebase.messaging").asJava)
}
if (googleCredentials.isEmpty) logger.warn(s"Missing $serviceAccountFile file, firebase push notifications will not work.")
private lazy val firebasePush = new FirebasePush(
googleCredentials,
deviceApi.findLastManyByUserId("firebase", 3) _,
url = FirebaseUrl
)
private lazy val webPush = new WebPush(
webSubscriptionApi.getSubscriptions(5) _,
url = WebUrl,
@ -64,7 +44,6 @@ final class Env(
)
private lazy val pushApi = new PushApi(
firebasePush,
oneSignalPush,
webPush,
getLightUser,

View File

@ -1,65 +0,0 @@
package lila.push
import java.io.FileInputStream
import scala.concurrent.Future
import com.google.auth.oauth2.GoogleCredentials
import com.google.auth.oauth2.AccessToken
import play.api.libs.json._
import play.api.libs.ws.WS
import play.api.Play.current
private final class FirebasePush(
credentialsOpt: Option[GoogleCredentials],
getDevices: String => Fu[List[Device]],
url: String
) {
def apply(userId: String)(data: => PushApi.Data): Funit =
credentialsOpt.fold(fuccess({})) { creds =>
getDevices(userId) flatMap {
case Nil => funit
// access token has 1h lifetime and is requested only if expired
case devices => BlockingIO {
creds.refreshIfExpired()
creds.getAccessToken()
} flatMap { token =>
// TODO http batch request is possible using a multipart/mixed content
// unfortuntely it doesn't seem easily doable with play WS
Future.sequence(devices.map(send(token, _, data))).map(_ => ())
}
}
}
private def send(token: AccessToken, device: Device, data: => PushApi.Data): Funit = {
WS.url(url)
.withHeaders(
"Authorization" -> s"Bearer ${token.getTokenValue}",
"Accept" -> "application/json",
"Content-type" -> "application/json; UTF-8"
)
.post(Json.obj(
"message" -> Json.obj(
"token" -> device._id,
// firebase doesn't support nested data object and we only use what is
// inside userData
"data" -> (data.payload \ "userData").asOpt[JsObject].map(transform(_)),
"notification" -> Json.obj(
"body" -> data.body,
"title" -> data.title
)
)
)) flatMap {
case res if res.status == 200 => funit
case res => fufail(s"[push] firebase: ${res.status} ${res.body}")
}
}
// filter out any non string value, otherwise Firebase API silently rejects
// the request
private def transform(obj: JsObject): JsObject =
JsObject(obj.fields.collect {
case (k, v: JsString) => s"lichess.$k" -> v
case (k, v: JsNumber) => s"lichess.$k" -> JsString(v.toString)
})
}

View File

@ -15,7 +15,6 @@ import lila.hub.actorApi.round.{ MoveEvent, IsOnGame }
import lila.message.{ Thread, Post }
private final class PushApi(
firebasePush: FirebasePush,
oneSignalPush: OneSignalPush,
webPush: WebPush,
implicit val lightUser: LightUser.GetterSync,
@ -42,7 +41,11 @@ private final class PushApi(
"userData" -> Json.obj(
"type" -> "gameFinish",
"gameId" -> game.id,
"fullId" -> pov.fullId
"fullId" -> pov.fullId,
"color" -> pov.color.name,
"fen" -> Forsyth.exportBoard(game.board),
"lastMove" -> game.lastMoveKeys,
"win" -> pov.win
)
)
))
@ -137,7 +140,11 @@ private final class PushApi(
private def corresGameJson(pov: Pov, typ: String) = Json.obj(
"type" -> typ,
"gameId" -> pov.gameId,
"fullId" -> pov.fullId
"fullId" -> pov.fullId,
"color" -> pov.color.name,
"fen" -> Forsyth.exportBoard(pov.game.board),
"lastMove" -> pov.game.lastMoveKeys,
"secondsLeft" -> pov.remainingSeconds
)
def newMessage(t: Thread, p: Post): Funit =
@ -152,7 +159,8 @@ private final class PushApi(
"userId" -> t.receiverOf(p),
"userData" -> Json.obj(
"type" -> "newMessage",
"threadId" -> t.id
"threadId" -> t.id,
"sender" -> sender
)
)
))
@ -189,7 +197,8 @@ private final class PushApi(
"userId" -> challenger.id,
"userData" -> Json.obj(
"type" -> "challengeAccept",
"challengeId" -> c.id
"challengeId" -> c.id,
"joiner" -> lightJoiner
)
)
))
@ -201,9 +210,6 @@ private final class PushApi(
webPush(userId)(data) >> oneSignalPush(userId) {
monitor(lila.mon.push.send)("onesignal")
data
} >> firebasePush(userId) {
monitor(lila.mon.push.send)("firebase")
data
}
private def describeChallenge(c: Challenge) = {

View File

@ -39,7 +39,6 @@ object Dependencies {
val scaffeine = "com.github.blemale" %% "scaffeine" % "2.6.0" % "compile"
val netty = "io.netty" % "netty" % "3.10.6.Final"
val guava = "com.google.guava" % "guava" % "21.0"
val googleOAuth = "com.google.auth" % "google-auth-library-oauth2-http" % "0.18.0"
val specs2 = "org.specs2" %% "specs2-core" % "4.0.2" % "test"
val specs2Scalaz = "org.specs2" %% "specs2-scalaz" % "4.0.2" % "test"
val scalaUri = "io.lemonlabs" %% "scala-uri" % "1.2.0"