From 1b4a3d32637eee52e105913c6af653d1e8c5c065 Mon Sep 17 00:00:00 2001 From: Amitai Burstein Date: Fri, 30 Jun 2023 22:10:51 +0300 Subject: [PATCH 1/3] Add `accessDeniedWhen` My brain can't work with the double negative of `accessDeniedUnless`. It's much easier for me to say when to access deny. --- IHP/AuthSupport/Authorization.hs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/IHP/AuthSupport/Authorization.hs b/IHP/AuthSupport/Authorization.hs index 5a56b6051..9409fa602 100644 --- a/IHP/AuthSupport/Authorization.hs +++ b/IHP/AuthSupport/Authorization.hs @@ -10,9 +10,23 @@ 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 = if condition then fail "Access denied" else pure () + +-- | 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 @@ -20,6 +34,7 @@ class CanView user model where -- > -- > 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" \ No newline at end of file +accessDeniedUnless condition = if condition then pure () else fail "Access denied" + From 8532eeea86d666968f13780667d7317149fe9fe7 Mon Sep 17 00:00:00 2001 From: Amitai Burstein Date: Sat, 1 Jul 2023 17:07:18 +0300 Subject: [PATCH 2/3] Add docs --- Guide/recipes.markdown | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Guide/recipes.markdown b/Guide/recipes.markdown index 21b4e2b92..ce66b54ab 100644 --- a/Guide/recipes.markdown +++ b/Guide/recipes.markdown @@ -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" @@ -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 { .. } From 017eba700cff38d3cbe44724ea224d6c036a4893 Mon Sep 17 00:00:00 2001 From: Amitai Burstein Date: Sat, 1 Jul 2023 17:46:17 +0300 Subject: [PATCH 3/3] Apply suggestions from code review --- IHP/AuthSupport/Authorization.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IHP/AuthSupport/Authorization.hs b/IHP/AuthSupport/Authorization.hs index 9409fa602..2baa5fb91 100644 --- a/IHP/AuthSupport/Authorization.hs +++ b/IHP/AuthSupport/Authorization.hs @@ -22,7 +22,7 @@ class CanView user model where -- -- 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 = if condition then fail "Access denied" else pure () +accessDeniedWhen condition = when condition (fail "Access denied") -- | Stops the action execution with an error message when the access condition is False. -- @@ -36,5 +36,5 @@ accessDeniedWhen condition = if condition then fail "Access denied" else pure () -- -- 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")