{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- |
-- Module      : Members
-- Description : Queries about and updates to members of projects and groups
-- Copyright   : (c) Rob Stewart, Heriot-Watt University, 2021
-- License     : BSD3
-- Maintainer  : robstewart57@gmail.com
-- Stability   : stable
module GitLab.API.Members
  ( AccessLevel (..),

    -- * Projects

    -- * Project membership
    memberOfProject,
    membersOfProject,
    memberOfProjectWithInherited,
    membersOfProjectWithInherited,

    -- ** Adding project members
    addMemberToProject,
    addMembersToProject,

    -- ** Editing project members
    editMemberOfProject,

    -- ** Removing project members
    removeUserFromProject,

    -- * Groups

    -- * Group membership
    memberOfGroup,
    membersOfGroup,
    memberOfGroupWithInherited,
    membersOfGroupWithInherited,

    -- ** Adding group members
    addAllUsersToGroup,
    addUserToGroup,
    addUsersToGroup,

    -- ** Editing group members
    editMemberOfGroup,

    -- ** Removing group members
    removeUserFromGroup,

    -- ** Pending members
    approvePendingMember,
    approveAllPendingMembers,
    pendingMembers,
  )
where

import qualified Data.ByteString.Lazy as BSL
import Data.Either
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import GitLab.API.Groups
import GitLab.API.Users
import GitLab.Types
import GitLab.WebRequests.GitLabWebCalls
import Network.HTTP.Client
import Network.HTTP.Types.URI

-----------
-- projects
-----------

-- | Gets a list of project members viewable by the authenticated
-- user. Returns only direct members and not inherited members through
-- ancestors groups.
membersOfProject :: Project -> GitLab [Member]
membersOfProject :: Project -> GitLab [Member]
membersOfProject Project
prj =
  forall b a. b -> Either a b -> b
fromRight (forall a. HasCallStack => [Char] -> a
error [Char]
"membersOfProject error")
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
addr []
  where
    addr :: Text
addr =
      Text
"/projects/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Project -> Int
project_id Project
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"

-- | Gets a list of project members viewable by the authenticated
-- user, including inherited members, invited users, and permissions
-- through ancestor groups.
--
-- If a user is a member of this project and also of one or more
-- ancestor groups, only its membership with the highest access_level
-- is returned. This represents the effective permission of the user.
--
-- Members from an invited group are returned if either: the invited
-- group is public, or the requester is also a member of the invited group.
membersOfProjectWithInherited :: Project -> GitLab (Either (Response BSL.ByteString) [Member])
membersOfProjectWithInherited :: Project -> GitLab (Either (Response ByteString) [Member])
membersOfProjectWithInherited Project
prj =
  forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
addr []
  where
    addr :: Text
addr =
      Text
"/projects/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Project -> Int
project_id Project
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"
        forall a. Semigroup a => a -> a -> a
<> Text
"/all"

-- | Gets a member of a project. Returns only direct members and not
-- inherited members through ancestor groups.
memberOfProject ::
  -- | The project
  Project ->
  -- | The user ID of the member
  Int ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
memberOfProject :: Project
-> Int -> GitLab (Either (Response ByteString) (Maybe Member))
memberOfProject Project
prj Int
usrId =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabGetOne Text
addr []
  where
    addr :: Text
addr =
      Text
"/projects/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Project -> Int
project_id Project
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show Int
usrId)

-- | Gets a member of a project, including members inherited or
-- invited through ancestor groups.
--
-- If a user is a member of this project and also of one or more
-- ancestor groups, only its membership with the highest access_level
-- is returned. This represents the effective permission of the user.
--
-- Members from an invited group are returned if either: the invited
-- group is public, or the requester is also a member of the invited
-- group.
memberOfProjectWithInherited ::
  -- | The project
  Project ->
  -- | The user ID of the member
  Int ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
memberOfProjectWithInherited :: Project
-> Int -> GitLab (Either (Response ByteString) (Maybe Member))
memberOfProjectWithInherited Project
prj Int
usrId =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabGetOne Text
addr []
  where
    addr :: Text
addr =
      Text
"/projects/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Project -> Int
project_id Project
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"
        forall a. Semigroup a => a -> a -> a
<> Text
"/all/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show Int
usrId)

-- | Adds a member to a project.
addMemberToProject ::
  -- | project ID
  Project ->
  -- | level of access
  AccessLevel ->
  -- | user ID
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
addMemberToProject :: Project
-> AccessLevel
-> User
-> GitLab (Either (Response ByteString) (Maybe Member))
addMemberToProject Project
prj AccessLevel
access User
usr =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabPost Text
addr [GitLabParam]
params
  where
    params :: [GitLabParam]
    params :: [GitLabParam]
params =
      [ (ByteString
"user_id", forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (User -> Int
user_id User
usr))))),
        (ByteString
"access_level", forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show AccessLevel
access))))
      ]
    addr :: Text
addr =
      Text
"/projects/" forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Project -> Int
project_id Project
prj)) forall a. Semigroup a => a -> a -> a
<> Text
"/members"

-- | adds a list of users to a project with the given access
-- level. Returns 'Right Member' for each successful action, otherwise
-- it returns 'Left Status'.
addMembersToProject ::
  -- | the project
  Project ->
  -- | level of access
  AccessLevel ->
  -- | users to add to the project
  [User] ->
  GitLab [Either (Response BSL.ByteString) (Maybe Member)]
addMembersToProject :: Project
-> AccessLevel
-> [User]
-> GitLab [Either (Response ByteString) (Maybe Member)]
addMembersToProject Project
project AccessLevel
access =
  forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Project
-> AccessLevel
-> User
-> GitLab (Either (Response ByteString) (Maybe Member))
addMemberToProject Project
project AccessLevel
access)

-- | Updates a member of a project.
editMemberOfProject ::
  -- | the project
  Project ->
  -- | the new level of access
  AccessLevel ->
  -- | user ID
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
editMemberOfProject :: Project
-> AccessLevel
-> User
-> GitLab (Either (Response ByteString) (Maybe Member))
editMemberOfProject Project
prj AccessLevel
access User
usr =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabPut Text
addr [GitLabParam]
params
  where
    params :: [GitLabParam]
    params :: [GitLabParam]
params =
      [ (ByteString
"access_level", forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show AccessLevel
access))))
      ]
    addr :: Text
addr =
      Text
"/projects/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Project -> Int
project_id Project
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (User -> Int
user_id User
usr))

---------
-- groups
---------

-- | Gets a list of group members viewable by the authenticated
-- user. Returns only direct members and not inherited members through
-- ancestors groups.
membersOfGroup :: Group -> GitLab (Either (Response BSL.ByteString) [Member])
membersOfGroup :: Group -> GitLab (Either (Response ByteString) [Member])
membersOfGroup Group
grp =
  forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
addr []
  where
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"

-- | Gets a member of a group. Returns only direct members
-- and not inherited members through ancestor groups.
memberOfGroup ::
  -- | The group
  Group ->
  -- | The user ID of the member
  Int ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
memberOfGroup :: Group
-> Int -> GitLab (Either (Response ByteString) (Maybe Member))
memberOfGroup Group
grp Int
usrId =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabGetOne Text
addr []
  where
    addr :: Text
addr =
      Text
"/projects/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show Int
usrId)

-- | Gets a member of a group, including members inherited or invited
-- through ancestor groups.
--
-- If a user is a member of this group and also of one or more
-- ancestor groups, only its membership with the highest access_level
-- is returned. This represents the effective permission of the user.
--
-- Members from an invited group are returned if either: the invited
-- group is public, or the requester is also a member of the invited
-- group.
memberOfGroupWithInherited ::
  -- | The group
  Group ->
  -- | The user ID of the member
  Int ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
memberOfGroupWithInherited :: Group
-> Int -> GitLab (Either (Response ByteString) (Maybe Member))
memberOfGroupWithInherited Group
prj Int
usrId =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabGetOne Text
addr []
  where
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"
        forall a. Semigroup a => a -> a -> a
<> Text
"/all/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show Int
usrId)

-- | Gets a list of group members viewable by the authenticated
-- user, including inherited members, invited users, and permissions
-- through ancestor groups.
--
-- If a user is a member of this group and also of one or more
-- ancestor groups, only its membership with the highest access_level
-- is returned. This represents the effective permission of the user.
--
-- Members from an invited group are returned if either: the invited
-- group is public, or the requester is also a member of the invited group.
membersOfGroupWithInherited :: Group -> GitLab (Either (Response BSL.ByteString) [Member])
membersOfGroupWithInherited :: Group -> GitLab (Either (Response ByteString) [Member])
membersOfGroupWithInherited Group
prj =
  forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
addr []
  where
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
prj))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"
        forall a. Semigroup a => a -> a -> a
<> Text
"/all"

-- | adds all registered users to a group.
addAllUsersToGroup ::
  -- | the group
  Group ->
  -- | level of access granted
  AccessLevel ->
  GitLab [Either (Response BSL.ByteString) (Maybe Member)]
addAllUsersToGroup :: Group
-> AccessLevel
-> GitLab [Either (Response ByteString) (Maybe Member)]
addAllUsersToGroup Group
grp AccessLevel
access = do
  [User]
allRegisteredUsers <- GitLab [User]
users
  Group
-> AccessLevel
-> [User]
-> GitLab [Either (Response ByteString) (Maybe Member)]
addUsersToGroup Group
grp AccessLevel
access [User]
allRegisteredUsers

-- | Adds a member to a group.
addUserToGroup ::
  -- | the group
  Group ->
  -- | level of access granted
  AccessLevel ->
  -- | the user
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
addUserToGroup :: Group
-> AccessLevel
-> User
-> GitLab (Either (Response ByteString) (Maybe Member))
addUserToGroup Group
grp AccessLevel
access User
usr = do
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabPost Text
addr [GitLabParam]
params
  where
    params :: [GitLabParam]
    params :: [GitLabParam]
params =
      [ (ByteString
"user_id", forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (User -> Int
user_id User
usr))))),
        (ByteString
"access_level", forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show AccessLevel
access))))
      ]
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
T.decodeUtf8 (Bool -> ByteString -> ByteString
urlEncode Bool
False (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp)))))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members"

-- | adds a list of users to a group.
addUsersToGroup ::
  -- | the group
  Group ->
  -- | level of access granted
  AccessLevel ->
  -- | list of usernames to be added to the group
  [User] ->
  GitLab [Either (Response BSL.ByteString) (Maybe Member)]
addUsersToGroup :: Group
-> AccessLevel
-> [User]
-> GitLab [Either (Response ByteString) (Maybe Member)]
addUsersToGroup Group
grp AccessLevel
access =
  forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Group
-> AccessLevel
-> User
-> GitLab (Either (Response ByteString) (Maybe Member))
addUserToGroup Group
grp AccessLevel
access)

-- | Updates a member of a group.
editMemberOfGroup ::
  -- | the group
  Group ->
  -- | the new level of access
  AccessLevel ->
  -- | user ID
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
editMemberOfGroup :: Group
-> AccessLevel
-> User
-> GitLab (Either (Response ByteString) (Maybe Member))
editMemberOfGroup Group
grp AccessLevel
access User
usr =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabPut Text
addr [GitLabParam]
params
  where
    params :: [GitLabParam]
    params :: [GitLabParam]
params =
      [ (ByteString
"access_level", forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show AccessLevel
access))))
      ]
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (User -> Int
user_id User
usr))

-- | Removes a user from a project where the user has been explicitly
-- assigned a role.
--
-- The user needs to be a group member to qualify for removal. For
-- example, if the user was added directly to a project within the
-- group but not this group explicitly, you cannot use this API to
-- remove them.
removeUserFromProject ::
  -- | the project
  Project ->
  -- | user
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe ()))
removeUserFromProject :: Project -> User -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromProject Project
prj =
  Text
-> Text -> User -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromEntity (Project -> Text
project_name Project
prj) Text
"projects"

-- | Removes a user from a group where the user has been explicitly
-- assigned a role.
--
-- The user needs to be a group member to qualify for removal. For
-- example, if the user was added directly to a project within the
-- group but not this group explicitly, you cannot use this API to
-- remove them.
removeUserFromGroup ::
  -- | the group
  Group ->
  -- | user
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe ()))
removeUserFromGroup :: Group -> User -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromGroup Group
grp =
  Text
-> Text -> User -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromEntity (Group -> Text
group_name Group
grp) Text
"groups"

-- | Approves a pending user for a group and its subgroups and
-- projects.
approvePendingMember ::
  -- | the group
  Group ->
  -- | the member
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
approvePendingMember :: Group
-> User -> GitLab (Either (Response ByteString) (Maybe Member))
approvePendingMember Group
grp User
usr =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabPut Text
addr []
  where
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (User -> Int
user_id User
usr))
        forall a. Semigroup a => a -> a -> a
<> Text
"/approve"

-- | Approves all pending users for a group and its subgroups and
-- projects.
approveAllPendingMembers ::
  -- | the group
  Group ->
  GitLab (Either (Response BSL.ByteString) (Maybe Member))
approveAllPendingMembers :: Group -> GitLab (Either (Response ByteString) (Maybe Member))
approveAllPendingMembers Group
grp =
  forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabPut Text
addr []
  where
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp))
        forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
        forall a. Semigroup a => a -> a -> a
<> Text
"/approve_all"

-- | For a group and its subgroups and projects, get a list of all
-- members in an awaiting state and those who are invited but do not
-- have a GitLab account. This request returns all matching group and
-- project members from all groups and projects in the root group’s
-- hierarchy. When the member is an invited user that has not signed
-- up for a GitLab account yet, the invited email address is
-- returned. This API endpoint works on top-level groups only. It does
-- not work on subgroups. This API endpoint requires permission to
-- administer members for the group.
pendingMembers ::
  -- | the group
  Group ->
  GitLab (Either (Response BSL.ByteString) [Member])
pendingMembers :: Group -> GitLab (Either (Response ByteString) [Member])
pendingMembers Group
grp =
  forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
addr []
  where
    addr :: Text
addr =
      Text
"/groups/"
        forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp))
        forall a. Semigroup a => a -> a -> a
<> Text
"/pending_members"

---------------------
-- Internal functions
---------------------

-- | removes a user from a group or project.
removeUserFromEntity ::
  -- | group name
  Text ->
  -- | entity ("groups" or "projects)
  Text ->
  -- | user
  User ->
  GitLab (Either (Response BSL.ByteString) (Maybe ()))
removeUserFromEntity :: Text
-> Text -> User -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromEntity Text
groupName Text
entity User
usr =
  Text
-> Text -> Int -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromEntity' Text
groupName Text
entity (User -> Int
user_id User
usr)

-- | removes a user with a given user ID from a group or project.
removeUserFromEntity' ::
  -- | group name
  Text ->
  -- | entity ("groups" or "projects")
  Text ->
  -- | user ID
  Int ->
  GitLab (Either (Response BSL.ByteString) (Maybe ()))
removeUserFromEntity' :: Text
-> Text -> Int -> GitLab (Either (Response ByteString) (Maybe ()))
removeUserFromEntity' Text
groupName Text
entity Int
usrId = do
  [Group]
attempt <- ListGroupsAttrs -> GitLab [Group]
groups (ListGroupsAttrs
defaultListGroupsFilters {listGroupsFilter_search :: Maybe Text
listGroupsFilter_search = forall a. a -> Maybe a
Just Text
groupName})
  case [Group]
attempt of
    [] ->
      forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right forall a. Maybe a
Nothing)
    [Group
grp] -> do
      Either (Response ByteString) (Maybe Version)
result <- forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabDelete Text
addr []
      case Either (Response ByteString) (Maybe Version)
result of
        Left Response ByteString
err -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left Response ByteString
err)
        -- GitLab version 14.2.3 returns Version JSON info when a
        -- member is removed from a group/project. I'm not sure if
        -- this is new behaviour, anyway we catch it here.
        Right (Just (Version {})) -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right (forall a. a -> Maybe a
Just ()))
        Right Maybe Version
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right (forall a. a -> Maybe a
Just ()))
      where
        addr :: Text
addr =
          Text
"/"
            forall a. Semigroup a => a -> a -> a
<> Text
entity
            forall a. Semigroup a => a -> a -> a
<> Text
"/"
            forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
T.decodeUtf8 (Bool -> ByteString -> ByteString
urlEncode Bool
False (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show (Group -> Int
group_id Group
grp)))))
            forall a. Semigroup a => a -> a -> a
<> Text
"/members/"
            forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
T.decodeUtf8 (Bool -> ByteString -> ByteString
urlEncode Bool
False (Text -> ByteString
T.encodeUtf8 ([Char] -> Text
T.pack (forall a. Show a => a -> [Char]
show Int
usrId))))
    (Group
_ : [Group]
_) ->
      forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right forall a. Maybe a
Nothing)