diff options
author | vlad <vlad@driver.xyz> | 2017-06-30 19:38:37 -0700 |
---|---|---|
committer | vlad <vlad@driver.xyz> | 2017-06-30 19:38:37 -0700 |
commit | 96d81a36286e41035ff4068859a3b0f9da924fbc (patch) | |
tree | 8d9f0014140d1f07ca449b56adaba8ccb3d2fc59 /src/main/scala/xyz/driver/pdsuidomain/services | |
parent | a997aa6539d1f0af4ab4fc395ff2033335da312a (diff) | |
download | rest-query-96d81a36286e41035ff4068859a3b0f9da924fbc.tar.gz rest-query-96d81a36286e41035ff4068859a3b0f9da924fbc.tar.bz2 rest-query-96d81a36286e41035ff4068859a3b0f9da924fbc.zip |
Latest PDS UI utils including all the domain stuffv0.1.12
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/services')
16 files changed, 361 insertions, 33 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala index 43e46ed..8c89505 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala @@ -33,7 +33,6 @@ object ArmService { case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError - } sealed trait GetListReply @@ -44,13 +43,12 @@ object ArmService { case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } sealed trait UpdateReply object UpdateReply { - case class Updated(updated: Arm) extends UpdateReply + final case class Updated(updated: Arm) extends UpdateReply type Error = UpdateReply with DomainError @@ -59,9 +57,9 @@ object ArmService { case object AuthorizationError extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError - case class AlreadyExistsError(x: Arm) extends UpdateReply with DomainError { + final case class AlreadyExistsError(x: Arm) extends UpdateReply with DomainError { val userMessage = s"The arm with such name of trial already exists." } @@ -80,9 +78,9 @@ object ArmService { case object AuthorizationError extends CreateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError - case class AlreadyExistsError(x: Arm) extends CreateReply with DomainError { + final case class AlreadyExistsError(x: Arm) extends CreateReply with DomainError { val userMessage = s"The arm with this name of trial already exists." } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala index a735ade..f8d820b 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala @@ -3,7 +3,6 @@ package xyz.driver.pdsuidomain.services import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db.Sorting import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ import xyz.driver.pdsuidomain.entities.CategoryWithLabels import scala.concurrent.Future @@ -19,7 +18,7 @@ object CategoryService { } } -trait CategoryService extends PhiLogging { +trait CategoryService { import CategoryService._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala index ffa252c..2c01a7e 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala @@ -99,7 +99,6 @@ object DocumentService { case class CommonError(userMessage: String) extends DeleteReply with DomainError } - } trait DocumentService { @@ -115,7 +114,6 @@ trait DocumentService { def create(draftDocument: Document)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - // Update operations are validated in internal.*Command def update(orig: Document, draft: Document)( implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala new file mode 100644 index 0000000..8fb399a --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala @@ -0,0 +1,64 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AnonymousRequestContext +import xyz.driver.pdsuicommon.db.SearchFilterExpr +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientWithLabels +import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrial, ExportTrialWithLabels} +import xyz.driver.pdsuidomain.entities.{MedicalRecord, Patient, Trial} + +import scala.concurrent.Future + +object ExportService { + + sealed trait GetPatientReply + object GetPatientReply { + type Error = GetPatientReply with DomainError + + case class Entity(x: ExportPatientWithLabels) extends GetPatientReply + + case object NotFoundError extends GetPatientReply with DomainError.NotFoundError { + def userMessage: String = "Patient not found" + } + } + + sealed trait GetTrialListReply + object GetTrialListReply { + case class EntityList(xs: Seq[ExportTrial], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetTrialListReply + } + + sealed trait GetTrialReply + object GetTrialReply { + type Error = GetTrialReply with DomainError + + case class Entity(x: ExportTrialWithLabels) extends GetTrialReply + + case object NotFoundError extends GetTrialReply with DomainError.NotFoundError { + def userMessage: String = "Trial not found" + } + } +} + +trait ExportService { + + import ExportService._ + + def getPatient(id: UuidId[Patient]) + (implicit requestContext: AnonymousRequestContext): Future[GetPatientReply] + + def getTrialList(filter: SearchFilterExpr = SearchFilterExpr.Empty) + (implicit requestContext: AnonymousRequestContext): Future[GetTrialListReply] + + def getTrial(trialId: StringId[Trial], condition: String) + (implicit requestContext: AnonymousRequestContext): Future[GetTrialReply] + + def getRecords(patientId: UuidId[Patient]) + (implicit requestContext: AnonymousRequestContext): Future[MedicalRecordService.GetListReply] + + def getRecordPdf(recordId: LongId[MedicalRecord]) + (implicit requestContext: AnonymousRequestContext): Future[MedicalRecordService.GetPdfSourceReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala index 0677584..aadc5fb 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala @@ -3,7 +3,6 @@ package xyz.driver.pdsuidomain.services import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db.Sorting import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging.PhiLogging import xyz.driver.pdsuidomain.entities.Label import scala.concurrent.Future @@ -20,7 +19,7 @@ object LabelService { } } -trait LabelService extends PhiLogging { +trait LabelService { import LabelService._ def getAll(sorting: Option[Sorting] = None)( diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/LinkedPatientService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/LinkedPatientService.scala new file mode 100644 index 0000000..8fc1662 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/LinkedPatientService.scala @@ -0,0 +1,62 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{LinkedPatient, Patient, Trial} + +import scala.concurrent.Future + +object LinkedPatientService { + + trait DefaultTrialNotFoundError { + def userMessage: String = "Trial not found" + } + + trait DefaultPatientNotFoundError { + def userMessage: String = "Patient not found" + } + + final case class RichLinkedPatient(email: Email, + name: String, + patientId: UuidId[Patient], + trialId: StringId[Trial]) { + def toLinkedPatient(user: User) = LinkedPatient( + userId = user.id, + patientId = patientId, + trialId = trialId + ) + } + + object RichLinkedPatient { + implicit def toPhiString(x: RichLinkedPatient): PhiString = { + import x._ + phi"RichLinkedPatient(email=${Unsafe(email)}, patientId=$patientId, trialId=$trialId)" + } + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + + /** + * @param createdUser None if a user was created before + */ + final case class Created(x: RichLinkedPatient, createdUser: Option[User]) extends CreateReply + + case object PatientNotFoundError + extends CreateReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object TrialNotFoundError + extends CreateReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + final case class CommonError(userMessage: String) extends CreateReply with DomainError + } +} + +trait LinkedPatientService { + + import LinkedPatientService._ + + def create(entity: RichLinkedPatient): Future[CreateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MailService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MailService.scala new file mode 100644 index 0000000..3022716 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/MailService.scala @@ -0,0 +1,39 @@ +package xyz.driver.pdsuidomain.services + +import java.io.{InputStream, StringReader, StringWriter} + +import xyz.driver.pdsuidomain.services.MailService.Template +import com.github.mustachejava.DefaultMustacheFactory +import com.twitter.mustache.ScalaObjectHandler + +import scala.io.Source + +object MailService { + + trait Template { + val subject: String + def parameters: Map[String, Any] + def filename: String + val contentType: String = "text/html" + + protected val factory = new DefaultMustacheFactory() + factory.setObjectHandler(new ScalaObjectHandler) + + protected def inputStream: InputStream = getClass.getClassLoader.getResourceAsStream(filename) + protected def templateContent: String = Source.fromInputStream(inputStream).getLines().mkString + + def content: String = { + val template = factory.compile(new StringReader(templateContent), filename) + val writer = new StringWriter + template + .execute(writer, parameters) + .close() + writer.toString + } + } +} + +trait MailService { + + def sendTo(email: String, template: Template): Boolean +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala index 8ce06f2..df57e17 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala @@ -6,7 +6,6 @@ import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} import xyz.driver.pdsuicommon.domain.LongId import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ import xyz.driver.pdsuidomain.entities.Message import scala.concurrent.Future @@ -66,10 +65,9 @@ object MessageService { case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError case class CommonError(userMessage: String) extends DeleteReply with DomainError } - } -trait MessageService extends PhiLogging { +trait MessageService { import MessageService._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala index 593e2ce..e23dfc5 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala @@ -84,7 +84,10 @@ object PatientCriterionService { object UpdateReply { type Error = UpdateReply with DomainError - case object Updated extends UpdateReply + case class Updated(x: PatientCriterion, labelId: LongId[Label], armList: List[Arm], criterionIsCompound: Boolean) + extends UpdateReply + + case object UpdatedList extends UpdateReply case object AuthorizationError extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -101,7 +104,7 @@ trait PatientCriterionService { import PatientCriterionService._ def getAll(patientId: UuidId[Patient], - filter: SearchFilterExpr = SearchFilterExpr.Empty, + origFilter: SearchFilterExpr = SearchFilterExpr.Empty, sorting: Option[Sorting] = None, pagination: Option[Pagination] = None)( implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala index 39ee2b1..a15e11f 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala @@ -25,7 +25,7 @@ object PatientHypothesisService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[PatientHypothesis], totalFound: Int) extends GetListReply + case class EntityList(xs: Seq[(PatientHypothesis, Boolean)], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -38,7 +38,7 @@ object PatientHypothesisService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: PatientHypothesis) extends GetByIdReply + case class Entity(x: PatientHypothesis, isRequired: Boolean) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -53,8 +53,8 @@ object PatientHypothesisService { case class CommonError(userMessage: String) extends GetByIdReply with DomainError implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x, isRequired) => phi"GetByIdReply.Entity($x, $isRequired)" } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala index f6039f0..2586798 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala @@ -1,7 +1,5 @@ package xyz.driver.pdsuidomain.services -import java.time.LocalDate - import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain.{LongId, UuidId} @@ -12,21 +10,23 @@ import scala.concurrent.Future object PatientLabelEvidenceService { - case class Aggregated(evidence: PatientLabelEvidence, date: LocalDate, documentType: String, providerType: String) - trait DefaultAccessDeniedError { def userMessage: String = "Access denied" } + trait DefaultPatientNotFoundError { + def userMessage: String = "Patient not found" + } + sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: Aggregated) extends GetByIdReply + case class Entity(x: PatientLabelEvidenceView) extends GetByIdReply type Error = GetByIdReply with DomainError - case class NotFoundError(userMessage: String) extends GetByIdReply with DomainError.NotFoundError + final case class NotFoundError(userMessage: String) extends GetByIdReply with DomainError.NotFoundError - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -34,10 +34,13 @@ object PatientLabelEvidenceService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[Aggregated], totalFound: Int) extends GetListReply + case class EntityList(xs: Seq[PatientLabelEvidenceView], totalFound: Int) extends GetListReply type Error = GetListReply with DomainError + case object PatientNotFoundError + extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError + case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala new file mode 100644 index 0000000..55a408f --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala @@ -0,0 +1,78 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue +import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} +import xyz.driver.pdsuicommon.error.DomainError + +import scala.concurrent.Future + +object QueueUploadService { + trait DefaultNotFoundError { + def userMessage: String = "Message not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + + case class Created(x: BridgeUploadQueue.Item) extends CreateReply + case object AuthorizationError extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + case class CommonError(userMessage: String) extends CreateReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + type Error = GetByIdReply with DomainError + + case class Entity(x: BridgeUploadQueue.Item) extends GetByIdReply + case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError + case class CommonError(userMessage: String) extends GetByIdReply with DomainError + } + + sealed trait GetListReply + object GetListReply { + type Error = GetListReply with DomainError + + case class EntityList(xs: Seq[BridgeUploadQueue.Item], + totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait ResetReply + object ResetReply { + type Error = ResetReply with DomainError + + case class Updated(updated: BridgeUploadQueue.Item) extends ResetReply + case object AuthorizationError extends ResetReply with DomainError.AuthorizationError with DefaultAccessDeniedError + case object NotFoundError extends ResetReply with DefaultNotFoundError with DomainError.NotFoundError + case class CommonError(userMessage: String) extends ResetReply with DomainError + } +} + +trait QueueUploadService { + + import QueueUploadService._ + + def create(kind: String, tag: String) + (implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def getById(kind: String, tag: String) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def reset(kind: String, tag: String) + (implicit requestContext: AuthenticatedRequestContext): Future[ResetReply] + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala new file mode 100644 index 0000000..3034027 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala @@ -0,0 +1,31 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.UserHistory + +import scala.concurrent.Future + +object UserHistoryService { + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[UserHistory], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait UserHistoryService { + + import UserHistoryService._ + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala index 79e9835..a1d4800 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala @@ -4,7 +4,6 @@ import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, AuthenticatedReques import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} import xyz.driver.pdsuicommon.domain.{Email, LongId, User} import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ import scala.concurrent.Future @@ -95,10 +94,9 @@ object UserService { case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError case class CommonError(userMessage: String) extends DeleteReply with DomainError } - } -trait UserService extends PhiLogging { +trait UserService { import UserService._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/fake/StubMailService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/fake/StubMailService.scala new file mode 100644 index 0000000..932da67 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/fake/StubMailService.scala @@ -0,0 +1,13 @@ +package xyz.driver.pdsuidomain.services.fake + +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.services.MailService +import xyz.driver.pdsuidomain.services.MailService.Template + +object StubMailService extends MailService with PhiLogging { + + override def sendTo(email: String, template: Template): Boolean = { + logger.debug(phi"sendTo(email=${Unsafe(email)}") + true + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/SendGridMailService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/SendGridMailService.scala new file mode 100644 index 0000000..37dc758 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/SendGridMailService.scala @@ -0,0 +1,45 @@ +package xyz.driver.pdsuidomain.services.rest + +import com.sendgrid._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.services.MailService +import xyz.driver.pdsuidomain.services.MailService.Template +import xyz.driver.pdsuidomain.services.rest.SendGridMailService._ + +import scala.util.control.NonFatal + +object SendGridMailService { + + private val ExpectedHttpCode = 202 + + case class Settings(provider: String, frontEndUrl: String, apiKey: String, from: String) +} + +class SendGridMailService(settings: Settings) extends MailService with PhiLogging { + + def sendTo(email: String, template: Template): Boolean = { + val to = new Email(email) + val content = new Content(template.contentType, template.content) + val mail = new Mail(new Email(settings.from), template.subject, to, content) + + val request = new Request() + val sendGrid = new SendGrid(settings.apiKey) + + try { + request.method = Method.POST + request.endpoint = "mail/send" + request.body = mail.build() + val response = sendGrid.api(request) + if (response.statusCode != ExpectedHttpCode) { + logger.error(phi"Unexpected response: ${Unsafe(response.statusCode)}, ${Unsafe(response.body.take(100))}") + } + + response.statusCode == ExpectedHttpCode + } + catch { + case NonFatal(e) => + logger.error(phi"Can not send an email: $e") + false + } + } +} |