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

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

import Data.Either
import Data.Text (Text)
import qualified Data.Text as T
import GitLab.Types
import GitLab.WebRequests.GitLabWebCalls
import Network.HTTP.Types.Status

-- | the access levels for project members. See <https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions>
data AccessLevel
  = Guest
  | Reporter
  | Developer
  | Maintainer
  | Owner

instance Show AccessLevel where
  show :: AccessLevel -> String
show AccessLevel
Guest = String
"10"
  show AccessLevel
Reporter = String
"20"
  show AccessLevel
Developer = String
"30"
  show AccessLevel
Maintainer = String
"40"
  show AccessLevel
Owner = String
"50"

-- | the members of a project.
membersOfProject :: Project -> GitLab [Member]
membersOfProject :: Project -> GitLab [Member]
membersOfProject Project
p = do
  Either Status [Member]
result <- Int -> GitLab (Either Status [Member])
membersOfProject' (Project -> Int
project_id Project
p)
  [Member] -> GitLab [Member]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Member] -> Either Status [Member] -> [Member]
forall b a. b -> Either a b -> b
fromRight (String -> [Member]
forall a. HasCallStack => String -> a
error String
"membersOfProject error") Either Status [Member]
result)

-- | the members of a project given its ID.
membersOfProject' :: Int -> GitLab (Either Status [Member])
membersOfProject' :: Int -> GitLab (Either Status [Member])
membersOfProject' Int
projectId =
  Text -> GitLab (Either Status [Member])
forall a. FromJSON a => Text -> GitLab (Either Status [a])
gitlab Text
addr
  where
    addr :: Text
addr =
      Text
"/projects/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
projectId) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/members"

-- | adds a user to a project with the given access level. Returns
-- 'Right Member' for each successful action, otherwise it returns
-- 'Left Status'.
addMemberToProject ::
  -- | the project
  Project ->
  -- | level of access
  AccessLevel ->
  -- | the user
  User ->
  GitLab (Either Status (Maybe Member))
addMemberToProject :: Project
-> AccessLevel -> User -> GitLab (Either Status (Maybe Member))
addMemberToProject Project
project AccessLevel
access User
usr =
  Int -> AccessLevel -> Int -> GitLab (Either Status (Maybe Member))
addMemberToProject' (Project -> Int
project_id Project
project) AccessLevel
access (User -> Int
user_id User
usr)

-- | adds a user to a project with the given access level, given the
-- project's ID and the user's ID. Returns @Right Member@ for each
-- successful action, otherwise it returns @Left Status@.
addMemberToProject' ::
  -- | project ID
  Int ->
  -- | level of access
  AccessLevel ->
  -- | user ID
  Int ->
  GitLab (Either Status (Maybe Member))
addMemberToProject' :: Int -> AccessLevel -> Int -> GitLab (Either Status (Maybe Member))
addMemberToProject' Int
projectId AccessLevel
access Int
userId =
  Text -> Text -> GitLab (Either Status (Maybe Member))
forall b.
FromJSON b =>
Text -> Text -> GitLab (Either Status (Maybe b))
gitlabPost Text
addr Text
dataBody
  where
    dataBody :: Text
    dataBody :: Text
dataBody =
      Text
"user_id=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
userId) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"&access_level=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (AccessLevel -> String
forall a. Show a => a -> String
show AccessLevel
access)
    addr :: Text
addr =
      Text
"/projects/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
projectId) Text -> Text -> Text
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 Status (Maybe Member)]
addMembersToProject :: Project
-> AccessLevel -> [User] -> GitLab [Either Status (Maybe Member)]
addMembersToProject Project
project AccessLevel
access =
  (User -> GitLab (Either Status (Maybe Member)))
-> [User] -> GitLab [Either Status (Maybe Member)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Project
-> AccessLevel -> User -> GitLab (Either Status (Maybe Member))
addMemberToProject Project
project AccessLevel
access)

-- | adds a list of users to a project with the given access level,
-- given the project's ID and the user IDs. Returns @Right Member@ for
-- each successful action, otherwise it returns @Left Status@.
addMembersToProject' ::
  -- | project ID
  Int ->
  -- | level of acces
  AccessLevel ->
  -- | IDs of users to add to the project
  [Int] ->
  GitLab [Either Status (Maybe Member)]
addMembersToProject' :: Int
-> AccessLevel -> [Int] -> GitLab [Either Status (Maybe Member)]
addMembersToProject' Int
projectId AccessLevel
access =
  (Int -> GitLab (Either Status (Maybe Member)))
-> [Int] -> GitLab [Either Status (Maybe Member)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Int -> AccessLevel -> Int -> GitLab (Either Status (Maybe Member))
addMemberToProject' Int
projectId AccessLevel
access)