From a86f5f44c84ccf97c9c48f8b0d17bf4661200ffb Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Wed, 29 May 2019 11:59:38 +0530 Subject: [PATCH 1/9] add NEText newtype --- .../src-lib/Hasura/GraphQL/Resolve/Insert.hs | 16 +++--- server/src-lib/Hasura/GraphQL/Schema.hs | 18 +++---- server/src-lib/Hasura/RQL/DDL/Permission.hs | 2 +- .../src-lib/Hasura/RQL/DDL/QueryCollection.hs | 2 +- server/src-lib/Hasura/RQL/DML/Internal.hs | 15 +++--- .../src-lib/Hasura/RQL/DML/Select/Internal.hs | 2 +- server/src-lib/Hasura/RQL/Types/BoolExp.hs | 2 +- server/src-lib/Hasura/RQL/Types/Common.hs | 50 ++++++++++++++++--- server/src-lib/Hasura/RQL/Types/Permission.hs | 18 ++++--- .../Hasura/RQL/Types/QueryCollection.hs | 5 +- .../src-lib/Hasura/RQL/Types/RemoteSchema.hs | 3 +- .../Hasura/RQL/Types/SchemaCacheTypes.hs | 6 +-- server/src-lib/Hasura/Server/App.hs | 11 ++-- server/src-lib/Hasura/Server/Auth/JWT.hs | 2 +- server/src-lib/Hasura/Server/Init.hs | 21 +++++--- 15 files changed, 111 insertions(+), 62 deletions(-) diff --git a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs index 31ab2e3dd63d4..c6b07478ec537 100644 --- a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs +++ b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs @@ -29,10 +29,9 @@ import Hasura.GraphQL.Resolve.Mutation import Hasura.GraphQL.Resolve.Select import Hasura.GraphQL.Validate.Field import Hasura.GraphQL.Validate.Types -import Hasura.RQL.DML.Internal ( dmlTxErrorHandler - , convPartialSQLExp - , sessVarFromCurrentSetting - ) +import Hasura.RQL.DML.Internal (convPartialSQLExp, + dmlTxErrorHandler, + sessVarFromCurrentSetting) import Hasura.RQL.DML.Mutation import Hasura.RQL.GBoolExp (toSQLBoolExp) import Hasura.RQL.Types @@ -115,8 +114,9 @@ traverseInsObj rim (gName, annVal) defVal@(AnnInsObj cols objRels arrRels) = -- if relational insert input is 'null' then ignore -- return default value fmap (fromMaybe defVal) $ forM objM $ \obj -> do - let relName = RelName $ G.unName gName + let relNameM = RelName <$> mkNEText (G.unName gName) onConflictM = OMap.lookup "on_conflict" obj + relName <- onNothing relNameM $ throw500 "found empty GName String" dataVal <- onNothing (OMap.lookup "data" obj) $ throw500 "\"data\" object not found" relInfo <- onNothing (Map.lookup relName rim) $ @@ -280,7 +280,7 @@ validateInsert insCols objRels addCols = do forM_ objRels $ \relInfo -> do let lCols = map fst $ riMapping relInfo relName = riName relInfo - relNameTxt = getRelTxt relName + relNameTxt = unNEText $ getRelTxt relName lColConflicts = lCols `intersect` (addCols <> insCols) withPathK relNameTxt $ unless (null lColConflicts) $ throwVE $ "cannot insert object relation ship " <> relName @@ -311,7 +311,7 @@ insertObjRel strfyNum role objRelIns = RelIns singleObjIns relInfo = objRelIns multiObjIns = singleToMulti singleObjIns relName = riName relInfo - relNameTxt = getRelTxt relName + relNameTxt = unNEText $ getRelTxt relName mapCols = riMapping relInfo tn = riRTable relInfo allCols = _aiTableCols singleObjIns @@ -352,7 +352,7 @@ insertArrRel strfyNum role resCols arrRelIns = RelIns multiObjIns relInfo = arrRelIns colMapping = riMapping relInfo tn = riRTable relInfo - relNameTxt = getRelTxt $ riName relInfo + relNameTxt = unNEText . getRelTxt $ riName relInfo mutFlds = [("affected_rows", RR.MCount)] -- | insert an object with object and array relationships diff --git a/server/src-lib/Hasura/GraphQL/Schema.hs b/server/src-lib/Hasura/GraphQL/Schema.hs index 36f29e6efe67c..e44c9fa77d74d 100644 --- a/server/src-lib/Hasura/GraphQL/Schema.hs +++ b/server/src-lib/Hasura/GraphQL/Schema.hs @@ -77,7 +77,7 @@ isValidCol :: PGCol -> Bool isValidCol = isValidName . G.Name . getPGColTxt isValidRel :: ToTxt a => RelName -> QualifiedObject a -> Bool -isValidRel rn rt = isValidName (G.Name $ getRelTxt rn) +isValidRel rn rt = isValidName (G.Name . unNEText $ getRelTxt rn) && isValidObjectName rt isValidField :: FieldInfo -> Bool @@ -128,10 +128,10 @@ mkColName :: PGCol -> G.Name mkColName (PGCol n) = G.Name n mkRelName :: RelName -> G.Name -mkRelName (RelName r) = G.Name r +mkRelName (RelName r) = G.Name $ unNEText r mkAggRelName :: RelName -> G.Name -mkAggRelName (RelName r) = G.Name $ r <> "_aggregate" +mkAggRelName (RelName r) = G.Name $ unNEText r <> "_aggregate" mkBoolExpName :: QualifiedTable -> G.Name mkBoolExpName tn = @@ -239,13 +239,13 @@ mkRelFld allowAgg (RelInfo rn rTy _ remTab isManual) isNullable = case rTy of ObjRel -> [objRelFld] where objRelFld = mkHsraObjFldInfo (Just "An object relationship") - (G.Name $ getRelTxt rn) Map.empty objRelTy + (G.Name . unNEText $ getRelTxt rn) Map.empty objRelTy objRelTy = bool (G.toGT $ G.toNT relTabTy) (G.toGT relTabTy) isObjRelNullable isObjRelNullable = isManual || isNullable relTabTy = mkTableTy remTab arrRelFld = - mkHsraObjFldInfo (Just "An array relationship") (G.Name $ getRelTxt rn) + mkHsraObjFldInfo (Just "An array relationship") (G.Name . unNEText $ getRelTxt rn) (fromInpValL $ mkSelArgs remTab) arrRelTy arrRelTy = G.toGT $ G.toNT $ G.toLT $ G.toNT $ mkTableTy remTab aggArrRelFld = mkHsraObjFldInfo (Just "An aggregated array relationship") @@ -547,7 +547,7 @@ mkBoolExpInp tn fields = Left (PGColInfo colName colTy _) -> mk (mkColName colName) (mkCompExpTy colTy) Right (RelInfo relName _ _ remTab _, _, _, _, _) -> - mk (G.Name $ getRelTxt relName) (mkBoolExpTy remTab) + mk (G.Name . unNEText $ getRelTxt relName) (mkBoolExpTy remTab) mkPGColInp :: PGColInfo -> InpValInfo mkPGColInp (PGColInfo colName colTy _) = @@ -954,9 +954,9 @@ mkInsInp tn insCols relInfoMap = let rty = riType relInfo remoteQT = riRTable relInfo in case rty of - ObjRel -> InpValInfo Nothing (G.Name $ getRelTxt relName) Nothing $ + ObjRel -> InpValInfo Nothing (G.Name . unNEText $ getRelTxt relName) Nothing $ G.toGT $ mkObjInsInpTy remoteQT - ArrRel -> InpValInfo Nothing (G.Name $ getRelTxt relName) Nothing $ + ArrRel -> InpValInfo Nothing (G.Name . unNEText $ getRelTxt relName) Nothing $ G.toGT $ mkArrInsInpTy remoteQT {- @@ -1333,7 +1333,7 @@ mkGCtxRole' tn insPermM selPermM updColsM mkFld ty = \case Left ci -> [((ty, mkColName $ pgiName ci), Left ci)] Right (ri, allowAgg, perm, lim, _) -> - let relFld = ( (ty, G.Name $ getRelTxt $ riName ri) + let relFld = ( (ty, G.Name . unNEText . getRelTxt $ riName ri) , Right (ri, False, perm, lim) ) aggRelFld = ( (ty, mkAggRelName $ riName ri) diff --git a/server/src-lib/Hasura/RQL/DDL/Permission.hs b/server/src-lib/Hasura/RQL/DDL/Permission.hs index 07a1f30c8486f..80be42dec89fc 100644 --- a/server/src-lib/Hasura/RQL/DDL/Permission.hs +++ b/server/src-lib/Hasura/RQL/DDL/Permission.hs @@ -84,7 +84,7 @@ type CreateInsPerm = CreatePerm InsPerm buildViewName :: QualifiedTable -> RoleName -> PermType -> QualifiedTable buildViewName (QualifiedObject sn tn) (RoleName rTxt) pt = QualifiedObject hdbViewsSchema $ TableName - (rTxt <> "__" <> T.pack (show pt) <> "__" <> snTxt <> "__" <> tnTxt) + (unNEText rTxt <> "__" <> T.pack (show pt) <> "__" <> snTxt <> "__" <> tnTxt) where snTxt = getSchemaTxt sn tnTxt = getTableTxt tn diff --git a/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs b/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs index eb94b12a49921..71eefed7d9910 100644 --- a/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs +++ b/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs @@ -34,7 +34,7 @@ addCollectionP2 (CollectionDef queryList) = withPathK "queries" $ unless (null duplicateNames) $ throw400 NotSupported $ "found duplicate query names " - <> T.intercalate ", " (map (T.dquote . unQueryName) duplicateNames) + <> T.intercalate ", " (map (T.dquote . unNEText . unQueryName) duplicateNames) where duplicateNames = duplicates $ map _lqName queryList diff --git a/server/src-lib/Hasura/RQL/DML/Internal.hs b/server/src-lib/Hasura/RQL/DML/Internal.hs index 117ffbc260a8a..93fa9fb3c65d6 100644 --- a/server/src-lib/Hasura/RQL/DML/Internal.hs +++ b/server/src-lib/Hasura/RQL/DML/Internal.hs @@ -133,14 +133,13 @@ checkPermOnCol pt allowedCols pgCol = do unless (HS.member pgCol allowedCols) $ throw400 PermissionDenied $ permErrMsg roleName where - permErrMsg (RoleName "admin") = - "no such column exists : " <>> pgCol - permErrMsg roleName = - mconcat - [ "role " <>> roleName - , " does not have permission to " - , permTypeToCode pt <> " column " <>> pgCol - ] + permErrMsg roleName + | roleName == adminRole = "no such column exists : " <>> pgCol + | otherwise = mconcat + [ "role " <>> roleName + , " does not have permission to " + , permTypeToCode pt <> " column " <>> pgCol + ] binRHSBuilder :: PGColType -> Value -> DMLP1 S.SQLExp diff --git a/server/src-lib/Hasura/RQL/DML/Select/Internal.hs b/server/src-lib/Hasura/RQL/DML/Select/Internal.hs index 629c697694502..ad2242cc5be23 100644 --- a/server/src-lib/Hasura/RQL/DML/Select/Internal.hs +++ b/server/src-lib/Hasura/RQL/DML/Select/Internal.hs @@ -641,7 +641,7 @@ mkAggSelect :: AnnAggSel -> S.Select mkAggSelect annAggSel = prefixNumToAliases $ arrNodeToSelect bn extr $ S.BELit True where - aggSel = AnnRelG (RelName "root") [] annAggSel + aggSel = AnnRelG rootRelName [] annAggSel ArrNode extr _ bn = aggSelToArrNode (Iden "root") (FieldName "root") aggSel diff --git a/server/src-lib/Hasura/RQL/Types/BoolExp.hs b/server/src-lib/Hasura/RQL/Types/BoolExp.hs index d9ab43b3eae78..1e21ae755f19f 100644 --- a/server/src-lib/Hasura/RQL/Types/BoolExp.hs +++ b/server/src-lib/Hasura/RQL/Types/BoolExp.hs @@ -287,7 +287,7 @@ instance ToJSON AnnBoolExpPartialSQL where , toJSON (pci, map opExpSToJSON opExps) ) AVRel ri relBoolExp -> - ( getRelTxt $ riName ri + ( unNEText . getRelTxt $ riName ri , toJSON (ri, toJSON relBoolExp) ) opExpSToJSON :: OpExpG PartialSQLExp -> Value diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index 82c7d631c87a7..b8d358021d112 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -2,6 +2,7 @@ module Hasura.RQL.Types.Common ( PGColInfo(..) , RelName(..) , RelType(..) + , rootRelName , relTypeToTxt , RelInfo(..) @@ -16,6 +17,12 @@ module Hasura.RQL.Types.Common , WithTable(..) , ColVals , MutateResp(..) + + , NEText + , mkNEText + , unNEText + , adminText + , rootText ) where import Hasura.Prelude @@ -40,15 +47,44 @@ data PGColInfo $(deriveJSON (aesonDrop 3 snakeCase) ''PGColInfo) +newtype NEText = NEText {unNEText :: T.Text} + deriving (Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, Lift, Q.ToPrepArg + , DQuote) + +mkNEText :: T.Text -> Maybe NEText +mkNEText "" = Nothing +mkNEText text = Just $ NEText text + +instance FromJSON NEText where + parseJSON = withText "String" + $ \text -> case mkNEText text of + Nothing -> fail "empty string not allowed" + Just neText -> return neText + +instance FromJSONKey NEText + +instance Q.FromCol NEText where + fromCol bs = mkNEText <$> Q.fromCol bs + >>= maybe (throwError "empty string not allowed") return + +adminText :: NEText +adminText = NEText "admin" + +rootText :: NEText +rootText = NEText "root" + newtype RelName - = RelName {getRelTxt :: T.Text} + = RelName {getRelTxt :: NEText} deriving (Show, Eq, Hashable, FromJSON, ToJSON, Q.ToPrepArg, Q.FromCol, Lift) instance IsIden RelName where - toIden (RelName r) = Iden r + toIden (RelName r) = Iden $ unNEText r instance DQuote RelName where - dquoteTxt (RelName r) = r + dquoteTxt (RelName r) = unNEText r + +rootRelName :: RelName +rootRelName = RelName rootText relTypeToTxt :: RelType -> T.Text relTypeToTxt ObjRel = "object" @@ -100,18 +136,18 @@ fromPGCol :: PGCol -> FieldName fromPGCol (PGCol c) = FieldName c fromRel :: RelName -> FieldName -fromRel (RelName r) = FieldName r +fromRel (RelName r) = FieldName $ unNEText r newtype TQueryName - = TQueryName { getTQueryName :: T.Text } + = TQueryName { getTQueryName :: NEText } deriving ( Show, Eq, Hashable, FromJSONKey, ToJSONKey , FromJSON, ToJSON, Q.ToPrepArg, Q.FromCol, Lift) instance IsIden TQueryName where - toIden (TQueryName r) = Iden r + toIden (TQueryName r) = Iden $ unNEText r instance DQuote TQueryName where - dquoteTxt (TQueryName r) = r + dquoteTxt (TQueryName r) = unNEText r newtype TemplateParam = TemplateParam { getTemplateParam :: T.Text } diff --git a/server/src-lib/Hasura/RQL/Types/Permission.hs b/server/src-lib/Hasura/RQL/Types/Permission.hs index 9404f1212ec66..93d6c4ffc4d17 100644 --- a/server/src-lib/Hasura/RQL/Types/Permission.hs +++ b/server/src-lib/Hasura/RQL/Types/Permission.hs @@ -23,6 +23,8 @@ module Hasura.RQL.Types.Permission ) where import Hasura.Prelude +import Hasura.RQL.Types.Common (NEText, adminText, mkNEText, + unNEText) import Hasura.Server.Utils (adminSecretHeader, deprecatedAccessKeyHeader, userRoleHeader) @@ -40,15 +42,15 @@ import qualified Data.Text as T import qualified PostgreSQL.Binary.Decoding as PD newtype RoleName - = RoleName {getRoleTxt :: T.Text} + = RoleName {getRoleTxt :: NEText} deriving ( Show, Eq, Hashable, FromJSONKey, ToJSONKey, FromJSON , ToJSON, Q.FromCol, Q.ToPrepArg, Lift) instance DQuote RoleName where - dquoteTxt (RoleName r) = r + dquoteTxt (RoleName r) = unNEText r adminRole :: RoleName -adminRole = RoleName "admin" +adminRole = RoleName adminText isAdmin :: RoleName -> Bool isAdmin = (adminRole ==) @@ -64,8 +66,8 @@ isUserVar :: T.Text -> Bool isUserVar = T.isPrefixOf "x-hasura-" . T.toLower roleFromVars :: UserVars -> Maybe RoleName -roleFromVars = - fmap RoleName . getVarVal userRoleHeader +roleFromVars uv = + getVarVal userRoleHeader uv >>= fmap RoleName . mkNEText getVarVal :: SessVar -> UserVars -> Maybe SessVarVal getVarVal k = @@ -90,7 +92,7 @@ data UserInfo mkUserInfo :: RoleName -> UserVars -> UserInfo mkUserInfo rn (UserVars v) = - UserInfo rn $ UserVars $ Map.insert userRoleHeader (getRoleTxt rn) $ + UserInfo rn $ UserVars $ Map.insert userRoleHeader (unNEText $ getRoleTxt rn) $ foldl (flip Map.delete) v [adminSecretHeader, deprecatedAccessKeyHeader] instance Hashable UserInfo @@ -102,7 +104,7 @@ instance Hashable UserInfo userInfoToList :: UserInfo -> [(Text, Text)] userInfoToList userInfo = let vars = Map.toList $ unUserVars . userVars $ userInfo - rn = getRoleTxt . userRole $ userInfo + rn = unNEText . getRoleTxt . userRole $ userInfo in (userRoleHeader, rn) : vars adminUserInfo :: UserInfo @@ -162,7 +164,7 @@ instance Show PermId where show $ mconcat [ getTableTxt tn , "." - , getRoleTxt rn + , unNEText $ getRoleTxt rn , "." , T.pack $ show pType ] diff --git a/server/src-lib/Hasura/RQL/Types/QueryCollection.hs b/server/src-lib/Hasura/RQL/Types/QueryCollection.hs index 7ffbe4b7d6343..016c0d7e6c1a0 100644 --- a/server/src-lib/Hasura/RQL/Types/QueryCollection.hs +++ b/server/src-lib/Hasura/RQL/Types/QueryCollection.hs @@ -2,6 +2,7 @@ module Hasura.RQL.Types.QueryCollection where import Hasura.GraphQL.Validate.Types (stripTypenames) import Hasura.Prelude +import Hasura.RQL.Types.Common (NEText) import Hasura.SQL.Types import Data.Aeson @@ -15,13 +16,13 @@ import qualified Database.PG.Query as Q import qualified Language.GraphQL.Draft.Syntax as G newtype CollectionName - = CollectionName {unCollectionName :: T.Text} + = CollectionName {unCollectionName :: NEText} deriving ( Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, Lift , FromJSON, Q.FromCol, Q.ToPrepArg, DQuote ) newtype QueryName - = QueryName {unQueryName :: T.Text} + = QueryName {unQueryName :: NEText} deriving (Show, Eq, Ord, Hashable, Lift, ToJSON, ToJSONKey, FromJSON, DQuote) newtype GQLQuery diff --git a/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs b/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs index 56189d0a83e8d..0ef216f7457f4 100644 --- a/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs +++ b/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs @@ -1,6 +1,7 @@ module Hasura.RQL.Types.RemoteSchema where import Hasura.Prelude +import Hasura.RQL.Types.Common (NEText) import Language.Haskell.TH.Syntax (Lift) import System.Environment (lookupEnv) @@ -19,7 +20,7 @@ type UrlFromEnv = Text newtype RemoteSchemaName = RemoteSchemaName - { unRemoteSchemaName :: Text} + { unRemoteSchemaName :: NEText} deriving (Show, Eq, Lift, Hashable, J.ToJSON, J.ToJSONKey, J.FromJSON, Q.ToPrepArg, Q.FromCol) data RemoteSchemaInfo diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs index ccc36f082f89d..11ed7d4680830 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs @@ -36,15 +36,15 @@ reportSchemaObj :: SchemaObjId -> T.Text reportSchemaObj (SOTable tn) = "table " <> qualObjectToText tn reportSchemaObj (SOFunction fn) = "function " <> qualObjectToText fn reportSchemaObj (SOQTemplate qtn) = - "query-template " <> getTQueryName qtn + "query-template " <> unNEText (getTQueryName qtn) reportSchemaObj (SOTableObj tn (TOCol cn)) = "column " <> qualObjectToText tn <> "." <> getPGColTxt cn reportSchemaObj (SOTableObj tn (TORel cn)) = - "relationship " <> qualObjectToText tn <> "." <> getRelTxt cn + "relationship " <> qualObjectToText tn <> "." <> unNEText (getRelTxt cn) reportSchemaObj (SOTableObj tn (TOCons cn)) = "constraint " <> qualObjectToText tn <> "." <> getConstraintTxt cn reportSchemaObj (SOTableObj tn (TOPerm rn pt)) = - "permission " <> qualObjectToText tn <> "." <> getRoleTxt rn + "permission " <> qualObjectToText tn <> "." <> unNEText (getRoleTxt rn) <> "." <> permTypeToCode pt reportSchemaObj (SOTableObj tn (TOTrigger trn )) = "event-trigger " <> qualObjectToText tn <> "." <> trn diff --git a/server/src-lib/Hasura/Server/App.hs b/server/src-lib/Hasura/Server/App.hs index d28f16a8c2f1e..1d998cb1fd2f3 100644 --- a/server/src-lib/Hasura/Server/App.hs +++ b/server/src-lib/Hasura/Server/App.hs @@ -519,18 +519,23 @@ httpApp corsCfg serverCtx enableConsole consoleAssetsDir enableTelemetry = do expQuery <- parseBody gqlExplainHandler expQuery + mkTmpltName tmpltText = + onNothing (mkNEText tmpltText) $ throw400 NotSupported "template name is empty string" + enableGraphQL = isGraphQLEnabled serverCtx enableMetadata = isMetadataEnabled serverCtx enablePGDump = isPGDumpEnabled serverCtx - tmpltGetOrDeleteH tmpltName = do + tmpltGetOrDeleteH tmpltText = do tmpltArgs <- tmpltArgsFromQueryParams - mkSpockAction encodeQErr id serverCtx $ mkAPIRespHandler $ + mkSpockAction encodeQErr id serverCtx $ mkAPIRespHandler $ do + tmpltName <- mkTmpltName tmpltText mkQTemplateAction tmpltName tmpltArgs - tmpltPutOrPostH tmpltName = do + tmpltPutOrPostH tmpltText = do tmpltArgs <- tmpltArgsFromQueryParams mkSpockAction encodeQErr id serverCtx $ mkAPIRespHandler $ do bodyTmpltArgs <- parseBody + tmpltName <- mkTmpltName tmpltText mkQTemplateAction tmpltName $ M.union bodyTmpltArgs tmpltArgs tmpltArgsFromQueryParams = do diff --git a/server/src-lib/Hasura/Server/Auth/JWT.hs b/server/src-lib/Hasura/Server/Auth/JWT.hs index 9a9b7b21ada91..b7244a7ef7759 100644 --- a/server/src-lib/Hasura/Server/Auth/JWT.hs +++ b/server/src-lib/Hasura/Server/Auth/JWT.hs @@ -259,7 +259,7 @@ processAuthZHeader jwtCtx headers authzHeader = do getCurrentRole defaultRole = let userRoleHeaderB = CS.cs userRoleHeader mUserRole = snd <$> find (\h -> fst h == CI.mk userRoleHeaderB) headers - in maybe defaultRole (RoleName . bsToTxt) mUserRole + in maybe defaultRole RoleName $ mUserRole >>= mkNEText . bsToTxt decodeJSON val = case A.fromJSON val of A.Error e -> throw400 JWTInvalidClaims ("x-hasura-* claims: " <> T.pack e) diff --git a/server/src-lib/Hasura/Server/Init.hs b/server/src-lib/Hasura/Server/Init.hs index 14a2bdce4c665..602361f56f313 100644 --- a/server/src-lib/Hasura/Server/Init.hs +++ b/server/src-lib/Hasura/Server/Init.hs @@ -17,8 +17,9 @@ import qualified Hasura.Logging as L import qualified Text.PrettyPrint.ANSI.Leijen as PP import Hasura.Prelude -import Hasura.RQL.Types (RoleName (..), - SchemaCache (..)) +import Hasura.RQL.Types ( RoleName (..) + , SchemaCache (..) + , mkNEText ) import Hasura.Server.Auth import Hasura.Server.Cors import Hasura.Server.Logging @@ -150,7 +151,9 @@ instance FromEnv AdminSecret where fromEnv = Right . AdminSecret . T.pack instance FromEnv RoleName where - fromEnv = Right . RoleName . T.pack + fromEnv string = case mkNEText (T.pack string) of + Nothing -> Left "empty string not allowed" + Just neText -> Right $ RoleName neText instance FromEnv Bool where fromEnv = parseStrAsBool @@ -746,11 +749,13 @@ jwtSecretHelp = "The JSON containing type and the JWK used for verifying. e.g: " <> "`{\"type\": \"RS256\", \"key\": \"\", \"claims_namespace\": \"\"}`" parseUnAuthRole :: Parser (Maybe RoleName) -parseUnAuthRole = optional $ - RoleName <$> strOption ( long "unauthorized-role" <> - metavar "" <> - help (snd unAuthRoleEnv) - ) +parseUnAuthRole = fmap mkRoleName $ optional $ + strOption ( long "unauthorized-role" <> + metavar "" <> + help (snd unAuthRoleEnv) + ) + where + mkRoleName mText = mText >>= (fmap RoleName . mkNEText) parseCorsConfig :: Parser (Maybe CorsConfig) parseCorsConfig = mapCC <$> disableCors <*> corsDomain From e4a1db03d07864d64246d0e4d27373edc848a555 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Wed, 29 May 2019 18:20:00 +0530 Subject: [PATCH 2/9] newtype TriggerName as NEText --- server/src-lib/Hasura/RQL/DDL/EventTrigger.hs | 4 ++-- server/src-lib/Hasura/RQL/Types.hs | 4 ++-- server/src-lib/Hasura/RQL/Types/Common.hs | 5 ++--- .../src-lib/Hasura/RQL/Types/EventTrigger.hs | 22 +++++++++++-------- .../Hasura/RQL/Types/SchemaCacheTypes.hs | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs b/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs index 2a04c76ce4c52..98d026aa0f37f 100644 --- a/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs +++ b/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs @@ -42,7 +42,7 @@ triggerTmplt = case parseGingerTmplt $(FE.embedStringFile "src-rsr/trigger.sql.j Right tmplt -> Just tmplt pgIdenTrigger:: Ops -> TriggerName -> T.Text -pgIdenTrigger op trn = pgFmtIden (qualifyTriggerName op trn) +pgIdenTrigger op trn = pgFmtIden . qualifyTriggerName op . unNEText $ unTriggerName trn where qualifyTriggerName op' trn' = "notify_hasura_" <> trn' <> "_" <> T.pack (show op') @@ -61,7 +61,7 @@ getTriggerSql -> Maybe T.Text getTriggerSql op trn qt allCols strfyNum spec = let globalCtx = HashMap.fromList - [ (T.pack "NAME", trn) + [ (T.pack "NAME", unNEText $ unTriggerName trn) , (T.pack "QUALIFIED_TRIGGER_NAME", pgIdenTrigger op trn) , (T.pack "QUALIFIED_TABLE", toSQLTxt qt) ] diff --git a/server/src-lib/Hasura/RQL/Types.hs b/server/src-lib/Hasura/RQL/Types.hs index 2a657f8517f14..22e3814dc6089 100644 --- a/server/src-lib/Hasura/RQL/Types.hs +++ b/server/src-lib/Hasura/RQL/Types.hs @@ -104,7 +104,7 @@ askTabInfoFromTrigger trn = do let tabInfos = M.elems $ scTables sc liftMaybe (err400 NotExists errMsg) $ find (isJust.M.lookup trn.tiEventTriggerInfoMap) tabInfos where - errMsg = "event trigger " <> trn <<> " does not exist" + errMsg = "event trigger " <> unNEText (unTriggerName trn) <<> " does not exist" askEventTriggerInfo :: (QErrM m, CacheRM m) @@ -114,7 +114,7 @@ askEventTriggerInfo trn = do let etim = tiEventTriggerInfoMap ti liftMaybe (err400 NotExists errMsg) $ M.lookup trn etim where - errMsg = "event trigger " <> trn <<> " does not exist" + errMsg = "event trigger " <> unNEText (unTriggerName trn) <<> " does not exist" askQTemplateInfo :: (P1C m) diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index b8d358021d112..464f54ea60e2d 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -48,8 +48,7 @@ data PGColInfo $(deriveJSON (aesonDrop 3 snakeCase) ''PGColInfo) newtype NEText = NEText {unNEText :: T.Text} - deriving (Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, Lift, Q.ToPrepArg - , DQuote) + deriving (Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, Lift, Q.ToPrepArg, DQuote) mkNEText :: T.Text -> Maybe NEText mkNEText "" = Nothing @@ -65,7 +64,7 @@ instance FromJSONKey NEText instance Q.FromCol NEText where fromCol bs = mkNEText <$> Q.fromCol bs - >>= maybe (throwError "empty string not allowed") return + >>= maybe (Left "empty string not allowed") Right adminText :: NEText adminText = NEText "admin" diff --git a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs index c13167bdac377..f22aefae561b7 100644 --- a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs +++ b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs @@ -2,7 +2,7 @@ module Hasura.RQL.Types.EventTrigger ( CreateEventTriggerQuery(..) , SubscribeOpSpec(..) , SubscribeColumns(..) - , TriggerName + , TriggerName(..) , Ops(..) , EventId , TriggerOpsDef(..) @@ -27,15 +27,19 @@ import Data.Aeson.Casing import Data.Aeson.TH import Hasura.Prelude import Hasura.RQL.DDL.Headers +import Hasura.RQL.Types.Common (NEText (..)) import Hasura.SQL.Types import Language.Haskell.TH.Syntax (Lift) import qualified Data.ByteString.Lazy as LBS import qualified Data.Text as T +import qualified Database.PG.Query as Q import qualified Text.Regex.TDFA as TDFA -type TriggerName = T.Text -type EventId = T.Text +newtype TriggerName = TriggerName { unTriggerName :: NEText } + deriving (Show, Eq, Hashable, Lift, FromJSON, ToJSON, ToJSONKey, Q.FromCol, Q.ToPrepArg) + +type EventId = T.Text data Ops = INSERT | UPDATE | DELETE | MANUAL deriving (Show) @@ -106,7 +110,7 @@ $(deriveToJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''WebhookConfInfo data CreateEventTriggerQuery = CreateEventTriggerQuery - { cetqName :: !T.Text + { cetqName :: !TriggerName , cetqTable :: !QualifiedTable , cetqInsert :: !(Maybe SubscribeOpSpec) , cetqUpdate :: !(Maybe SubscribeOpSpec) @@ -134,7 +138,7 @@ instance FromJSON CreateEventTriggerQuery where replace <- o .:? "replace" .!= False let regex = "^[A-Za-z]+[A-Za-z0-9_\\-]*$" :: LBS.ByteString compiledRegex = TDFA.makeRegex regex :: TDFA.Regex - isMatch = TDFA.match compiledRegex (T.unpack name) + isMatch = TDFA.match compiledRegex . T.unpack . unNEText $ unTriggerName name if isMatch then return () else fail "only alphanumeric and underscore and hyphens allowed for name" if any isJust [insert, update, delete] || enableManual then @@ -170,7 +174,7 @@ $(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''TriggerOpsDef) data DeleteEventTriggerQuery = DeleteEventTriggerQuery - { detqName :: !T.Text + { detqName :: !TriggerName } deriving (Show, Eq, Lift) $(deriveJSON (aesonDrop 4 snakeCase){omitNothingFields=True} ''DeleteEventTriggerQuery) @@ -187,16 +191,16 @@ data EventTriggerConf $(deriveJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''EventTriggerConf) -data RedeliverEventQuery +newtype RedeliverEventQuery = RedeliverEventQuery - { rdeqEventId :: !EventId + { rdeqEventId :: EventId } deriving (Show, Eq, Lift) $(deriveJSON (aesonDrop 4 snakeCase){omitNothingFields=True} ''RedeliverEventQuery) data InvokeEventTriggerQuery = InvokeEventTriggerQuery - { ietqName :: !T.Text + { ietqName :: !TriggerName , ietqPayload :: !Value } deriving (Show, Eq, Lift) diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs index 11ed7d4680830..48867f76f7cd9 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs @@ -47,7 +47,7 @@ reportSchemaObj (SOTableObj tn (TOPerm rn pt)) = "permission " <> qualObjectToText tn <> "." <> unNEText (getRoleTxt rn) <> "." <> permTypeToCode pt reportSchemaObj (SOTableObj tn (TOTrigger trn )) = - "event-trigger " <> qualObjectToText tn <> "." <> trn + "event-trigger " <> qualObjectToText tn <> "." <> unNEText (unTriggerName trn) instance Show SchemaObjId where show soi = T.unpack $ reportSchemaObj soi From 32dc7e21668ba7b5cc5d18b8745349560ea44f1d Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Wed, 29 May 2019 18:20:51 +0530 Subject: [PATCH 3/9] add tests for NEText --- .../non_empty_text/create_event_trigger.yaml | 31 +++++++++++++++++++ .../create_insert_permission.yaml | 21 +++++++++++++ .../create_object_relationship.yaml | 15 +++++++++ .../create_query_collection.yaml | 17 ++++++++++ .../create_query_collection_queryname.yaml | 17 ++++++++++ .../non_empty_text/create_remote_schema.yaml | 19 ++++++++++++ server/tests-py/test_v1_queries.py | 25 +++++++++++++++ 7 files changed, 145 insertions(+) create mode 100644 server/tests-py/queries/v1/non_empty_text/create_event_trigger.yaml create mode 100644 server/tests-py/queries/v1/non_empty_text/create_insert_permission.yaml create mode 100644 server/tests-py/queries/v1/non_empty_text/create_object_relationship.yaml create mode 100644 server/tests-py/queries/v1/non_empty_text/create_query_collection.yaml create mode 100644 server/tests-py/queries/v1/non_empty_text/create_query_collection_queryname.yaml create mode 100644 server/tests-py/queries/v1/non_empty_text/create_remote_schema.yaml diff --git a/server/tests-py/queries/v1/non_empty_text/create_event_trigger.yaml b/server/tests-py/queries/v1/non_empty_text/create_event_trigger.yaml new file mode 100644 index 0000000000000..5737f5b302223 --- /dev/null +++ b/server/tests-py/queries/v1/non_empty_text/create_event_trigger.yaml @@ -0,0 +1,31 @@ +description: Create event trigger with role "" +url: /v1/query +status: 400 +response: + path: $.name + error: >- + empty string not allowed + code: parse-failed +query: + type: create_event_trigger + args: + name: "" + table: users + webhook: https://httpbin.org/post + insert: + columns: "*" + payload: + - username + update: + columns: + - username + - real_name + payload: "*" + delete: + columns: "*" + headers: + - name: X-Hasura-From-Val + value: myvalue + - name: X-Hasura-From-Env + value_from_env: EVENT_WEBHOOK_HEADER + replace: false diff --git a/server/tests-py/queries/v1/non_empty_text/create_insert_permission.yaml b/server/tests-py/queries/v1/non_empty_text/create_insert_permission.yaml new file mode 100644 index 0000000000000..3302f357d1b23 --- /dev/null +++ b/server/tests-py/queries/v1/non_empty_text/create_insert_permission.yaml @@ -0,0 +1,21 @@ +description: Create permission with role "" +url: /v1/query +status: 400 +response: + path: $.role + error: >- + empty string not allowed + code: parse-failed +query: + type: create_insert_permission + args: + table: article + role: "" + permission: + check: + author_id: X-HASURA-USER-ID + "$or": + - category: editorial + is_reviewed: false + - category: + "$neq": editorial diff --git a/server/tests-py/queries/v1/non_empty_text/create_object_relationship.yaml b/server/tests-py/queries/v1/non_empty_text/create_object_relationship.yaml new file mode 100644 index 0000000000000..00f46f0f59bea --- /dev/null +++ b/server/tests-py/queries/v1/non_empty_text/create_object_relationship.yaml @@ -0,0 +1,15 @@ +description: Create object relationship with name "" +url: /v1/query +status: 400 +response: + path: $.name + error: >- + empty string not allowed + code: parse-failed +query: + type: create_object_relationship + args: + table: article + name: "" + using: + foreign_key_constraint_on: author_id diff --git a/server/tests-py/queries/v1/non_empty_text/create_query_collection.yaml b/server/tests-py/queries/v1/non_empty_text/create_query_collection.yaml new file mode 100644 index 0000000000000..6cb43ce248c9e --- /dev/null +++ b/server/tests-py/queries/v1/non_empty_text/create_query_collection.yaml @@ -0,0 +1,17 @@ +description: Create query collection with name "" +url: /v1/query +status: 400 +response: + path: $.name + error: >- + empty string not allowed + code: parse-failed +query: + type: create_query_collection + args: + name: "" + comment: an optional comment + definition: + queries: + - name: query_1 + query: query { test {id name}} diff --git a/server/tests-py/queries/v1/non_empty_text/create_query_collection_queryname.yaml b/server/tests-py/queries/v1/non_empty_text/create_query_collection_queryname.yaml new file mode 100644 index 0000000000000..6cb43ce248c9e --- /dev/null +++ b/server/tests-py/queries/v1/non_empty_text/create_query_collection_queryname.yaml @@ -0,0 +1,17 @@ +description: Create query collection with name "" +url: /v1/query +status: 400 +response: + path: $.name + error: >- + empty string not allowed + code: parse-failed +query: + type: create_query_collection + args: + name: "" + comment: an optional comment + definition: + queries: + - name: query_1 + query: query { test {id name}} diff --git a/server/tests-py/queries/v1/non_empty_text/create_remote_schema.yaml b/server/tests-py/queries/v1/non_empty_text/create_remote_schema.yaml new file mode 100644 index 0000000000000..8cfbf7cb5fc06 --- /dev/null +++ b/server/tests-py/queries/v1/non_empty_text/create_remote_schema.yaml @@ -0,0 +1,19 @@ +description: Create remote schema with name "" +url: /v1/query +status: 400 +response: + path: $.name + error: >- + empty string not allowed + code: parse-failed +query: + type: add_remote_schema + args: + name: "" + definition: + url: https://remote-server.com/graphql + headers: + - name: X-Server-Request-From + value: Hasura + forward_client_headers: false + comment: some optional comment diff --git a/server/tests-py/test_v1_queries.py b/server/tests-py/test_v1_queries.py index 75f153dd47a49..d603e3f05aa85 100644 --- a/server/tests-py/test_v1_queries.py +++ b/server/tests-py/test_v1_queries.py @@ -573,3 +573,28 @@ def test_create_permission_user_role_error(self, hge_ctx): @classmethod def dir(cls): return "queries/v1/permissions" + + +class TestNEText: + + def test_create_event_trigger(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/create_event_trigger.yaml') + + def test_create_insert_permission(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/create_insert_permission.yaml') + + def test_create_query_collection(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/create_query_collection.yaml') + + def test_create_query_collection_queryname(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/create_query_collection_queryname.yaml') + + def test_create_object_relationship(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/create_object_relationship.yaml') + + def test_create_remote_schema(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/create_remote_schema.yaml') + + @classmethod + def dir(cls): + return "queries/v1/non_empty_text" From d25479a0f6c0a0390ab8a213ee85fad622a660c4 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 30 May 2019 11:53:42 +0530 Subject: [PATCH 4/9] Fix FromJSONKey instance of NEText --- server/src-lib/Hasura/RQL/Types/Common.hs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index 464f54ea60e2d..ede94fb787aa2 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -31,6 +31,7 @@ import Hasura.SQL.Types import Data.Aeson import Data.Aeson.Casing import Data.Aeson.TH +import Data.Aeson.Types import qualified Data.HashMap.Strict as HM import qualified Data.Text as T import qualified Database.PG.Query as Q @@ -54,13 +55,16 @@ mkNEText :: T.Text -> Maybe NEText mkNEText "" = Nothing mkNEText text = Just $ NEText text +parseNEText :: T.Text -> Parser NEText +parseNEText text = case mkNEText text of + Nothing -> fail "empty string not allowed" + Just neText -> return neText + instance FromJSON NEText where - parseJSON = withText "String" - $ \text -> case mkNEText text of - Nothing -> fail "empty string not allowed" - Just neText -> return neText + parseJSON = withText "String" parseNEText -instance FromJSONKey NEText +instance FromJSONKey NEText where + fromJSONKey = FromJSONKeyTextParser parseNEText instance Q.FromCol NEText where fromCol bs = mkNEText <$> Q.fromCol bs From 7d8801f825a420d1b7e07bb714ba7104cc16c471 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 30 May 2019 14:56:08 +0530 Subject: [PATCH 5/9] Reduce code duplication for unboxing NEText --- .../src-lib/Hasura/GraphQL/Resolve/Insert.hs | 6 ++-- server/src-lib/Hasura/GraphQL/Schema.hs | 29 +++++++++---------- server/src-lib/Hasura/RQL/Types/BoolExp.hs | 2 +- server/src-lib/Hasura/RQL/Types/Common.hs | 10 +++++-- .../Hasura/RQL/Types/SchemaCacheTypes.hs | 2 +- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs index c6b07478ec537..8b5a7695a5cd4 100644 --- a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs +++ b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs @@ -280,7 +280,7 @@ validateInsert insCols objRels addCols = do forM_ objRels $ \relInfo -> do let lCols = map fst $ riMapping relInfo relName = riName relInfo - relNameTxt = unNEText $ getRelTxt relName + relNameTxt = relNameToTxt relName lColConflicts = lCols `intersect` (addCols <> insCols) withPathK relNameTxt $ unless (null lColConflicts) $ throwVE $ "cannot insert object relation ship " <> relName @@ -311,7 +311,7 @@ insertObjRel strfyNum role objRelIns = RelIns singleObjIns relInfo = objRelIns multiObjIns = singleToMulti singleObjIns relName = riName relInfo - relNameTxt = unNEText $ getRelTxt relName + relNameTxt = relNameToTxt relName mapCols = riMapping relInfo tn = riRTable relInfo allCols = _aiTableCols singleObjIns @@ -352,7 +352,7 @@ insertArrRel strfyNum role resCols arrRelIns = RelIns multiObjIns relInfo = arrRelIns colMapping = riMapping relInfo tn = riRTable relInfo - relNameTxt = unNEText . getRelTxt $ riName relInfo + relNameTxt = relNameToTxt $ riName relInfo mutFlds = [("affected_rows", RR.MCount)] -- | insert an object with object and array relationships diff --git a/server/src-lib/Hasura/GraphQL/Schema.hs b/server/src-lib/Hasura/GraphQL/Schema.hs index e44c9fa77d74d..9a2b4a0512b6b 100644 --- a/server/src-lib/Hasura/GraphQL/Schema.hs +++ b/server/src-lib/Hasura/GraphQL/Schema.hs @@ -77,8 +77,7 @@ isValidCol :: PGCol -> Bool isValidCol = isValidName . G.Name . getPGColTxt isValidRel :: ToTxt a => RelName -> QualifiedObject a -> Bool -isValidRel rn rt = isValidName (G.Name . unNEText $ getRelTxt rn) - && isValidObjectName rt +isValidRel rn rt = isValidName (mkRelName rn) && isValidObjectName rt isValidField :: FieldInfo -> Bool isValidField = \case @@ -128,10 +127,10 @@ mkColName :: PGCol -> G.Name mkColName (PGCol n) = G.Name n mkRelName :: RelName -> G.Name -mkRelName (RelName r) = G.Name $ unNEText r +mkRelName rn = G.Name $ relNameToTxt rn mkAggRelName :: RelName -> G.Name -mkAggRelName (RelName r) = G.Name $ unNEText r <> "_aggregate" +mkAggRelName rn = G.Name $ relNameToTxt rn <> "_aggregate" mkBoolExpName :: QualifiedTable -> G.Name mkBoolExpName tn = @@ -239,13 +238,13 @@ mkRelFld allowAgg (RelInfo rn rTy _ remTab isManual) isNullable = case rTy of ObjRel -> [objRelFld] where objRelFld = mkHsraObjFldInfo (Just "An object relationship") - (G.Name . unNEText $ getRelTxt rn) Map.empty objRelTy + (mkRelName rn) Map.empty objRelTy objRelTy = bool (G.toGT $ G.toNT relTabTy) (G.toGT relTabTy) isObjRelNullable isObjRelNullable = isManual || isNullable relTabTy = mkTableTy remTab arrRelFld = - mkHsraObjFldInfo (Just "An array relationship") (G.Name . unNEText $ getRelTxt rn) + mkHsraObjFldInfo (Just "An array relationship") (mkRelName rn) (fromInpValL $ mkSelArgs remTab) arrRelTy arrRelTy = G.toGT $ G.toNT $ G.toLT $ G.toNT $ mkTableTy remTab aggArrRelFld = mkHsraObjFldInfo (Just "An aggregated array relationship") @@ -547,7 +546,7 @@ mkBoolExpInp tn fields = Left (PGColInfo colName colTy _) -> mk (mkColName colName) (mkCompExpTy colTy) Right (RelInfo relName _ _ remTab _, _, _, _, _) -> - mk (G.Name . unNEText $ getRelTxt relName) (mkBoolExpTy remTab) + mk (mkRelName relName) (mkBoolExpTy remTab) mkPGColInp :: PGColInfo -> InpValInfo mkPGColInp (PGColInfo colName colTy _) = @@ -951,13 +950,13 @@ mkInsInp tn insCols relInfoMap = relInps = flip map (Map.toList relInfoMap) $ \(relName, relInfo) -> - let rty = riType relInfo - remoteQT = riRTable relInfo - in case rty of - ObjRel -> InpValInfo Nothing (G.Name . unNEText $ getRelTxt relName) Nothing $ - G.toGT $ mkObjInsInpTy remoteQT - ArrRel -> InpValInfo Nothing (G.Name . unNEText $ getRelTxt relName) Nothing $ - G.toGT $ mkArrInsInpTy remoteQT + let remoteQT = riRTable relInfo + tyMaker = case riType relInfo of + ObjRel -> mkObjInsInpTy + ArrRel -> mkArrInsInpTy + in InpValInfo Nothing (mkRelName relName) Nothing $ + G.toGT $ tyMaker remoteQT + {- @@ -1333,7 +1332,7 @@ mkGCtxRole' tn insPermM selPermM updColsM mkFld ty = \case Left ci -> [((ty, mkColName $ pgiName ci), Left ci)] Right (ri, allowAgg, perm, lim, _) -> - let relFld = ( (ty, G.Name . unNEText . getRelTxt $ riName ri) + let relFld = ( (ty, mkRelName $ riName ri) , Right (ri, False, perm, lim) ) aggRelFld = ( (ty, mkAggRelName $ riName ri) diff --git a/server/src-lib/Hasura/RQL/Types/BoolExp.hs b/server/src-lib/Hasura/RQL/Types/BoolExp.hs index 1e21ae755f19f..8d6d44c4f919a 100644 --- a/server/src-lib/Hasura/RQL/Types/BoolExp.hs +++ b/server/src-lib/Hasura/RQL/Types/BoolExp.hs @@ -287,7 +287,7 @@ instance ToJSON AnnBoolExpPartialSQL where , toJSON (pci, map opExpSToJSON opExps) ) AVRel ri relBoolExp -> - ( unNEText . getRelTxt $ riName ri + ( relNameToTxt $ riName ri , toJSON (ri, toJSON relBoolExp) ) opExpSToJSON :: OpExpG PartialSQLExp -> Value diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index ede94fb787aa2..f54bb9fc9885b 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -1,6 +1,7 @@ module Hasura.RQL.Types.Common ( PGColInfo(..) , RelName(..) + , relNameToTxt , RelType(..) , rootRelName , relTypeToTxt @@ -81,14 +82,17 @@ newtype RelName deriving (Show, Eq, Hashable, FromJSON, ToJSON, Q.ToPrepArg, Q.FromCol, Lift) instance IsIden RelName where - toIden (RelName r) = Iden $ unNEText r + toIden rn = Iden $ relNameToTxt rn instance DQuote RelName where - dquoteTxt (RelName r) = unNEText r + dquoteTxt = relNameToTxt rootRelName :: RelName rootRelName = RelName rootText +relNameToTxt :: RelName -> T.Text +relNameToTxt = unNEText . getRelTxt + relTypeToTxt :: RelType -> T.Text relTypeToTxt ObjRel = "object" relTypeToTxt ArrRel = "array" @@ -139,7 +143,7 @@ fromPGCol :: PGCol -> FieldName fromPGCol (PGCol c) = FieldName c fromRel :: RelName -> FieldName -fromRel (RelName r) = FieldName $ unNEText r +fromRel rn = FieldName $ relNameToTxt rn newtype TQueryName = TQueryName { getTQueryName :: NEText } diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs index 48867f76f7cd9..696f112e1af47 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs @@ -40,7 +40,7 @@ reportSchemaObj (SOQTemplate qtn) = reportSchemaObj (SOTableObj tn (TOCol cn)) = "column " <> qualObjectToText tn <> "." <> getPGColTxt cn reportSchemaObj (SOTableObj tn (TORel cn)) = - "relationship " <> qualObjectToText tn <> "." <> unNEText (getRelTxt cn) + "relationship " <> qualObjectToText tn <> "." <> relNameToTxt cn reportSchemaObj (SOTableObj tn (TOCons cn)) = "constraint " <> qualObjectToText tn <> "." <> getConstraintTxt cn reportSchemaObj (SOTableObj tn (TOPerm rn pt)) = From 65823098b8f7c180c854b4f1fa71ec83a495e4b5 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Mon, 3 Jun 2019 12:25:32 +0530 Subject: [PATCH 6/9] Reduce code duplication for unboxing NEText #2 --- server/src-lib/Hasura/RQL/DDL/EventTrigger.hs | 4 ++-- server/src-lib/Hasura/RQL/Types.hs | 4 ++-- server/src-lib/Hasura/RQL/Types/Common.hs | 2 +- server/src-lib/Hasura/RQL/Types/EventTrigger.hs | 4 ++++ server/src-lib/Hasura/RQL/Types/Permission.hs | 10 +++++++--- server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs | 4 ++-- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs b/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs index 98d026aa0f37f..45f15bec275b4 100644 --- a/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs +++ b/server/src-lib/Hasura/RQL/DDL/EventTrigger.hs @@ -42,7 +42,7 @@ triggerTmplt = case parseGingerTmplt $(FE.embedStringFile "src-rsr/trigger.sql.j Right tmplt -> Just tmplt pgIdenTrigger:: Ops -> TriggerName -> T.Text -pgIdenTrigger op trn = pgFmtIden . qualifyTriggerName op . unNEText $ unTriggerName trn +pgIdenTrigger op trn = pgFmtIden . qualifyTriggerName op $ triggerNameToTxt trn where qualifyTriggerName op' trn' = "notify_hasura_" <> trn' <> "_" <> T.pack (show op') @@ -61,7 +61,7 @@ getTriggerSql -> Maybe T.Text getTriggerSql op trn qt allCols strfyNum spec = let globalCtx = HashMap.fromList - [ (T.pack "NAME", unNEText $ unTriggerName trn) + [ (T.pack "NAME", triggerNameToTxt trn) , (T.pack "QUALIFIED_TRIGGER_NAME", pgIdenTrigger op trn) , (T.pack "QUALIFIED_TABLE", toSQLTxt qt) ] diff --git a/server/src-lib/Hasura/RQL/Types.hs b/server/src-lib/Hasura/RQL/Types.hs index 22e3814dc6089..593d46b940a18 100644 --- a/server/src-lib/Hasura/RQL/Types.hs +++ b/server/src-lib/Hasura/RQL/Types.hs @@ -104,7 +104,7 @@ askTabInfoFromTrigger trn = do let tabInfos = M.elems $ scTables sc liftMaybe (err400 NotExists errMsg) $ find (isJust.M.lookup trn.tiEventTriggerInfoMap) tabInfos where - errMsg = "event trigger " <> unNEText (unTriggerName trn) <<> " does not exist" + errMsg = "event trigger " <> triggerNameToTxt trn <<> " does not exist" askEventTriggerInfo :: (QErrM m, CacheRM m) @@ -114,7 +114,7 @@ askEventTriggerInfo trn = do let etim = tiEventTriggerInfoMap ti liftMaybe (err400 NotExists errMsg) $ M.lookup trn etim where - errMsg = "event trigger " <> unNEText (unTriggerName trn) <<> " does not exist" + errMsg = "event trigger " <> triggerNameToTxt trn <<> " does not exist" askQTemplateInfo :: (P1C m) diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index f54bb9fc9885b..dc1d0100a8834 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -143,7 +143,7 @@ fromPGCol :: PGCol -> FieldName fromPGCol (PGCol c) = FieldName c fromRel :: RelName -> FieldName -fromRel rn = FieldName $ relNameToTxt rn +fromRel = FieldName . relNameToTxt newtype TQueryName = TQueryName { getTQueryName :: NEText } diff --git a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs index f22aefae561b7..359cb13d5f071 100644 --- a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs +++ b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs @@ -3,6 +3,7 @@ module Hasura.RQL.Types.EventTrigger , SubscribeOpSpec(..) , SubscribeColumns(..) , TriggerName(..) + , triggerNameToTxt , Ops(..) , EventId , TriggerOpsDef(..) @@ -39,6 +40,9 @@ import qualified Text.Regex.TDFA as TDFA newtype TriggerName = TriggerName { unTriggerName :: NEText } deriving (Show, Eq, Hashable, Lift, FromJSON, ToJSON, ToJSONKey, Q.FromCol, Q.ToPrepArg) +triggerNameToTxt :: TriggerName -> Text +triggerNameToTxt = unNEText . unTriggerName + type EventId = T.Text data Ops = INSERT | UPDATE | DELETE | MANUAL deriving (Show) diff --git a/server/src-lib/Hasura/RQL/Types/Permission.hs b/server/src-lib/Hasura/RQL/Types/Permission.hs index 93d6c4ffc4d17..0838a803db778 100644 --- a/server/src-lib/Hasura/RQL/Types/Permission.hs +++ b/server/src-lib/Hasura/RQL/Types/Permission.hs @@ -1,5 +1,6 @@ module Hasura.RQL.Types.Permission ( RoleName(..) + , roleNameToTxt , SessVar , SessVarVal @@ -49,6 +50,9 @@ newtype RoleName instance DQuote RoleName where dquoteTxt (RoleName r) = unNEText r +roleNameToTxt :: RoleName -> Text +roleNameToTxt = unNEText . getRoleTxt + adminRole :: RoleName adminRole = RoleName adminText @@ -92,7 +96,7 @@ data UserInfo mkUserInfo :: RoleName -> UserVars -> UserInfo mkUserInfo rn (UserVars v) = - UserInfo rn $ UserVars $ Map.insert userRoleHeader (unNEText $ getRoleTxt rn) $ + UserInfo rn $ UserVars $ Map.insert userRoleHeader (roleNameToTxt rn) $ foldl (flip Map.delete) v [adminSecretHeader, deprecatedAccessKeyHeader] instance Hashable UserInfo @@ -104,7 +108,7 @@ instance Hashable UserInfo userInfoToList :: UserInfo -> [(Text, Text)] userInfoToList userInfo = let vars = Map.toList $ unUserVars . userVars $ userInfo - rn = unNEText . getRoleTxt . userRole $ userInfo + rn = roleNameToTxt . userRole $ userInfo in (userRoleHeader, rn) : vars adminUserInfo :: UserInfo @@ -164,7 +168,7 @@ instance Show PermId where show $ mconcat [ getTableTxt tn , "." - , unNEText $ getRoleTxt rn + , roleNameToTxt rn , "." , T.pack $ show pType ] diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs index 696f112e1af47..20e0461353d4b 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs @@ -44,10 +44,10 @@ reportSchemaObj (SOTableObj tn (TORel cn)) = reportSchemaObj (SOTableObj tn (TOCons cn)) = "constraint " <> qualObjectToText tn <> "." <> getConstraintTxt cn reportSchemaObj (SOTableObj tn (TOPerm rn pt)) = - "permission " <> qualObjectToText tn <> "." <> unNEText (getRoleTxt rn) + "permission " <> qualObjectToText tn <> "." <> roleNameToTxt rn <> "." <> permTypeToCode pt reportSchemaObj (SOTableObj tn (TOTrigger trn )) = - "event-trigger " <> qualObjectToText tn <> "." <> unNEText (unTriggerName trn) + "event-trigger " <> qualObjectToText tn <> "." <> triggerNameToTxt trn instance Show SchemaObjId where show soi = T.unpack $ reportSchemaObj soi From 9b239c8f519a8bdbcb0bb845ae71ce98f80541c7 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Thu, 6 Jun 2019 19:10:46 +0530 Subject: [PATCH 7/9] Reduce code duplication for unboxing NEText #3 --- server/src-lib/Hasura/RQL/DDL/Permission.hs | 4 ++-- server/src-lib/Hasura/RQL/Types/EventTrigger.hs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src-lib/Hasura/RQL/DDL/Permission.hs b/server/src-lib/Hasura/RQL/DDL/Permission.hs index 80be42dec89fc..30a9dfd6b7696 100644 --- a/server/src-lib/Hasura/RQL/DDL/Permission.hs +++ b/server/src-lib/Hasura/RQL/DDL/Permission.hs @@ -82,9 +82,9 @@ type InsPermDef = PermDef InsPerm type CreateInsPerm = CreatePerm InsPerm buildViewName :: QualifiedTable -> RoleName -> PermType -> QualifiedTable -buildViewName (QualifiedObject sn tn) (RoleName rTxt) pt = +buildViewName (QualifiedObject sn tn) rn pt = QualifiedObject hdbViewsSchema $ TableName - (unNEText rTxt <> "__" <> T.pack (show pt) <> "__" <> snTxt <> "__" <> tnTxt) + (roleNameToTxt rn <> "__" <> T.pack (show pt) <> "__" <> snTxt <> "__" <> tnTxt) where snTxt = getSchemaTxt sn tnTxt = getTableTxt tn diff --git a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs index 359cb13d5f071..3abe282568ec8 100644 --- a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs +++ b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs @@ -142,7 +142,7 @@ instance FromJSON CreateEventTriggerQuery where replace <- o .:? "replace" .!= False let regex = "^[A-Za-z]+[A-Za-z0-9_\\-]*$" :: LBS.ByteString compiledRegex = TDFA.makeRegex regex :: TDFA.Regex - isMatch = TDFA.match compiledRegex . T.unpack . unNEText $ unTriggerName name + isMatch = TDFA.match compiledRegex . T.unpack $ triggerNameToTxt name if isMatch then return () else fail "only alphanumeric and underscore and hyphens allowed for name" if any isJust [insert, update, delete] || enableManual then From fa166e8e0334faef09605af9366b897d28d298e4 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Fri, 21 Jun 2019 14:00:01 +0530 Subject: [PATCH 8/9] Add comments --- server/src-lib/Hasura/RQL/Types/Permission.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src-lib/Hasura/RQL/Types/Permission.hs b/server/src-lib/Hasura/RQL/Types/Permission.hs index 0838a803db778..b52efc3c007e6 100644 --- a/server/src-lib/Hasura/RQL/Types/Permission.hs +++ b/server/src-lib/Hasura/RQL/Types/Permission.hs @@ -69,6 +69,7 @@ newtype UserVars isUserVar :: T.Text -> Bool isUserVar = T.isPrefixOf "x-hasura-" . T.toLower +-- returns Nothing if x-hasura-role is an empty string roleFromVars :: UserVars -> Maybe RoleName roleFromVars uv = getVarVal userRoleHeader uv >>= fmap RoleName . mkNEText From be236b371e11d3e68c6abf67e22cf05f9a1009a1 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Mon, 8 Jul 2019 18:10:34 +0530 Subject: [PATCH 9/9] Rename NEText to NonEmptyText --- .../src-lib/Hasura/GraphQL/Resolve/Insert.hs | 2 +- .../src-lib/Hasura/RQL/DDL/QueryCollection.hs | 2 +- server/src-lib/Hasura/RQL/Types/Common.hs | 48 +++++++++---------- .../src-lib/Hasura/RQL/Types/EventTrigger.hs | 6 +-- server/src-lib/Hasura/RQL/Types/Permission.hs | 12 ++--- .../Hasura/RQL/Types/QueryCollection.hs | 6 +-- .../src-lib/Hasura/RQL/Types/RemoteSchema.hs | 4 +- .../Hasura/RQL/Types/SchemaCacheTypes.hs | 2 +- server/src-lib/Hasura/Server/App.hs | 2 +- server/src-lib/Hasura/Server/Auth/JWT.hs | 2 +- server/src-lib/Hasura/Server/Init.hs | 6 +-- server/tests-py/test_v1_queries.py | 2 +- 12 files changed, 47 insertions(+), 47 deletions(-) diff --git a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs index 8b5a7695a5cd4..ce9d30cfed629 100644 --- a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs +++ b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs @@ -114,7 +114,7 @@ traverseInsObj rim (gName, annVal) defVal@(AnnInsObj cols objRels arrRels) = -- if relational insert input is 'null' then ignore -- return default value fmap (fromMaybe defVal) $ forM objM $ \obj -> do - let relNameM = RelName <$> mkNEText (G.unName gName) + let relNameM = RelName <$> mkNonEmptyText (G.unName gName) onConflictM = OMap.lookup "on_conflict" obj relName <- onNothing relNameM $ throw500 "found empty GName String" dataVal <- onNothing (OMap.lookup "data" obj) $ diff --git a/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs b/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs index 71eefed7d9910..c18208aa3a0a6 100644 --- a/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs +++ b/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs @@ -34,7 +34,7 @@ addCollectionP2 (CollectionDef queryList) = withPathK "queries" $ unless (null duplicateNames) $ throw400 NotSupported $ "found duplicate query names " - <> T.intercalate ", " (map (T.dquote . unNEText . unQueryName) duplicateNames) + <> T.intercalate ", " (map (T.dquote . unNonEmptyText . unQueryName) duplicateNames) where duplicateNames = duplicates $ map _lqName queryList diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index 265bd01b17633..d05330ae28ddd 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -20,9 +20,9 @@ module Hasura.RQL.Types.Common , MutateResp(..) , ForeignKey(..) - , NEText - , mkNEText - , unNEText + , NonEmptyText + , mkNonEmptyText + , unNonEmptyText , adminText , rootText ) where @@ -50,36 +50,36 @@ data PGColInfo $(deriveJSON (aesonDrop 3 snakeCase) ''PGColInfo) -newtype NEText = NEText {unNEText :: T.Text} +newtype NonEmptyText = NonEmptyText {unNonEmptyText :: T.Text} deriving (Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, Lift, Q.ToPrepArg, DQuote) -mkNEText :: T.Text -> Maybe NEText -mkNEText "" = Nothing -mkNEText text = Just $ NEText text +mkNonEmptyText :: T.Text -> Maybe NonEmptyText +mkNonEmptyText "" = Nothing +mkNonEmptyText text = Just $ NonEmptyText text -parseNEText :: T.Text -> Parser NEText -parseNEText text = case mkNEText text of +parseNonEmptyText :: T.Text -> Parser NonEmptyText +parseNonEmptyText text = case mkNonEmptyText text of Nothing -> fail "empty string not allowed" Just neText -> return neText -instance FromJSON NEText where - parseJSON = withText "String" parseNEText +instance FromJSON NonEmptyText where + parseJSON = withText "String" parseNonEmptyText -instance FromJSONKey NEText where - fromJSONKey = FromJSONKeyTextParser parseNEText +instance FromJSONKey NonEmptyText where + fromJSONKey = FromJSONKeyTextParser parseNonEmptyText -instance Q.FromCol NEText where - fromCol bs = mkNEText <$> Q.fromCol bs +instance Q.FromCol NonEmptyText where + fromCol bs = mkNonEmptyText <$> Q.fromCol bs >>= maybe (Left "empty string not allowed") Right -adminText :: NEText -adminText = NEText "admin" +adminText :: NonEmptyText +adminText = NonEmptyText "admin" -rootText :: NEText -rootText = NEText "root" +rootText :: NonEmptyText +rootText = NonEmptyText "root" newtype RelName - = RelName {getRelTxt :: NEText} + = RelName {getRelTxt :: NonEmptyText} deriving (Show, Eq, Hashable, FromJSON, ToJSON, Q.ToPrepArg, Q.FromCol, Lift) instance IsIden RelName where @@ -92,7 +92,7 @@ rootRelName :: RelName rootRelName = RelName rootText relNameToTxt :: RelName -> T.Text -relNameToTxt = unNEText . getRelTxt +relNameToTxt = unNonEmptyText . getRelTxt relTypeToTxt :: RelType -> T.Text relTypeToTxt ObjRel = "object" @@ -147,15 +147,15 @@ fromRel :: RelName -> FieldName fromRel = FieldName . relNameToTxt newtype TQueryName - = TQueryName { getTQueryName :: NEText } + = TQueryName { getTQueryName :: NonEmptyText } deriving ( Show, Eq, Hashable, FromJSONKey, ToJSONKey , FromJSON, ToJSON, Q.ToPrepArg, Q.FromCol, Lift) instance IsIden TQueryName where - toIden (TQueryName r) = Iden $ unNEText r + toIden (TQueryName r) = Iden $ unNonEmptyText r instance DQuote TQueryName where - dquoteTxt (TQueryName r) = unNEText r + dquoteTxt (TQueryName r) = unNonEmptyText r newtype TemplateParam = TemplateParam { getTemplateParam :: T.Text } diff --git a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs index 3abe282568ec8..8dfc4115a62a9 100644 --- a/server/src-lib/Hasura/RQL/Types/EventTrigger.hs +++ b/server/src-lib/Hasura/RQL/Types/EventTrigger.hs @@ -28,7 +28,7 @@ import Data.Aeson.Casing import Data.Aeson.TH import Hasura.Prelude import Hasura.RQL.DDL.Headers -import Hasura.RQL.Types.Common (NEText (..)) +import Hasura.RQL.Types.Common (NonEmptyText (..)) import Hasura.SQL.Types import Language.Haskell.TH.Syntax (Lift) @@ -37,11 +37,11 @@ import qualified Data.Text as T import qualified Database.PG.Query as Q import qualified Text.Regex.TDFA as TDFA -newtype TriggerName = TriggerName { unTriggerName :: NEText } +newtype TriggerName = TriggerName { unTriggerName :: NonEmptyText } deriving (Show, Eq, Hashable, Lift, FromJSON, ToJSON, ToJSONKey, Q.FromCol, Q.ToPrepArg) triggerNameToTxt :: TriggerName -> Text -triggerNameToTxt = unNEText . unTriggerName +triggerNameToTxt = unNonEmptyText . unTriggerName type EventId = T.Text diff --git a/server/src-lib/Hasura/RQL/Types/Permission.hs b/server/src-lib/Hasura/RQL/Types/Permission.hs index b52efc3c007e6..dacc4af0251dd 100644 --- a/server/src-lib/Hasura/RQL/Types/Permission.hs +++ b/server/src-lib/Hasura/RQL/Types/Permission.hs @@ -24,8 +24,8 @@ module Hasura.RQL.Types.Permission ) where import Hasura.Prelude -import Hasura.RQL.Types.Common (NEText, adminText, mkNEText, - unNEText) +import Hasura.RQL.Types.Common (NonEmptyText, adminText, mkNonEmptyText, + unNonEmptyText) import Hasura.Server.Utils (adminSecretHeader, deprecatedAccessKeyHeader, userRoleHeader) @@ -43,15 +43,15 @@ import qualified Data.Text as T import qualified PostgreSQL.Binary.Decoding as PD newtype RoleName - = RoleName {getRoleTxt :: NEText} + = RoleName {getRoleTxt :: NonEmptyText} deriving ( Show, Eq, Hashable, FromJSONKey, ToJSONKey, FromJSON , ToJSON, Q.FromCol, Q.ToPrepArg, Lift) instance DQuote RoleName where - dquoteTxt (RoleName r) = unNEText r + dquoteTxt = roleNameToTxt roleNameToTxt :: RoleName -> Text -roleNameToTxt = unNEText . getRoleTxt +roleNameToTxt = unNonEmptyText . getRoleTxt adminRole :: RoleName adminRole = RoleName adminText @@ -72,7 +72,7 @@ isUserVar = T.isPrefixOf "x-hasura-" . T.toLower -- returns Nothing if x-hasura-role is an empty string roleFromVars :: UserVars -> Maybe RoleName roleFromVars uv = - getVarVal userRoleHeader uv >>= fmap RoleName . mkNEText + getVarVal userRoleHeader uv >>= fmap RoleName . mkNonEmptyText getVarVal :: SessVar -> UserVars -> Maybe SessVarVal getVarVal k = diff --git a/server/src-lib/Hasura/RQL/Types/QueryCollection.hs b/server/src-lib/Hasura/RQL/Types/QueryCollection.hs index 016c0d7e6c1a0..96477eaae9909 100644 --- a/server/src-lib/Hasura/RQL/Types/QueryCollection.hs +++ b/server/src-lib/Hasura/RQL/Types/QueryCollection.hs @@ -2,7 +2,7 @@ module Hasura.RQL.Types.QueryCollection where import Hasura.GraphQL.Validate.Types (stripTypenames) import Hasura.Prelude -import Hasura.RQL.Types.Common (NEText) +import Hasura.RQL.Types.Common (NonEmptyText) import Hasura.SQL.Types import Data.Aeson @@ -16,13 +16,13 @@ import qualified Database.PG.Query as Q import qualified Language.GraphQL.Draft.Syntax as G newtype CollectionName - = CollectionName {unCollectionName :: NEText} + = CollectionName {unCollectionName :: NonEmptyText} deriving ( Show, Eq, Ord, Hashable, ToJSON, ToJSONKey, Lift , FromJSON, Q.FromCol, Q.ToPrepArg, DQuote ) newtype QueryName - = QueryName {unQueryName :: NEText} + = QueryName {unQueryName :: NonEmptyText} deriving (Show, Eq, Ord, Hashable, Lift, ToJSON, ToJSONKey, FromJSON, DQuote) newtype GQLQuery diff --git a/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs b/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs index 13ab4f594ac36..bd03abf4268d1 100644 --- a/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs +++ b/server/src-lib/Hasura/RQL/Types/RemoteSchema.hs @@ -1,7 +1,7 @@ module Hasura.RQL.Types.RemoteSchema where import Hasura.Prelude -import Hasura.RQL.Types.Common (NEText) +import Hasura.RQL.Types.Common (NonEmptyText) import Language.Haskell.TH.Syntax (Lift) import System.Environment (lookupEnv) @@ -20,7 +20,7 @@ type UrlFromEnv = Text newtype RemoteSchemaName = RemoteSchemaName - { unRemoteSchemaName :: NEText } + { unRemoteSchemaName :: NonEmptyText } deriving ( Show, Eq, Lift, Hashable, J.ToJSON, J.ToJSONKey , J.FromJSON, Q.ToPrepArg, Q.FromCol, DQuote ) diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs index 20e0461353d4b..0833504aa1283 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCacheTypes.hs @@ -36,7 +36,7 @@ reportSchemaObj :: SchemaObjId -> T.Text reportSchemaObj (SOTable tn) = "table " <> qualObjectToText tn reportSchemaObj (SOFunction fn) = "function " <> qualObjectToText fn reportSchemaObj (SOQTemplate qtn) = - "query-template " <> unNEText (getTQueryName qtn) + "query-template " <> unNonEmptyText (getTQueryName qtn) reportSchemaObj (SOTableObj tn (TOCol cn)) = "column " <> qualObjectToText tn <> "." <> getPGColTxt cn reportSchemaObj (SOTableObj tn (TORel cn)) = diff --git a/server/src-lib/Hasura/Server/App.hs b/server/src-lib/Hasura/Server/App.hs index 16a47b7ec6c19..0565d6d118b05 100644 --- a/server/src-lib/Hasura/Server/App.hs +++ b/server/src-lib/Hasura/Server/App.hs @@ -528,7 +528,7 @@ httpApp corsCfg serverCtx enableConsole consoleAssetsDir enableTelemetry = do gqlExplainHandler expQuery mkTmpltName tmpltText = - onNothing (mkNEText tmpltText) $ throw400 NotSupported "template name is empty string" + onNothing (mkNonEmptyText tmpltText) $ throw400 NotSupported "template name is empty string" enableGraphQL = isGraphQLEnabled serverCtx enableMetadata = isMetadataEnabled serverCtx diff --git a/server/src-lib/Hasura/Server/Auth/JWT.hs b/server/src-lib/Hasura/Server/Auth/JWT.hs index 08b637c0f9d8b..9b0a520249559 100644 --- a/server/src-lib/Hasura/Server/Auth/JWT.hs +++ b/server/src-lib/Hasura/Server/Auth/JWT.hs @@ -260,7 +260,7 @@ processAuthZHeader jwtCtx headers authzHeader = do getCurrentRole defaultRole = let userRoleHeaderB = CS.cs userRoleHeader mUserRole = snd <$> find (\h -> fst h == CI.mk userRoleHeaderB) headers - in maybe defaultRole RoleName $ mUserRole >>= mkNEText . bsToTxt + in maybe defaultRole RoleName $ mUserRole >>= mkNonEmptyText . bsToTxt decodeJSON val = case A.fromJSON val of A.Error e -> throw400 JWTInvalidClaims ("x-hasura-* claims: " <> T.pack e) diff --git a/server/src-lib/Hasura/Server/Init.hs b/server/src-lib/Hasura/Server/Init.hs index 1e48543a8a942..3af503ebae518 100644 --- a/server/src-lib/Hasura/Server/Init.hs +++ b/server/src-lib/Hasura/Server/Init.hs @@ -19,7 +19,7 @@ import qualified Text.PrettyPrint.ANSI.Leijen as PP import Hasura.Prelude import Hasura.RQL.Types ( RoleName (..) , SchemaCache (..) - , mkNEText ) + , mkNonEmptyText ) import Hasura.Server.Auth import Hasura.Server.Cors import Hasura.Server.Logging @@ -152,7 +152,7 @@ instance FromEnv AdminSecret where fromEnv = Right . AdminSecret . T.pack instance FromEnv RoleName where - fromEnv string = case mkNEText (T.pack string) of + fromEnv string = case mkNonEmptyText (T.pack string) of Nothing -> Left "empty string not allowed" Just neText -> Right $ RoleName neText @@ -757,7 +757,7 @@ parseUnAuthRole = fmap mkRoleName $ optional $ help (snd unAuthRoleEnv) ) where - mkRoleName mText = mText >>= (fmap RoleName . mkNEText) + mkRoleName mText = mText >>= (fmap RoleName . mkNonEmptyText) parseCorsConfig :: Parser (Maybe CorsConfig) parseCorsConfig = mapCC <$> disableCors <*> corsDomain diff --git a/server/tests-py/test_v1_queries.py b/server/tests-py/test_v1_queries.py index 1b93483c351f4..ea5073fb450cc 100644 --- a/server/tests-py/test_v1_queries.py +++ b/server/tests-py/test_v1_queries.py @@ -578,7 +578,7 @@ def dir(cls): return "queries/v1/permissions" -class TestNEText: +class TestNonEmptyText: def test_create_event_trigger(self, hge_ctx): check_query_f(hge_ctx, self.dir() + '/create_event_trigger.yaml')