Skip to content

Commit

Permalink
refactor(domain/errors): rename sealed trait from Error to `Domai…
Browse files Browse the repository at this point in the history
…nError`
  • Loading branch information
yoshinorin committed Dec 1, 2024
1 parent 1b244f4 commit 3997cd2
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 39 deletions.
46 changes: 23 additions & 23 deletions src/main/scala/net/yoshinorin/qualtet/domains/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,113 +2,113 @@ package net.yoshinorin.qualtet.domains.errors

import net.yoshinorin.qualtet.http.ProblemDetailsError

sealed trait Error extends Exception
sealed trait DomainError extends Exception

final case class AuthorNotFound(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class ArticleNotFound(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class ContentNotFound(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class ContentTypeNotFound(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class SeriesNotFound(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class TagNotFound(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class Unauthorized(
detail: String = "Unauthorized", // NOTE: no-need to set error details for secure reason. set default value instead.
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidAuthorName(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidAuthorDisplayName(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidAttributes(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidAuthor(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidContentType(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidExternalResourceKind(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidSearchConditions(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class InvalidSeries(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class ContentTitleRequired(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class RawContentRequired(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class HtmlContentRequired(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class SeriesNameRequired(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class SeriesTitleRequired(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class UnexpectedJsonFormat(
detail: String,
errors: Option[Seq[ProblemDetailsError]] = None
) extends Error
) extends DomainError

final case class UnexpectedException(
detail: String = "Internal Server Error"
) extends Error
) extends DomainError
12 changes: 6 additions & 6 deletions src/main/scala/net/yoshinorin/qualtet/http/AuthProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.http4s.headers.Authorization
import org.slf4j.LoggerFactory
import net.yoshinorin.qualtet.domains.authors.ResponseAuthor
import net.yoshinorin.qualtet.auth.AuthService
import net.yoshinorin.qualtet.domains.errors.{AuthorNotFound, Error, Unauthorized}
import net.yoshinorin.qualtet.domains.errors.{AuthorNotFound, DomainError, Unauthorized}
import net.yoshinorin.qualtet.syntax.*

class AuthProvider[F[_]: Monad](
Expand All @@ -18,15 +18,15 @@ class AuthProvider[F[_]: Monad](
private val logger = LoggerFactory.getLogger(this.getClass)

// TODO: cleanup messy code
private def authUser: Kleisli[IO, Request[IO], Either[Error, (ResponseAuthor, String)]] =
private def authUser: Kleisli[IO, Request[IO], Either[DomainError, (ResponseAuthor, String)]] =
Kleisli({ request =>
request.headers.get[Authorization].asEither[Error](Unauthorized("Authorization header is none")) match {
case Left(f: Error) => IO(Left(f))
request.headers.get[Authorization].asEither[DomainError](Unauthorized("Authorization header is none")) match {
case Left(f: DomainError) => IO(Left(f))
case Right(auth: Authorization) =>
val renderString = auth.credentials.renderString.replace("Bearer ", "").replace("bearer ", "")
for {
maybeAuthor <- authService.findAuthorFromJwtString(renderString)
author <- IO(maybeAuthor.asEither[Error](AuthorNotFound(detail = "author not found")))
author <- IO(maybeAuthor.asEither[DomainError](AuthorNotFound(detail = "author not found")))
payload <- request.as[String]
} yield {
author match {
Expand All @@ -42,7 +42,7 @@ class AuthProvider[F[_]: Monad](
}
})

private def onFailure: AuthedRoutes[Error, IO] = Kleisli { req =>
private def onFailure: AuthedRoutes[DomainError, IO] = Kleisli { req =>
OptionT.pure[IO](Response[IO](status = Status.Unauthorized))
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/net/yoshinorin/qualtet/http/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final case class InternalServerError(
) extends HttpError

object HttpError {
def fromDomainError(e: Error): HttpError = {
def fromDomainError(e: DomainError): HttpError = {
e match {
case e: AuthorNotFound => NotFound(detail = e.detail, errors = e.errors)
case e: ArticleNotFound => NotFound(detail = e.detail, errors = e.errors)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package net.yoshinorin.qualtet.http

import com.github.plokhotnyuk.jsoniter_scala.core.*
import net.yoshinorin.qualtet.domains.Request
import net.yoshinorin.qualtet.domains.errors.{Error, UnexpectedException, UnexpectedJsonFormat}
import net.yoshinorin.qualtet.domains.errors.{DomainError, UnexpectedException, UnexpectedJsonFormat}
import net.yoshinorin.qualtet.syntax.*
import org.slf4j.LoggerFactory

Expand All @@ -12,14 +12,14 @@ trait RequestDecoder {

private val logger = LoggerFactory.getLogger(this.getClass)

def decode[T <: Request[T]](maybeJsonString: String): JsonValueCodec[T] ?=> Either[Error, T] = {
def decode[T <: Request[T]](maybeJsonString: String): JsonValueCodec[T] ?=> Either[DomainError, T] = {
try {
Right(maybeJsonString.decode.postDecode)
} catch {
case NonFatal(t) =>
logger.error(t.getMessage())
t match {
case t: Error => Left(t)
case t: DomainError => Left(t)
case t: JsonReaderException =>
// TODO: consider error message
Left(UnexpectedJsonFormat(detail = "Wrong JSON format or missing required field. Please see API document."))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import org.http4s.{Request, Response}
import org.http4s.Challenge
import org.http4s.headers.{`Content-Type`, `WWW-Authenticate`}
import com.github.plokhotnyuk.jsoniter_scala.core.*
import net.yoshinorin.qualtet.domains.errors.Error
import net.yoshinorin.qualtet.domains.errors.DomainError
import net.yoshinorin.qualtet.http.HttpError.*
import net.yoshinorin.qualtet.syntax.*

object ResponseTranslator {

// NOTE: can't use `ContextFunctions`.
private def failToResponse(f: Error)(using req: Request[IO]): IO[Response[IO]] = {
private def failToResponse(f: DomainError)(using req: Request[IO]): IO[Response[IO]] = {
fromDomainError(f) match {
case e: NotFound =>
NotFound(
Expand Down Expand Up @@ -74,7 +74,7 @@ object ResponseTranslator {

def toResponse(e: Throwable): Request[IO] ?=> IO[Response[IO]] = {
e match {
case f: Error => this.failToResponse(f)
case f: DomainError => this.failToResponse(f)
case _ => InternalServerError("Internal Server Error")
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/net/yoshinorin/qualtet/syntax/optionSpec.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.yoshinorin.qualtet.syntax

import org.scalatest.wordspec.AnyWordSpec
import net.yoshinorin.qualtet.domains.errors.{Error, UnexpectedException}
import net.yoshinorin.qualtet.domains.errors.{DomainError, UnexpectedException}

// testOnly net.yoshinorin.qualtet.syntax.OptionSpec
class OptionSpec extends AnyWordSpec {
Expand All @@ -25,13 +25,13 @@ class OptionSpec extends AnyWordSpec {
"asEither" should {

"return Right if not None" in {
val result = Some("some values").asEither[Error](UnexpectedException(detail = "unprocessable!!"))
val result = Some("some values").asEither[DomainError](UnexpectedException(detail = "unprocessable!!"))
assert(result.isRight)
assert(result.toOption.get === "some values")
}

"return Left if None" in {
val result = None.asEither[Error](UnexpectedException(detail = "unprocessable!!"))
val result = None.asEither[DomainError](UnexpectedException(detail = "unprocessable!!"))
assert(result.isLeft)
assert(result.swap.getOrElse("").isInstanceOf[UnexpectedException])
}
Expand Down

0 comments on commit 3997cd2

Please sign in to comment.