diff --git a/postgrest.cabal b/postgrest.cabal index fd5f3ec28..1f7b716c7 100644 --- a/postgrest.cabal +++ b/postgrest.cabal @@ -66,6 +66,7 @@ library PostgREST.SchemaCache.Representations PostgREST.SchemaCache.Table PostgREST.Error + PostgREST.Error.Types PostgREST.Listener PostgREST.Logger PostgREST.MainTx diff --git a/src/PostgREST/Error.hs b/src/PostgREST/Error.hs index 57ba2b4b4..5890e4889 100644 --- a/src/PostgREST/Error.hs +++ b/src/PostgREST/Error.hs @@ -51,6 +51,9 @@ import PostgREST.SchemaCache.Relationship (Cardinality (..), RelationshipsMap) import PostgREST.SchemaCache.Routine (Routine (..), RoutineParam (..)) + +import PostgREST.Error.Types + import Protolude class (ErrorBody a, JSON.ToJSON a) => PgrstError a where @@ -75,48 +78,6 @@ class ErrorBody a where details :: a -> Maybe JSON.Value hint :: a -> Maybe JSON.Value -data ApiRequestError - = AggregatesNotAllowed - | MediaTypeError [ByteString] - | InvalidBody ByteString - | InvalidFilters - | InvalidPreferences [ByteString] - | InvalidRange RangeError - | InvalidRpcMethod ByteString - | NotEmbedded Text - | NotImplemented Text - | PutLimitNotAllowedError - | QueryParamError QPError - | RelatedOrderNotToOne Text Text - | UnacceptableFilter Text - | UnacceptableSchema Text [Text] - | UnsupportedMethod ByteString - | GucHeadersError - | GucStatusError - | PutMatchingPkError - | SingularityError Integer - | PGRSTParseError RaiseError - | MaxAffectedViolationError Integer - | InvalidResourcePath - | OpenAPIDisabled - | MaxAffectedRpcViolation - deriving Show - -data QPError = QPError Text Text - deriving Show - -data RaiseError - = MsgParseError ByteString - | DetParseError ByteString - | NoDetail - deriving Show - -data RangeError - = NegativeLimit - | LowerGTUpper - | OutOfBounds Text Text - deriving Show - instance PgrstError ApiRequestError where status AggregatesNotAllowed{} = HTTP.status400 status MediaTypeError{} = HTTP.status406 @@ -245,15 +206,6 @@ instance JSON.ToJSON ApiRequestError where toJSON err = toJsonPgrstError (code err) (message err) (details err) (hint err) -data SchemaCacheError - = AmbiguousRelBetween Text Text [Relationship] - | AmbiguousRpc [Routine] - | NoRelBetween Text Text (Maybe Text) Text RelationshipsMap - | NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine] - | ColumnNotFound Text Text - | TableNotFound Text Text SchemaCache - deriving Show - instance PgrstError SchemaCacheError where status AmbiguousRelBetween{} = HTTP.status300 status AmbiguousRpc{} = HTTP.status300 @@ -486,11 +438,6 @@ pgrstParseErrorHint err = case err of MsgParseError _ -> "MESSAGE must be a JSON object with obligatory keys: 'code', 'message' and optional keys: 'details', 'hint'." _ -> "DETAIL must be a JSON object with obligatory keys: 'status', 'headers' and optional key: 'status_text'." -data PgError = PgError Authenticated SQL.UsageError - deriving Show - -type Authenticated = Bool - instance PgrstError PgError where status (PgError authed usageError) = pgErrorStatus authed usageError @@ -637,43 +584,6 @@ pgErrorStatus authed (SQL.SessionUsageError (SQL.QueryError _ _ (SQL.ResultError _ -> HTTP.status500 -data Error - = ApiRequestError ApiRequestError - | SchemaCacheErr SchemaCacheError - | JwtErr JwtError - | NoSchemaCacheError - | PgErr PgError - deriving Show - -data JwtError - = JwtDecodeErr JwtDecodeError - | JwtSecretMissing - | JwtTokenRequired - | JwtClaimsErr JwtClaimsError - deriving Show - -data JwtDecodeError - = EmptyAuthHeader - | UnexpectedParts Int - | KeyError Text - | BadAlgorithm Text - | BadCrypto - | UnsupportedTokenType - | UnreachableDecodeError - deriving Show - -data JwtClaimsError - = JWTExpired - | JWTNotYetValid - | JWTIssuedAtFuture - | JWTNotInAudience - | ParsingClaimsFailed - | ExpClaimNotNumber - | NbfClaimNotNumber - | IatClaimNotNumber - | AudClaimNotStringOrArray - deriving Show - instance PgrstError Error where status (ApiRequestError err) = status err status (SchemaCacheErr err) = status err @@ -774,18 +684,6 @@ requiredTokenHeader :: Header requiredTokenHeader = ("WWW-Authenticate", "Bearer") -- For parsing byteString to JSON Object, used for allowing full response control -data PgRaiseErrMessage = PgRaiseErrMessage { - getCode :: Text, - getMessage :: Text, - getDetails :: Maybe Text, - getHint :: Maybe Text -} - -data PgRaiseErrDetails = PgRaiseErrDetails { - getStatus :: Int, - getStatusText :: Maybe Text, - getHeaders :: Map Text Text -} instance JSON.FromJSON PgRaiseErrMessage where parseJSON (JSON.Object m) = diff --git a/src/PostgREST/Error/Types.hs b/src/PostgREST/Error/Types.hs new file mode 100644 index 000000000..ae4e2924f --- /dev/null +++ b/src/PostgREST/Error/Types.hs @@ -0,0 +1,139 @@ +{-| +Module : PostgREST.Error.Types +Description : PostgREST Error Data Types +-} +module PostgREST.Error.Types + ( ApiRequestError(..) + , QPError(..) + , RangeError(..) + , RaiseError(..) + , SchemaCacheError(..) + , PgError(..) + , Error(..) + , JwtError (..) + , JwtDecodeError(..) + , JwtClaimsError(..) + , PgRaiseErrMessage(..) + , PgRaiseErrDetails(..) + ) where + +import qualified Hasql.Pool as SQL + +import PostgREST.MediaType (MediaType (..)) +import PostgREST.SchemaCache (SchemaCache (..)) +import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) +import PostgREST.SchemaCache.Relationship (Relationship (..), + RelationshipsMap) +import PostgREST.SchemaCache.Routine (Routine (..)) + +import Protolude + +data Error + = ApiRequestError ApiRequestError + | SchemaCacheErr SchemaCacheError + | JwtErr JwtError + | NoSchemaCacheError + | PgErr PgError + deriving Show + +-- API REQUEST ERRORS: PGRST1XX +data ApiRequestError + = AggregatesNotAllowed + | MediaTypeError [ByteString] + | InvalidBody ByteString + | InvalidFilters + | InvalidPreferences [ByteString] + | InvalidRange RangeError + | InvalidRpcMethod ByteString + | NotEmbedded Text + | NotImplemented Text + | PutLimitNotAllowedError + | QueryParamError QPError + | RelatedOrderNotToOne Text Text + | UnacceptableFilter Text + | UnacceptableSchema Text [Text] + | UnsupportedMethod ByteString + | GucHeadersError + | GucStatusError + | PutMatchingPkError + | SingularityError Integer + | PGRSTParseError RaiseError + | MaxAffectedViolationError Integer + | InvalidResourcePath + | OpenAPIDisabled + | MaxAffectedRpcViolation + deriving Show + +data QPError = QPError Text Text + deriving Show + +data RaiseError + = MsgParseError ByteString + | DetParseError ByteString + | NoDetail + deriving Show + +data RangeError + = NegativeLimit + | LowerGTUpper + | OutOfBounds Text Text + deriving Show + +-- SCHEMA CACHE ERRORS: PGRST2XX +data SchemaCacheError + = AmbiguousRelBetween Text Text [Relationship] + | AmbiguousRpc [Routine] + | NoRelBetween Text Text (Maybe Text) Text RelationshipsMap + | NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine] + | ColumnNotFound Text Text + | TableNotFound Text Text SchemaCache + deriving Show + +-- JWT ERRORS: PGRST3XX +data JwtError + = JwtDecodeErr JwtDecodeError + | JwtSecretMissing + | JwtTokenRequired + | JwtClaimsErr JwtClaimsError + deriving Show + +data JwtDecodeError + = EmptyAuthHeader + | UnexpectedParts Int + | KeyError Text + | BadAlgorithm Text + | BadCrypto + | UnsupportedTokenType + | UnreachableDecodeError + deriving Show + +data JwtClaimsError + = JWTExpired + | JWTNotYetValid + | JWTIssuedAtFuture + | JWTNotInAudience + | ParsingClaimsFailed + | ExpClaimNotNumber + | NbfClaimNotNumber + | IatClaimNotNumber + | AudClaimNotStringOrArray + deriving Show + +-- PG ERRORS +type Authenticated = Bool +data PgError = PgError Authenticated SQL.UsageError + deriving Show + +-- For parsing byteString to JSON Object, used for allowing full response control +data PgRaiseErrMessage = PgRaiseErrMessage { + getCode :: Text, + getMessage :: Text, + getDetails :: Maybe Text, + getHint :: Maybe Text +} + +data PgRaiseErrDetails = PgRaiseErrDetails { + getStatus :: Int, + getStatusText :: Maybe Text, + getHeaders :: Map Text Text +}