Skip to content

Commit 1345be0

Browse files
committed
Refactors some of the logic around frontend logging endpoint
1 parent 86ff6ab commit 1345be0

File tree

8 files changed

+61
-59
lines changed

8 files changed

+61
-59
lines changed

hat/app/org/hatdex/hat/api/controllers/Authentication.scala

+25-10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ package org.hatdex.hat.api.controllers
2626

2727
import java.net.{ URLDecoder, URLEncoder }
2828

29+
import akka.Done
2930
import javax.inject.Inject
3031
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
3132
import com.mohiva.play.silhouette.api.util.{ Credentials, PasswordHasherRegistry }
@@ -246,9 +247,10 @@ class Authentication @Inject() (
246247
case Some(user) =>
247248
applicationsService.applicationStatus()(request.dynamicEnvironment, user, request).flatMap { applications =>
248249
val maybeApplication = applications.find(_.application.id.equals(claimHatRequest.applicationId))
249-
val maybeEmailDetails = maybeApplication.map(app => {
250-
(app.application.info.name, app.application.info.graphics.logo.normal)
251-
})
250+
val maybeAppDetails = maybeApplication.map { app =>
251+
((app.application.info.name, app.application.developer.logo.map(_.normal).getOrElse("#")),
252+
(app.application.id, app.application.info.version.toString))
253+
}
252254

253255
val scheme = if (request.secure) {
254256
"https://"
@@ -260,23 +262,36 @@ class Authentication @Inject() (
260262
tokenService.retrieve(email, isSignup = true).flatMap {
261263
case Some(existingTokenUser) if !existingTokenUser.isExpired =>
262264
val claimLink = s"$scheme${request.host}/#/hat/claim/${existingTokenUser.id}?email=${URLEncoder.encode(email, "UTF-8")}"
263-
mailer.claimHat(email, claimLink, maybeEmailDetails)
265+
mailer.claimHat(email, claimLink, maybeAppDetails.map(_._1))
264266

265267
Future.successful(response)
266268
case Some(_) => Future.successful(Ok(Json.toJson(SuccessResponse("The HAT is already claimed"))))
267269

268270
case None =>
269-
logService.logAction(request.dynamicEnvironment.domain, "unclaimed", None, None, Some((claimHatRequest.applicationId, applicationVersion))) recover {
270-
case _ => logger.error("LogActionError::unclaimed")
271-
}
272-
273271
val token = MailClaimTokenUser(email)
274-
tokenService.create(token).map { _ =>
272+
273+
val eventualResult = for {
274+
_ <- tokenService.create(token)
275+
_ <- logService
276+
.logAction(request.dynamicEnvironment.domain, LogRequest("unclaimed", None, None), maybeAppDetails.map(_._2))
277+
.recover {
278+
case e =>
279+
logger.error(s"LogActionError::unclaimed. Reason: ${e.getMessage}")
280+
Done
281+
}
282+
} yield {
283+
275284
val claimLink = s"$scheme${request.host}/#/hat/claim/${token.id}?email=${URLEncoder.encode(email, "UTF-8")}"
276-
mailer.claimHat(email, claimLink, maybeEmailDetails)
285+
mailer.claimHat(email, claimLink, maybeAppDetails.map(_._1))
277286

278287
response
279288
}
289+
290+
eventualResult.recover {
291+
case e =>
292+
logger.error(s"Could not create new HAT claim token. Reason: ${e.getMessage}")
293+
InternalServerError(Json.toJson(ErrorMessage("Internal Server Error", "Failed to initialize HAT claim process")))
294+
}
280295
}
281296
}
282297
case None => Future.successful(response)

hat/app/org/hatdex/hat/api/controllers/HattersRequestProxy.scala

+12-5
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,30 @@ class HattersRequestProxy @Inject() (
4848
case Some(token) if token.isSignUp && !token.isExpired && token.email == request.dynamicEnvironment.ownerEmail =>
4949
usersService.listUsers.map(_.find(_.roles.contains(Owner()))).flatMap {
5050
case Some(user) =>
51-
for {
51+
val eventualResult = for {
5252
_ <- updateHatMembership(hatClaimComplete)
5353
_ <- authInfoRepository.update(user.loginInfo, passwordHasherRegistry.current.hash(request.body.password))
5454
_ <- tokenService.expire(token.id)
5555
authenticator <- env.authenticatorService.create(user.loginInfo)
5656
result <- env.authenticatorService.renew(authenticator, Ok(Json.toJson(SuccessResponse("HAT claimed"))))
57+
_ <- logService.logAction(request.dynamicEnvironment.domain, LogRequest("claimed", None, None), None).recover {
58+
case e =>
59+
logger.error(s"LogActionError::unclaimed. Reason: ${e.getMessage}")
60+
Done
61+
}
5762
} yield {
5863
//env.eventBus.publish(LoginEvent(user, request))
5964
//mailer.passwordChanged(token.email, user)
6065

61-
logService.logAction(request.dynamicEnvironment.domain, "claimed", None, None, None).recover {
62-
case _ => logger.error("LogActionError::claimed")
63-
}
64-
6566
result
6667
}
6768

69+
eventualResult.recover {
70+
case e =>
71+
logger.error(s"HAT claim process failed with error ${e.getMessage}")
72+
BadRequest(Json.toJson(ErrorMessage("Bad Request", "HAT claim process failed")))
73+
}
74+
6875
case None => Future.successful(Unauthorized(Json.toJson(ErrorMessage("HAT claim unauthorized", "No user matching token"))))
6976
}
7077

hat/app/org/hatdex/hat/api/controllers/LogController.scala

+15-21
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,39 @@ package org.hatdex.hat.api.controllers
22

33
import com.mohiva.play.silhouette.api.Silhouette
44
import javax.inject.Inject
5-
import org.hatdex.hat.api.json.ApplicationJsonProtocol
5+
import org.hatdex.hat.api.json.HatJsonFormats
66
import org.hatdex.hat.api.models._
77
import org.hatdex.hat.api.service.{ LogService, RemoteExecutionContext }
8-
<<<<<<< HEAD
9-
import org.hatdex.hat.authentication.{ ContainsApplicationRole, HatApiAuthEnvironment, HatApiController, WithRole }
10-
=======
118
import org.hatdex.hat.authentication.{ HatApiAuthEnvironment, HatApiController }
12-
>>>>>>> b8d0df1... Completed ActionLog fixes
139
import org.hatdex.hat.utils.HatBodyParsers
14-
import org.hatdex.hat.api.json.HatJsonFormats._
1510
import play.api.Logger
1611
import play.api.libs.json.Json
1712
import play.api.mvc.{ Action, ControllerComponents }
1813

14+
import scala.util.Try
15+
1916
class LogController @Inject() (
2017
components: ControllerComponents,
2118
parsers: HatBodyParsers,
22-
silhouette: Silhouette[HatApiAuthEnvironment])(
23-
implicit
24-
val ec: RemoteExecutionContext,
25-
logService: LogService)
26-
extends HatApiController(components, silhouette) with ApplicationJsonProtocol {
19+
logService: LogService,
20+
silhouette: Silhouette[HatApiAuthEnvironment])(implicit val ec: RemoteExecutionContext)
21+
extends HatApiController(components, silhouette) with HatJsonFormats {
2722

28-
protected val logger = Logger(this.getClass)
23+
private val logger = Logger(this.getClass)
2924

30-
def log(): Action[LogRequest] = SecuredAction.async(parsers.json[LogRequest]) { request =>
25+
def logFrontendAction(): Action[LogRequest] = SecuredAction.async(parsers.json[LogRequest]) { request =>
3126
val logRequest = request.body
3227
val hatAddress = request.dynamicEnvironment.domain
33-
val (applicationId, applicationVersion) = request.authenticator.customClaims.map { customClaims =>
34-
((customClaims \ "application").asOpt[String], (customClaims \ "applicationVersion").asOpt[String])
35-
}.getOrElse((None, None))
28+
val appDetails = request.authenticator.customClaims.flatMap { customClaims =>
29+
Try(((customClaims \ "application").as[String], (customClaims \ "applicationVersion").as[String])).toOption
30+
}
3631

37-
logService.logAction(hatAddress, logRequest.actionCode, logRequest.message, logRequest.logGroup, applicationData).map { _ =>
32+
logService.logAction(hatAddress, logRequest, appDetails).map { _ =>
3833
Ok(Json.toJson(SuccessResponse(s"${logRequest.actionCode} logged")))
3934
}.recover {
40-
case _ => {
41-
logger.error(s"LogActionError::${logRequest.actionCode}")
42-
BadRequest(Json.toJson(ErrorMessage("LogActionError", s"LogActionError::${logRequest.actionCode} logging failed")))
43-
}
35+
case e =>
36+
logger.error(s"Failed to log action ${logRequest.actionCode}. Reason:\n${e.getMessage}")
37+
InternalServerError(Json.toJson(ErrorMessage("Internal server error", s"Could not log ${logRequest.actionCode} action")))
4438
}
4539
}
4640
}

hat/app/org/hatdex/hat/api/models/LogRequest.scala

-16
This file was deleted.

hat/app/org/hatdex/hat/api/service/LogService.scala

+7-3
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,23 @@ package org.hatdex.hat.api.service
2626

2727
import java.util.UUID
2828

29+
import akka.Done
2930
import javax.inject.Inject
31+
import org.hatdex.hat.api.models.LogRequest
3032
import play.api.Logger
3133

3234
import scala.concurrent.Future
3335

3436
class LogService @Inject() (implicit val ec: DalExecutionContext) {
3537
val logger = Logger(this.getClass)
3638

37-
def logAction(hat: String, actionCode: String, message: Option[String], logGroup: Option[String], applicationData: Option[(String, String)]): Future[Unit] = {
39+
def logAction(hat: String, logDetails: LogRequest, applicationDetails: Option[(String, String)]): Future[Done] = {
3840
Future {
3941
val logId = UUID.randomUUID()
40-
val appVersion = applicationData.map(app => s"${app._1}@${app._2}")
41-
logger.info(s"[${logGroup.getOrElse("STATS")}] [$hat] [$logId] [$actionCode] [${message.getOrElse("")}] ${appVersion.getOrElse("_")}")
42+
val applicationVersion = applicationDetails.map(a => s"${a._1}@${a._2}").getOrElse("Unknown")
43+
logger.info(s"[${logDetails.logGroup.getOrElse("STATS")}] [$hat] [$logId] [${logDetails.actionCode}] [$applicationVersion] ${logDetails.message.getOrElse("")}")
44+
45+
Done
4246
}
4347
}
4448
}

hat/conf/routes

-3
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ POST /control/v2/auth/passwordreset/confirm/:token org.hatdex.hat.
2828
POST /control/v2/auth/claim org.hatdex.hat.api.controllers.Authentication.claim
2929
POST /control/v2/auth/claim/complete/:claimToken org.hatdex.hat.api.controllers.HattersRequestProxy.proxyRequestHatClaim(claimToken: String)
3030

31-
# LOG routes
32-
POST /log org.hatdex.hat.api.controllers.LogController.log
33-
3431
-> /api/v2 v20.Routes
3532
-> /api/v2.0 v20.Routes
3633
-> /api/v2.6 v26.Routes

hat/conf/v26.routes

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
GET /system/status org.hatdex.hat.api.controllers.SystemStatus.status()
33
GET /phata/profile org.hatdex.hat.phata.controllers.Phata.profile
4+
POST /report-frontend-action org.hatdex.hat.api.controllers.LogController.logFrontendAction
45

56
# FILE routes
67
POST /files/upload org.hatdex.hat.api.controllers.Files.startUpload

project/Dependencies.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ object Dependencies {
9393
}
9494

9595
object HATDeX {
96-
private val version = "2.6.2-SNAPSHOT"
96+
private val version = "2.6.5-SNAPSHOT"
9797
val hatClient = "org.hatdex" %% "hat-client-scala-play" % version
9898
val dexClient = "org.hatdex" %% "dex-client-scala-play" % "2.6.4-SNAPSHOT"
9999
val codegen = "org.hatdex" %% "slick-postgres-driver" % "0.0.9"

0 commit comments

Comments
 (0)