cats.data.EitherT Scala Examples
The following examples show how to use cats.data.EitherT.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: NoOpHttpClient.scala From cornichon with Apache License 2.0 | 6 votes |
package com.github.agourlay.cornichon.http.client import cats.Show import cats.data.EitherT import cats.syntax.either._ import com.github.agourlay.cornichon.core.Done import com.github.agourlay.cornichon.http.{ CornichonHttpResponse, HttpRequest, HttpStreamedRequest } import monix.eval.Task import org.http4s.EntityEncoder import scala.concurrent.duration.FiniteDuration class NoOpHttpClient extends HttpClient { def runRequest[A: Show](cReq: HttpRequest[A], t: FiniteDuration)(implicit ee: EntityEncoder[Task, A]) = EitherT.apply(Task.now(CornichonHttpResponse(200, Nil, "NoOpBody").asRight)) def openStream(req: HttpStreamedRequest, t: FiniteDuration) = Task.now(CornichonHttpResponse(200, Nil, "NoOpBody").asRight) def shutdown() = Done.taskDone def paramsFromUrl(url: String) = Right(Nil) }
Example 2
Source File: Selective.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.control import cats.data.{EitherT, OptionT, ReaderT, WriterT} import cats.instances.option._ import cats.syntax.coflatMap._ import cats.syntax.option._ import cats.{Applicative, Monad, Monoid} import simulacrum._ import tofu.control.impl._ @typeclass trait Selective[F[_]] extends Applicative[F] { @noop def selectAp[A, B](fe: F[Either[A, B]])(ff: => F[A => B]): F[B] @noop def select[A](fo: F[Option[A]])(fa: => F[A]): F[A] = selectAp[Unit, A](map(fo)(_.toRight(())))(map(fa)(a => (_: Unit) => a)) def selectRight[A](fb: F[A], fo: F[Option[A]]): F[A] = select(fo)(fb) @noop def orElses[A](fx: F[Option[A]])(fy: => F[Option[A]]): F[Option[A]] = select(map(fx)(_.coflatten))(fy) def whens[A](fb: F[Boolean])(fa: => F[A]): F[Option[A]] = select(map(fb)(x => if (x) None else Some(none[A])))(map(fa)(_.some)) def unlesss[A](fb: F[Boolean])(fa: => F[A]): F[Option[A]] = select(map(fb)(x => if (x) Some(none[A]) else None))(map(fa)(_.some)) def whens_[A](fb: F[Boolean])(fa: => F[A]): F[Unit] = select(map(fb)(x => if (x) None else Some(())))(void(fa)) def unlesss_[A](fb: F[Boolean])(fa: => F[A]): F[Unit] = select(map(fb)(x => if (x) Some(()) else None))(void(fa)) @noop def optionMonoid[A]: Monoid[F[Option[A]]] = new Monoid[F[Option[A]]] { def empty: F[Option[A]] = pure(None) def combine(x: F[Option[A]], y: F[Option[A]]): F[Option[A]] = orElses(x)(y) } } object Selective extends SelectiveInstances trait SelectiveInstances extends SelectiveInstances2 { final implicit def selectiveOverMonad[F[_]: Monad]: SelectiveOverMonad[F] = new SelectiveOverMonad[F] } trait SelectiveInstances2 { final implicit def selectiveOptionT[F[_]: Selective]: Selective[OptionT[F, *]] = new SelectiveOptionT[F] final implicit def selectiveEitherT[F[_]: Selective, E]: Selective[EitherT[F, E, *]] = new SelectiveEitherT[F, E] final implicit def selectiveReaderT[F[_]: Selective, R]: Selective[ReaderT[F, R, *]] = new SelectiveReaderT[F, R] final implicit def selectiveWriterT[F[_]: Selective, W: Monoid]: Selective[WriterT[F, W, *]] = new SelectiveWriterT[F, W] }
Example 3
Source File: IndexLogic.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.indexing_logic import akka.NotUsed import akka.stream.scaladsl.Source import cats.Monad import cats.data.EitherT import com.sksamuel.elastic4s.streams.RequestBuilder import com.yannick_cw.elastic_indexer4s.Index_results.{IndexError, RunResult, StageSucceeded} import com.yannick_cw.elastic_indexer4s.elasticsearch.EsAccess trait IndexOps[F[_]] { def write[A: RequestBuilder](source: Source[A, NotUsed]): EitherT[F, IndexError, RunResult] def addSwitch(writeDone: EitherT[F, IndexError, RunResult], minT: Double, maxT: Double, alias: String): EitherT[F, IndexError, RunResult] def addDelete(writeDone: EitherT[F, IndexError, RunResult], keep: Int, aliasProtection: Boolean): EitherT[F, IndexError, RunResult] } class IndexingWithEs[F[_]: Monad](implicit ES: EsAccess[F]) extends IndexOps[F] { private def addRunStep(actionDone: EitherT[F, IndexError, RunResult], nextStep: EitherT[F, IndexError, StageSucceeded]) = for { indexResult <- actionDone success <- nextStep .leftMap(_.copy(succeededStages = indexResult.succeededStages.toList)) } yield RunResult(indexResult.succeededStages :+ success: _*) def write[A: RequestBuilder](source: Source[A, NotUsed]): EitherT[F, IndexError, RunResult] = addRunStep(ES.createIndex().map(RunResult(_)), ES.indexSource(source)) def addSwitch(writeDone: EitherT[F, IndexError, RunResult], minT: Double, maxT: Double, alias: String): EitherT[F, IndexError, RunResult] = addRunStep(writeDone, ES.switchAlias(minT, maxT, alias)) def addDelete(writeDone: EitherT[F, IndexError, RunResult], keep: Int, aliasProtection: Boolean): EitherT[F, IndexError, RunResult] = addRunStep(writeDone, ES.deleteOldIndices(keep, aliasProtection)) }
Example 4
Source File: SyncEffect.scala From cats-effect with Apache License 2.0 | 5 votes |
package cats package effect import simulacrum._ import cats.data.{EitherT, WriterT} implicit def catsWriterTSyncEffect[F[_]: SyncEffect, L: Monoid]: SyncEffect[WriterT[F, L, *]] = new WriterTSyncEffect[F, L] { def F = SyncEffect[F]; def L = Monoid[L] } private[effect] trait EitherTSyncEffect[F[_]] extends SyncEffect[EitherT[F, Throwable, *]] with Sync.EitherTSync[F, Throwable] { protected def F: SyncEffect[F] def runSync[G[_], A](fa: EitherT[F, Throwable, A])(implicit G: Sync[G]): G[A] = F.runSync(F.rethrow(fa.value)) } private[effect] trait WriterTSyncEffect[F[_], L] extends SyncEffect[WriterT[F, L, *]] with Sync.WriterTSync[F, L] { protected def F: SyncEffect[F] protected def L: Monoid[L] def runSync[G[_], A](fa: WriterT[F, L, A])(implicit G: Sync[G]): G[A] = F.runSync(F.map(fa.run)(_._2)) } }
Example 5
Source File: Effect.scala From cats-effect with Apache License 2.0 | 5 votes |
package cats package effect import simulacrum._ import cats.data.{EitherT, WriterT} import scala.annotation.implicitNotFound import scala.util.Either implicit def catsWriterTEffect[F[_]: Effect, L: Monoid]: Effect[WriterT[F, L, *]] = new WriterTEffect[F, L] { def F = Effect[F]; def L = Monoid[L] } private[effect] trait EitherTEffect[F[_]] extends Effect[EitherT[F, Throwable, *]] with Async.EitherTAsync[F, Throwable] { protected def F: Effect[F] def runAsync[A](fa: EitherT[F, Throwable, A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit] = F.runAsync(fa.value)(cb.compose(_.flatMap(x => x))) override def toIO[A](fa: EitherT[F, Throwable, A]): IO[A] = F.toIO(F.rethrow(fa.value)) } private[effect] trait WriterTEffect[F[_], L] extends Effect[WriterT[F, L, *]] with Async.WriterTAsync[F, L] { protected def F: Effect[F] protected def L: Monoid[L] def runAsync[A](fa: WriterT[F, L, A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit] = F.runAsync(fa.run)(cb.compose(_.map(_._2))) override def toIO[A](fa: WriterT[F, L, A]): IO[A] = F.toIO(fa.value(F)) } }
Example 6
Source File: SyncEffectTests.scala From cats-effect with Apache License 2.0 | 5 votes |
package cats package effect package laws package discipline import cats.data.EitherT import cats.laws.discipline._ import cats.laws.discipline.SemigroupalTests.Isomorphisms import org.scalacheck._, Prop.forAll trait SyncEffectTests[F[_]] extends SyncTests[F] { def laws: SyncEffectLaws[F] def syncEffect[A: Arbitrary: Eq, B: Arbitrary: Eq, C: Arbitrary: Eq](implicit ArbFA: Arbitrary[F[A]], ArbFB: Arbitrary[F[B]], ArbFC: Arbitrary[F[C]], ArbFU: Arbitrary[F[Unit]], ArbFAtoB: Arbitrary[F[A => B]], ArbFBtoC: Arbitrary[F[B => C]], ArbT: Arbitrary[Throwable], CogenA: Cogen[A], CogenB: Cogen[B], CogenC: Cogen[C], CogenT: Cogen[Throwable], EqFA: Eq[F[A]], EqFB: Eq[F[B]], EqFC: Eq[F[C]], EqFU: Eq[F[Unit]], EqT: Eq[Throwable], EqFEitherTU: Eq[F[Either[Throwable, Unit]]], EqFEitherTA: Eq[F[Either[Throwable, A]]], EqEitherTFTA: Eq[EitherT[F, Throwable, A]], EqFABC: Eq[F[(A, B, C)]], EqFInt: Eq[F[Int]], iso: Isomorphisms[F], params: Parameters): RuleSet = new RuleSet { val name = "syncEffect" val bases = Nil val parents = Seq(sync[A, B, C]) val props = Seq( "to[SyncIO] andThen to[F] is identity" -> forAll(laws.toSyncIOAndBackIsIdentity[A] _) ) } } object SyncEffectTests { def apply[F[_]: SyncEffect]: SyncEffectTests[F] = new SyncEffectTests[F] { def laws = SyncEffectLaws[F] } }
Example 7
Source File: PetValidationInterpreter.scala From scala-pet-store with Apache License 2.0 | 5 votes |
package io.github.pauljamescleary.petstore.domain package pets import cats.Applicative import cats.data.EitherT import cats.implicits._ class PetValidationInterpreter[F[_]: Applicative](repository: PetRepositoryAlgebra[F]) extends PetValidationAlgebra[F] { def doesNotExist(pet: Pet): EitherT[F, PetAlreadyExistsError, Unit] = EitherT { repository.findByNameAndCategory(pet.name, pet.category).map { matches => if (matches.forall(possibleMatch => possibleMatch.bio != pet.bio)) { Right(()) } else { Left(PetAlreadyExistsError(pet)) } } } def exists(petId: Option[Long]): EitherT[F, PetNotFoundError.type, Unit] = EitherT { petId match { case Some(id) => // Ensure is a little tough to follow, it says "make sure this condition is true, otherwise throw the error specified // In this example, we make sure that the option returned has a value, otherwise the pet was not found repository.get(id).map { case Some(_) => Right(()) case _ => Left(PetNotFoundError) } case _ => Either.left[PetNotFoundError.type, Unit](PetNotFoundError).pure[F] } } } object PetValidationInterpreter { def apply[F[_]: Applicative](repository: PetRepositoryAlgebra[F]) = new PetValidationInterpreter[F](repository) }
Example 8
Source File: OrderService.scala From scala-pet-store with Apache License 2.0 | 5 votes |
package io.github.pauljamescleary.petstore.domain package orders import cats.Functor import cats.data.EitherT import cats.implicits._ class OrderService[F[_]](orderRepo: OrderRepositoryAlgebra[F]) { def placeOrder(order: Order): F[Order] = orderRepo.create(order) def get(id: Long)(implicit F: Functor[F]): EitherT[F, OrderNotFoundError.type, Order] = EitherT.fromOptionF(orderRepo.get(id), OrderNotFoundError) def delete(id: Long)(implicit F: Functor[F]): F[Unit] = orderRepo.delete(id).as(()) } object OrderService { def apply[F[_]](orderRepo: OrderRepositoryAlgebra[F]): OrderService[F] = new OrderService(orderRepo) }
Example 9
Source File: UserValidationInterpreter.scala From scala-pet-store with Apache License 2.0 | 5 votes |
package io.github.pauljamescleary.petstore.domain package users import cats.Applicative import cats.data.EitherT import cats.implicits._ class UserValidationInterpreter[F[_]: Applicative](userRepo: UserRepositoryAlgebra[F]) extends UserValidationAlgebra[F] { def doesNotExist(user: User): EitherT[F, UserAlreadyExistsError, Unit] = userRepo .findByUserName(user.userName) .map(UserAlreadyExistsError) .toLeft(()) def exists(userId: Option[Long]): EitherT[F, UserNotFoundError.type, Unit] = userId match { case Some(id) => userRepo .get(id) .toRight(UserNotFoundError) .void case None => EitherT.left[Unit](UserNotFoundError.pure[F]) } } object UserValidationInterpreter { def apply[F[_]: Applicative](repo: UserRepositoryAlgebra[F]): UserValidationAlgebra[F] = new UserValidationInterpreter[F](repo) }
Example 10
Source File: SlackSrvImpl.scala From gospeak with Apache License 2.0 | 5 votes |
package gospeak.infra.services.slack import cats.data.EitherT import cats.effect.IO import gospeak.core.services.slack.SlackSrv import gospeak.core.services.slack.domain.SlackAction.PostMessage import gospeak.core.services.slack.domain._ import gospeak.infra.services.slack.SlackSrvImpl._ import gospeak.libs.scala.Crypto.AesSecretKey import gospeak.libs.scala.Extensions._ import gospeak.libs.scala.domain.{CustomException, Markdown} import gospeak.libs.slack.{SlackClient, domain => api} import io.circe.Json import scala.util.Try // SlackSrv should not use Slack classes in the API, it's independent and the implementation should do the needed conversion class SlackSrvImpl(client: SlackClient) extends SlackSrv { override def getInfos(token: SlackToken, key: AesSecretKey): IO[SlackTokenInfo] = toSlack(token, key).toIO.flatMap(client.info).map(_.map(toGospeak)).flatMap(toIO) override def exec(action: SlackAction, data: Json, creds: SlackCredentials, key: AesSecretKey): IO[Unit] = action match { case a: PostMessage => postMessage(a, data, creds, key).map(_ => ()) } private def postMessage(action: PostMessage, data: Json, creds: SlackCredentials, key: AesSecretKey): IO[Either[api.SlackError, api.SlackMessage]] = { val sender = api.SlackSender.Bot(creds.name, creds.avatar.map(_.value)) for { token <- toSlack(creds.token, key).toIO channel <- action.channel.render(data).map(toSlackName).toIO(e => CustomException(e.message)) message <- action.message.render(data).map(toSlack).toIO(e => CustomException(e.message)) attempt1 <- client.postMessage(token, sender, channel, message) attempt2 <- attempt1 match { case Left(api.SlackError(false, "channel_not_found", _, _)) if action.createdChannelIfNotExist => (for { createdChannel <- EitherT(client.createChannel(token, channel)) invitedUsers <- EitherT.liftF(if (action.inviteEverybody) { client.listUsers(token).flatMap(_.getOrElse(Seq()).map(_.id).map(client.inviteToChannel(token, createdChannel.id, _)).sequence) } else { IO.pure(Seq()) }) attempt2 <- EitherT(client.postMessage(token, sender, createdChannel.id, message)) } yield attempt2).value case _ => IO.pure(attempt1) } } yield attempt2 } private def toSlack(token: SlackToken, key: AesSecretKey): Try[api.SlackToken] = token.decode(key).map(api.SlackToken) private def toSlack(md: Markdown): api.SlackContent.Markdown = api.SlackContent.Markdown(md.value) private def toSlackName(name: String): api.SlackChannel.Name = api.SlackChannel.Name(name) private def toGospeak(id: api.SlackUser.Id): SlackUser.Id = SlackUser.Id(id.value) private def toGospeak(info: api.SlackTokenInfo): SlackTokenInfo = SlackTokenInfo(SlackTeam.Id(info.team_id.value), info.team, info.url, toGospeak(info.user_id), info.user) private def toIO[A](e: Either[api.SlackError, A]): IO[A] = e.toIO(e => CustomException(format(e))) } object SlackSrvImpl { private[slack] def format(err: api.SlackError): String = err.error + err.needed.map(" " + _).getOrElse("") + err.provided.map(" (provided: " + _ + ")").getOrElse("") }
Example 11
Source File: monadError.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.syntax import cats.{ApplicativeError, MonadError} import cats.data.EitherT import cats.syntax.applicativeError._ import cats.syntax.either._ import cats.syntax.functor._ import either._ object monadError { implicit final class MonadErrorFOps[F[_], A](private val fa: F[A]) extends AnyVal { def retryAttempt[E](count: Int)(implicit F: MonadError[F, E]): F[Either[List[E], A]] = F.tailRecM((count, List.empty[E])) { case (cnt, acc) => if (cnt <= 0) F.pure(acc.reverse.asLeft.asRight) else fa.attempt.map { case Left(err) => (cnt - 1, err :: acc).asLeft case Right(v) => v.asRight.asRight } } def retry[E](count: Int)(implicit F: MonadError[F, E]): F[A] = F.tailRecM(count) { case cnt if cnt <= 1 => fa.map(_.asRight) case cnt => fa.attempt.map(_.leftMap(_ => cnt - 1)) } } implicit final class MonadErrorEitherTOps[F[_], E, A](private val fea: EitherT[F, E, A]) extends AnyVal { def attemptXor[U](implicit F: ApplicativeError[F, U]): EitherT[F, Either[U, E], A] = EitherT(fea.value.attempt.map(_.assocR)) } }
Example 12
Source File: IndexableStream.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.indexing_logic import akka.NotUsed import akka.stream.scaladsl.Source import cats.Monad import cats.syntax.flatMap._ import cats.syntax.functor._ import cats.data.EitherT import com.sksamuel.elastic4s.streams.RequestBuilder import com.yannick_cw.elastic_indexer4s.Index_results.{IndexError, RunResult} class IndexableStream[A: RequestBuilder, M[_]: Monad](source: Source[A, NotUsed], shutdown: () => M[Unit])( implicit indexing: IndexOps[M]) { private val writeStep = indexing.write(source) def run: M[Either[IndexError, RunResult]] = writeStep.value.flatMap(res => shutdown().map(_ => res)) def switchAliasFrom(alias: String, minT: Double = 0.95, maxT: Double = 1.25): IndexableStreamWithSwitching[A, M] = new IndexableStreamWithSwitching(writeStep, minT, maxT, alias, shutdown) def deleteOldIndices(keep: Int, aliasProtection: Boolean = true): IndexableStreamWithDeletion[A, M] = new IndexableStreamWithDeletion(writeStep, keep, aliasProtection, shutdown) } class IndexableStreamWithSwitching[A, M[_]](done: EitherT[M, IndexError, RunResult], minT: Double, maxT: Double, alias: String, shutdown: () => M[Unit])(implicit M: Monad[M], indexing: IndexOps[M]) { private val switchStep = indexing.addSwitch(done, minT, maxT, alias) def run: M[Either[IndexError, RunResult]] = switchStep.value.flatMap(res => shutdown().map(_ => res)) def deleteOldIndices(keep: Int, aliasProtection: Boolean = true): IndexableStreamWithDeletion[A, M] = new IndexableStreamWithDeletion(switchStep, keep, aliasProtection, shutdown) } class IndexableStreamWithDeletion[A, M[_]: Monad](done: EitherT[M, IndexError, RunResult], keep: Int, aliasProtection: Boolean, shutdown: () => M[Unit])(implicit indexing: IndexOps[M]) { def run: M[Either[IndexError, RunResult]] = indexing.addDelete(done, keep, aliasProtection).value.flatMap(res => shutdown().map(_ => res)) }
Example 13
Source File: SelectiveInstances.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.control.impl import cats.data.{EitherT, OptionT, ReaderT, WriterT} import cats.instances.either._ import cats.instances.option._ import cats.instances.tuple._ import cats.{Applicative, Monad, Monoid} import tofu.control.Selective import tofu.syntax.either._ import tofu.syntax.monadic._ class SelectiveOverMonad[F[_]](implicit val F: Monad[F]) extends Selective[F] with ApplicativeDelegate[F] { def selectAp[A, B](fe: F[Either[A, B]])(ff: => F[A => B]): F[B] = F.flatMap(fe) { case Left(a) => F.map(ff)(_(a)) case Right(b) => F.pure(b) } override def select[A](fo: F[Option[A]])(fa: => F[A]): F[A] = F.flatMap(fo) { case None => fa case Some(a) => F.pure(a) } override def whens[A](fb: F[Boolean])(fa: => F[A]): F[Option[A]] = F.flatMap(fb) { if (_) F.map(fa)(Some(_)) else F.pure(None) } override def unlesss[A](fb: F[Boolean])(fa: => F[A]): F[Option[A]] = F.flatMap(fb) { if (_) F.pure(None) else F.map(fa)(Some(_)) } override def whens_[A](fb: F[Boolean])(fa: => F[A]): F[Unit] = F.flatMap(fb) { if (_) F.unit else F.void(fa) } override def unlesss_[A](fb: F[Boolean])(fa: => F[A]): F[Unit] = F.flatMap(fb) { if (_) F.void(fa) else F.unit } } trait SelectiveWithMap[F[_]] extends Selective[F] { def smap[A, B](fa: F[A])(f: A => B): F[B] def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = selectAp[A, B](smap(fa)(Left(_)))(ff) override def map[A, B](fa: F[A])(f: A => B): F[B] = smap(fa)(f) } class SelectiveOptionT[F[_]](implicit F: Selective[F]) extends Selective[OptionT[F, *]] { def selectAp[A, B](fe: OptionT[F, Either[A, B]])(ff: => OptionT[F, A => B]): OptionT[F, B] = OptionT(F.selectAp(fe.value.map { case Some(Left(a)) => Left(a) case Some(Right(b)) => Right(Some(b)) case None => Right(None) })(ff.value.map { case Some(f) => b => Some(f(b)) case None => _ => None })) def ap[A, B](ff: OptionT[F, A => B])(fa: OptionT[F, A]): OptionT[F, B] = OptionT(F.ap[Option[A], Option[B]](ff.value.map(fo => (fo ap _)))(fa.value)) def pure[A](x: A): OptionT[F, A] = OptionT.pure(x) } class SelectiveEitherT[F[_], L](implicit F: Selective[F]) extends Selective[EitherT[F, L, *]] { def selectAp[A, B](fe: EitherT[F, L, Either[A, B]])(ff: => EitherT[F, L, A => B]): EitherT[F, L, B] = EitherT(F.selectAp[A, Either[L, B]](fe.value.map { case Right(Left(a)) => Left(a) case rr @ Right(Right(_)) => rr.asInstanceOf[Either[A, Either[L, B]]] case l @ Left(_) => Right(l.coerceR[B]) })(ff.value.map { case Right(f) => b => Right(f(b)) case l @ Left(_) => _ => l.coerceR[B] })) def ap[A, B](ff: EitherT[F, L, A => B])(fa: EitherT[F, L, A]): EitherT[F, L, B] = EitherT(F.ap[Either[L, A], Either[L, B]](ff.value.map(fo => (fo ap _)))(fa.value)) def pure[A](x: A): EitherT[F, L, A] = EitherT.pure(x) } class SelectiveReaderT[F[_], R](implicit FS: Selective[F]) extends Selective[ReaderT[F, R, *]] with ApplicativeDelegate[ReaderT[F, R, *]] { val F: Applicative[ReaderT[F, R, *]] = implicitly def selectAp[A, B](fe: ReaderT[F, R, Either[A, B]])(ff: => ReaderT[F, R, A => B]): ReaderT[F, R, B] = ReaderT(r => FS.selectAp(fe.run(r))(ff.run(r))) } class SelectiveWriterT[F[_], W: Monoid](implicit FS: Selective[F]) extends Selective[WriterT[F, W, *]] with ApplicativeDelegate[WriterT[F, W, *]] { val F: Applicative[WriterT[F, W, *]] = implicitly def selectAp[A, B](fe: WriterT[F, W, Either[A, B]])(ff: => WriterT[F, W, A => B]): WriterT[F, W, B] = WriterT(FS.selectAp[(W, A), (W, B)](FS.map(fe.run) { case (w, Left(a)) => Left((w, a)) case (w, Right(b)) => Right((w, b)) })(FS.map(ff.run)(wf => (wf ap _)))) }
Example 14
Source File: BindInstanceChain.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.control.impl import tofu.control.Bind import cats.Monad import scala.annotation.tailrec import cats.Bifunctor import cats.data.EitherT import tofu.syntax.monadic._ trait BindInstanceChain[TC[f[_, _]] >: Bind[f]] { implicit val eitherInstance: TC[Either] = new Bind[Either] { import cats.instances.either._ def pure[E, A](a: A): Either[E, A] = Right(a) def raise[E, A](e: E): Either[E, A] = Left(e) def foldWith[E, A, X, R](fa: Either[E, A], h: E => Either[X, R], f: A => Either[X, R]): Either[X, R] = fa.fold(h, f) def foldRec[E, A, X, B](init: Either[E, A])( step: Either[E, A] => Either[Either[E, X], Either[A, B]] ): Either[X, B] = { @tailrec def go(e: Either[E, A]): Either[X, B] = step(e) match { case Left(Left(e)) => go(Left(e)) case Left(Right(x)) => Left(x) case Right(Left(a)) => go(Right(a)) case Right(Right(b)) => Right(b) } go(init) } override def fromEither[E, A](ea: Either[E, A]): Either[E, A] = ea override def fold[E, A, X, R](fa: Either[E, A])(h: E => R, f: A => R): Either[X, R] = Right(fa.fold(h, f)) override def handle[E, X, A](fa: Either[E, A], h: E => A): Either[X, A] = Right(fa.fold(h, identity)) override def monad[E]: Monad[Either[E, *]] = implicitly override def bifunctor: Bifunctor[Either] = implicitly } implicit def eitherTInstance[F[_]](implicit F: Monad[F]): TC[EitherT[F, *, *]] = new Bind[EitherT[F, *, *]] { def foldRec[E, A, X, B](init: Either[E, A])( step: Either[E, A] => EitherT[F, Either[E, X], Either[A, B]] ): EitherT[F, X, B] = EitherT(init.tailRecM { step(_).value.map { case Left(Left(e)) => Left(Left(e)) case Left(Right(x)) => Right(Left(x)) case Right(Left(a)) => Left(Right(a)) case Right(Right(b)) => Right(Right(b)) } }) def pure[E, A](a: A): EitherT[F, E, A] = EitherT.rightT(a) def raise[E, A](e: E): EitherT[F, E, A] = EitherT.leftT(e) def foldWith[E, A, X, R]( fa: EitherT[F, E, A], h: E => EitherT[F, X, R], f: A => EitherT[F, X, R] ): EitherT[F, X, R] = fa.biflatMap(h, f) override def fromEither[E, A](ea: Either[E, A]): EitherT[F, E, A] = EitherT.fromEither(ea) override def monad[E]: Monad[EitherT[F, E, *]] = implicitly override val bifunctor: Bifunctor[EitherT[F, *, *]] = implicitly } }
Example 15
Source File: CornichonError.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.core import java.io.{ PrintWriter, StringWriter } import cats.data.EitherT import cats.syntax.either._ import cats.instances.future._ import scala.concurrent.{ ExecutionContext, Future } import scala.util.control.NoStackTrace trait CornichonError { def baseErrorMessage: String val causedBy: List[CornichonError] = Nil lazy val renderedMessage: String = { if (causedBy.isEmpty) baseErrorMessage else s"""$baseErrorMessage |caused by: |${causedBy.iterator.map(c => c.renderedMessage).mkString("\nand\n")}""".stripMargin } def toException = CornichonException(renderedMessage) } object CornichonError { def genStacktrace(exception: Throwable): String = { val sw = new StringWriter() val pw = new PrintWriter(sw) exception.printStackTrace(pw) sw.toString } def fromString(error: String): CornichonError = BasicError(error) def fromThrowable(exception: Throwable): CornichonError = StepExecutionError(exception) def catchThrowable[A](f: => A): Either[CornichonError, A] = Either.catchNonFatal(f).leftMap(fromThrowable) implicit class fromEither[A](e: Either[CornichonError, A]) { def valueUnsafe: A = e.fold(e => throw e.toException, identity) def futureEitherT(implicit ec: ExecutionContext): EitherT[Future, CornichonError, A] = EitherT.fromEither[Future](e) } } case class StepExecutionError(e: Throwable) extends CornichonError { lazy val baseErrorMessage = s"exception thrown ${CornichonError.genStacktrace(e)}" } case class BasicError(error: String) extends CornichonError { lazy val baseErrorMessage = error } case class CornichonException(m: String) extends Exception with NoStackTrace { override def getMessage = m }
Example 16
Source File: EffectStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.cats import cats.data.{ EitherT, NonEmptyList } import cats.effect.Effect import cats.syntax.either._ import com.github.agourlay.cornichon.core.ScenarioRunner.{ errorsToFailureStep, successLog } import com.github.agourlay.cornichon.core._ import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.duration.Duration case class EffectStep[F[_]: Effect](title: String, effect: ScenarioContext => F[Either[CornichonError, Session]], show: Boolean = true) extends SessionValueStep { def setTitle(newTitle: String): Step = copy(title = newTitle) override def runSessionValueStep(runState: RunState): Task[Either[NonEmptyList[CornichonError], Session]] = Task.fromEffect(effect(runState.scenarioContext)).map(_.leftMap(NonEmptyList.one)) override def onError(errors: NonEmptyList[CornichonError], runState: RunState, executionTime: Duration): (LogInstruction, FailedStep) = errorsToFailureStep(this, runState.depth, errors, Some(executionTime)) override def logOnSuccess(result: Session, runState: RunState, executionTime: Duration): LogInstruction = successLog(title, runState.depth, show, executionTime) } object EffectStep { def fromEitherT[F[_]: Effect](title: String, effect: ScenarioContext => EitherT[F, CornichonError, Session], show: Boolean = true): Step = { val effectT: ScenarioContext => F[Either[CornichonError, Session]] = s => effect(s).value EffectStep(title, effectT, show) } def fromSync(title: String, effect: ScenarioContext => Session, show: Boolean = true): Step = { import Scheduler.Implicits.global val effectF: ScenarioContext => Task[Either[CornichonError, Session]] = s => Task.now(effect(s).asRight) EffectStep(title, effectF, show) } def fromSyncE(title: String, effect: ScenarioContext => Either[CornichonError, Session], show: Boolean = true): Step = { import Scheduler.Implicits.global val effectF: ScenarioContext => Task[Either[CornichonError, Session]] = s => Task.now(effect(s)) EffectStep(title, effectF, show) } def fromAsync[F[_]: Effect](title: String, effect: ScenarioContext => F[Session], show: Boolean = true): Step = { import Scheduler.Implicits.global val effectF: ScenarioContext => Task[Either[CornichonError, Session]] = s => Task.fromEffect(effect(s)).map(Right.apply) EffectStep(title, effectF, show) } }
Example 17
Source File: EffectStep.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.steps.regular import cats.data.{ EitherT, NonEmptyList } import cats.syntax.either._ import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.core.ScenarioRunner._ import monix.eval.Task import scala.concurrent.duration.Duration import scala.concurrent.{ ExecutionContext, Future } case class EffectStep(title: String, effect: ScenarioContext => Future[Either[CornichonError, Session]], show: Boolean = true) extends SessionValueStep { def setTitle(newTitle: String): Step = copy(title = newTitle) override def runSessionValueStep(runState: RunState): Task[Either[NonEmptyList[CornichonError], Session]] = Task.deferFuture(effect(runState.scenarioContext)).map(_.leftMap(NonEmptyList.one)) override def onError(errors: NonEmptyList[CornichonError], runState: RunState, executionTime: Duration): (LogInstruction, FailedStep) = errorsToFailureStep(this, runState.depth, errors, Some(executionTime)) override def logOnSuccess(result: Session, runState: RunState, executionTime: Duration): LogInstruction = successLog(title, runState.depth, show, executionTime) } object EffectStep { def fromEitherT(title: String, effect: ScenarioContext => EitherT[Future, CornichonError, Session], show: Boolean = true): EffectStep = { val effectT: ScenarioContext => Future[Either[CornichonError, Session]] = s => effect(s).value EffectStep(title, effectT, show) } def fromSync(title: String, effect: ScenarioContext => Session, show: Boolean = true): EffectStep = { val effectF: ScenarioContext => Future[Either[CornichonError, Session]] = s => Future.successful(effect(s).asRight) EffectStep(title, effectF, show) } def fromSyncE(title: String, effect: ScenarioContext => Either[CornichonError, Session], show: Boolean = true): EffectStep = { val effectF: ScenarioContext => Future[Either[CornichonError, Session]] = s => Future.successful(effect(s)) EffectStep(title, effectF, show) } def fromAsync(title: String, effect: ScenarioContext => Future[Session], show: Boolean = true)(implicit ec: ExecutionContext): EffectStep = { val effectF: ScenarioContext => Future[Either[CornichonError, Session]] = s => effect(s).map(Right.apply) EffectStep(title, effectF, show) } }
Example 18
Source File: MonadAction.scala From aecor with MIT License | 5 votes |
package aecor import cats.data.EitherT import cats.{ Applicative, Monad } trait MonadAction[F[_], S, E] extends Monad[F] { def read: F[S] def append(es: E, other: E*): F[Unit] def reset: F[Unit] def ignore: F[Unit] = unit } trait MonadActionReject[F[_], S, E, R] extends MonadAction[F, S, E] { def reject[A](r: R): F[A] } object MonadActionReject { implicit def eitherTMonadActionRejectInstance[I[_]: Applicative, S, E, R]( implicit F: MonadAction[I, S, E], eitherTMonad: Monad[EitherT[I, R, *]] ): MonadActionReject[EitherT[I, R, *], S, E, R] = new MonadActionReject[EitherT[I, R, *], S, E, R] { override def reject[A](r: R): EitherT[I, R, A] = EitherT.leftT(r) override def read: EitherT[I, R, S] = EitherT.right(F.read) override def append(es: E, other: E*): EitherT[I, R, Unit] = EitherT.right(F.append(es, other: _*)) override def reset: EitherT[I, R, Unit] = EitherT.right(F.reset) override def pure[A](x: A): EitherT[I, R, A] = EitherT.pure[I, R](x) override def map[A, B](fa: EitherT[I, R, A])(f: A => B): EitherT[I, R, B] = fa.map(f) override def flatMap[A, B](fa: EitherT[I, R, A])(f: A => EitherT[I, R, B]): EitherT[I, R, B] = fa.flatMap(f) override def tailRecM[A, B](a: A)(f: A => EitherT[I, R, Either[A, B]]): EitherT[I, R, B] = eitherTMonad.tailRecM(a)(f) } } trait MonadActionLift[I[_], F[_], S, E] extends MonadAction[I, S, E] { def liftF[A](fa: F[A]): I[A] } trait MonadActionLiftReject[I[_], F[_], S, E, R] extends MonadActionLift[I, F, S, E] with MonadActionReject[I, S, E, R] object MonadActionLiftReject { implicit def eitherTMonadActionLiftRejectInstance[I[_], F[_], S, E, R]( implicit I: MonadActionLift[I, F, S, E], eitherTMonad: Monad[EitherT[I, R, *]] ): MonadActionLiftReject[EitherT[I, R, *], F, S, E, R] = new MonadActionLiftReject[EitherT[I, R, *], F, S, E, R] { override def reject[A](r: R): EitherT[I, R, A] = EitherT.leftT(r) override def liftF[A](fa: F[A]): EitherT[I, R, A] = EitherT.right(I.liftF(fa)) override def read: EitherT[I, R, S] = EitherT.right(I.read) override def append(es: E, other: E*): EitherT[I, R, Unit] = EitherT.right(I.append(es, other: _*)) override def reset: EitherT[I, R, Unit] = EitherT.right(I.reset) override def pure[A](x: A): EitherT[I, R, A] = EitherT.pure[I, R](x) override def map[A, B](fa: EitherT[I, R, A])(f: A => B): EitherT[I, R, B] = fa.map(f) override def flatMap[A, B](fa: EitherT[I, R, A])(f: A => EitherT[I, R, B]): EitherT[I, R, B] = fa.flatMap(f) override def tailRecM[A, B](a: A)(f: A => EitherT[I, R, Either[A, B]]): EitherT[I, R, B] = eitherTMonad.tailRecM(a)(f) } }
Example 19
Source File: EventsourcedBehavior.scala From aecor with MIT License | 5 votes |
package aecor.data import aecor.Has import aecor.arrow.Invocation import cats.{ Monad, ~> } import cats.data.{ Chain, EitherT } import cats.tagless.FunctorK import cats.tagless.syntax.functorK._ final case class EventsourcedBehavior[M[_[_]], F[_], S, E](actions: M[ActionT[F, S, E, *]], fold: Fold[Folded, S, E]) { def enrich[Env](f: F[Env])(implicit M: FunctorK[M], F: Monad[F]): EventsourcedBehavior[M, F, S, Enriched[Env, E]] = EventsourcedBehavior( actions.mapK(ActionT.sampleK[F, S, E, Env, Enriched[Env, E]](f)(Enriched(_, _))(_.event)), fold.contramap(_.event) ) def mapK[G[_]](fg: F ~> G)(implicit M: FunctorK[M]): EventsourcedBehavior[M, G, S, E] = copy(actions.mapK(λ[ActionT[F, S, E, *] ~> ActionT[G, S, E, *]](_.mapK(fg)))) def run[A](state: S, invocation: Invocation[M, A]): F[Folded[(Chain[E], A)]] = invocation .run(actions) .run(fold.init(state)) } object EventsourcedBehavior extends EventsourcedBehaviourIntances { def rejectable[M[_[_]], F[_], S, E, R]( actions: M[EitherT[ActionT[F, S, E, *], R, *]], fold: Fold[Folded, S, E] ): EventsourcedBehavior[EitherK[M, R, *[_]], F, S, E] = EventsourcedBehavior[EitherK[M, R, *[_]], F, S, E](EitherK(actions), fold) } trait EventsourcedBehaviourIntances { implicit def eventsourcedBehaviourFunctorKInstance[M[_[_]]: FunctorK, S, E] : FunctorK[EventsourcedBehavior[M, *[_], S, E]] = new FunctorK[EventsourcedBehavior[M, *[_], S, E]] { def mapK[F[_], G[_]](a: EventsourcedBehavior[M, F, S, E])( f: F ~> G ): EventsourcedBehavior[M, G, S, E] = a.mapK(f) } } final case class Enriched[M, E](metadata: M, event: E) object Enriched { implicit def hasMetadata[M, E, X](implicit M: Has[M, X]): Has[Enriched[M, E], X] = M.contramap(_.metadata) implicit def hasEvent[M, E, X](implicit E: Has[E, X]): Has[Enriched[M, E], X] = E.contramap(_.event) }
Example 20
Source File: HealthServiceSpec.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import cats.data.EitherT import cats.effect.IO import com.smartbackpackerapp.common.IOAssertion import com.smartbackpackerapp.model._ import com.smartbackpackerapp.repository.algebra.HealthRepository import org.scalatest.{FlatSpecLike, Matchers} class HealthServiceSpec extends FlatSpecLike with Matchers { private val testHealth = Health( vaccinations = Vaccinations(List.empty[Vaccine], List.empty[Vaccine], List.empty[Vaccine]), notices = HealthNotices( alertLevel = LevelOne, alerts = List.empty[HealthAlert] ) ) private val repo = new HealthRepository[IO] { override def findHealthInfo(countryCode: CountryCode): IO[Option[Health]] = IO { if (countryCode.value == "AR") Some(testHealth) else None } } private val service = new HealthService[IO](repo) it should "find the health information" in IOAssertion { EitherT(service.findHealthInfo(CountryCode("AR"))).map { index => index should be (testHealth) }.value } it should "NOT find the health information" in IOAssertion { EitherT(service.findHealthInfo(CountryCode("XX"))).leftMap { error => error shouldBe a [HealthInfoNotFound] }.value } }
Example 21
Source File: ExtraEntityDecoderInstances.scala From aws4s with MIT License | 5 votes |
package org.aws4s.core import cats.Applicative import cats.data.EitherT import cats.effect.Effect import cats.implicits._ import fs2.Stream import io.circe.Decoder import org.http4s.scalaxml._ import org.http4s.{DecodeFailure, EntityDecoder, InvalidMessageBodyFailure, MediaRange} private[aws4s] object ExtraEntityDecoderInstances { implicit def streamEntityDecoder[F[_]: Applicative]: EntityDecoder[F, Stream[F, Byte]] = EntityDecoder.decodeBy(MediaRange.`*/*`) { msg => EitherT.fromEither(msg.body.asRight[DecodeFailure]) } def fromXml[F[_]: Effect, A](f: scala.xml.Elem => Option[A]): EntityDecoder[F, A] = EntityDecoder[F, scala.xml.Elem] flatMapR { elem => val result = f(elem) EitherT.fromEither(result.toRight(InvalidMessageBodyFailure("Response was not as expected"))) } implicit def circeEntityDecoder[F[_]: Effect, A: Decoder]: EntityDecoder[F, A] = org.http4s.circe.jsonOf[F, A] }
Example 22
Source File: EitherTransformers.scala From advanced-scala-code with Apache License 2.0 | 5 votes |
package manual import cats.{Functor, Monad} import cats.data.{EitherT} import scala.concurrent.Future import scalaz.concurrent.Task implicit val taskMonad = new Monad[Task] { def tailRecM[A,B](a: A)(f: A => Task[Either[A,B]]): Task[B] = Task.suspend(f(a)).flatMap { case Left(continueA) => tailRecM(continueA)(f) case Right(b) => Task.now(b) } override def flatMap[A, B](fa: Task[A])(f: (A) => Task[B]): Task[B] = fa.flatMap(f) override def pure[A](x: A): Task[A] = Task.now(x) } val resultTXT = for { num1 <- EitherT(num1TX) num2 <- EitherT(num2TX) } yield num1 + num2 val resultX = resultTXT.value.unsafePerformSync println(s"Result: $resultX") } }
Example 23
Source File: MicroblockAppender.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.state.appender import cats.data.EitherT import com.wavesplatform.block.Block.BlockId import com.wavesplatform.block.MicroBlock import com.wavesplatform.lang.ValidationError import com.wavesplatform.metrics.{BlockStats, _} import com.wavesplatform.network.MicroBlockSynchronizer.MicroblockData import com.wavesplatform.network._ import com.wavesplatform.state.Blockchain import com.wavesplatform.transaction.BlockchainUpdater import com.wavesplatform.transaction.TxValidationError.InvalidSignature import com.wavesplatform.utils.ScorexLogging import com.wavesplatform.utx.UtxPool import io.netty.channel.Channel import io.netty.channel.group.ChannelGroup import kamon.Kamon import monix.eval.Task import monix.execution.Scheduler import scala.util.{Left, Right} object MicroblockAppender extends ScorexLogging { def apply(blockchainUpdater: BlockchainUpdater with Blockchain, utxStorage: UtxPool, scheduler: Scheduler, verify: Boolean = true)( microBlock: MicroBlock ): Task[Either[ValidationError, BlockId]] = { Task(metrics.microblockProcessingTimeStats.measureSuccessful { blockchainUpdater .processMicroBlock(microBlock, verify) .map { totalBlockId => utxStorage.removeAll(microBlock.transactionData) totalBlockId } }).executeOn(scheduler) } def apply( blockchainUpdater: BlockchainUpdater with Blockchain, utxStorage: UtxPool, allChannels: ChannelGroup, peerDatabase: PeerDatabase, scheduler: Scheduler )(ch: Channel, md: MicroblockData): Task[Unit] = { import md.microBlock val microblockTotalResBlockSig = microBlock.totalResBlockSig (for { _ <- EitherT(Task.now(microBlock.signaturesValid())) _ <- EitherT(apply(blockchainUpdater, utxStorage, scheduler)(microBlock)) } yield ()).value.map { case Right(_) => md.invOpt match { case Some(mi) => allChannels.broadcast(mi, except = md.microblockOwners()) case None => log.warn(s"${id(ch)} Not broadcasting MicroBlockInv") } BlockStats.applied(microBlock) case Left(is: InvalidSignature) => peerDatabase.blacklistAndClose(ch, s"Could not append microblock $microblockTotalResBlockSig: $is") case Left(ve) => BlockStats.declined(microBlock) log.debug(s"${id(ch)} Could not append microblock $microblockTotalResBlockSig: $ve") } } private[this] object metrics { val microblockProcessingTimeStats = Kamon.timer("microblock-appender.processing-time").withoutTags() } }
Example 24
Source File: ScriptEstimatorV1.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.lang.v1.estimator import cats.data.EitherT import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Terms._ import monix.eval.Coeval object ScriptEstimatorV1 extends ScriptEstimator { override val version: Int = 1 override def apply(declaredVals: Set[String], functionCosts: Map[FunctionHeader, Coeval[Long]], t: EXPR): Either[String, Long] = { type Result[T] = EitherT[Coeval, String, T] def aux(t: Result[EXPR], syms: Map[String, (EXPR, Boolean)], funcs: Map[FunctionHeader, Coeval[Long]]): Result[(Long, Map[String, (EXPR, Boolean)])] = t.flatMap { case _: CONST_LONG | _: CONST_BYTESTR | _: CONST_STRING | _: CONST_BOOLEAN => EitherT.pure((1, syms)) case t: GETTER => aux(EitherT.pure(t.expr), syms, funcs).map { case (comp, out) => (comp + 2, out) } case LET_BLOCK(let: LET, body) => aux(EitherT.pure(body), syms + ((let.name, (let.value, false))), funcs) .map { case (comp, out) => (comp + 5, out) } case BLOCK(let: LET, body) => aux(EitherT.pure(body), syms + ((let.name, (let.value, false))), funcs) .map { case (comp, out) => (comp + 5, out) } case BLOCK(f: FUNC, body) => { aux(EitherT.pure(f.body), syms ++ f.args.map(arg => (arg, (TRUE, false))).toMap, funcs) .flatMap { case (funcComplexity, _) => aux( EitherT.pure(body), syms, funcs + (FunctionHeader.User(f.name) -> Coeval.evalOnce(funcComplexity + f.args.size * 5)) ).map { case (comp, out) => (comp + 5, out) } } } case REF(key) => val ei: EitherT[Coeval, String, (Long, Map[String, (EXPR, Boolean)])] = syms.get(key) match { case None => EitherT.fromEither(Left(s"ScriptValidator: Undeclared variable '$key'")) case Some((_, true)) => EitherT.pure[Coeval, String]((0L, syms)) case Some((expr, false)) => aux(EitherT.pure(expr), syms + ((key, (expr, true))), funcs) } ei.map { case (comp: Long, out: Map[String, (EXPR, Boolean)]) => (comp + 2, out) } case t: IF => for { cond <- aux(EitherT.pure(t.cond), syms, funcs) (condComp, condSyms) = cond right <- aux(EitherT.pure(t.ifTrue), condSyms, funcs) left <- aux(EitherT.pure(t.ifFalse), condSyms, funcs) (bodyComp, bodySyms) = if (right._1 > left._1) right else left } yield (condComp + bodyComp + 1, bodySyms) case t: FUNCTION_CALL => for { callCost <- EitherT.fromOption[Coeval](functionCosts.get(t.function).orElse(funcs.get(t.function)), s"ScriptValidator: Unknown function '${t.function}'") args <- t.args.foldLeft(EitherT.pure[Coeval, String]((0L, syms))) { case (accEi, arg) => for { acc <- accEi (accComp, accSyms) = acc v <- aux(EitherT.pure[Coeval, String](arg), accSyms, funcs) (comp, out) = v } yield (accComp + comp, out) } (argsComp, argsSyms) = args } yield (callCost() + argsComp, argsSyms) case _ => ??? //TODO: FIx exhaustivness } aux(EitherT.pure(t), declaredVals.map(_ -> ((TRUE, true))).toMap, Map.empty).value().map(_._1) } }
Example 25
Source File: package.scala From Waves with MIT License | 5 votes |
package com.wavesplatform.lang.v1 import cats.Eval import cats.data.EitherT import com.wavesplatform.lang.v1.evaluator.ctx.LoggedEvaluationContext import com.wavesplatform.lang.v1.task.TaskMT import com.wavesplatform.lang.{EvalF, ExecutionError, TrampolinedExecResult} package object evaluator { type EvalM[F[_], C[_[_]], A] = TaskMT[F, LoggedEvaluationContext[C, F], ExecutionError, A] implicit class EvalMOps[F[_], C[_[_]], A](ev: EvalM[F, C, A]) { def ter(ctx: LoggedEvaluationContext[C, F]): TrampolinedExecResult[F, A] = EitherT[EvalF[F, ?], ExecutionError, A](ev.run(ctx).map(_._2)) } def liftTER[F[_], C[_[_]], A](ter: Eval[F[Either[ExecutionError, A]]]): EvalM[F, C, A] = TaskMT(_ => ter) type LetExecResult[F[_]] = F[Either[ExecutionError, compiler.Terms.EVALUATED]] type LogItem[F[_]] = (String, LetExecResult[F]) type Log[F[_]] = List[LogItem[F]] type LogCallback[F[_]] = LetExecResult[F] => Unit type LetLogCallback[F[_]] = String => LogCallback[F] }
Example 26
Source File: package.scala From nexus-kg with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg import akka.http.scaladsl.model.StatusCode import akka.http.scaladsl.server.Directives.complete import akka.http.scaladsl.server.{MalformedQueryParamRejection, Route} import cats.Functor import cats.data.{EitherT, OptionT} import cats.instances.future._ import ch.epfl.bluebrain.nexus.iam.client.types._ import ch.epfl.bluebrain.nexus.kg.marshallers.instances._ import ch.epfl.bluebrain.nexus.kg.resources.Rejection.NotFound.notFound import ch.epfl.bluebrain.nexus.kg.resources.{Ref, Rejection, ResourceV} import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.{DOT, Triples} import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import monix.execution.Scheduler.Implicits.global import scala.concurrent.Future package object routes { private[routes] def completeWithFormat( fetched: Future[Either[Rejection, (StatusCode, ResourceV)]] )(implicit format: NonBinaryOutputFormat): Route = completeWithFormat(EitherT(fetched)) private def completeWithFormat( fetched: EitherT[Future, Rejection, (StatusCode, ResourceV)] )(implicit format: NonBinaryOutputFormat): Route = format match { case f: JsonLDOutputFormat => implicit val format = f complete(fetched.value) case Triples => implicit val format = Triples complete(fetched.map { case (status, resource) => status -> resource.value.graph.ntriples }.value) case DOT => implicit val format = DOT complete(fetched.map { case (status, resource) => status -> resource.value.graph.dot() }.value) } private[routes] val read: Permission = Permission.unsafe("resources/read") private[routes] val schemaError = MalformedQueryParamRejection("schema", "The provided schema does not match the schema on the Uri") private[routes] implicit class FOptionSyntax[F[_], A](private val fOpt: F[Option[A]]) extends AnyVal { def toNotFound(id: AbsoluteIri)(implicit F: Functor[F]): EitherT[F, Rejection, A] = OptionT(fOpt).toRight(notFound(Ref(id))) } }
Example 27
Source File: AirlineServiceSpec.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import cats.data.EitherT import cats.effect.IO import com.smartbackpackerapp.common.IOAssertion import com.smartbackpackerapp.model.{Airline, AirlineName, BaggageAllowance, BaggagePolicy} import com.smartbackpackerapp.repository.algebra.AirlineRepository import org.scalatest.{FlatSpecLike, Matchers} class AirlineServiceSpec extends FlatSpecLike with Matchers { private val testAirline = Airline( name = AirlineName("Ryan Air"), baggagePolicy = BaggagePolicy( allowance = List.empty[BaggageAllowance], extra = None, website = None ) ) private val repo = new AirlineRepository[IO] { override def findAirline(airlineName: AirlineName): IO[Option[Airline]] = IO { if (airlineName.value == "Ryan Air") Some(testAirline) else None } } private val service = new AirlineService[IO](repo) it should "find the airline" in IOAssertion { EitherT(service.baggagePolicy(AirlineName("Ryan Air"))).map { airline => airline should be (testAirline) }.value } it should "NOT find the airline" in IOAssertion { EitherT(service.baggagePolicy(AirlineName("Futur Airways"))).leftMap { error => error shouldBe a [AirlineNotFound] }.value } }
Example 28
Source File: DestinationInfoServiceSpec.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import cats.Parallel import cats.data.EitherT import cats.syntax.option._ import com.smartbackpackerapp.common.TaskAssertion import com.smartbackpackerapp.config.SBConfiguration import com.smartbackpackerapp.model._ import com.smartbackpackerapp.repository.algebra.VisaRequirementsRepository import monix.eval.Task import org.scalatest.{FlatSpecLike, Matchers} class DestinationInfoServiceSpec extends FlatSpecLike with Matchers { private lazy val sbConfig = new SBConfiguration[Task] private val repo = new VisaRequirementsRepository[Task] { override def findVisaRequirements(from: CountryCode, to: CountryCode): Task[Option[VisaRequirementsData]] = Task { VisaRequirementsData( from = Country(CountryCode("AR"), CountryName("Argentina"), Currency("ARS")), to = Country(CountryCode("RO"), CountryName("Romania"), Currency("RON")), visaCategory = VisaNotRequired, description = "90 days within any 180 day period" ).some } } private val rateService = new AbstractExchangeRateService[Task](sbConfig) { override protected def retrieveExchangeRate(uri: String): Task[CurrencyExchangeDTO] = Task { CurrencyExchangeDTO("EUR", "", Map("RON" -> 4.59)) } } private implicit val parallel: Parallel[Task, Task] = Parallel[Task, Task.Par].asInstanceOf[Parallel[Task, Task]] private val service = new DestinationInfoService[Task](sbConfig, repo, rateService) it should "retrieve destination information" in TaskAssertion { EitherT(service.find(CountryCode("AR"), CountryCode("RO"), Currency("EUR"))).map { info => info.countryCode.value should be ("RO") info.countryName.value should be ("Romania") info.exchangeRate should be (ExchangeRate(Currency("EUR"), Currency("RON"), 4.59)) info.visaRequirements should be (VisaRequirements(VisaNotRequired, "90 days within any 180 day period")) }.value } it should "validate countries" in TaskAssertion { EitherT(service.find(CountryCode("AR"), CountryCode("AR"), Currency("EUR"))).leftMap { error => error should be (CountriesMustBeDifferent) }.value } }
Example 29
Source File: VisaRestrictionsIndexServiceSpec.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import cats.data.EitherT import cats.effect.IO import com.smartbackpackerapp.common.IOAssertion import com.smartbackpackerapp.model.{Count, CountryCode, Ranking, Sharing, VisaRestrictionsIndex} import com.smartbackpackerapp.repository.algebra.VisaRestrictionsIndexRepository import org.scalatest.{FlatSpecLike, Matchers} class VisaRestrictionsIndexServiceSpec extends FlatSpecLike with Matchers { private val testIndex = VisaRestrictionsIndex(Ranking(3), Count(2), Sharing(1)) private val repo = new VisaRestrictionsIndexRepository[IO] { override def findRestrictionsIndex(countryCode: CountryCode): IO[Option[VisaRestrictionsIndex]] = IO { if (countryCode.value == "AR") Some(testIndex) else None } } private val service = new VisaRestrictionIndexService[IO](repo) it should "find the visa restrictions index" in IOAssertion { EitherT(service.findIndex(CountryCode("AR"))).map { index => index should be (testIndex) }.value } it should "NOT find the visa restrictions index" in IOAssertion { EitherT(service.findIndex(CountryCode("XX"))).leftMap { error => error shouldBe a [VisaRestrictionsIndexNotFound] }.value } }
Example 30
Source File: EitherK.scala From aecor with MIT License | 5 votes |
package aecor.data import aecor.encoding.WireProtocol import aecor.encoding.WireProtocol.{ Encoded, Invocation } import cats.data.EitherT import cats.~> import cats.implicits._ import cats.tagless.FunctorK import scodec.{ Codec, Decoder, Encoder } import scodec.codecs._ import cats.tagless.syntax.functorK._ final case class EitherK[M[_[_]], A, F[_]](value: M[EitherT[F, A, *]]) extends AnyVal { def unwrap(implicit M: FunctorK[M]): M[λ[α => F[Either[A, α]]]] = value.mapK(new (EitherT[F, A, *] ~> λ[α => F[Either[A, α]]]) { override def apply[X](fa: EitherT[F, A, X]): F[Either[A, X]] = fa.value }) def mapK[G[_]](fg: F ~> G)(implicit M: FunctorK[M]): EitherK[M, A, G] = EitherK(M.mapK(value)(new (EitherT[F, A, *] ~> EitherT[G, A, *]) { override def apply[X](fa: EitherT[F, A, X]): EitherT[G, A, X] = fa.mapK(fg) })) } object EitherK { implicit def wireProtocol[M[_[_]]: FunctorK, A]( implicit M: WireProtocol[M], aCodec: Codec[A] ): WireProtocol[EitherK[M, A, *[_]]] = new WireProtocol[EitherK[M, A, *[_]]] { final override val encoder: EitherK[M, A, Encoded] = EitherK[M, A, Encoded] { M.encoder.mapK(new (Encoded ~> EitherT[Encoded, A, *]) { override def apply[B](ma: Encoded[B]): EitherT[Encoded, A, B] = EitherT[Encoded, A, B] { val (bytes, resultDecoder) = ma val dec = bool.flatMap { case true => resultDecoder.map(_.asRight[A]) case false => aCodec.map(_.asLeft[B]) } (bytes, dec) } }) } final override val decoder: Decoder[PairE[Invocation[EitherK[M, A, *[_]], *], Encoder]] = M.decoder.map { p => val (invocation, encoder) = (p.first, p.second) val eitherKInvocation = new Invocation[EitherK[M, A, *[_]], Either[A, p.A]] { override def run[G[_]](target: EitherK[M, A, G]): G[Either[A, p.A]] = invocation.run(target.value).value override def toString: String = invocation.toString } val eitherEncoder = Encoder { m: Either[A, p.A] => m match { case Right(a) => Encoder.encodeBoth(bool, encoder)(true, a) case Left(r) => Encoder.encodeBoth(bool, aCodec)(false, r) } } PairE(eitherKInvocation, eitherEncoder) } } implicit def functorK[M[_[_]]: FunctorK, A]: FunctorK[EitherK[M, A, *[_]]] = new FunctorK[EitherK[M, A, *[_]]] { override def mapK[F[_], G[_]](af: EitherK[M, A, F])(fk: ~>[F, G]): EitherK[M, A, G] = af.mapK(fk) } object syntax { implicit final class EitherKSyntaxImpl[M[_[_]], F[_], A](val self: M[EitherT[F, A, *]]) extends AnyVal { def toEitherK: EitherK[M, A, F] = EitherK(self) } } }
Example 31
Source File: DestinationInfoService.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.service import cats.data.EitherT import cats.syntax.either._ import cats.syntax.functor._ import cats.syntax.parallel._ import cats.{MonadError, Parallel} import com.smartbackpackerapp.config.SBConfiguration import com.smartbackpackerapp.model.{CountryCode, Currency, DestinationInfo, ExchangeRate, VisaRequirements, VisaRequirementsData} import com.smartbackpackerapp.repository.algebra.VisaRequirementsRepository class DestinationInfoService[F[_]](sbConfig: SBConfiguration[F], visaRequirementsRepo: VisaRequirementsRepository[F], exchangeRateService: AbstractExchangeRateService[F]) (implicit F: MonadError[F, Throwable], P: Parallel[F, F]) { def find(from: CountryCode, to: CountryCode, baseCurrency: Currency): F[ValidationError Either DestinationInfo] = { val result = for { _ <- EitherT.fromEither(validateCountries(from, to)) fc <- EitherT.liftF(sbConfig.countryCurrency(to, default = Currency("EUR"))) rs <- EitherT(retrieveDestinationInfoInParallel(from, to, baseCurrency, fc)) } yield rs result.value } private def retrieveDestinationInfoInParallel(from: CountryCode, to: CountryCode, baseCurrency: Currency, foreignCurrency: Currency): F[ValidationError Either DestinationInfo] = { (visaRequirementsFor(from, to), exchangeRateService.exchangeRateFor(baseCurrency, foreignCurrency)).parMapN { case (Right(vr), er) => DestinationInfo( countryName = vr.to.name, countryCode = vr.to.code, visaRequirements = VisaRequirements(vr.visaCategory, vr.description), exchangeRate = ExchangeRate(Currency(er.base), foreignCurrency, er.rates.getOrElse(foreignCurrency.value, -1.0)) ).asRight[ValidationError] case (Left(e), _) => e.asLeft[DestinationInfo] } } private def validateCountries(from: CountryCode, to: CountryCode): Either[ValidationError, (CountryCode, CountryCode)] = { if (from != to) (from, to).asRight else CountriesMustBeDifferent.asLeft } private def visaRequirementsFor(from: CountryCode, to: CountryCode): F[ValidationError Either VisaRequirementsData] = visaRequirementsRepo.findVisaRequirements(from, to) map { data => data.toRight[ValidationError](CountryNotFound(to)) } }
Example 32
Source File: JwtTokenAuthMiddleware.scala From core with Apache License 2.0 | 5 votes |
package com.smartbackpackerapp.http.auth import cats.data.{EitherT, Kleisli, OptionT} import cats.effect.Sync import cats.syntax.applicativeError._ import cats.syntax.functor._ import com.smartbackpackerapp.http.auth.JwtTokenAuthMiddleware.AuthConfig import org.http4s.Credentials.Token import org.http4s.dsl.Http4sDsl import org.http4s.{AuthScheme, AuthedService, Request} import org.http4s.headers.Authorization import org.http4s.server.AuthMiddleware import tsec.jws.mac.JWTMac import tsec.mac.imports._ object JwtTokenAuthMiddleware { def apply[F[_] : Sync](apiToken: Option[String]): F[AuthMiddleware[F, String]] = new Middleware[F](apiToken).middleware case class AuthConfig(jwtKey: MacSigningKey[HMACSHA256]) } class Middleware[F[_]](apiToken: Option[String])(implicit F: Sync[F]) { private val ifEmpty = F.raiseError[AuthMiddleware[F, String]](new Exception("Api Token not found")) private def generateJwtKey(token: String): F[MacSigningKey[HMACSHA256]] = { F.catchNonFatal(HMACSHA256.buildKeyUnsafe(token.getBytes)) } val middleware: F[AuthMiddleware[F, String]] = apiToken.fold(ifEmpty) { token => generateJwtKey(token).map { jwtKey => val config = AuthConfig(jwtKey) new JwtTokenAuthMiddleware[F](config).middleware } } } class JwtTokenAuthMiddleware[F[_] : Sync](config: AuthConfig) extends Http4sDsl[F] { private val onFailure: AuthedService[String, F] = Kleisli(req => OptionT.liftF(Forbidden(req.authInfo))) private def bearerTokenFromRequest(request: Request[F]): OptionT[F, String] = OptionT.fromOption[F] { request.headers.get(Authorization).collect { case Authorization(Token(AuthScheme.Bearer, token)) => token } } private def verifyToken(request: Request[F], jwtKey: MacSigningKey[HMACSHA256]): OptionT[F, String] = for { token <- bearerTokenFromRequest(request) verified <- OptionT.liftF(JWTMac.verifyAndParse[F, HMACSHA256](token, jwtKey)) accessToken <- OptionT.fromOption[F](verified.body.subject) } yield accessToken private def authUser(jwtKey: MacSigningKey[HMACSHA256]): Kleisli[F, Request[F], Either[String, String]] = Kleisli { request => verifyToken(request, jwtKey).value.map { option => Either.cond[String, String](option.isDefined, option.get, "Unable to authorize token") }.recoverWith { case MacVerificationError(msg) => EitherT.leftT(msg).value } } def middleware: AuthMiddleware[F, String] = AuthMiddleware(authUser(config.jwtKey), onFailure) }
Example 33
Source File: IndexDeletionSpec.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.elasticsearch.index_ops import cats.data.EitherT import cats.implicits._ import com.yannick_cw.elastic_indexer4s.Index_results.{IndexError, StageSucceeded} import com.yannick_cw.elastic_indexer4s.specs.AsyncSpec import scala.concurrent.Future class IndexDeletionSpec extends AsyncSpec { val newIndex = IndexWithInfo("newIndex", List("alias"), 99) "The IndexDeletion" should { "never delete the new index" in { val opsClient = testEsOpsClient(newIndex) val deleter = IndexDeletion(opsClient) deleter.deleteOldest("new", "newIndex", 0, false).map { deletionResult => deletionResult.right.value shouldBe a[StageSucceeded] opsClient.deletedIndices shouldBe empty } } "never delete an index with alias if protected" in { val protectedIndices = (1 to 10).map(i => IndexWithInfo(s"index$i", List(s"alias$i"), i)) val opsClient = testEsOpsClient(newIndex +: protectedIndices: _*) val deleter = IndexDeletion(opsClient) deleter.deleteOldest("inde", "index0", 0, true).map { deletionResult => deletionResult.right.value shouldBe a[StageSucceeded] opsClient.deletedIndices shouldBe empty } } "only delete indices with the same prefix" in { val indicesWithSamePrefix = (1 to 10).map(i => IndexWithInfo(s"index$i", List(s"alias"), i)) val differentIndices = (1 to 10).map(i => IndexWithInfo(s"some$i", List(s"alias"), i)) val opsClient = testEsOpsClient(newIndex +: (indicesWithSamePrefix ++ differentIndices): _*) val deleter = IndexDeletion(opsClient) deleter.deleteOldest("inde", "index0", 0, false).map { deletionResult => deletionResult.right.value shouldBe a[StageSucceeded] opsClient.deletedIndices should contain theSameElementsAs indicesWithSamePrefix.map(_.index) } } "keep at least defined amount of indices, even if there are newer indices with different prefix" in { val indicesWithSamePrefix = (1 to 10).map(i => IndexWithInfo(s"index$i", List(s"alias"), i)) val differentIndices = (11 to 20).map(i => IndexWithInfo(s"some$i", List(s"alias"), i)) val opsClient = testEsOpsClient(newIndex +: (indicesWithSamePrefix ++ differentIndices): _*) val deleter = IndexDeletion(opsClient) deleter.deleteOldest("inde", "index0", 3, false).map { deletionResult => deletionResult.right.value shouldBe a[StageSucceeded] opsClient.deletedIndices should have length 7 } } "delete the oldest indices first if more indices than defined to keep" in { val indices = scala.util.Random.shuffle((1 to 10).map(i => IndexWithInfo(s"index$i", List.empty, i))) val opsClient = testEsOpsClient(newIndex +: indices: _*) val deleter = IndexDeletion(opsClient) deleter.deleteOldest("inde", "newIndex", 5, false).map { deletionResult => deletionResult.right.value shouldBe a[StageSucceeded] opsClient.deletedIndices should contain theSameElementsAs indices.sortBy(_.creationTime).take(5).map(_.index) } } } private def testEsOpsClient(oldIndicesWithAlias: IndexWithInfo*) = new EsOpsClientApi { val deletedIndices = scala.collection.mutable.Buffer.empty[String] def removeAliasFromIndex(index: String, alias: String): OpsResult[Boolean] = ??? def addAliasToIndex(index: String, alias: String): OpsResult[Boolean] = ??? def sizeFor(index: String): OpsResult[Long] = ??? def delete(index: String): OpsResult[Boolean] = { deletedIndices += index EitherT.pure[Future, IndexError](true) } def allIndicesWithAliasInfo: OpsResult[List[IndexWithInfo]] = EitherT.pure[Future, IndexError](oldIndicesWithAlias.toList) } }
Example 34
Source File: AliasSwitchSpec.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.elasticsearch.index_ops import cats.data.EitherT import cats.implicits._ import com.yannick_cw.elastic_indexer4s.Index_results.IndexError import com.yannick_cw.elastic_indexer4s.specs.AsyncSpec import scala.concurrent.Future class AliasSwitchSpec extends AsyncSpec { val newIndex = "index" val oldIndexAlias = "alias" val oldIndexName = "oldIndex" def switchAlias(oldSize: Int, newSize: Int, failForNew: Boolean, expectSwitchFrom: String, oldIndicesWithAlias: IndexWithInfo*) = AliasSwitching( esClient = testEsOpsClient(oldSize, newSize, failForNew, expectSwitchFrom, oldIndicesWithAlias), minThreshold = 0.95, maxThreshold = 1.25, waitForElastic = 0 ) "AliasSwitching" should { "create a new alias if no old one was found" in { switchAlias(0, 10, false, "noSwitch").switchAlias(oldIndexAlias, newIndex).map { switchResult => switchResult.right.value shouldBe a[NewAliasCreated] } } "switch the alias if the threshold was not exceeded" in { switchAlias(10, 10, false, oldIndexName, IndexWithInfo(oldIndexName, List(oldIndexAlias), 1)) .switchAlias(oldIndexAlias, newIndex) .map { switchResult => switchResult.right.value shouldBe an[AliasSwitched] } } "not switch the alias if threshold was exceeded" in { switchAlias(5, 10, false, "noSwitch", IndexWithInfo(oldIndexName, List(oldIndexAlias), 1)) .switchAlias(oldIndexAlias, newIndex) .map { switchResult => switchResult.left.value shouldBe an[IndexError] } } "not switch if the new size could not be queried" in { switchAlias(10, 10, true, "noSwitch").switchAlias(oldIndexAlias, newIndex).map { switchResult => switchResult.left.value shouldBe an[IndexError] } } "compare size with the latest and switch alias from the oldest" in { switchAlias( 10, 10, false, "aOldestIndex", IndexWithInfo("aOldestIndex", List(oldIndexAlias), 1), IndexWithInfo("oldIndex", List(oldIndexAlias), 2) ).switchAlias(oldIndexAlias, newIndex).map { switchResult => switchResult.right.value shouldBe an[AliasSwitched] } } } def testEsOpsClient(oldSize: Int, newSize: Int, failForNew: Boolean, expectSwitchFrom: String, oldIndicesWithAlias: Seq[IndexWithInfo]): EsOpsClientApi = new EsOpsClientApi { def removeAliasFromIndex(index: String, alias: String): OpsResult[Boolean] = EitherT.pure[Future, IndexError] { index should be(expectSwitchFrom) true } def addAliasToIndex(index: String, alias: String): OpsResult[Boolean] = EitherT.pure[Future, IndexError](true) def sizeFor(index: String): OpsResult[Long] = EitherT.pure[Future, IndexError](index match { case "oldIndex" => oldSize.toLong case "index" => if (failForNew) throw new IllegalArgumentException("fail") else newSize.toLong }) def delete(index: String): OpsResult[Boolean] = EitherT.pure[Future, IndexError](true) def allIndicesWithAliasInfo: OpsResult[List[IndexWithInfo]] = EitherT.pure[Future, IndexError](oldIndicesWithAlias.toList) } }
Example 35
Source File: EsTestInterpreter.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.indexing_logic import akka.NotUsed import akka.stream.scaladsl.Source import cats.data.WriterT._ import cats.instances.list.catsKernelStdMonoidForList import cats.data.{EitherT, Writer} import com.sksamuel.elastic4s.streams.RequestBuilder import com.yannick_cw.elastic_indexer4s.Index_results.{IndexError, RunResult, StageSucceeded, StageSuccess} import com.yannick_cw.elastic_indexer4s.elasticsearch.EsAccess import com.yannick_cw.elastic_indexer4s.indexing_logic.TestMonad.W sealed trait Command case object CreateIndex extends Command case object IndexIt extends Command case object Switch extends Command case object Delete extends Command case object Shutdown extends Command object TestMonad { type W[A] = Writer[List[Command], A] implicit val r: RequestBuilder[String] = (t: String) => ??? } object EsTestInterpreter extends EsAccess[W] { def createIndex(): EitherT[W, IndexError, StageSucceeded] = EitherT.liftF[W, IndexError, StageSucceeded](Writer(List(CreateIndex), StageSuccess("create"))) def indexSource[A: RequestBuilder](source: Source[A, NotUsed]): EitherT[W, IndexError, StageSucceeded] = EitherT.liftF[W, IndexError, StageSucceeded](Writer(List(IndexIt), StageSuccess("index"))) def switchAlias(minT: Double, maxT: Double, alias: String): EitherT[W, IndexError, StageSucceeded] = if (alias == "failAlias") EitherT[W, IndexError, StageSucceeded]( Writer[List[Command], Either[IndexError, StageSucceeded]](List(Switch), Left(IndexError("fail")))) else EitherT.liftF[W, IndexError, StageSucceeded](Writer(List(Switch), StageSuccess("switch"))) def deleteOldIndices(keep: Int, aliasProtection: Boolean): EitherT[W, IndexError, StageSucceeded] = EitherT.liftF[W, IndexError, StageSucceeded](Writer(List(Delete), StageSuccess("delete"))) } object IndexOpsTestInterpreter extends IndexOps[W] { def write[A: RequestBuilder](source: Source[A, NotUsed]): EitherT[W, IndexError, RunResult] = EitherT.liftF[W, IndexError, RunResult](Writer(List(IndexIt), RunResult(StageSuccess("index")))) def addSwitch(writeDone: EitherT[W, IndexError, RunResult], minT: Double, maxT: Double, alias: String): EitherT[W, IndexError, RunResult] = writeDone.flatMap( _ => if (alias == "failAlias") EitherT[W, IndexError, RunResult]( Writer[List[Command], Either[IndexError, RunResult]](List(Switch), Left(IndexError("fail")))) else EitherT.liftF[W, IndexError, RunResult](Writer(List(Switch), RunResult(StageSuccess("switch"))))) def addDelete(writeDone: EitherT[W, IndexError, RunResult], keep: Int, aliasProtection: Boolean): EitherT[W, IndexError, RunResult] = writeDone.flatMap(_ => EitherT.liftF[W, IndexError, RunResult](Writer(List(Delete), RunResult(StageSuccess("delete"))))) }
Example 36
Source File: AliasSwitching.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.elasticsearch.index_ops import cats.data.EitherT import cats.implicits._ import com.yannick_cw.elastic_indexer4s.Index_results.{IndexError, StageSucceeded} import scala.concurrent.{ExecutionContext, Future, blocking} import scala.util.control.NonFatal class AliasSwitching(esClient: EsOpsClientApi, waitForElastic: Long, minThreshold: Double, maxThreshold: Double)( implicit ec: ExecutionContext) { import esClient._ def switchAlias(alias: String, newIndexName: String): Future[Either[IndexError, StageSucceeded]] = trySwitching(alias, newIndexName) .recover { case NonFatal(ex) => Left(IndexError("Could not switch alias.", Some(ex))) } private def trySwitching(alias: String, newIndexName: String): Future[Either[IndexError, StageSucceeded]] = (for { _ <- EitherT.liftF[Future, IndexError, Unit](Future(blocking(Thread.sleep(waitForElastic)))) oldSize <- latestIndexWithAliasSize(alias) newSize <- sizeFor(newIndexName) optSwitchRes <- oldSize .traverse(oldIndexSize => switchAliasBetweenIndices(oldIndexSize, newSize, alias, newIndexName)) switchRes <- optSwitchRes match { case None => addAliasToIndex(newIndexName, alias) .map(_ => NewAliasCreated(s"Added alias $alias to index $newIndexName"): StageSucceeded) case Some(x) => EitherT.pure[Future, IndexError](x) } } yield switchRes).value private def switchAliasBetweenIndices(oldSize: Long, newSize: Long, alias: String, newIndexName: String): OpsResult[StageSucceeded] = { val percentage = newSize / oldSize.toDouble if (checkThreshold(percentage)) switchAliasToIndex(alias, newIndexName) .map(_ => AliasSwitched(s"Switched alias, new index size is ${(percentage * 100).toInt}% of old index")) else EitherT.leftT( IndexError( s"Switching failed, new index size is ${(percentage * 100).toInt}% of old index,\n" + s" $oldSize documents in old index with alias $alias, $newSize documents in new index $newIndexName.\n\n" + s"If you think the size of the new index is not correct, try to increase the `waitForElasticTimeout` property in the config." + s"This run spent ${waitForElastic / 1000} seconds waiting")) } private def checkThreshold(percentage: Double): Boolean = minThreshold < percentage && percentage <= maxThreshold } object AliasSwitching { def apply(esClient: EsOpsClientApi, minThreshold: Double, maxThreshold: Double, waitForElastic: Long)( implicit ec: ExecutionContext): AliasSwitching = new AliasSwitching(esClient, waitForElastic, minThreshold, maxThreshold) } case class AliasSwitched(override val msg: String) extends StageSucceeded case class NewAliasCreated(override val msg: String) extends StageSucceeded
Example 37
Source File: EsOpsClientApi.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.elasticsearch.index_ops import cats.data.EitherT import cats.implicits._ import com.sksamuel.elastic4s.http.ElasticDsl.{addAlias, removeAlias, search, _} import com.sksamuel.elastic4s.http.settings.IndexSettingsResponse import com.sksamuel.elastic4s.http.{ElasticClient, Response} import com.yannick_cw.elastic_indexer4s.Index_results.IndexError import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future case class IndexWithInfo(index: String, aliases: List[String], creationTime: Long) trait EsOpsClientApi { type OpsResult[A] = EitherT[Future, IndexError, A] def removeAliasFromIndex(index: String, alias: String): OpsResult[Boolean] def addAliasToIndex(index: String, alias: String): OpsResult[Boolean] def sizeFor(index: String): OpsResult[Long] def delete(index: String): OpsResult[Boolean] def allIndicesWithAliasInfo: OpsResult[List[IndexWithInfo]] def indicesByAgeFor(alias: String): OpsResult[List[String]] = for { indices <- allIndicesWithAliasInfo } yield indices.filter(_.aliases.contains(alias)).sortBy(_.creationTime).map(_.index) def latestIndexWithAliasSize(alias: String): OpsResult[Option[Long]] = for { indices <- indicesByAgeFor(alias) size <- indices.lastOption.traverse(sizeFor) } yield size def removeAliasFromOldestIfExists(alias: String): OpsResult[Option[Boolean]] = for { indices <- indicesByAgeFor(alias) optRemoved <- indices.headOption.traverse(removeAliasFromIndex(_, alias)) } yield optRemoved def switchAliasToIndex(alias: String, index: String): OpsResult[Option[Boolean]] = for { rSuccess <- removeAliasFromOldestIfExists(alias) aSuccess <- addAliasToIndex(index, alias) } yield rSuccess.map(_ && aSuccess) } class EsOpsClient(client: ElasticClient) extends EsOpsClientApi { implicit class WithEitherTResult[A](f: Future[Response[A]]) { def opsResult: OpsResult[A] = EitherT( f.map(response => response.fold[Either[IndexError, A]]( Left(IndexError(s"Index creation failed with error: ${response.error}")))(Right(_)))) def opsResult[B](to: A => B): OpsResult[B] = opsResult.map(to) } def delete(index: String): OpsResult[Boolean] = client.execute(deleteIndex(index)).opsResult(_.acknowledged) private def indexCreationDate(indexName: String, response: IndexSettingsResponse): Option[Long] = for { indexSettings <- response.settings.get(indexName) creationDate <- indexSettings.get("index.creation_date") } yield creationDate.toLong def allIndicesWithAliasInfo: OpsResult[List[IndexWithInfo]] = for { aliases <- client.execute(getAliases()).opsResult settings <- client.execute(getSettings(aliases.mappings.keys.map(_.name))).opsResult } yield aliases.mappings .map { case (index, aliasi) => indexCreationDate(index.name, settings).map(date => IndexWithInfo(index.name, aliasi.toList.map(_.name), date)) } .collect { case Some(x) => x } .toList def removeAliasFromIndex(index: String, alias: String): OpsResult[Boolean] = client.execute(removeAlias(alias) on index).opsResult(_.acknowledged) def addAliasToIndex(index: String, alias: String): OpsResult[Boolean] = client.execute(addAlias(alias) on index).opsResult(_.acknowledged) def sizeFor(index: String): OpsResult[Long] = client.execute(search(index) size 0).opsResult(_.totalHits) } object EsOpsClient { def apply(client: ElasticClient): EsOpsClient = new EsOpsClient(client) }
Example 38
Source File: ElasticseachInterpreter.scala From elastic-indexer4s with MIT License | 5 votes |
package com.yannick_cw.elastic_indexer4s.elasticsearch import akka.NotUsed import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl.Source import cats.data.EitherT import com.sksamuel.elastic4s.streams.RequestBuilder import com.yannick_cw.elastic_indexer4s.Index_results.{IndexError, StageSucceeded} import com.yannick_cw.elastic_indexer4s.elasticsearch.elasic_config.ElasticWriteConfig import com.yannick_cw.elastic_indexer4s.elasticsearch.index_ops.{AliasSwitching, EsOpsClient, IndexDeletion} import com.yannick_cw.elastic_indexer4s.indexing_logic.FullStream import scala.concurrent.{ExecutionContext, Future} trait EsAccess[F[_]] { def createIndex(): EitherT[F, IndexError, StageSucceeded] def indexSource[A: RequestBuilder](source: Source[A, NotUsed]): EitherT[F, IndexError, StageSucceeded] def switchAlias(minT: Double, maxT: Double, alias: String): EitherT[F, IndexError, StageSucceeded] def deleteOldIndices(keep: Int, aliasProtection: Boolean): EitherT[F, IndexError, StageSucceeded] } class ElasticseachInterpreter(esConf: ElasticWriteConfig)(implicit ex: ExecutionContext, system: ActorSystem, materializer: ActorMaterializer) extends EsAccess[Future] { private val writer = ElasticWriter(esConf) private val esOpsClient = EsOpsClient(esConf.client) def createIndex(): EitherT[Future, IndexError, StageSucceeded] = EitherT(writer.createNewIndex) def indexSource[A: RequestBuilder](source: Source[A, NotUsed]): EitherT[Future, IndexError, StageSucceeded] = EitherT(FullStream.run(source, writer.esSink, esConf.logWriteSpeedEvery)) def switchAlias(minT: Double, maxT: Double, alias: String): EitherT[Future, IndexError, StageSucceeded] = EitherT( AliasSwitching(esOpsClient, minT, maxT, esConf.waitForElasticTimeout.toMillis) .switchAlias(alias, esConf.indexName)) def deleteOldIndices(keep: Int, aliasProtection: Boolean): EitherT[Future, IndexError, StageSucceeded] = EitherT( IndexDeletion(esOpsClient) .deleteOldest(esConf.indexPrefix, esConf.indexName, keep, aliasProtection)) }
Example 39
Source File: ViewReturnService.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.services import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import uk.gov.hmrc.http.HeaderCarrier import utils.{EndpointLogContext, Logging} import v1.connectors.ViewReturnConnector import v1.models.errors._ import v1.models.request.viewReturn.ViewRequest import v1.models.response.viewReturn.ViewReturnResponse import v1.support.DesResponseMappingSupport import scala.concurrent.{ExecutionContext, Future} @Singleton class ViewReturnService @Inject()(connector: ViewReturnConnector) extends DesResponseMappingSupport with Logging { def viewReturn(request: ViewRequest)( implicit hc: HeaderCarrier, ec: ExecutionContext, logContext: EndpointLogContext): Future[ServiceOutcome[ViewReturnResponse]] = { val result = for { desResponseWrapper <- EitherT(connector.viewReturn(request)).leftMap(mapDesErrors(desErrorMap)) } yield desResponseWrapper result.value } private def desErrorMap: Map[String, MtdError] = Map( "INVALID_VRN" -> VrnFormatErrorDes, "INVALID_PERIODKEY" -> PeriodKeyFormatErrorDes, "INVALID_IDENTIFIER" -> PeriodKeyFormatErrorDesNotFound, "NOT_FOUND_VRN" -> DownstreamError, "DATE_RANGE_TOO_LARGE" -> RuleDateRangeTooLargeError, "INVALID_INPUTDATA" -> InvalidInputDataError, "NOT_FOUND" -> EmptyNotFoundError, "SERVICE_ERROR" -> DownstreamError, "SERVICE_UNAVAILABLE" -> DownstreamError ) }
Example 40
Source File: resources.scala From vat-api with Apache License 2.0 | 5 votes |
package uk.gov.hmrc.vatapi import cats.data.EitherT import cats.implicits._ import play.api.Logger import play.api.http.Status import play.api.libs.json._ import play.api.mvc.Result import play.api.mvc.Results.InternalServerError import uk.gov.hmrc.vatapi.models.{AuthorisationErrorResult, ErrorResult, Errors, GenericErrorResult, InternalServerErrorResult, JsonValidationErrorResult, ValidationErrorResult} import uk.gov.hmrc.vatapi.resources.wrappers.Response import scala.concurrent.{ExecutionContext, Future} package object resources { type BusinessResult[T] = EitherT[Future, ErrorResult, T] val GovTestScenarioHeader = "Gov-Test-Scenario" def unhandledResponse(status: Int, logger: Logger): Result = { logger.error(s"Unhandled response from DES. Status code: $status. Returning 500 to client.") InternalServerError(Json.toJson(Errors.InternalServerError("An internal server error occurred"))) } def handleErrors(errorResult: ErrorResult): VatResult = { errorResult match { case GenericErrorResult(message) => VatResult.Failure(Status.BAD_REQUEST, Errors.badRequest(message)) case JsonValidationErrorResult(errors) => VatResult.Failure(Status.BAD_REQUEST,Errors.badRequest(errors)) case ValidationErrorResult(error) => VatResult.Failure(Status.BAD_REQUEST, Errors.badRequest(error)) case AuthorisationErrorResult(error) => VatResult.Failure(Status.FORBIDDEN, error) case InternalServerErrorResult(error) => VatResult.Failure(Status.INTERNAL_SERVER_ERROR, Errors.InternalServerError(error)) } } def validateJson[T](json: JsValue)(implicit reads: Reads[T], ec: ExecutionContext): BusinessResult[T] = BusinessResult { for { errors <- json.validate[T].asEither.left } yield JsonValidationErrorResult(errors) } def validate[T](value: T)(validate: PartialFunction[T, Errors.Error])(implicit ec: ExecutionContext): BusinessResult[T] = if (validate.isDefinedAt(value)) BusinessResult.failure(ValidationErrorResult(validate(value))) else BusinessResult.success(value) def authorise[T](value: T)(auth: PartialFunction[T, Errors.Error])(implicit ec: ExecutionContext): BusinessResult[T] = if (auth.isDefinedAt(value)) BusinessResult.failure(AuthorisationErrorResult(Errors.businessError(auth(value)))) else BusinessResult.success(value) def execute[T](torun: Unit => Future[T])(implicit ec: ExecutionContext): BusinessResult[T] = BusinessResult { for { result <- torun(()) } yield Right(result) } def fromDes[R <: Response](result: BusinessResult[R]): DesBusinessResult[R] = DesBusinessResult(result) object BusinessResult { def apply[T](eventuallyErrorOrResult: Future[Either[ErrorResult, T]]): BusinessResult[T] = new EitherT(eventuallyErrorOrResult) def apply[T](errorOrResult: Either[ErrorResult, T])(implicit ec: ExecutionContext): BusinessResult[T] = EitherT.fromEither(errorOrResult) def success[T](value: T)(implicit ec: ExecutionContext): BusinessResult[T] = EitherT.fromEither(Right(value)) def failure[T](error: ErrorResult)(implicit ec: ExecutionContext): BusinessResult[T] = EitherT.fromEither(Left(error)) } }
Example 41
Source File: ViewReturnController.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.controllers import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import play.api.libs.json.Json import play.api.mvc.{Action, AnyContent, ControllerComponents} import play.mvc.Http.MimeTypes import utils.{EndpointLogContext, Logging} import v1.audit.AuditEvents import v1.controllers.requestParsers.ViewReturnRequestParser import v1.models.audit.AuditResponse import v1.models.errors._ import v1.models.request.viewReturn.ViewRawData import v1.services.{AuditService, EnrolmentsAuthService, ViewReturnService} import scala.concurrent.{ExecutionContext, Future} @Singleton class ViewReturnController @Inject()(val authService: EnrolmentsAuthService, requestParser: ViewReturnRequestParser, service: ViewReturnService, auditService: AuditService, cc: ControllerComponents)(implicit ec: ExecutionContext) extends AuthorisedController(cc) with BaseController with Logging { implicit val endpointLogContext: EndpointLogContext = EndpointLogContext( controllerName = "ViewReturnController", endpointName = "viewReturn" ) def viewReturn(vrn: String, periodKey: String): Action[AnyContent] = authorisedAction(vrn).async{ implicit request => logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " + s"Retrieve VAT returns for VRN : $vrn") val rawRequest: ViewRawData = ViewRawData( vrn = vrn, periodKey = periodKey ) val result = for { parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest)) serviceResponse <- EitherT(service.viewReturn(parsedRequest)) } yield { logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " + s"Successfully retrieved Vat Return from DES") auditService.auditEvent(AuditEvents.auditReturns(serviceResponse.correlationId, request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData)))))) Ok(Json.toJson(serviceResponse.responseData)) .withApiHeaders(serviceResponse.correlationId) .as(MimeTypes.JSON) } result.leftMap { errorWrapper => val correlationId = getCorrelationId(errorWrapper) val result = errorResult(errorWrapper).withApiHeaders(correlationId) logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message)) auditService.auditEvent(AuditEvents.auditReturns(correlationId, request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors)))) result }.merge } private def errorResult(errorWrapper: ErrorWrapper) = { (errorWrapper.error: @unchecked) match { case VrnFormatError | VrnFormatErrorDes | PeriodKeyFormatError | PeriodKeyFormatErrorDes | BadRequestError => BadRequest(Json.toJson(errorWrapper)) case RuleDateRangeTooLargeError | InvalidInputDataError => Forbidden(Json.toJson(errorWrapper)) case PeriodKeyFormatErrorDesNotFound => NotFound(Json.toJson(errorWrapper)) case EmptyNotFoundError => NotFound case DownstreamError => InternalServerError(Json.toJson(errorWrapper)) } } }
Example 42
Source File: ObligationsController.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.controllers import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import play.api.libs.json.Json import play.api.mvc.{Action, AnyContent, ControllerComponents} import play.mvc.Http.MimeTypes import utils.{EndpointLogContext, Logging} import v1.audit.AuditEvents import v1.controllers.requestParsers.ObligationsRequestParser import v1.models.audit.AuditResponse import v1.models.errors._ import v1.models.request.obligations.ObligationsRawData import v1.services.{AuditService, EnrolmentsAuthService, ObligationsService} import scala.concurrent.{ExecutionContext, Future} @Singleton class ObligationsController @Inject()(val authService: EnrolmentsAuthService, requestParser: ObligationsRequestParser, service: ObligationsService, auditService: AuditService, cc: ControllerComponents)(implicit ec: ExecutionContext) extends AuthorisedController(cc) with BaseController with Logging { implicit val endpointLogContext: EndpointLogContext = EndpointLogContext( controllerName = "ObligationsController", endpointName = "retrieveObligations" ) def retrieveObligations(vrn: String, from: Option[String], to: Option[String], status: Option[String]): Action[AnyContent] = authorisedAction(vrn).async{ implicit request => logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] Retrieve obligations for VRN : $vrn") val rawRequest: ObligationsRawData = ObligationsRawData( vrn = vrn, from = from, to = to, status = status ) val result = for { parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest)) serviceResponse <- EitherT(service.retrieveObligations(parsedRequest)) } yield { logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] Successfully retrieved Obligations from DES") auditService.auditEvent(AuditEvents.auditObligations(serviceResponse.correlationId, request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData)))))) Ok(Json.toJson(serviceResponse.responseData)) .withApiHeaders(serviceResponse.correlationId) .as(MimeTypes.JSON) } result.leftMap { errorWrapper => val correlationId = getCorrelationId(errorWrapper) val result = errorResult(errorWrapper).withApiHeaders(correlationId) logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message)) auditService.auditEvent(AuditEvents.auditObligations(correlationId, request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors)))) result }.merge } private def errorResult(errorWrapper: ErrorWrapper) = { (errorWrapper.error: @unchecked) match { case VrnFormatError | VrnFormatErrorDes | InvalidFromError | InvalidToError | InvalidStatusError | InvalidDateFromErrorDes | InvalidDateToErrorDes | InvalidStatusErrorDes | RuleDateRangeInvalidError | RuleOBLDateRangeTooLargeError | RuleMissingDateRangeError | BadRequestError => BadRequest(Json.toJson(errorWrapper)) case LegacyNotFoundError => NotFound(Json.toJson(errorWrapper)) case DownstreamError => InternalServerError(Json.toJson(errorWrapper)) } } }
Example 43
Source File: LiabilitiesController.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.controllers import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import play.api.libs.json.Json import play.api.mvc.{Action, AnyContent, ControllerComponents} import play.mvc.Http.MimeTypes import utils.{EndpointLogContext, Logging} import v1.audit.AuditEvents import v1.controllers.requestParsers.LiabilitiesRequestParser import v1.models.audit.AuditResponse import v1.models.errors.ControllerError._ import v1.models.errors._ import v1.models.request.liabilities.LiabilitiesRawData import v1.services.{AuditService, EnrolmentsAuthService, LiabilitiesService} import scala.concurrent.{ExecutionContext, Future} @Singleton class LiabilitiesController @Inject()(val authService: EnrolmentsAuthService, requestParser: LiabilitiesRequestParser, service: LiabilitiesService, auditService: AuditService, cc: ControllerComponents)(implicit ec: ExecutionContext) extends AuthorisedController(cc) with BaseController with Logging { implicit val endpointLogContext: EndpointLogContext = EndpointLogContext( controllerName = "LiabilitiesController", endpointName = "retrieveLiabilities" ) def retrieveLiabilities(vrn: String, from: Option[String], to: Option[String]): Action[AnyContent] = authorisedAction(vrn).async { implicit request => logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " + s"Retrieving Liabilities from DES") val rawRequest: LiabilitiesRawData = LiabilitiesRawData(vrn, from, to) val result = for { parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest)) serviceResponse <- EitherT(service.retrieveLiabilities(parsedRequest)) } yield { logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " + s"Successfully retrieved Liabilities from DES") auditService.auditEvent(AuditEvents.auditLiabilities(serviceResponse.correlationId, request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData)))))) Ok(Json.toJson(serviceResponse.responseData)) .withApiHeaders(serviceResponse.correlationId) .as(MimeTypes.JSON) } result.leftMap { errorWrapper => val correlationId = getCorrelationId(errorWrapper) val result = errorResult(errorWrapper).withApiHeaders(correlationId) logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message)) auditService.auditEvent(AuditEvents.auditLiabilities(correlationId, request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors)))) result }.merge } private def errorResult(errorWrapper: ErrorWrapper) = { (errorWrapper.error: @unchecked) match { case VrnFormatError | VrnFormatErrorDes | BadRequestError | FinancialDataInvalidDateFromError | InvalidDateFromErrorDes | FinancialDataInvalidDateToError | InvalidDateToErrorDes | FinancialDataInvalidDateRangeError | InvalidDataError => BadRequest(Json.toJson(errorWrapper)) case LegacyNotFoundError => NotFound(Json.toJson(errorWrapper)) case DownstreamError => InternalServerError(Json.toJson(errorWrapper)) } } }
Example 44
Source File: PaymentsController.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.controllers import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import play.api.http.MimeTypes import play.api.libs.json.Json import play.api.mvc.{Action, AnyContent, ControllerComponents, Result} import utils.{EndpointLogContext, Logging} import v1.audit.AuditEvents import v1.controllers.requestParsers.PaymentsRequestParser import v1.models.audit.AuditResponse import v1.models.errors._ import v1.models.request.payments.PaymentsRawData import v1.services.{AuditService, EnrolmentsAuthService, PaymentsService} import scala.concurrent.{ExecutionContext, Future} @Singleton class PaymentsController @Inject()(val authService: EnrolmentsAuthService, requestParser: PaymentsRequestParser, service: PaymentsService, auditService: AuditService, cc: ControllerComponents)(implicit ec: ExecutionContext) extends AuthorisedController(cc) with BaseController with Logging { implicit val endpointLogContext: EndpointLogContext = EndpointLogContext( controllerName = "PaymentsController", endpointName = "retrievePayments" ) def retrievePayments(vrn: String, from: Option[String], to: Option[String]): Action[AnyContent] = authorisedAction(vrn).async{ implicit request => logger.info(s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " + s"Successfully retrieved Payments from DES") val rawRequest: PaymentsRawData = PaymentsRawData( vrn = vrn, from = from, to = to ) val result = for { parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest)) serviceResponse <- EitherT(service.retrievePayments(parsedRequest)) } yield { logger.info(s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " + s"Successfully retrieved Payments from DES") auditService.auditEvent(AuditEvents.auditPayments(serviceResponse.correlationId, request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData)))))) Ok(Json.toJson(serviceResponse.responseData)) .withApiHeaders(serviceResponse.correlationId) .as(MimeTypes.JSON) } result.leftMap{errorWrapper => val correlationId = getCorrelationId(errorWrapper) val result = errorResult(errorWrapper).withApiHeaders(correlationId) logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message)) auditService.auditEvent(AuditEvents.auditPayments(correlationId, request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors)))) result }.merge } private def errorResult(errorWrapper: ErrorWrapper): Result = { (errorWrapper.error: @unchecked) match { case VrnFormatError | VrnFormatErrorDes | FinancialDataInvalidDateFromError | InvalidDateFromErrorDes | FinancialDataInvalidDateToError | InvalidDateToErrorDes | FinancialDataInvalidDateRangeError | InvalidDataError => BadRequest(Json.toJson(errorWrapper)) case LegacyNotFoundError => NotFound(Json.toJson(errorWrapper)) case DownstreamError => InternalServerError(Json.toJson(errorWrapper)) } } }
Example 45
Source File: PaymentsService.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.services import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import uk.gov.hmrc.http.HeaderCarrier import utils.{EndpointLogContext, Logging} import v1.connectors.PaymentsConnector import v1.models.errors._ import v1.models.request.payments.PaymentsRequest import v1.models.response.payments.PaymentsResponse import v1.support.DesResponseMappingSupport import scala.concurrent.{ExecutionContext, Future} @Singleton class PaymentsService @Inject()(connector: PaymentsConnector) extends DesResponseMappingSupport with Logging { def retrievePayments(request: PaymentsRequest)( implicit hc: HeaderCarrier, ec: ExecutionContext, logContext: EndpointLogContext): Future[ServiceOutcome[PaymentsResponse]] = { val result = for { desResponseWrapper <- EitherT(connector.retrievePayments(request)).leftMap(mapDesErrors(desErrorMap)) mtdResponseWrapper <- EitherT.fromEither[Future](validatePaymentsSuccessResponse(desResponseWrapper)) } yield mtdResponseWrapper result.value } private def desErrorMap: Map[String, MtdError] = Map( "INVALID_IDTYPE" -> DownstreamError, "INVALID_IDNUMBER" -> VrnFormatErrorDes, "INVALID_REGIMETYPE" -> DownstreamError, "INVALID_ONLYOPENITEMS" -> DownstreamError, "INVALID_INCLUDELOCKS" -> DownstreamError, "INVALID_CALCULATEACCRUEDINTEREST" -> DownstreamError, "INVALID_CUSTOMERPAYMENTINFORMATION" -> DownstreamError, "INVALID_DATEFROM" -> InvalidDateFromErrorDes, "INVALID_DATETO" -> InvalidDateToErrorDes, "INVALID_DATA" -> InvalidDataError, "NOT_FOUND" -> LegacyNotFoundError, "SERVER_ERROR" -> DownstreamError, "SERVICE_UNAVAILABLE" -> DownstreamError ) }
Example 46
Source File: LiabilitiesService.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.services import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import uk.gov.hmrc.http.HeaderCarrier import utils.{EndpointLogContext, Logging} import v1.connectors.LiabilitiesConnector import v1.models.errors._ import v1.models.request.liabilities.LiabilitiesRequest import v1.models.response.liabilities.LiabilitiesResponse import v1.support.DesResponseMappingSupport import scala.concurrent.{ExecutionContext, Future} @Singleton class LiabilitiesService @Inject()(connector: LiabilitiesConnector) extends DesResponseMappingSupport with Logging { def retrieveLiabilities(request: LiabilitiesRequest)( implicit hc: HeaderCarrier, ec: ExecutionContext, logContext: EndpointLogContext): Future[ServiceOutcome[LiabilitiesResponse]] = { val result = for { desResponseWrapper <- EitherT(connector.retrieveLiabilities(request)).leftMap(mapDesErrors(desErrorMap)) mtdResponseWrapper <- EitherT.fromEither[Future](validateLiabilitiesSuccessResponse(desResponseWrapper)) } yield mtdResponseWrapper result.value } private def desErrorMap: Map[String, MtdError] = Map( "INVALID_IDTYPE" -> DownstreamError, "INVALID_IDNUMBER" -> VrnFormatErrorDes, "INVALID_REGIMETYPE" -> DownstreamError, "INVALID_ONLYOPENITEMS" -> DownstreamError, "INVALID_INCLUDELOCKS" -> DownstreamError, "INVALID_CALCULATEACCRUEDINTEREST" -> DownstreamError, "INVALID_CUSTOMERPAYMENTINFORMATION" -> DownstreamError, "INVALID_DATEFROM" -> InvalidDateFromErrorDes, "INVALID_DATETO" -> InvalidDateToErrorDes, "NOT_FOUND" -> LegacyNotFoundError, "INVALID_DATA" -> InvalidDataError, "SERVER_ERROR" -> DownstreamError, "SERVICE_UNAVAILABLE" -> DownstreamError ) }
Example 47
Source File: NrsService.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.services import java.nio.charset.StandardCharsets import java.util.Base64 import cats.data.EitherT import cats.implicits._ import javax.inject.Inject import org.joda.time.DateTime import play.api.libs.json.Json import uk.gov.hmrc.http.HeaderCarrier import v1.connectors.NrsConnector import v1.controllers.UserRequest import v1.models.errors.{DownstreamError, ErrorWrapper} import v1.models.nrs.request.{Metadata, NrsSubmission, SearchKeys} import v1.models.nrs.response.NrsResponse import v1.models.request.submit.SubmitRequest import scala.concurrent.{ExecutionContext, Future} class NrsService @Inject()(connector: NrsConnector) { def submitNrs(vatSubmission: SubmitRequest, submissionTimestamp: DateTime)( implicit request: UserRequest[_], hc: HeaderCarrier, ec: ExecutionContext): Future[Either[ErrorWrapper, NrsResponse]] = { val result = for { nrsResponse <- EitherT(connector.submitNrs(buildNrsSubmission(vatSubmission, submissionTimestamp, request))) .leftMap(_ => ErrorWrapper(None, DownstreamError, None)) } yield nrsResponse result.value } def buildNrsSubmission(vatSubmission: SubmitRequest, submissionTimestamp: DateTime, request: UserRequest[_]): NrsSubmission = { import vatSubmission._ val payloadString: String = Base64.getEncoder.encodeToString( Json.toJson(body) .toString() .getBytes(StandardCharsets.UTF_8) ) NrsSubmission( payload = payloadString, Metadata( businessId = "vat", notableEvent = "vat-return", payloadContentType = "application/json", payloadSha256Checksum = None, userSubmissionTimestamp = submissionTimestamp, identityData = request.userDetails.identityData, userAuthToken = request.headers.get("Authorization").get, headerData = Json.toJson(request.headers.toMap.map { h => h._1 -> h._2.head }), searchKeys = SearchKeys( vrn = Some(vrn.vrn), companyName = None, periodKey = body.periodKey, taxPeriodEndDate = None ) ) ) } }
Example 48
Source File: SubmitReturnService.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.services import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import uk.gov.hmrc.http.HeaderCarrier import utils.{EndpointLogContext, Logging} import v1.connectors.SubmitReturnConnector import v1.models.errors._ import v1.models.request.submit.SubmitRequest import v1.models.response.submit.SubmitResponse import v1.support.DesResponseMappingSupport import scala.concurrent.{ExecutionContext, Future} @Singleton class SubmitReturnService @Inject()(connector: SubmitReturnConnector) extends DesResponseMappingSupport with Logging { def submitReturn(request: SubmitRequest)( implicit hc: HeaderCarrier, ec: ExecutionContext, logContext: EndpointLogContext): Future[ServiceOutcome[SubmitResponse]] = { val result = for { desResponseWrapper <- EitherT(connector.submitReturn(request)).leftMap(mapDesErrors(desErrorMap)) } yield desResponseWrapper result.value } private def desErrorMap: Map[String, MtdError] = Map( "INVALID_VRN" -> VrnFormatErrorDes, "INVALID_PERIODKEY" -> PeriodKeyFormatErrorDes, "INVALID_PAYLOAD" -> BadRequestError, "TAX_PERIOD_NOT_ENDED" -> TaxPeriodNotEnded, "DUPLICATE_SUBMISSION" -> DuplicateVatSubmission, "NOT_FOUND_VRN" -> DownstreamError, "INVALID_SUBMISSION" -> DownstreamError, "INVALID_ORIGINATOR_ID" -> DownstreamError, "SERVICE_ERROR" -> DownstreamError, "SERVICE_UNAVAILABLE" -> DownstreamError ) }
Example 49
Source File: RedisLiftKDemo.scala From redis4cats with Apache License 2.0 | 5 votes |
package dev.profunktor.redis4cats import cats.data.EitherT import cats.effect.{ IO, Resource } import dev.profunktor.redis4cats.effect.Log.NoOp._ object RedisLiftKDemo extends LoggerIOApp { import Demo._ val program: IO[Unit] = { val usernameKey = "test" val showResult: Option[String] => IO[Unit] = _.fold(putStrLn(s"Not found key: $usernameKey"))(s => putStrLn(s)) val commandsApi: Resource[IO, RedisCommands[IO, String, String]] = Redis[IO].utf8(redisURI) commandsApi.use( _.liftK[EitherT[IO, String, *]] .get(usernameKey) .semiflatMap(x => showResult(x)) .value .void ) } }
Example 50
Source File: ObligationsService.scala From vat-api with Apache License 2.0 | 5 votes |
package v1.services import cats.data.EitherT import cats.implicits._ import javax.inject.{Inject, Singleton} import play.api.Logger import uk.gov.hmrc.http.HeaderCarrier import utils.{EndpointLogContext, Logging} import v1.connectors.ObligationsConnector import v1.models.errors._ import v1.models.request.obligations.ObligationsRequest import v1.models.response.obligations.ObligationsResponse import v1.support.DesResponseMappingSupport import scala.concurrent.{ExecutionContext, Future} @Singleton class ObligationsService @Inject()(connector: ObligationsConnector) extends DesResponseMappingSupport with Logging { def retrieveObligations(request: ObligationsRequest)( implicit hc: HeaderCarrier, ec: ExecutionContext, logContext: EndpointLogContext): Future[ServiceOutcome[ObligationsResponse]] = { val result = for { desResponseWrapper <- EitherT(connector.retrieveObligations(request)).leftMap(mapDesErrors(desErrorMap)) } yield desResponseWrapper result.value } private def desErrorMap: Map[String, MtdError] = Map( "INVALID_IDTYPE" -> DownstreamError, "INVALID_IDNUMBER" -> VrnFormatErrorDes, "INVALID_STATUS" -> InvalidStatusErrorDes, "INVALID_REGIME" -> DownstreamError, "INVALID_DATE_FROM" -> InvalidDateFromErrorDes, "INVALID_DATE_TO" -> InvalidDateToErrorDes, "INVALID_DATE_RANGE" -> RuleOBLDateRangeTooLargeError, "NOT_FOUND_BP_KEY" -> { Logger.warn("[ObligationsService] [desErrorMap] - Backend returned NOT_FOUND_BPKEY error") DownstreamError }, "NOT_FOUND" -> LegacyNotFoundError, "SERVICE_ERROR" -> DownstreamError, "SERVICE_UNAVAILABLE" -> DownstreamError ) }
Example 51
Source File: GrantHandler.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider package grantHandler import cats.data.EitherT import cats.effect.Sync import cats.implicits._ import scala.concurrent.duration.FiniteDuration sealed abstract class GrantType extends Product with Serializable { def name: String } object GrantType { val header = "grant_type" case object AuthorizationCode extends GrantType { def name: String = "authorization_code" } case object RefreshToken extends GrantType { def name: String = "refresh_token" } case object ClientCrendentials extends GrantType { def name: String = "client_credentials" } case object Password extends GrantType { def name: String = "password" } case object Implicit extends GrantType { def name: String = "implicit" } val strToGrantType = Map( AuthorizationCode.name -> AuthorizationCode, RefreshToken.name -> RefreshToken, ClientCrendentials.name -> ClientCrendentials, Password.name -> Password, Implicit.name -> Implicit ) } final case class GrantHandlerResult[U]( authInfo: AuthInfo[U], tokenType: String, accessToken: String, expiresIn: Option[FiniteDuration], refreshToken: Option[String], scope: Option[String], params: Map[String, String] ) trait GrantHandler[F[_], U] { type A def handleRequest(req: A)(implicit F: Sync[F]): EitherT[F, OAuthError, GrantHandlerResult[U]] def refreshAccessToken(authInfo: AuthInfo[U], refreshToken: String): F[AccessToken] }
Example 52
Source File: PasswordNoClientCredGrantHandler.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider package grantHandler import cats.data.EitherT import cats.effect.Sync import cats.implicits._ import tsec.oauth2.provider.ValidatedRequest._ class PasswordNoClientCredGrantHandler[F[_], U](handler: PasswordNoClientCredHandler[F, U]) extends GrantHandler[F, U] { type A = ValidatedPasswordNoClientCred def handleRequest( req: ValidatedPasswordNoClientCred )(implicit F: Sync[F]): EitherT[F, OAuthError, GrantHandlerResult[U]] = for { user <- EitherT[F, OAuthError, U]( handler.findUser(None, req).map(_.toRight(InvalidGrant("username or password is incorrect"))) ) authInfo = AuthInfo(user, None, req.scope, None) grantResult <- EitherT( issueAccessToken(handler, authInfo).attempt .map(_.leftMap(t => FailedToIssueAccessToken(t.getMessage): OAuthError)) ) } yield grantResult } trait PasswordNoClientCredHandler[F[_], U] extends IssueAccessToken[F, U] { def findUser(maybeCredential: Option[ClientCredential], request: ValidatedPasswordNoClientCred): F[Option[U]] }
Example 53
Source File: RrefreshTokenHandler.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider package grantHandler import cats.data.EitherT import cats.effect.Sync import cats.implicits._ import tsec.oauth2.provider.ValidatedRequest._ class RefreshTokenGrantHandler[F[_], U](handler: RefreshTokenHandler[F, U]) extends GrantHandler[F, U] { type A = ValidatedRefreshToken def handleRequest(req: ValidatedRefreshToken)(implicit F: Sync[F]): EitherT[F, OAuthError, GrantHandlerResult[U]] = for { _ <- EitherT[F, OAuthError, Unit]( handler .validateClient(req) .map( isValid => Either.cond(isValid, (), InvalidClient("Invalid client or client is not authorized"): OAuthError) ) ) auth <- EitherT[F, OAuthError, AuthInfo[U]]( handler .findAuthInfoByRefreshToken(req.refreshToken) .map(_.toRight(InvalidGrant("Authorized information is not found by the refresh token"))) ) _ <- EitherT .cond[F](auth.clientId.contains(req.clientCredential.clientId), (), InvalidClient("invalid clientId")) token <- EitherT( handler .refreshAccessToken(auth, req.refreshToken) .attempt .map(_.leftMap(t => RefreshTokenFailed(t.getMessage): OAuthError)) ) grantResult <- EitherT( token.expiresIn .map(GrantHandler.createGrantHandlerResult(auth, token, _)) .attempt .map(_.leftMap(t => RefreshTokenFailed(t.getMessage): OAuthError)) ) } yield grantResult } trait RefreshTokenHandler[F[_], U] { def findAuthInfoByRefreshToken(refreshToken: String): F[Option[AuthInfo[U]]] }
Example 54
Source File: ImplicitGrantHandler.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider package grantHandler import cats.implicits._ import cats.data.EitherT import cats.effect.Sync import tsec.oauth2.provider.ValidatedRequest._ class ImplicitGrantHandler[F[_], U](handler: ImplicitHandler[F, U]) extends GrantHandler[F, U] { type A = ValidatedImplicit def handleRequest( req: ValidatedImplicit )(implicit F: Sync[F]): EitherT[F, OAuthError, GrantHandlerResult[U]] = for { _ <- EitherT[F, OAuthError, Unit]( handler .validateClient(req) .map( isValid => Either.cond(isValid, (), InvalidClient("Invalid client or client is not authorized"): OAuthError) ) ) user <- EitherT[F, OAuthError, U]( handler.findUser(req).map(_.toRight(InvalidGrant("user cannot be authenticated"))) ) authInfo = AuthInfo(user, Some(req.clientCredential.clientId), req.scope, None) token = handler.getStoredAccessToken(authInfo).flatMap { token => val res = token match { case Some(token) => F.pure(token) case None => handler.createAccessToken(authInfo) } for { t <- res expiresIn <- t.expiresIn } yield GrantHandlerResult( authInfo, "Bearer", t.token, expiresIn, None, t.scope, t.params ) } grantResult <- EitherT( token.attempt .map(_.leftMap(t => FailedToIssueAccessToken(t.getMessage): OAuthError)) ) } yield grantResult } trait ImplicitHandler[F[_], U] { def getStoredAccessToken(authInfo: AuthInfo[U]): F[Option[AccessToken]] }
Example 55
Source File: ClientCredentialsGrantHandler.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider package grantHandler import cats.data.EitherT import cats.effect.Sync import cats.implicits._ import tsec.oauth2.provider.ValidatedRequest._ class ClientCredentialsGrantHandler[F[_], U](handler: ClientCredentialsHandler[F, U]) extends GrantHandler[F, U] { type A = ValidatedClientCredentials def handleRequest( req: ValidatedClientCredentials )(implicit F: Sync[F]): EitherT[F, OAuthError, GrantHandlerResult[U]] = for { _ <- EitherT[F, OAuthError, Unit]( handler .validateClient(req) .map( isValid => Either.cond(isValid, (), InvalidClient("Invalid client or client is not authorized"): OAuthError) ) ) user <- EitherT[F, OAuthError, U]( handler .findUser(req) .map(_.toRight(InvalidGrant("client_id or client_secret or scope is incorrect"))) ) authInfo = AuthInfo(user, Some(req.clientCredential.clientId), req.scope, None) grantResult <- EitherT( issueAccessToken(handler, authInfo).attempt .map(_.leftMap(t => FailedToIssueAccessToken(t.getMessage): OAuthError)) ) } yield grantResult } trait ClientCredentialsHandler[F[_], U] extends IssueAccessToken[F, U] { def refreshAccessToken(authInfo: AuthInfo[U], refreshToken: String): F[AccessToken] }
Example 56
Source File: AuthorizationCodeGrantHandler.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider package grantHandler import cats.data.EitherT import cats.effect.Sync import cats.implicits._ import tsec.oauth2.provider.ValidatedRequest._ class AuthorizationCodeGrantHandler[F[_], U](handler: AuthorizationCodeHandler[F, U]) extends GrantHandler[F, U] { type A = ValidatedAuthorizationCode def handleRequest( req: ValidatedAuthorizationCode )(implicit F: Sync[F]): EitherT[F, OAuthError, GrantHandlerResult[U]] = for { _ <- EitherT( handler .validateClient(req) .map( isValid => Either.cond(isValid, (), InvalidClient("Invalid client or client is not authorized"): OAuthError) ) ) auth <- EitherT[F, OAuthError, AuthInfo[U]]( handler .findAuthInfoByCode(req.code) .map(_.toRight(InvalidGrant("Authorized information is not found by the code"))) ) _ <- EitherT .cond[F](auth.clientId.contains(req.clientCredential.clientId), (), InvalidClient("invalid clientId")) _ <- EitherT.cond[F]( auth.redirectUri.isEmpty || (auth.redirectUri.isDefined && auth.redirectUri == req.redirectUri), (), RedirectUriMismatch ) grantResult <- EitherT( issueAccessToken(handler, auth).attempt .map(_.leftMap(t => FailedToIssueAccessToken(t.getMessage): OAuthError)) ) _ <- EitherT( handler.deleteAuthCode(req.code).attempt.map(_.leftMap(t => FailedToDeleteAuthCode(t.getMessage): OAuthError)) ) } yield grantResult } trait AuthorizationCodeHandler[F[_], U] extends IssueAccessToken[F, U] { def deleteAuthCode(code: String): F[Unit] }
Example 57
Source File: ProtectedResource.scala From tsec with MIT License | 5 votes |
package tsec.oauth2.provider import cats.implicits._ import cats.data.EitherT import cats.effect.Sync import tsec.oauth2.provider.AccessTokenFetcher._ object ProtectedResource { def apply[F[_], U](handler: ProtectedResourceHandler[F, U]): ProtectedResource[F, U] = new ProtectedResource[F, U](handler) } class ProtectedResource[F[_], U](handler: ProtectedResourceHandler[F, U]) { val fetchers = Set(RequestParameter, AuthHeader) def authorize( request: ProtectedResourceRequest )(implicit F: Sync[F]): EitherT[F, OAuthError, AuthInfo[U]] = for { result <- EitherT.fromEither[F]( fetchers .find { fetcher => fetcher.matches(request) } .toRight(InvalidRequest("Access token is not found")) .flatMap(x => x.fetch(request)) ) token <- EitherT[F, OAuthError, AccessToken]( handler.findAccessToken(result.token).map(_.toRight[OAuthError](InvalidToken("The access token is not found"))) ) _ <- EitherT(token.isExpired.map(expired => Either.cond(!expired, (), ExpiredToken))) authInfo <- EitherT[F, OAuthError, AuthInfo[U]]( handler.findAuthInfoByAccessToken(token).map(_.toRight[OAuthError](InvalidToken("The access token is invalid"))) ) } yield authInfo }
Example 58
Source File: OptionalDependencyTest.scala From hotpotato with Apache License 2.0 | 5 votes |
import org.scalatest.wordspec.AnyWordSpec import hotpotato._ import cats.data.EitherT import cats.implicits._ import cats.effect.{IO => CatsIO} import zio.{IO => ZIOIO} class OptionalDependencyTest extends AnyWordSpec { "Cats EitherT" should { "have ErrorTrans instance" in { val _ = implicitly[ErrorTrans[EitherT[Option, *, *]]] } "have ErrorTransThrow instance" in { val _ = implicitly[ErrorTransThrow[EitherT[CatsIO, *, *]]] } } "ZIO IO" should { "have ErrorTrans instance" in { val _ = implicitly[ErrorTrans[ZIOIO]] } "have ErrorTransThrow instance" in { val _ = implicitly[ErrorTransThrow[ZIOIO]] } } }
Example 59
Source File: IOTest.scala From cats-effect-testing with Apache License 2.0 | 5 votes |
package cats.effect.testing.scalatest.scalacheck import cats.data.EitherT import cats.effect.testing.scalatest.AsyncIOSpec import cats.effect.{IO, Sync} import org.scalatest.matchers.should.Matchers import org.scalatest.freespec.AsyncFreeSpec import org.scalatestplus.scalacheck.{CheckerAsserting, ScalaCheckPropertyChecks} class IOTest extends AsyncFreeSpec with AsyncIOSpec with Matchers with ScalaCheckPropertyChecks { "Scalacheck IO assertions" - { "Assert success" in { forAll { (l1: List[Int], l2: List[Int]) => IO.delay(l1.size + l2.size shouldBe (l1 ::: l2).size) } } "Assert exception" in { val check: IO[Unit] = forAll { (l1: List[Int], l2: List[Int]) => IO.delay(l1.size + l2.size shouldBe -1) } check.assertThrows[Exception] } implicit def ioCheckingAsserting[A]: CheckerAsserting[IO[A]] { type Result = IO[Unit] } = new EffectCheckerAsserting } "Scalacheck EitherT[IO, Throwable, A] assertions" - { type Eff[A] = EitherT[IO, Throwable, A] "Assert success" in { val check = forAll { (l1: List[Int], l2: List[Int]) => Sync[Eff].delay(l1.size + l2.size shouldBe (l1 ::: l2).size) } check.leftSemiflatMap[Unit](IO.raiseError).merge.assertNoException } "Assert exception" in { val check = forAll { (l1: List[Int], l2: List[Int]) => Sync[Eff].delay(l1.size + l2.size shouldBe -1) } check.leftSemiflatMap[Unit](IO.raiseError[Unit]).merge.assertThrows[Exception] } implicit def checkingAsserting[A]: CheckerAsserting[Eff[A]] { type Result = Eff[Unit] } = new EffectCheckerAsserting } }
Example 60
Source File: EitherTValues.scala From guardrail with MIT License | 5 votes |
package tests.scalatest import cats.Functor import cats.data.EitherT import org.scalactic.source import org.scalatest._ import org.scalatest.exceptions.{ StackDepthException, TestFailedException } import scala.language.higherKinds import scala.language.implicitConversions trait EitherTValues { implicit def convertEitherTToValuable[F[_]: Functor, L, R](eitherT: EitherT[F, L, R]) = new EitherTValuable(eitherT) class EitherTValuable[F[_]: Functor, L, R](eitherT: EitherT[F, L, R]) { def leftValue(implicit pos: source.Position): F[L] = eitherT.fold(identity, { _ => throw new TestFailedException((_: StackDepthException) => Option.empty[String], Option.empty[Throwable], pos) }) def rightValue(implicit pos: source.Position): F[R] = eitherT.fold({ _ => throw new TestFailedException((_: StackDepthException) => Option.empty[String], Option.empty[Throwable], pos) }, identity) } }
Example 61
Source File: EitherTValues.scala From guardrail with MIT License | 5 votes |
package tests.scalatest import cats.Functor import cats.data.EitherT import org.scalactic.source import org.scalatest._ import org.scalatest.exceptions.{ StackDepthException, TestFailedException } import scala.language.higherKinds import scala.language.implicitConversions trait EitherTValues { implicit def convertEitherTToValuable[F[_]: Functor, L, R](eitherT: EitherT[F, L, R]) = new EitherTValuable(eitherT) class EitherTValuable[F[_]: Functor, L, R](eitherT: EitherT[F, L, R]) { def leftValue(implicit pos: source.Position): F[L] = eitherT.fold(identity, { _ => throw new TestFailedException((_: StackDepthException) => Option.empty[String], Option.empty[Throwable], pos) }) def rightValue(implicit pos: source.Position): F[R] = eitherT.fold({ _ => throw new TestFailedException((_: StackDepthException) => Option.empty[String], Option.empty[Throwable], pos) }, identity) } }
Example 62
Source File: EitherTValues.scala From guardrail with MIT License | 5 votes |
package tests.scalatest import cats.Functor import cats.data.EitherT import org.scalactic.source import org.scalatest._ import org.scalatest.exceptions.{ StackDepthException, TestFailedException } import scala.language.higherKinds import scala.language.implicitConversions trait EitherTValues { implicit def convertEitherTToValuable[F[_]: Functor, L, R](eitherT: EitherT[F, L, R]) = new EitherTValuable(eitherT) class EitherTValuable[F[_]: Functor, L, R](eitherT: EitherT[F, L, R]) { def leftValue(implicit pos: source.Position): F[L] = eitherT.fold(identity, { _ => throw new TestFailedException((_: StackDepthException) => Option.empty[String], Option.empty[Throwable], pos) }) def rightValue(implicit pos: source.Position): F[R] = eitherT.fold({ _ => throw new TestFailedException((_: StackDepthException) => Option.empty[String], Option.empty[Throwable], pos) }, identity) } }
Example 63
Source File: ExtendedController.scala From bay-scalajs.g8 with Apache License 2.0 | 5 votes |
package controllers import cats.data.EitherT import play.api.data.Form import play.api.mvc.Controller import play.api.mvc.Request import play.api.mvc.Result import shared.utils.Codecs import shared.utils.Implicits import cats.syntax.either._ import play.api.i18n.MessagesApi import services.Services import scala.concurrent.ExecutionContext import scala.concurrent.Future trait ExtendedController extends Controller with Implicits with Codecs { val services: Services implicit val ec: ExecutionContext type HttpResult[A] = EitherT[Future, Result, A] // Constructors for our result type object HttpResult { def point[A](a: A): HttpResult[A] = EitherT[Future, Result, A](Future.successful(Right(a))) def fromFuture[A](fa: Future[A]): HttpResult[A] = EitherT[Future, Result, A](fa.map(Right(_))) def fromEither[A](va: Either[Result, A]): HttpResult[A] = EitherT[Future, Result, A](Future.successful(va)) def fromEither[A, B](failure: B => Result)(va: Either[B, A]): HttpResult[A] = EitherT[Future, Result, A](Future.successful(va.leftMap(failure))) def fromOption[A](failure: Result)(oa: Option[A]): HttpResult[A] = EitherT[Future, Result, A](Future.successful(oa.toRight(failure))) def fromFOption[A](failure: Result)(foa: Future[Option[A]]): HttpResult[A] = EitherT[Future, Result, A](foa.map(_.toRight(failure))) def fromFEither[A, B](failure: B => Result)(fva: Future[Either[B, A]]): HttpResult[A] = EitherT[Future, Result, A](fva.map(_.leftMap(failure))) def fromForm[FormType](failure: Form[FormType] => Result)(form: Form[FormType])( implicit request: Request[_]): HttpResult[FormType] = EitherT[Future, Result, FormType]( form.bindFromRequest.fold(errorForm => Left(failure(errorForm)).asFuture, formEntity => Right(formEntity).asFuture)) } def constructResult(result: HttpResult[Result]): Future[Result] = result.value.map(_.merge) implicit class ExtResult(e: Result) { def pureResult: HttpResult[Result] = EitherT[Future, Result, Result](Future.successful(Right(e))) } implicit class EnrichedOps[T](t: T) { def |>[R](f: T => R): R = f(t) } def messagesApi: MessagesApi = services.messagesApi }
Example 64
Source File: SchemaTest.scala From shaclex with MIT License | 5 votes |
package es.weso.schema import es.weso.rdf.jena.RDFAsJenaModel import es.weso.rdf.nodes.{ IRI, RDFNode } import org.scalatest._ import matchers.should._ import funspec._ import cats.data.EitherT import cats.effect._ import es.weso.utils.IOUtils._ class SchemaTest extends AnyFunSpec with Matchers with EitherValues { describe("Simple schema") { it("Validates a simple Schema using ShEx") { val schema = """|prefix : <http://example.org/> |:S { :p . } |""".stripMargin val data = """|prefix : <http://example.org/> |prefix sh: <http://www.w3.org/ns/shacl#> |:x :p 1 . |:S sh:targetNode :x . |""".stripMargin val schemaFormat = "SHEXC" val dataFormat = "TURTLE" val triggerMode = "TARGETDECLS" val schemaEngine = "SHEX" val node: RDFNode = IRI("http://example.org/x") val shape: SchemaLabel = SchemaLabel(IRI("http://example.org/S")) val tryResult: EitherT[IO, String, Result] = for { schema <- Schemas.fromString(schema, schemaFormat, schemaEngine, None) rdf <- io2es(RDFAsJenaModel.fromString(data, dataFormat)) result <- io2es(schema.validate(rdf, triggerMode, "", None, None, schema.pm)) } yield result tryResult.value.unsafeRunSync match { case Right(result) => { info(s"Result: ${result.serialize(Result.TEXT)}") info(s"Result solution: ${result.solution}") result.isValid should be(true) result.hasShapes(node) should contain only (shape) } case Left(e) => fail(s"Error trying to validate: $e") } } it("fails to validate a wrong SHACL validation") { val data = """ |@prefix : <http://example.org/> . |@prefix sh: <http://www.w3.org/ns/shacl#> . |@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . | |:User a sh:NodeShape , rdfs:Class ; | sh:nodeKind sh:BlankNode . |:alice a :User . """.stripMargin val eitherResult = for { schema <- Schemas.fromString(data,"TURTLE","SHACLEX",None) rdf <- io2es(RDFAsJenaModel.fromString(data,"TURTLE",None)) result <- io2es(schema.validate(rdf,"TargetDecls","",None,None,rdf.getPrefixMap,schema.pm)) } yield result eitherResult.value.unsafeRunSync.fold(e => fail(s"Error: $e"), result => { result.isValid should be(false) }) } } }
Example 65
Source File: Schema.scala From shaclex with MIT License | 5 votes |
package es.weso.schema import es.weso.rdf._ import es.weso.rdf.nodes._ import es.weso.shapeMaps.ShapeMap import es.weso.utils.FileUtils import cats.effect._ import cats.data.EitherT //import util._ abstract class Schema { /** * Name of this schema. Example: ShEx, Shacl_TQ, ... */ def name: String /** * Supported input formats */ def formats: Seq[String] def validate(rdf: RDFReader, trigger: ValidationTrigger): IO[Result] def validate( rdf: RDFReader, triggerMode: String, shapeMap: String, optNode: Option[String], optShape: Option[String], nodePrefixMap: PrefixMap = PrefixMap.empty, shapesPrefixMap: PrefixMap = pm): IO[Result] = { val base = Some(FileUtils.currentFolderURL) ValidationTrigger.findTrigger(triggerMode, shapeMap, base, optNode, optShape, nodePrefixMap, shapesPrefixMap) match { case Left(err) => { IO(Result.errStr(s"Cannot get trigger: $err. TriggerMode: $triggerMode, prefixMap: $pm")) } case Right(trigger) => validate(rdf, trigger) } } def fromString(cs: CharSequence, format: String, base: Option[String]): EitherT[IO, String, Schema] def fromRDF(rdf: RDFReader): EitherT[IO, String, Schema] def serialize(format: String, base: Option[IRI] = None): IO[String] def defaultFormat: String = formats.head def defaultTriggerMode: ValidationTrigger /** * Creates an empty schema */ def empty: Schema /** * List of shapes */ def shapes: List[String] /** * Prefix Map of this schema */ def pm: PrefixMap def convert(targetFormat: Option[String], targetEngine: Option[String], base: Option[IRI] ): EitherT[IO,String,String] def info: SchemaInfo def toClingo(rdf: RDFReader, shapeMap: ShapeMap): EitherT[IO,String,String] }
Example 66
Source File: Schemas.scala From shaclex with MIT License | 5 votes |
package es.weso.schema import java.io.File import util._ import cats.effect._ import cats.data.EitherT import es.weso.rdf.RDFReader import es.weso.utils.FileUtils._ object Schemas { type SchemaParser = (CharSequence, String, Option[String]) => EitherT[IO, String, Schema] lazy val shEx: Schema = ShExSchema.empty lazy val shaclex : Schema = ShaclexSchema.empty // lazy val shacl_tq = Shacl_TQ.empty val availableSchemas: List[Schema] = List(shEx, shaclex) // shEx,shaclex) //,shacl_tq) val defaultSchema: Schema = shEx val defaultSchemaName: String = defaultSchema.name val defaultSchemaFormat: String = defaultSchema.defaultFormat val availableSchemaNames: List[String] = availableSchemas.map(_.name) val availableFormats: List[String] = { availableSchemas.map(_.formats).flatten.distinct } val availableTriggerModes: List[String] = { ValidationTrigger.triggerValues.map(_._1) } val defaultTriggerMode: String = ValidationTrigger.default.name def lookupSchema(schemaName: String): Either[String, Schema] = { if (schemaName == "") Right(defaultSchema) else { val found = availableSchemas.filter(_.name.compareToIgnoreCase(schemaName) == 0) if (found.isEmpty) Left(s"Schema $schemaName not found. Available schemas: ${availableSchemaNames.mkString(",")}") else Right(found.head) } } def getSchemaParser(schemaName: String): EitherT[IO, String, SchemaParser] = for { schema <- EitherT.fromEither[IO](lookupSchema(schemaName)) parser = schema.fromString _ } yield parser val schemaNames: List[String] = availableSchemas.map(_.name) def fromFile( file: File, format: String, schemaName: String, base: Option[String] = None): EitherT[IO, String, Schema] = for { cs <- getContents(file) schema <- fromString(cs, format, schemaName, base) } yield schema def fromString( cs: CharSequence, format: String, schemaName: String, base: Option[String] = None): EitherT[IO, String, Schema] = for { schema <- EitherT.fromEither[IO](lookupSchema(schemaName)) schemaParsed <- if (cs.length == 0) EitherT.pure[IO,String](schema.empty) else schema.empty.fromString(cs, format, base) } yield schemaParsed def fromRDF(rdf: RDFReader, schemaName: String): EitherT[IO, String, Schema] = { for { defaultSchema <- EitherT.fromEither[IO](lookupSchema(schemaName)) schema <- defaultSchema.fromRDF(rdf) } yield schema } def fromRDFIO(rdf: RDFReader, schemaName: String): IO[Schema] = lookupSchema(schemaName) match { case Left(s) => IO.raiseError(new RuntimeException(s"fromRDFIO: Cannot obtain default schema ${schemaName}: $s")) case Right(defaultSchema) => defaultSchema.fromRDF(rdf).value.flatMap(either => either.fold( s => IO.raiseError(new RuntimeException(s"fromRDFIO: Error obtaining schema ${schemaName}: $s")), schema => IO(schema) )) } }
Example 67
Source File: ErrorTransInstanceSpec.scala From hotpotato with Apache License 2.0 | 5 votes |
package hotpotato import cats.Eq import cats.data.EitherT import cats.implicits._ import cats.laws.discipline.arbitrary._ import hotpotato.ErrorTransInstanceSpec.SimpleError import hotpotato.laws.{ErrorTransTests, ErrorTransThrowTests} import org.scalacheck.Arbitrary import org.scalatest.funsuite.AnyFunSuite import org.typelevel.discipline.scalatest.Discipline class ErrorTransInstanceSpec extends AnyFunSuite with Discipline { checkAll( "Either.ErrorTransLaws", ErrorTransTests[Either[*, *]].errorTrans[Int, Int, Int, String, String, String], ) checkAll( "EitherT.ErrorTransLaws", ErrorTransTests[EitherT[Option, *, *]].errorTrans[Int, Int, Int, String, String, String], ) // Cheat a little bit by only generating only one type of throwable private implicit val arbThrowable: Arbitrary[Throwable] = Arbitrary( Arbitrary.arbitrary[String].map(SimpleError).map(x => x: Throwable), ) private implicit val eqThrowable: Eq[Throwable] = new Eq[Throwable] { override def eqv(x: Throwable, y: Throwable): Boolean = x == y } checkAll( "EitherT.ErrorTransThrowLaws", ErrorTransThrowTests[EitherT[Either[Throwable, *], *, *]] .errorTransThrow[Int, Int, Int, String, String, String], ) } object ErrorTransInstanceSpec { final case class SimpleError(message: String) extends Exception(message) }
Example 68
Source File: GlobalConfig.scala From sonar-scala with GNU Lesser General Public License v3.0 | 5 votes |
package com.mwz.sonar.scala import cats.data.EitherT import cats.instances.option._ import cats.instances.string._ import cats.syntax.alternative._ import cats.syntax.either._ import cats.syntax.eq._ import cats.syntax.functor._ import com.mwz.sonar.scala.GlobalConfig._ import com.mwz.sonar.scala.util.syntax.Optionals._ import com.mwz.sonar.scala.util.syntax.SonarConfig._ import org.http4s.{ParseFailure, ParseResult, Uri} import org.sonar.api.CoreProperties import org.sonar.api.batch.{InstantiationStrategy, ScannerSide} import org.sonar.api.config.Configuration @SuppressWarnings(Array("IncorrectlyNamedExceptions")) final case class ConfigError(error: String) extends Exception // TODO: Both @ScannerSide and @InstantiationStrategy are deprecated, we should switch // to the org.sonar.api.scanner.ScannerSide in the future. @ScannerSide @InstantiationStrategy(InstantiationStrategy.PER_BATCH) final class GlobalConfig(config: Configuration) { val baseUrl: ConfigErrorOr[Uri] = config .get(CoreProperties.SERVER_BASE_URL) .toOption .orElse(config.get("sonar.host.url").toOption) .fold[ParseResult[Uri]]( Left( ParseFailure( "Missing SonarQube base URI - please configure the server base URL in your SonarQube instance or set the 'sonar.host.url' property.", "" ) ) )(Uri.fromString) .leftMap(f => ConfigError(f.sanitized)) val pullRequest: EitherT[Option, ConfigError, PullRequest] = getPullRequest final case class PullRequest( provider: String, prNumber: String, github: Github, disableIssues: Boolean, disableInlineComments: Boolean, disableCoverage: Boolean, dryRun: Boolean ) final case class Github( apiuri: Uri = DEFAULT_GITHUB_API_URI, repository: String, oauth: String ) }
Example 69
Source File: package.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.kg import akka.http.scaladsl.model.StatusCode import akka.http.scaladsl.server.Directives.complete import akka.http.scaladsl.server.{MalformedQueryParamRejection, Route} import cats.Functor import cats.data.{EitherT, OptionT} import cats.instances.future._ import ch.epfl.bluebrain.nexus.iam.types.Permission import ch.epfl.bluebrain.nexus.kg.marshallers.instances._ import ch.epfl.bluebrain.nexus.kg.resources.Rejection.NotFound.notFound import ch.epfl.bluebrain.nexus.kg.resources.{Ref, Rejection, ResourceV} import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.{DOT, Triples} import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri import monix.execution.Scheduler.Implicits.global import scala.concurrent.Future package object routes { private[routes] def completeWithFormat( fetched: Future[Either[Rejection, (StatusCode, ResourceV)]] )(implicit format: NonBinaryOutputFormat): Route = completeWithFormat(EitherT(fetched)) private def completeWithFormat( fetched: EitherT[Future, Rejection, (StatusCode, ResourceV)] )(implicit format: NonBinaryOutputFormat): Route = format match { case f: JsonLDOutputFormat => implicit val format = f complete(fetched.value) case Triples => implicit val format = Triples complete(fetched.map { case (status, resource) => status -> resource.value.graph.ntriples }.value) case DOT => implicit val format = DOT complete(fetched.map { case (status, resource) => status -> resource.value.graph.dot() }.value) } private[routes] val read: Permission = Permission.unsafe("resources/read") private[routes] val schemaError = MalformedQueryParamRejection("schema", "The provided schema does not match the schema on the Uri") implicit private[routes] class FOptionSyntax[F[_], A](private val fOpt: F[Option[A]]) extends AnyVal { def toNotFound(id: AbsoluteIri)(implicit F: Functor[F]): EitherT[F, Rejection, A] = OptionT(fOpt).toRight(notFound(Ref(id))) } }
Example 70
Source File: BroccoliMessageHandlerSpec.scala From cluster-broccoli with Apache License 2.0 | 5 votes |
package de.frosner.broccoli.websocket import cats.data.EitherT import cats.instances.future._ import de.frosner.broccoli.auth.Account import de.frosner.broccoli.instances.NomadInstances import de.frosner.broccoli.models._ import de.frosner.broccoli.nomad import de.frosner.broccoli.services.InstanceService import org.scalacheck.Gen import org.specs2.ScalaCheck import org.specs2.concurrent.ExecutionEnv import org.specs2.mock.Mockito import org.specs2.mutable.Specification import scala.concurrent.Future class BroccoliMessageHandlerSpec extends Specification with ScalaCheck with Mockito with nomad.ModelArbitraries with ModelArbitraries { "The Broccoli Message Handler" should { "send back instance tasks" in { implicit ee: ExecutionEnv => prop { (account: Account, id: String, tasks: List[AllocatedTask], periodicRunTasks: Map[String, List[AllocatedTask]]) => val instances = mock[NomadInstances] val instanceTasks = InstanceTasks(id, tasks, periodicRunTasks) instances.getInstanceTasks(account)(id) returns EitherT.pure[Future, InstanceError](instanceTasks) val outgoingMessage = new BroccoliMessageHandler(instances, mock[InstanceService]) .processMessage(account)(IncomingMessage.GetInstanceTasks(id)) outgoingMessage must beEqualTo(OutgoingMessage.GetInstanceTasksSuccess(instanceTasks)).await }.setGen2(Gen.identifier) } "send back an error if instance tasks failed" in { implicit ee: ExecutionEnv => prop { (account: Account, id: String, error: InstanceError) => val instances = mock[NomadInstances] instances.getInstanceTasks(account)(id) returns EitherT.leftT[Future, InstanceTasks](error) val outgoingMessage = new BroccoliMessageHandler(instances, mock[InstanceService]) .processMessage(account)(IncomingMessage.GetInstanceTasks(id)) outgoingMessage must beEqualTo(OutgoingMessage.GetInstanceTasksError(id, error)).await }.setGen2(Gen.identifier) } } }
Example 71
Source File: SecurityController.scala From cluster-broccoli with Apache License 2.0 | 5 votes |
package de.frosner.broccoli.controllers import javax.inject.Inject import cats.data.{EitherT, OptionT} import cats.instances.future._ import cats.syntax.either._ import com.mohiva.play.silhouette.api.util.Credentials import com.mohiva.play.silhouette.impl.providers.CredentialsProvider import de.frosner.broccoli.services.{SecurityService, WebSocketService} import jp.t2v.lab.play2.auth.{BroccoliSimpleAuthorization, LoginLogout} import play.api.{Environment, Logger} import play.api.cache.CacheApi import play.api.data.Forms._ import play.api.data._ import play.api.libs.json.Json import play.api.mvc.{Action, AnyContent, Controller, Results} import scala.concurrent.Future case class SecurityController @Inject()( override val securityService: SecurityService, override val cacheApi: CacheApi, override val playEnv: Environment, webSocketService: WebSocketService ) extends Controller with LoginLogout with BroccoliSimpleAuthorization { private val log = Logger(getClass) import scala.concurrent.ExecutionContext.Implicits.global // https://www.playframework.com/documentation/2.5.x/ScalaForms val loginForm = Form { mapping( SecurityController.UsernameFormKey -> text, SecurityController.PasswordFormKey -> text )(Credentials.apply)(Credentials.unapply) } def login: Action[AnyContent] = Action.async { implicit request => getSessionId(request).map(id => (id, webSocketService.closeConnections(id))) match { case Some((id, true)) => log.info(s"Removing websocket connection of $id due to another login") case _ => } (for { credentials <- EitherT.fromEither[Future]( loginForm.bindFromRequest().fold(Function.const(Results.BadRequest.asLeft), _.asRight)) login <- OptionT(securityService.authenticate(credentials)).toRight(Results.Unauthorized) result <- EitherT.right(gotoLoginSucceeded(login.providerKey)) user <- OptionT(resolveUser(login.providerKey)).toRight(Results.Unauthorized) } yield { val userResult = Results.Ok(Json.toJson(user)) result.copy( header = result.header.copy( headers = userResult.header.headers .get("Content-Type") .map { contentType => result.header.headers.updated("Content-Type", contentType) } .getOrElse(result.header.headers) ), body = userResult.body ) }).merge } def logout = Action.async(parse.empty) { implicit request => gotoLogoutSucceeded.andThen { case tryResult => getSessionId(request).map(id => (id, webSocketService.closeConnections(id))) match { case Some((id, true)) => log.info(s"Removing websocket connection of $id due to logout") case Some((id, false)) => log.info(s"There was no websocket connection for session $id") case None => log.info(s"No session available to logout from") } } } def verify = StackAction(parse.empty) { implicit request => Ok(loggedIn.name) } } object SecurityController { val UsernameFormKey = "username" val PasswordFormKey = "password" }
Example 72
Source File: WebSocketController.scala From cluster-broccoli with Apache License 2.0 | 5 votes |
package de.frosner.broccoli.controllers import javax.inject.Inject import cats.data.EitherT import cats.instances.future._ import de.frosner.broccoli.services.WebSocketService.Msg import de.frosner.broccoli.services._ import de.frosner.broccoli.websocket.{IncomingMessage, OutgoingMessage, WebSocketMessageHandler} import jp.t2v.lab.play2.auth.BroccoliWebsocketSecurity import play.api.cache.CacheApi import play.api.libs.concurrent.Execution.Implicits._ import play.api.libs.iteratee._ import play.api.libs.json._ import play.api.mvc._ import play.api.{Environment, Logger} import scala.concurrent.Future case class WebSocketController @Inject()(webSocketService: WebSocketService, templateService: TemplateService, instanceService: InstanceService, aboutService: AboutInfoService, messageHandler: WebSocketMessageHandler, override val cacheApi: CacheApi, override val playEnv: Environment, override val securityService: SecurityService) extends Controller with BroccoliWebsocketSecurity { protected val log = Logger(getClass) def requestToSocket(request: RequestHeader): Future[Either[Result, (Iteratee[Msg, _], Enumerator[Msg])]] = withSecurity(request) { (maybeToken, user, request) => val (connectionId, connectionEnumerator) = maybeToken match { case Some(token) => (token, webSocketService.newConnection(token, user)) // auth is enabled and we can use the session ID case None => webSocketService.newConnection(user) // no session ID available so we generate one } val connectionLogString = s"$connectionId by $user from ${request.remoteAddress} at $request" log.info(s"New connection $connectionLogString") // TODO receive string and try json decoding here because I can handle the error better val in = Enumeratee.mapM[Msg] { incomingMessage => EitherT .fromEither(Json.fromJson[IncomingMessage](incomingMessage).asEither) .leftMap[OutgoingMessage] { jsonErrors => log.warn(s"Can't parse a message from $connectionId: $jsonErrors") OutgoingMessage.Error(s"Failed to parse message message: $jsonErrors") } .semiflatMap { incomingMessage => // Catch all exceptions from the message handler and map them to a generic error message to send over the // websocket, to prevent the Enumeratee from stopping at the failure, causing the websocket to be closed and // preventing all future messages. messageHandler.processMessage(user)(incomingMessage).recover { case exception => log.error(s"Message handler threw exception for message $incomingMessage: ${exception.getMessage}", exception) OutgoingMessage.Error("Unexpected error in message handler") } } .merge } transform Iteratee .foreach[OutgoingMessage](msg => webSocketService.send(connectionId, Json.toJson(msg))) .map { _ => webSocketService.closeConnections(connectionId) log.info(s"Closed connection $connectionLogString") } val aboutEnumerator = Enumerator[Msg](Json.toJson(OutgoingMessage.AboutInfoMsg(AboutController.about(aboutService, user)))) val templateEnumerator = Enumerator[Msg]( Json.toJson( OutgoingMessage.ListTemplates(TemplateController.list(templateService)) )) val instanceEnumerator = Enumerator[Msg]( Json.toJson(OutgoingMessage.ListInstances(InstanceController.list(None, user, instanceService)))) (in, aboutEnumerator.andThen(templateEnumerator).andThen(instanceEnumerator).andThen(connectionEnumerator)) } def socket: WebSocket = WebSocket.tryAccept[Msg](requestToSocket) }
Example 73
Source File: SecurityService.scala From cluster-broccoli with Apache License 2.0 | 5 votes |
package de.frosner.broccoli.services import javax.inject.{Inject, Singleton} import cats.data.{EitherT, OptionT} import cats.instances.future._ import cats.syntax.either._ import com.mohiva.play.silhouette.api.LoginInfo import com.mohiva.play.silhouette.api.services.IdentityService import com.mohiva.play.silhouette.api.util.Credentials import com.mohiva.play.silhouette.impl.exceptions.{IdentityNotFoundException, InvalidPasswordException} import com.mohiva.play.silhouette.impl.providers.CredentialsProvider import de.frosner.broccoli.auth.{Account, AuthConfiguration, AuthMode} import scala.concurrent.{ExecutionContext, Future} sealed trait LoginError object LoginError { final case object InvalidPassword extends LoginError final case object UnknownUser extends LoginError final case object Locked extends LoginError } @Singleton() case class SecurityService @Inject()( configuration: AuthConfiguration, credentialsProvider: CredentialsProvider, identityService: IdentityService[Account] )(implicit ec: ExecutionContext) { private val log = play.api.Logger(getClass) val sessionTimeoutInSeconds: Int = configuration.session.timeout.toSeconds.toInt val allowedFailedLogins: Int = configuration.allowedFailedLogins val authMode: AuthMode = configuration.mode val cookieSecure: Boolean = configuration.cookie.secure val allowMultiLogin: Boolean = configuration.session.allowMultiLogin @volatile private var failedLoginAttempts: Map[String, Int] = Map.empty def authenticate(credentials: Credentials): Future[Option[LoginInfo]] = EitherT .rightT(credentials) .ensure(LoginError.Locked)(c => failedLoginAttempts.getOrElse(c.identifier, 0) <= allowedFailedLogins) .flatMapF(credentialsProvider.authenticate(_).map(_.asRight).recover { case _: InvalidPasswordException => LoginError.InvalidPassword.asLeft case _: IdentityNotFoundException => LoginError.UnknownUser.asLeft }) .leftMap { error => // Login if an account was locked val attempts = failedLoginAttempts.getOrElse(credentials.identifier, 0) if (error == LoginError.Locked) { log.warn( s"Credentials for '${credentials.identifier}' exceeded the allowed number of failed logins: " + s"$allowedFailedLogins (has $attempts)") } // Track the failed attempt failedLoginAttempts = failedLoginAttempts.updated(credentials.identifier, attempts + 1) error } .toOption .value }
Example 74
Source File: PoiExtract.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.extract.poi import java.io.{ByteArrayInputStream, InputStream} import scala.util.Try import cats.data.EitherT import cats.effect.Sync import cats.implicits._ import fs2.Stream import docspell.common._ import docspell.extract.internal.Text import docspell.files.TikaMimetype import org.apache.poi.hssf.extractor.ExcelExtractor import org.apache.poi.hssf.usermodel.HSSFWorkbook import org.apache.poi.hwpf.extractor.WordExtractor import org.apache.poi.xssf.extractor.XSSFExcelExtractor import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.apache.poi.xwpf.extractor.XWPFWordExtractor import org.apache.poi.xwpf.usermodel.XWPFDocument object PoiExtract { def get[F[_]: Sync]( data: Stream[F, Byte], hint: MimeTypeHint ): F[Either[Throwable, Text]] = TikaMimetype.detect(data, hint).flatMap(mt => get(data, mt)) def get[F[_]: Sync]( data: Stream[F, Byte], mime: MimeType ): F[Either[Throwable, Text]] = mime match { case PoiType.doc => getDoc(data) case PoiType.xls => getXls(data) case PoiType.xlsx => getXlsx(data) case PoiType.docx => getDocx(data) case PoiType.msoffice => EitherT(getDoc[F](data)) .recoverWith({ case _ => EitherT(getXls[F](data)) }) .value case PoiType.ooxml => EitherT(getDocx[F](data)) .recoverWith({ case _ => EitherT(getXlsx[F](data)) }) .value case mt => Sync[F].pure(Left(new Exception(s"Unsupported content: ${mt.asString}"))) } def getDocx(is: InputStream): Either[Throwable, Text] = Try { val xt = new XWPFWordExtractor(new XWPFDocument(is)) Text(Option(xt.getText)) }.toEither def getDoc(is: InputStream): Either[Throwable, Text] = Try { val xt = new WordExtractor(is) Text(Option(xt.getText)) }.toEither def getXlsx(is: InputStream): Either[Throwable, Text] = Try { val xt = new XSSFExcelExtractor(new XSSFWorkbook(is)) Text(Option(xt.getText)) }.toEither def getXls(is: InputStream): Either[Throwable, Text] = Try { val xt = new ExcelExtractor(new HSSFWorkbook(is)) Text(Option(xt.getText)) }.toEither def getDocx[F[_]: Sync](data: Stream[F, Byte]): F[Either[Throwable, Text]] = data.compile.to(Array).map(new ByteArrayInputStream(_)).map(getDocx) def getDoc[F[_]: Sync](data: Stream[F, Byte]): F[Either[Throwable, Text]] = data.compile.to(Array).map(new ByteArrayInputStream(_)).map(getDoc) def getXlsx[F[_]: Sync](data: Stream[F, Byte]): F[Either[Throwable, Text]] = data.compile.to(Array).map(new ByteArrayInputStream(_)).map(getXlsx) def getXls[F[_]: Sync](data: Stream[F, Byte]): F[Either[Throwable, Text]] = data.compile.to(Array).map(new ByteArrayInputStream(_)).map(getXls) }
Example 75
Source File: EnvelopeDecoderSpec.scala From fs2-rabbit with Apache License 2.0 | 5 votes |
package dev.profunktor.fs2rabbit.effects import java.nio.charset.StandardCharsets import cats.data.EitherT import cats.effect.{IO, SyncIO} import cats.instances.either._ import cats.instances.try_._ import dev.profunktor.fs2rabbit.model.{AmqpEnvelope, AmqpProperties, DeliveryTag, ExchangeName, RoutingKey} import org.scalatest.funsuite.AsyncFunSuite import scala.util.Try class EnvelopeDecoderSpec extends AsyncFunSuite { // Available instances of EnvelopeDecoder for any ApplicativeError[F, Throwable] EnvelopeDecoder[Either[Throwable, ?], String] EnvelopeDecoder[SyncIO, String] EnvelopeDecoder[EitherT[IO, String, ?], String] EnvelopeDecoder[Try, String] test("should decode a UTF-8 string") { val msg = "hello world!" val raw = msg.getBytes(StandardCharsets.UTF_8) EnvelopeDecoder[IO, String] .run( AmqpEnvelope(DeliveryTag(0L), raw, AmqpProperties.empty, ExchangeName("test"), RoutingKey("test.route"), false)) .flatMap { result => IO(assert(result == msg)) } .unsafeToFuture() } test("should decode payload with the given content encoding") { val msg = "hello world!" val raw = msg.getBytes(StandardCharsets.UTF_8) EnvelopeDecoder[IO, String] .run( AmqpEnvelope(DeliveryTag(0L), raw, AmqpProperties.empty.copy(contentEncoding = Some("UTF-16")), ExchangeName("test"), RoutingKey("test.route"), false)) .flatMap { result => IO(assert(result != msg)) } .unsafeToFuture() } test("should decode a UTF-16 string into a UTF-8 (default)") { val msg = "hello world!" val raw = msg.getBytes(StandardCharsets.UTF_16) EnvelopeDecoder[IO, String] .run( AmqpEnvelope(DeliveryTag(0L), raw, AmqpProperties.empty, ExchangeName("test"), RoutingKey("test.route"), false)) .flatMap { result => IO(assert(result != msg)) } .unsafeToFuture() } }
Example 76
Source File: autoApplyKTests.scala From cats-tagless with Apache License 2.0 | 5 votes |
package cats.tagless package tests import cats.Eq import cats.data.EitherT import cats.instances.all._ import cats.laws.discipline.SerializableTests import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ import cats.tagless.instances.all._ import cats.tagless.laws.discipline.ApplyKTests import cats.tagless.tests.autoApplyKTests.AutoApplyKTestAlg import org.scalacheck.Arbitrary import scala.util.Try class autoApplyKTests extends CatsTaglessTestSuite { // Type inference limitation. implicit val eqTuple3K = AutoApplyKTestAlg.eqForAutoApplyKTestAlg[Tuple3K[Try, Option, List]#λ] checkAll("ApplyK[AutoApplyKTestAlg]", ApplyKTests[AutoApplyKTestAlg].applyK[Try, Option, List, Int]) checkAll("ApplyK is Serializable", SerializableTests.serializable(ApplyK[AutoApplyKTestAlg])) } object autoApplyKTests { @autoApplyK(autoDerivation = false) trait AutoApplyKTestAlg[F[_]] { def parseInt(str: String): F[Int] def parseDouble(str: String): EitherT[F, String, Double] def divide(dividend: Float, divisor: Float): F[Float] } object AutoApplyKTestAlg { import TestInstances._ implicit def eqForAutoApplyKTestAlg[F[_]]( implicit eqFi: Eq[F[Int]], eqFf: Eq[F[Float]], eqEfd: Eq[EitherT[F, String, Double]] ): Eq[AutoApplyKTestAlg[F]] = Eq.by { algebra => (algebra.parseInt _, algebra.parseDouble _, algebra.divide _) } implicit def arbitraryAutoApplyKTestAlg[F[_]]( implicit arbFi: Arbitrary[F[Int]], arbFf: Arbitrary[F[Float]], arbEfd: Arbitrary[EitherT[F, String, Double]] ): Arbitrary[AutoApplyKTestAlg[F]] = Arbitrary { for { pInt <- Arbitrary.arbitrary[String => F[Int]] pDouble <- Arbitrary.arbitrary[String => EitherT[F, String, Double]] div <- Arbitrary.arbitrary[(Float, Float) => F[Float]] } yield new AutoApplyKTestAlg[F] { def parseInt(str: String) = pInt(str) def parseDouble(str: String) = pDouble(str) def divide(dividend: Float, divisor: Float) = div(dividend, divisor) } } } @autoApplyK trait AlgWithVarArgsParameter[F[_]] { def sum(xs: Int*): Int def fSum(xs: Int*): F[Int] } }