Skip to content

Commit

Permalink
Merge pull request #1732 from digitallyinduced/amitaibu-patch-2
Browse files Browse the repository at this point in the history
Add `accessDeniedWhen`
  • Loading branch information
mpscholten authored Jul 1, 2023
2 parents 0bf5b47 + 017eba7 commit 45902cc
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
16 changes: 14 additions & 2 deletions Guide/recipes.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ You can easily upload a user profile picture using [`uploadImageWithOptions`](ht
```haskell
action UpdateUserAction { userId } = do
user <- fetch userId
accessDeniedUnless (userId == currentUserId)
accessDeniedWhen (userId /= currentUserId)

let profilePictureOptions = ImageUploadOptions
{ convertTo = "jpg"
Expand Down Expand Up @@ -133,11 +133,23 @@ instance View EditView where

## Checking that the current user has permission to access the action

Use [accessDeniedUnless](https://ihp.digitallyinduced.com/api-docs/IHP-LoginSupport-Helper-Controller.html#v:accessDeniedUnless) like this:
Use [accessDeniedWhen](https://ihp.digitallyinduced.com/api-docs/IHP-LoginSupport-Helper-Controller.html#v:accessDeniedWhen) like this:

```haskell
action EditPostAction { postId } = do
post <- fetch postId
-- Access denied if the current user is not the author of the post.
accessDeniedWhen (post.authorId /= currentUserId)

renderHtml EditView { .. }
```

Or the opposite command [accessDeniedUnless](https://ihp.digitallyinduced.com/api-docs/IHP-LoginSupport-Helper-Controller.html#v:accessDeniedUnless) like this:

```haskell
action EditPostAction { postId } = do
post <- fetch postId
-- Access denied if the current user is not the author of the post.
accessDeniedUnless (post.authorId == currentUserId)

renderHtml EditView { .. }
Expand Down
23 changes: 19 additions & 4 deletions IHP/AuthSupport/Authorization.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,31 @@ import IHP.Prelude
class CanView user model where
canView :: (?modelContext :: ModelContext) => model -> user -> IO Bool

-- | Stops the action execution with an error message when the access condition is false.
-- | Stops the action execution with an error message when the access condition is True.
--
-- __Example:__ Checking a user is author of a blog post.
-- __Example:__ Checking a user is the author of a blog post.
--
-- > action EditPostAction { postId } = do
-- > post <- fetch postId
-- > accessDeniedWhen (post.authorId /= currentUserId)
-- >
-- > renderHtml EditView { .. }
--
-- This will throw an error and prevent the view from being rendered when the current user is not the author of the post.
accessDeniedWhen :: Bool -> IO ()
accessDeniedWhen condition = when condition (fail "Access denied")

-- | Stops the action execution with an error message when the access condition is False.
--
-- __Example:__ Checking a user is the author of a blog post.
--
-- > action EditPostAction { postId } = do
-- > post <- fetch postId
-- > accessDeniedUnless (post.authorId == currentUserId)
-- >
-- > renderHtml EditView { .. }
--
-- This will throw an error and prevent the view from being rendered when the current user is not author of the post.
-- This will throw an error and prevent the view from being rendered when the current user is not the author of the post.
accessDeniedUnless :: Bool -> IO ()
accessDeniedUnless condition = if condition then pure () else fail "Access denied"
accessDeniedUnless condition = unless condition (fail "Access denied")

0 comments on commit 45902cc

Please sign in to comment.