fixing stuff and start adding authorization check

This commit is contained in:
nek0 2020-07-24 07:47:35 +02:00
parent 6de4bd9460
commit b80fc8786b
3 changed files with 97 additions and 15 deletions

View file

@ -72,7 +72,8 @@ type MateAPI = "v1" :> (
:> Get '[JSON] [Role] :> Get '[JSON] [Role]
:<|> "role" :> AuthProtect "header-auth" :> ReqBody '[JSON] RoleSubmit :<|> "role" :> AuthProtect "header-auth" :> ReqBody '[JSON] RoleSubmit
:> Post '[JSON] Int :> Post '[JSON] Int
:<|> "role" :> AuthProtect "header-auth" :> ReqBody '[JSON] Role :<|> "role" :> AuthProtect "header-auth" :> Capture "rid" Int
:> ReqBody '[JSON] RoleSubmit
:> Patch '[JSON] () :> Patch '[JSON] ()
:<|> "role" :> AuthProtect "header-auth" :> ReqBody '[JSON] Int :<|> "role" :> AuthProtect "header-auth" :> ReqBody '[JSON] Int
:> Delete '[JSON] () :> Delete '[JSON] ()
@ -123,7 +124,7 @@ avatarListLink :: Link
roleListLink :: Link roleListLink :: Link
roleNewLink :: Link roleNewLink :: Link
roleUpdateLink :: Link roleUpdateLink :: Int -> Link
roleDeleteLink :: Link roleDeleteLink :: Link
roleAssociationListLink :: Link roleAssociationListLink :: Link
roleAssociationSubmitLink :: Link roleAssociationSubmitLink :: Link

View file

@ -25,20 +25,36 @@ roleNew
:: Maybe (Int, AuthMethod) :: Maybe (Int, AuthMethod)
-> RoleSubmit -> RoleSubmit
-> MateHandler Int -> MateHandler Int
roleNew (Just (_, auth)) (RoleSubmit name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11) = roleNew (Just (uid, auth)) (RoleSubmit name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11) =
insertRole name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 =<< asks rsConnection do
roleNew Nothing _ -> isRoleManager <- checkCapability uid roleCanManageRoles
if (auth `elem` [PrimaryPass, ChallengeResponse] && isRoleManager)
then
insertRole name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 =<< asks rsConnection
else
throwError $ err401
{ errBody = "You are not authorized for this action."
}
roleNew Nothing _ =
throwError $ err401 throwError $ err401
{ errBody = "No Authentication present." { errBody = "No Authentication present."
} }
roleUpdate roleUpdate
:: Maybe (Int, AuthMethod) :: Maybe (Int, AuthMethod)
-> Role -> Int
-> RoleSubmit
-> MateHandler () -> MateHandler ()
roleUpdate Just (_, auth) role = roleUpdate (Just (uid, auth)) id_ roleSubmit = do
updateRole role =<< asks rsConnection isRoleManager <- checkCapability uid roleCanManageRoles
roleUpdate Nothing _ -> if (auth `elem` [PrimaryPass, ChallengeResponse] && isRoleManager)
then
void $ updateRole id_ roleSubmit =<< asks rsConnection
else
throwError $ err401
{ errBody = "You are not authorized for this action."
}
roleUpdate Nothing _ _ =
throwError $ err401 throwError $ err401
{ errBody = "No Authentication present." { errBody = "No Authentication present."
} }
@ -54,6 +70,19 @@ roleAssociationSubmit _ _ = notImplemented
roleAssociationDelete _ _ = notImplemented roleAssociationDelete _ _ = notImplemented
-- | This is the internal function to check a users authorization to do certain
-- actions
checkCapability
:: Int -- ^ User Id to check
-> (Role -> Bool) -- ^ Predicate to check
-> MateHandler Bool -- ^ Result
checkCapability uid accessRule = do
conn <- asks rsConnection
assocs <- selectUserAssociations uid conn
let rids = map roleAssociationRole assocs
roles <- selectRoleList rids conn
return $ any accessRule roles
notImplemented :: MateHandler a notImplemented :: MateHandler a
notImplemented = throwError $ err501 notImplemented = throwError $ err501
{ errBody = "Function has not yet been implemented!" { errBody = "Function has not yet been implemented!"

View file

@ -10,6 +10,8 @@ import Data.Profunctor.Product (p2, p13)
import qualified Data.Text as T import qualified Data.Text as T
import Data.Int (Int64)
import Opaleye as O hiding (null, not) import Opaleye as O hiding (null, not)
import Opaleye.Constant as C import Opaleye.Constant as C
@ -194,6 +196,38 @@ selectAllRoles conn = do
rawRoles rawRoles
selectRoleList
:: [Int]
-> PGS.Connection
-> MateHandler [Role]
selectRoleList ids conn = do
rawRoles <- liftIO $ runSelect conn (
(keepWhen (\(id_, _, _, _, _, _, _, _, _, _, _, _, _) ->
in_ (map C.constant ids) id_))
<<< queryTable roleTable
) :: MateHandler
[
( Int
, T.Text
, Bool
, Bool
, Bool
, Bool
, Bool
, Bool
, Bool
, Bool
, Bool
, Bool
, Bool
)
]
return $ map
(\(id_, name, c1, c2, c3, c4, c5, c6, c7, c8, c9 ,c10, c11) ->
Role id_ name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11)
rawRoles
insertRole insertRole
:: T.Text :: T.Text
-> Bool -> Bool
@ -319,6 +353,23 @@ selectAllRoleAssociations conn = do
rawRoleAssocs rawRoleAssocs
selectUserAssociations
:: Int
-> PGS.Connection
-> MateHandler [RoleAssociation]
selectUserAssociations uid conn = do
rawAssocs <- liftIO $ runSelect conn(
keepWhen (\(auid, _) -> auid .== C.constant uid)
<<< queryTable userToRoleTable
) :: MateHandler
[
( Int
, Int
)
]
return $ map (\(auid, arid) -> RoleAssociation auid arid) rawAssocs
associateUserToRole associateUserToRole
:: Int -- ^ User id :: Int -- ^ User id
-> Int -- ^ Role id -> Int -- ^ Role id
@ -339,13 +390,14 @@ associateUserToRole uid rid conn =
updateRole updateRole
:: Role -- The role with already updated info :: Int -- ID of the updated role
-> RoleSubmit -- The role with already updated info
-> PGS.Connection -> PGS.Connection
-> MateHandler () -> MateHandler Int64
updateRole role@(Role idnr name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11) conn = updateRole rid role@(RoleSubmit name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11) conn =
liftIO $ runUpdate_ conn $ Update liftIO $ runUpdate_ conn $ Update
{ uTable = roleTable { uTable = roleTable
, uUpadteWith = updateEasy (\(id_, _, _, _, _, _, _, _, _, _, _, _, _) -> , uUpdateWith = updateEasy (\(id_, _, _, _, _, _, _, _, _, _, _, _, _) ->
( id_ ( id_
, C.constant name , C.constant name
, C.constant c1 , C.constant c1
@ -361,7 +413,7 @@ updateRole role@(Role idnr name c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11) conn =
, C.constant c11 , C.constant c11
) )
) )
, uWhere = \(id_, _, _, _, _, _, _, _, _, _, _, _, _) .> , uWhere = \(id_, _, _, _, _, _, _, _, _, _, _, _, _) ->
id_ .== C.constant idnr id_ .== C.constant rid
, uReturning = rCount , uReturning = rCount
} }