Repository: hasura/graphql-engine
File: server/src-lib/Hasura/RQL/DDL/Permission.hs (Haskell)

Code before:
buildSelPermInfo
  :: (QErrM m, CacheRM m)
  => TableInfo PGColumnInfo
  -> SelPerm
  -> m (WithDeps SelPermInfo)
buildSelPermInfo tabInfo sp = do
  let pgCols     = convColSpec fieldInfoMap $ spColumns sp

  (be, beDeps) <- withPathK "filter" $
    procBoolExp tn fieldInfoMap  $ spFilter sp

  -- check if the columns exist
  void $ withPathK "columns" $ indexedForM pgCols $ \pgCol ->
    askPGType fieldInfoMap pgCol autoInferredErr

  -- validate computed fields
  withPathK "computed_fields" $ indexedForM_ computedFields $ \name -> do
    void $ askComputedFieldInfo fieldInfoMap name

  let deps = mkParentDep tn : beDeps ++ map (mkColDep DRUntyped tn) pgCols
             ++ map (mkComputedFieldDep DRUntyped tn) computedFields
      depHeaders = getDependentHeaders $ spFilter sp
      mLimit = spLimit sp

  withPathK "limit" $ mapM_ onlyPositiveInt mLimit

  return ( SelPermInfo (HS.fromList pgCols) (HS.fromList computedFields)
                        tn be mLimit allowAgg depHeaders
         , deps
         )
  where
    tn = _tiName tabInfo
    fieldInfoMap = _tiFieldInfoMap tabInfo
    allowAgg = spAllowAggregations sp
    computedFields = spComputedFields sp
    autoInferredErr = "permissions for relationships are automatically inferred"

type SelPermDef = PermDef SelPerm
type CreateSelPerm = CreatePerm SelPerm
type DropSelPerm = DropPerm SelPerm

type instance PermInfo SelPerm = SelPermInfo

dropSelPermP2
  :: (CacheRWM m, MonadTx m)
  => DropSelPerm -> m ()
dropSelPermP2 dp =
  dropPermP2 dp ()

instance IsPerm SelPerm where


Review comment (security):
Why these checks are removed?

Defining select permission of a table depends upon the existence of select permission on another table. It complicates the adding permissions to metadata in `replace_metadata` query API. The order of permissions in query payload matters here. The `replace_metadata` shouldn't bother about the order. Hence the check for select permission is being removed.

While generating the schema for a role, the select permission for computed field returning table is taken into account and omitted if it is not defined. However, this logic is been there.

Code after:
buildSelPermInfo
  :: (QErrM m, CacheRM m)
  => TableInfo PGColumnInfo
  -> SelPerm
  -> m (WithDeps SelPermInfo)
buildSelPermInfo tabInfo sp = withPathK "permission" $ do
  let pgCols     = convColSpec fieldInfoMap $ spColumns sp

  (be, beDeps) <- withPathK "filter" $
    procBoolExp tn fieldInfoMap  $ spFilter sp

  -- check if the columns exist
  void $ withPathK "columns" $ indexedForM pgCols $ \pgCol ->
    askPGType fieldInfoMap pgCol autoInferredErr

  -- validate computed fields
  scalarComputedFields <-
    withPathK "computed_fields" $ indexedForM computedFields $ \fieldName -> do
      computedFieldInfo <- askComputedFieldInfo fieldInfoMap fieldName
      case _cfiReturnType computedFieldInfo of
        CFRScalar _               -> pure fieldName
        CFRSetofTable returnTable -> throw400 NotSupported $
          "select permissions on computed field " <> fieldName
          <<> " are auto-derived from the permissions on its returning table "
          <> returnTable <<> " and cannot be specified manually"

  let deps = mkParentDep tn : beDeps ++ map (mkColDep DRUntyped tn) pgCols
             ++ map (mkComputedFieldDep DRUntyped tn) scalarComputedFields
      depHeaders = getDependentHeaders $ spFilter sp
      mLimit = spLimit sp

  withPathK "limit" $ mapM_ onlyPositiveInt mLimit

  return ( SelPermInfo (HS.fromList pgCols) (HS.fromList computedFields)
                        tn be mLimit allowAgg depHeaders
         , deps
         )
  where
    tn = _tiName tabInfo
    fieldInfoMap = _tiFieldInfoMap tabInfo
    allowAgg = spAllowAggregations sp
    computedFields = spComputedFields sp
    autoInferredErr = "permissions for relationships are automatically inferred"

type SelPermDef = PermDef SelPerm
type CreateSelPerm = CreatePerm SelPerm
type DropSelPerm = DropPerm SelPerm

type instance PermInfo SelPerm = SelPermInfo

dropSelPermP2