Skip to content

Commit 73d008d

Browse files
authored
Helpful error message on missing group membership (#1054)
1 parent c3a876a commit 73d008d

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

src/Distribution/Client/Mirror/Session.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,9 @@ requestPUT uri mimetype body = do
455455
_ -> return (Just (mkErrorResponse uri rsp))
456456
where
457457
headers = [ Header HdrContentLength (show (BS.length body))
458-
, Header HdrContentType mimetype ]
458+
, Header HdrContentType mimetype
459+
, Header HdrAccept "text/plain"
460+
]
459461

460462
{-------------------------------------------------------------------------------
461463
Auxiliary functions used by HttpSession actions

src/Distribution/Server/Features/Mirror.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ mirrorFeature ServerEnv{serverBlobStore = store}
159159
groupsAllowedToAdd = [adminGroup]
160160
}
161161

162+
guardMirrorGroup = guardAuthorisedWhenInAnyGroup [mirrorGroup]
163+
guardMirrorGroup_ = void guardMirrorGroup
162164

163165
-- result: error from unpacking, bad request error, or warning lines
164166
--
@@ -169,7 +171,7 @@ mirrorFeature ServerEnv{serverBlobStore = store}
169171
-- http://localhost:8080/package/$PACKAGENAME/$PACKAGEID.tar.gz
170172
tarballPut :: DynamicPath -> ServerPartE Response
171173
tarballPut dpath = do
172-
uid <- guardAuthorised [InGroup mirrorGroup]
174+
uid <- guardMirrorGroup
173175
pkgid <- packageTarballInPath dpath
174176
fileContent <- expectCompressedTarball
175177
time <- liftIO getCurrentTime
@@ -202,7 +204,7 @@ mirrorFeature ServerEnv{serverBlobStore = store}
202204

203205
uploaderPut :: DynamicPath -> ServerPartE Response
204206
uploaderPut dpath = do
205-
guardAuthorised_ [InGroup mirrorGroup]
207+
guardMirrorGroup_
206208
pkgid <- packageInPath dpath
207209
nameContent <- expectTextPlain
208210
let uname = UserName (unpackUTF8 nameContent)
@@ -225,7 +227,7 @@ mirrorFeature ServerEnv{serverBlobStore = store}
225227
parseTimeMaybe "%c" timeStr
226228
<|> parseTimeMaybe "%Y-%m-%dT%H:%M:%SZ" timeStr
227229
)
228-
guardAuthorised_ [InGroup mirrorGroup]
230+
guardMirrorGroup_
229231
pkgid <- packageInPath dpath
230232
timeContent <- expectTextPlain
231233
case altParseTimeMaybe (unpackUTF8 timeContent) of
@@ -239,7 +241,7 @@ mirrorFeature ServerEnv{serverBlobStore = store}
239241
-- return: error from parsing, bad request error, or warning lines
240242
cabalPut :: DynamicPath -> ServerPartE Response
241243
cabalPut dpath = do
242-
uid <- guardAuthorised [InGroup mirrorGroup]
244+
uid <- guardMirrorGroup
243245
pkgid :: PackageId <- packageInPath dpath
244246
fileContent <- expectTextPlain
245247
time <- liftIO getCurrentTime

src/Distribution/Server/Features/Users.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ data UserFeature = UserFeature {
5858
groupChangedHook :: Hook (GroupDescription, Bool, UserId, UserId, String) (),
5959

6060
-- Authorisation
61+
-- | Require any of a set of groups, with a friendly error message
62+
guardAuthorisedWhenInAnyGroup :: [Group.UserGroup] -> ServerPartE UserId,
6163
-- | Require any of a set of privileges.
6264
guardAuthorised_ :: [PrivilegeCondition] -> ServerPartE (),
6365
-- | Require any of a set of privileges, giving the id of the current user.
@@ -406,6 +408,15 @@ userFeature templates usersState adminsState
406408
-- Authorisation: authentication checks and privilege checks
407409
--
408410

411+
guardAuthorisedWhenInAnyGroup :: [Group.UserGroup] -> ServerPartE UserId
412+
guardAuthorisedWhenInAnyGroup [] =
413+
fail "Group list is empty, this is not meant to happen"
414+
guardAuthorisedWhenInAnyGroup groups = do
415+
users <- queryGetUserDb
416+
uid <- guardAuthenticatedWithErrHook users
417+
Auth.guardInAnyGroup users uid groups
418+
return uid
419+
409420
-- High level, all in one check that the client is authenticated as a
410421
-- particular user and has an appropriate privilege, but then ignore the
411422
-- identity of the user.

src/Distribution/Server/Framework/Auth.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module Distribution.Server.Framework.Auth (
2222
-- ** Special cases
2323
guardAuthenticated, checkAuthenticated,
2424
guardPriviledged, checkPriviledged,
25+
guardInAnyGroup,
2526
PrivilegeCondition(..),
2627

2728
-- ** Errors
@@ -128,6 +129,17 @@ data PrivilegeCondition = InGroup Group.UserGroup
128129
| IsUserId UserId
129130
| AnyKnownUser
130131

132+
guardInAnyGroup :: Users.Users -> UserId -> [Group.UserGroup] -> ServerPartE ()
133+
guardInAnyGroup _ _ [] =
134+
fail "Group list is empty, this is not meant to happen"
135+
guardInAnyGroup users uid groups = do
136+
allok <- checkPriviledged users uid (map InGroup groups)
137+
let groupTitles = map (Group.groupTitle . Group.groupDesc) groups
138+
errMsg = "Access denied, you must be member of either of the following groups: "
139+
<> show groupTitles
140+
when (not allok) $
141+
errForbidden "Missing group membership" [MText errMsg]
142+
131143
-- | Check that a given user is permitted to perform certain privileged
132144
-- actions.
133145
--

0 commit comments

Comments
 (0)