module IHP.IDE.SchemaDesigner.View.Policies.New where import IHP.ViewPrelude import IHP.IDE.SchemaDesigner.Types import qualified IHP.IDE.SchemaDesigner.Compiler as Compiler import IHP.IDE.ToolServer.Types import IHP.IDE.SchemaDesigner.View.Layout data NewPolicyView = NewPolicyView { NewPolicyView -> [Statement] statements :: [Statement] , NewPolicyView -> Text tableName :: Text , NewPolicyView -> [Column] columns :: [Column] , NewPolicyView -> Statement policy :: Statement } instance View NewPolicyView where html :: (?context::ControllerContext, ?view::NewPolicyView) => NewPolicyView -> Html html NewPolicyView { [Column] [Statement] Text Statement $sel:statements:NewPolicyView :: NewPolicyView -> [Statement] $sel:tableName:NewPolicyView :: NewPolicyView -> Text $sel:columns:NewPolicyView :: NewPolicyView -> [Column] $sel:policy:NewPolicyView :: NewPolicyView -> Statement statements :: [Statement] tableName :: Text columns :: [Column] policy :: Statement .. } = [hsx| <div class="row no-gutters bg-white" id="schema-designer-viewer"> {renderObjectSelector (zip [0..] statements) (Just tableName)} {renderColumnSelector tableName (zip [0..] columns) statements} </div> {migrationStatus} {renderModal modal} |] where modalContent :: Html modalContent = [hsx| <form method="POST" action={CreatePolicyAction} class="edit-policy"> <input type="hidden" name="tableName" value={tableName}/> <!-- These will be filled via JS from the ace editors --> <input type="hidden" name="using" value={using}/> <input type="hidden" name="check" value={check}/> <div class="form-group"> <input id="nameInput" name="policyName" type="text" class="form-control" autofocus="autofocus" value={policy.name} /> </div> <div class="form-group"> <label for="using">Visible if:</label> <textarea id="using" name="using" type="text" class="form-control sql-expression" data-autocomplete-suggestions={autocompleteSuggestions} >{using}</textarea> <small class="form-text text-muted">This SQL expression needs to return True if the row should be visible to the current user. This is the <code>USING</code> condition of the Postgres Policy</small> </div> <div class="form-group"> <label for="using">Additionally, allow INSERT and UPDATE only if:</label> <textarea id="check" name="check" type="text" class="form-control sql-expression" data-autocomplete-suggestions={autocompleteSuggestions} >{check}</textarea> <small class="form-text text-muted">Use this to e.g. disallow users changing the user_id to another user's id. This is the <code>CHECK</code> condition of the Postgres Policy</small> </div> <div class="text-right"> <button type="submit" class="btn btn-primary">Create Policy</button> </div> </form> |] modalFooter :: Maybe Html modalFooter = Maybe Html forall a. Monoid a => a mempty modalCloseUrl :: Text modalCloseUrl = TablesController -> Text forall controller. HasPath controller => controller -> Text pathTo ShowTableAction { Text tableName :: Text $sel:tableName:TablesAction :: Text tableName } modalTitle :: Text modalTitle = Text "New Policy" modal :: Modal modal = Modal { Html modalContent :: Html $sel:modalContent:Modal :: Html modalContent, Maybe Html modalFooter :: Maybe Html $sel:modalFooter:Modal :: Maybe Html modalFooter, Text modalCloseUrl :: Text $sel:modalCloseUrl:Modal :: Text modalCloseUrl, Text modalTitle :: Text $sel:modalTitle:Modal :: Text modalTitle } using :: Text using = Statement policy.using Maybe Expression -> (Maybe Expression -> Text) -> Text forall {t1} {t2}. t1 -> (t1 -> t2) -> t2 |> Text -> (Expression -> Text) -> Maybe Expression -> Text forall b a. b -> (a -> b) -> Maybe a -> b maybe Text "" Expression -> Text Compiler.compileExpression check :: Text check = Statement policy.check Maybe Expression -> (Maybe Expression -> Text) -> Text forall {t1} {t2}. t1 -> (t1 -> t2) -> t2 |> Text -> (Expression -> Text) -> Maybe Expression -> Text forall b a. b -> (a -> b) -> Maybe a -> b maybe Text "" Expression -> Text Compiler.compileExpression autocompleteSuggestions :: Text autocompleteSuggestions = [Column] columns [Column] -> ([Column] -> [Text]) -> [Text] forall {t1} {t2}. t1 -> (t1 -> t2) -> t2 |> (Column -> Text) -> [Column] -> [Text] forall a b. (a -> b) -> [a] -> [b] map (.name) [Text] -> ([Text] -> Text) -> Text forall {t1} {t2}. t1 -> (t1 -> t2) -> t2 |> Text -> [Text] -> Text intercalate Text ","