refactor: move ApiRequestError to Error module
This commit is contained in:
committed by
Steve Chavez
parent
33b69b5894
commit
e04cd70d83
@@ -44,10 +44,10 @@ import Network.Wai.Parse (parseHttpAccept)
|
|||||||
import Web.Cookie (parseCookies)
|
import Web.Cookie (parseCookies)
|
||||||
|
|
||||||
import PostgREST.ApiRequest.QueryParams (QueryParams (..))
|
import PostgREST.ApiRequest.QueryParams (QueryParams (..))
|
||||||
import PostgREST.ApiRequest.Types (ApiRequestError (..),
|
|
||||||
RangeError (..))
|
|
||||||
import PostgREST.Config (AppConfig (..),
|
import PostgREST.Config (AppConfig (..),
|
||||||
OpenAPIMode (..))
|
OpenAPIMode (..))
|
||||||
|
import PostgREST.Error (ApiRequestError (..),
|
||||||
|
RangeError (..))
|
||||||
import PostgREST.MediaType (MediaType (..))
|
import PostgREST.MediaType (MediaType (..))
|
||||||
import PostgREST.RangeQuery (NonnegRange, allRange,
|
import PostgREST.RangeQuery (NonnegRange, allRange,
|
||||||
convertToLimitZeroRange,
|
convertToLimitZeroRange,
|
||||||
|
|||||||
@@ -54,10 +54,12 @@ import PostgREST.ApiRequest.Types (AggregateFunction (..),
|
|||||||
OpQuantifier (..), Operation (..),
|
OpQuantifier (..), Operation (..),
|
||||||
OrderDirection (..),
|
OrderDirection (..),
|
||||||
OrderNulls (..), OrderTerm (..),
|
OrderNulls (..), OrderTerm (..),
|
||||||
QPError (..), QuantOperator (..),
|
QuantOperator (..),
|
||||||
SelectItem (..),
|
SelectItem (..),
|
||||||
SimpleOperator (..), SingleVal)
|
SimpleOperator (..), SingleVal)
|
||||||
|
|
||||||
|
import PostgREST.Error (QPError (..))
|
||||||
|
|
||||||
import Protolude hiding (Sum, try)
|
import Protolude hiding (Sum, try)
|
||||||
|
|
||||||
data QueryParams =
|
data QueryParams =
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ module PostgREST.ApiRequest.Types
|
|||||||
, Cast
|
, Cast
|
||||||
, Depth
|
, Depth
|
||||||
, EmbedParam(..)
|
, EmbedParam(..)
|
||||||
, ApiRequestError(..)
|
|
||||||
, EmbedPath
|
, EmbedPath
|
||||||
, Field
|
, Field
|
||||||
, Filter(..)
|
, Filter(..)
|
||||||
@@ -25,9 +24,6 @@ module PostgREST.ApiRequest.Types
|
|||||||
, OrderDirection(..)
|
, OrderDirection(..)
|
||||||
, OrderNulls(..)
|
, OrderNulls(..)
|
||||||
, OrderTerm(..)
|
, OrderTerm(..)
|
||||||
, QPError(..)
|
|
||||||
, RaiseError(..)
|
|
||||||
, RangeError(..)
|
|
||||||
, SingleVal
|
, SingleVal
|
||||||
, IsVal(..)
|
, IsVal(..)
|
||||||
, SimpleOperator(..)
|
, SimpleOperator(..)
|
||||||
@@ -36,12 +32,7 @@ module PostgREST.ApiRequest.Types
|
|||||||
, SelectItem(..)
|
, SelectItem(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import PostgREST.MediaType (MediaType (..))
|
import PostgREST.SchemaCache.Identifiers (FieldName)
|
||||||
import PostgREST.SchemaCache.Identifiers (FieldName,
|
|
||||||
QualifiedIdentifier)
|
|
||||||
import PostgREST.SchemaCache.Relationship (Relationship,
|
|
||||||
RelationshipsMap)
|
|
||||||
import PostgREST.SchemaCache.Routine (Routine (..))
|
|
||||||
|
|
||||||
import Protolude
|
import Protolude
|
||||||
|
|
||||||
@@ -69,49 +60,6 @@ data SelectItem
|
|||||||
}
|
}
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data ApiRequestError
|
|
||||||
= AggregatesNotAllowed
|
|
||||||
| AmbiguousRelBetween Text Text [Relationship]
|
|
||||||
| AmbiguousRpc [Routine]
|
|
||||||
| MediaTypeError [ByteString]
|
|
||||||
| InvalidBody ByteString
|
|
||||||
| InvalidFilters
|
|
||||||
| InvalidPreferences [ByteString]
|
|
||||||
| InvalidRange RangeError
|
|
||||||
| InvalidRpcMethod ByteString
|
|
||||||
| NotFound
|
|
||||||
| NoRelBetween Text Text (Maybe Text) Text RelationshipsMap
|
|
||||||
| NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine]
|
|
||||||
| NotEmbedded Text
|
|
||||||
| PutLimitNotAllowedError
|
|
||||||
| QueryParamError QPError
|
|
||||||
| RelatedOrderNotToOne Text Text
|
|
||||||
| SpreadNotToOne Text Text
|
|
||||||
| UnacceptableFilter Text
|
|
||||||
| UnacceptableSchema [Text]
|
|
||||||
| UnsupportedMethod ByteString
|
|
||||||
| ColumnNotFound Text Text
|
|
||||||
| GucHeadersError
|
|
||||||
| GucStatusError
|
|
||||||
| PutMatchingPkError
|
|
||||||
| SingularityError Integer
|
|
||||||
| PGRSTParseError RaiseError
|
|
||||||
| MaxAffectedViolationError Integer
|
|
||||||
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
|
|
||||||
|
|
||||||
type NodeName = Text
|
type NodeName = Text
|
||||||
type Depth = Integer
|
type Depth = Integer
|
||||||
|
|
||||||
|
|||||||
+49
-6
@@ -8,6 +8,8 @@ Description : PostgREST error HTTP responses
|
|||||||
module PostgREST.Error
|
module PostgREST.Error
|
||||||
( errorResponseFor
|
( errorResponseFor
|
||||||
, ApiRequestError(..)
|
, ApiRequestError(..)
|
||||||
|
, QPError(..)
|
||||||
|
, RangeError(..)
|
||||||
, PgError(..)
|
, PgError(..)
|
||||||
, Error(..)
|
, Error(..)
|
||||||
, errorPayload
|
, errorPayload
|
||||||
@@ -32,12 +34,8 @@ import Network.Wai (Response, responseLBS)
|
|||||||
|
|
||||||
import Network.HTTP.Types.Header (Header)
|
import Network.HTTP.Types.Header (Header)
|
||||||
|
|
||||||
import PostgREST.ApiRequest.Types (ApiRequestError (..),
|
import PostgREST.MediaType (MediaType (..))
|
||||||
QPError (..),
|
import qualified PostgREST.MediaType as MediaType
|
||||||
RaiseError (..),
|
|
||||||
RangeError (..))
|
|
||||||
import PostgREST.MediaType (MediaType (..))
|
|
||||||
import qualified PostgREST.MediaType as MediaType
|
|
||||||
|
|
||||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
||||||
Schema)
|
Schema)
|
||||||
@@ -62,6 +60,51 @@ class (JSON.ToJSON a) => PgrstError a where
|
|||||||
let baseHeader = MediaType.toContentType MTApplicationJSON in
|
let baseHeader = MediaType.toContentType MTApplicationJSON in
|
||||||
responseLBS (status err) (baseHeader : headers err) $ errorPayload err
|
responseLBS (status err) (baseHeader : headers err) $ errorPayload err
|
||||||
|
|
||||||
|
data ApiRequestError
|
||||||
|
= AggregatesNotAllowed
|
||||||
|
| AmbiguousRelBetween Text Text [Relationship]
|
||||||
|
| AmbiguousRpc [Routine]
|
||||||
|
| MediaTypeError [ByteString]
|
||||||
|
| InvalidBody ByteString
|
||||||
|
| InvalidFilters
|
||||||
|
| InvalidPreferences [ByteString]
|
||||||
|
| InvalidRange RangeError
|
||||||
|
| InvalidRpcMethod ByteString
|
||||||
|
| NotFound
|
||||||
|
| NoRelBetween Text Text (Maybe Text) Text RelationshipsMap
|
||||||
|
| NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine]
|
||||||
|
| NotEmbedded Text
|
||||||
|
| PutLimitNotAllowedError
|
||||||
|
| QueryParamError QPError
|
||||||
|
| RelatedOrderNotToOne Text Text
|
||||||
|
| SpreadNotToOne Text Text
|
||||||
|
| UnacceptableFilter Text
|
||||||
|
| UnacceptableSchema [Text]
|
||||||
|
| UnsupportedMethod ByteString
|
||||||
|
| ColumnNotFound Text Text
|
||||||
|
| GucHeadersError
|
||||||
|
| GucStatusError
|
||||||
|
| PutMatchingPkError
|
||||||
|
| SingularityError Integer
|
||||||
|
| PGRSTParseError RaiseError
|
||||||
|
| MaxAffectedViolationError Integer
|
||||||
|
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
|
instance PgrstError ApiRequestError where
|
||||||
status AggregatesNotAllowed{} = HTTP.status400
|
status AggregatesNotAllowed{} = HTTP.status400
|
||||||
status AmbiguousRelBetween{} = HTTP.status300
|
status AmbiguousRelBetween{} = HTTP.status300
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ import PostgREST.ApiRequest (Action (..),
|
|||||||
Mutation (..),
|
Mutation (..),
|
||||||
Payload (..))
|
Payload (..))
|
||||||
import PostgREST.Config (AppConfig (..))
|
import PostgREST.Config (AppConfig (..))
|
||||||
import PostgREST.Error (Error (..))
|
import PostgREST.Error (ApiRequestError (..),
|
||||||
|
Error (..))
|
||||||
import PostgREST.MediaType (MediaType (..))
|
import PostgREST.MediaType (MediaType (..))
|
||||||
import PostgREST.Query.SqlFragment (sourceCTEName)
|
import PostgREST.Query.SqlFragment (sourceCTEName)
|
||||||
import PostgREST.RangeQuery (NonnegRange, allRange,
|
import PostgREST.RangeQuery (NonnegRange, allRange,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import qualified Hasql.DynamicStatements.Statement as SQL
|
|||||||
import qualified Hasql.Transaction as SQL
|
import qualified Hasql.Transaction as SQL
|
||||||
import qualified Hasql.Transaction.Sessions as SQL
|
import qualified Hasql.Transaction.Sessions as SQL
|
||||||
|
|
||||||
import qualified PostgREST.ApiRequest.Types as ApiRequestTypes
|
|
||||||
import qualified PostgREST.AppState as AppState
|
import qualified PostgREST.AppState as AppState
|
||||||
import qualified PostgREST.Error as Error
|
import qualified PostgREST.Error as Error
|
||||||
import qualified PostgREST.Query.QueryBuilder as QueryBuilder
|
import qualified PostgREST.Query.QueryBuilder as QueryBuilder
|
||||||
@@ -217,7 +216,7 @@ failPut RSPlan{} = pure ()
|
|||||||
failPut RSStandard{rsQueryTotal=queryTotal} =
|
failPut RSStandard{rsQueryTotal=queryTotal} =
|
||||||
when (queryTotal /= 1) $ do
|
when (queryTotal /= 1) $ do
|
||||||
lift SQL.condemn
|
lift SQL.condemn
|
||||||
throwError $ Error.ApiRequestError ApiRequestTypes.PutMatchingPkError
|
throwError $ Error.ApiRequestError Error.PutMatchingPkError
|
||||||
|
|
||||||
resultSetWTotal :: AppConfig -> ApiRequest -> ResultSet -> SQL.Snippet -> DbHandler ResultSet
|
resultSetWTotal :: AppConfig -> ApiRequest -> ResultSet -> SQL.Snippet -> DbHandler ResultSet
|
||||||
resultSetWTotal _ _ rs@RSPlan{} _ = return rs
|
resultSetWTotal _ _ rs@RSPlan{} _ = return rs
|
||||||
@@ -249,14 +248,14 @@ failNotSingular _ RSPlan{} = pure ()
|
|||||||
failNotSingular mediaType RSStandard{rsQueryTotal=queryTotal} =
|
failNotSingular mediaType RSStandard{rsQueryTotal=queryTotal} =
|
||||||
when (elem mediaType [MTVndSingularJSON True, MTVndSingularJSON False] && queryTotal /= 1) $ do
|
when (elem mediaType [MTVndSingularJSON True, MTVndSingularJSON False] && queryTotal /= 1) $ do
|
||||||
lift SQL.condemn
|
lift SQL.condemn
|
||||||
throwError $ Error.ApiRequestError . ApiRequestTypes.SingularityError $ toInteger queryTotal
|
throwError $ Error.ApiRequestError . Error.SingularityError $ toInteger queryTotal
|
||||||
|
|
||||||
failExceedsMaxAffectedPref :: (Maybe PreferMaxAffected, Maybe PreferHandling) -> ResultSet -> DbHandler ()
|
failExceedsMaxAffectedPref :: (Maybe PreferMaxAffected, Maybe PreferHandling) -> ResultSet -> DbHandler ()
|
||||||
failExceedsMaxAffectedPref (Nothing,_) _ = pure ()
|
failExceedsMaxAffectedPref (Nothing,_) _ = pure ()
|
||||||
failExceedsMaxAffectedPref _ RSPlan{} = pure ()
|
failExceedsMaxAffectedPref _ RSPlan{} = pure ()
|
||||||
failExceedsMaxAffectedPref (Just (PreferMaxAffected n), handling) RSStandard{rsQueryTotal=queryTotal} = when ((queryTotal > n) && (handling == Just Strict)) $ do
|
failExceedsMaxAffectedPref (Just (PreferMaxAffected n), handling) RSStandard{rsQueryTotal=queryTotal} = when ((queryTotal > n) && (handling == Just Strict)) $ do
|
||||||
lift SQL.condemn
|
lift SQL.condemn
|
||||||
throwError $ Error.ApiRequestError . ApiRequestTypes.MaxAffectedViolationError $ toInteger queryTotal
|
throwError $ Error.ApiRequestError . Error.MaxAffectedViolationError $ toInteger queryTotal
|
||||||
|
|
||||||
-- | Set a transaction to roll back if requested
|
-- | Set a transaction to roll back if requested
|
||||||
optionalRollback :: AppConfig -> ApiRequest -> DbHandler ()
|
optionalRollback :: AppConfig -> ApiRequest -> DbHandler ()
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import PostgREST.SchemaCache.Routine (FuncVolatility (..),
|
|||||||
Routine (..))
|
Routine (..))
|
||||||
import PostgREST.SchemaCache.Table (Table (..))
|
import PostgREST.SchemaCache.Table (Table (..))
|
||||||
|
|
||||||
import qualified PostgREST.ApiRequest.Types as ApiRequestTypes
|
|
||||||
import qualified PostgREST.SchemaCache.Routine as Routine
|
import qualified PostgREST.SchemaCache.Routine as Routine
|
||||||
|
|
||||||
import Protolude hiding (Handler, toS)
|
import Protolude hiding (Handler, toS)
|
||||||
@@ -83,8 +82,8 @@ actionResponse (DbCrudResult WrappedReadPlan{wrMedia, wrHdrsOnly=headersOnly, cr
|
|||||||
|
|
||||||
(ovStatus, ovHeaders) <- overrideStatusHeaders rsGucStatus rsGucHeaders status headers
|
(ovStatus, ovHeaders) <- overrideStatusHeaders rsGucStatus rsGucHeaders status headers
|
||||||
|
|
||||||
let bod | status == HTTP.status416 = Error.errorPayload $ Error.ApiRequestError $ ApiRequestTypes.InvalidRange $
|
let bod | status == HTTP.status416 = Error.errorPayload $ Error.ApiRequestError $ Error.InvalidRange $
|
||||||
ApiRequestTypes.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal)
|
Error.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal)
|
||||||
| headersOnly = mempty
|
| headersOnly = mempty
|
||||||
| otherwise = LBS.fromStrict rsBody
|
| otherwise = LBS.fromStrict rsBody
|
||||||
|
|
||||||
@@ -203,8 +202,8 @@ actionResponse (DbCallResult CallReadPlan{crMedia, crInvMthd=invMethod, crProc=p
|
|||||||
(status, contentRange) =
|
(status, contentRange) =
|
||||||
RangeQuery.rangeStatusHeader iTopLevelRange rsQueryTotal rsTableTotal
|
RangeQuery.rangeStatusHeader iTopLevelRange rsQueryTotal rsTableTotal
|
||||||
rsOrErrBody = if status == HTTP.status416
|
rsOrErrBody = if status == HTTP.status416
|
||||||
then Error.errorPayload $ Error.ApiRequestError $ ApiRequestTypes.InvalidRange
|
then Error.errorPayload $ Error.ApiRequestError $ Error.InvalidRange
|
||||||
$ ApiRequestTypes.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal)
|
$ Error.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal)
|
||||||
else LBS.fromStrict rsBody
|
else LBS.fromStrict rsBody
|
||||||
prefHeader = maybeToList . prefAppliedHeader $ Preferences Nothing Nothing preferCount preferTransaction Nothing preferHandling preferTimezone preferMaxAffected []
|
prefHeader = maybeToList . prefAppliedHeader $ Preferences Nothing Nothing preferCount preferTransaction Nothing preferHandling preferTimezone preferMaxAffected []
|
||||||
headers = contentRange : prefHeader
|
headers = contentRange : prefHeader
|
||||||
@@ -232,7 +231,7 @@ actionResponse (MaybeDbResult InspectPlan{ipHdrsOnly=headersOnly} body) _ versio
|
|||||||
actionResponse (NoDbResult (RelInfoPlan identifier)) _ _ _ sCache _ _ =
|
actionResponse (NoDbResult (RelInfoPlan identifier)) _ _ _ sCache _ _ =
|
||||||
case HM.lookup identifier (dbTables sCache) of
|
case HM.lookup identifier (dbTables sCache) of
|
||||||
Just tbl -> respondInfo $ allowH tbl
|
Just tbl -> respondInfo $ allowH tbl
|
||||||
Nothing -> Left $ Error.ApiRequestError ApiRequestTypes.NotFound
|
Nothing -> Left $ Error.ApiRequestError Error.NotFound
|
||||||
where
|
where
|
||||||
allowH table =
|
allowH table =
|
||||||
let hasPK = not . null $ tablePKCols table in
|
let hasPK = not . null $ tablePKCols table in
|
||||||
@@ -263,11 +262,11 @@ overrideStatusHeaders rsGucStatus rsGucHeaders pgrstStatus pgrstHeaders = do
|
|||||||
|
|
||||||
decodeGucHeaders :: Maybe BS.ByteString -> Either Error.Error [GucHeader]
|
decodeGucHeaders :: Maybe BS.ByteString -> Either Error.Error [GucHeader]
|
||||||
decodeGucHeaders =
|
decodeGucHeaders =
|
||||||
maybe (Right []) $ first (const . Error.ApiRequestError $ ApiRequestTypes.GucHeadersError) . JSON.eitherDecode . LBS.fromStrict
|
maybe (Right []) $ first (const . Error.ApiRequestError $ Error.GucHeadersError) . JSON.eitherDecode . LBS.fromStrict
|
||||||
|
|
||||||
decodeGucStatus :: Maybe Text -> Either Error.Error (Maybe HTTP.Status)
|
decodeGucStatus :: Maybe Text -> Either Error.Error (Maybe HTTP.Status)
|
||||||
decodeGucStatus =
|
decodeGucStatus =
|
||||||
maybe (Right Nothing) $ first (const . Error.ApiRequestError $ ApiRequestTypes.GucStatusError) . fmap (Just . toEnum . fst) . decimal
|
maybe (Right Nothing) $ first (const . Error.ApiRequestError $ Error.GucStatusError) . fmap (Just . toEnum . fst) . decimal
|
||||||
|
|
||||||
contentTypeHeaders :: MediaType -> ApiRequest -> [HTTP.Header]
|
contentTypeHeaders :: MediaType -> ApiRequest -> [HTTP.Header]
|
||||||
contentTypeHeaders mediaType ApiRequest{..} =
|
contentTypeHeaders mediaType ApiRequest{..} =
|
||||||
|
|||||||
Reference in New Issue
Block a user