Repository: Nerzal/gocloak
Pull request #33 (2019-03-14 18:29:20)

Add missing AddUserToGroup/DeleteUserFromGroup functions
Added unit tests fom all user functions.
Grouped all user functions.

Partial: #31 


Patch:
diff --git a/client.go b/client.go
index 02f2a27..19aaa01 100644
--- a/client.go
+++ b/client.go
@@ -352,16 +352,6 @@ func (client *gocloak) RequestPermission(clientID string, clientSecret string, r
 	return &result, nil
 }
 
-// SetPassword sets a new password for the user with the given id. Needs elevated privileges
-func (client *gocloak) SetPassword(token string, userID string, realm string, password string, temporary bool) error {
-	requestBody := SetPasswordRequest{Password: password, Temporary: temporary, Type: "password"}
-	resp, err := getRequestWithBearerAuth(token).
-		SetBody(requestBody).
-		Put(client.getAdminRealmURL(realm, "users", userID, "reset-password"))
-
-	return checkForError(resp, err)
-}
-
 // ExecuteActionsEmail executes an actions email
 func (client *gocloak) ExecuteActionsEmail(token string, realm string, params ExecuteActionsEmail) error {
 	queryParams, err := GetQueryParams(params)
@@ -376,23 +366,6 @@ func (client *gocloak) ExecuteActionsEmail(token string, realm string, params Ex
 	return checkForError(resp, err)
 }
 
-// CreateUser tries to create the given user in the given realm and returns it's userID
-func (client *gocloak) CreateUser(token string, realm string, user User) (*string, error) {
-	resp, err := getRequestWithBearerAuth(token).
-		SetBody(user).
-		Post(client.getAdminRealmURL(realm, "users"))
-
-	if err := checkForError(resp, err); err != nil {
-		return nil, err
-	}
-
-	userPath := resp.Header().Get("Location")
-	splittedPath := strings.Split(userPath, urlSeparator)
-	userID := splittedPath[len(splittedPath)-1]
-
-	return &userID, nil
-}
-
 // CreateUser creates a new user
 func (client *gocloak) CreateGroup(token string, realm string, group Group) error {
 	resp, err := getRequestWithBearerAuth(token).
@@ -438,15 +411,6 @@ func (client *gocloak) CreateClientScope(token string, realm string, scope Clien
 	return checkForError(resp, err)
 }
 
-// UpdateUser creates a new user
-func (client *gocloak) UpdateUser(token string, realm string, user User) error {
-	resp, err := getRequestWithBearerAuth(token).
-		SetBody(user).
-		Put(client.getAdminRealmURL(realm, "users", user.ID))
-
-	return checkForError(resp, err)
-}
-
 // UpdateUser creates a new user
 func (client *gocloak) UpdateGroup(token string, realm string, group Group) error {
 	resp, err := getRequestWithBearerAuth(token).
@@ -483,14 +447,6 @@ func (client *gocloak) UpdateClientScope(token string, realm string, scope Clien
 	return checkForError(resp, err)
 }
 
-// DeleteUser creates a new user
-func (client *gocloak) DeleteUser(token string, realm string, userID string) error {
-	resp, err := getRequestWithBearerAuth(token).
-		Delete(client.getAdminRealmURL(realm, "users", userID))
-
-	return checkForError(resp, err)
-}
-
 // DeleteUser creates a new user
 func (client *gocloak) DeleteGroup(token string, realm string, groupID string) error {
 	resp, err := getRequestWithBearerAuth(token).
@@ -574,24 +530,6 @@ func (client *gocloak) GetKeyStoreConfig(token string, realm string) (*KeyStoreC
 	return &result, nil
 }
 
-// GetUserByID fetches a user from the given realm with he given userID
-func (client *gocloak) GetUserByID(accessToken string, realm string, userID string) (*User, error) {
-	if userID == "" {
-		return nil, errors.New("UserID shall not be empty")
-	}
-
-	var result User
-	resp, err := getRequestWithBearerAuth(accessToken).
-		SetResult(&result).
-		Get(client.getAdminRealmURL(realm, "users", userID))
-
-	if err := checkForError(resp, err); err != nil {
-		return nil, err
-	}
-
-	return &result, nil
-}
-
 // GetComponents get all cimponents in realm
 func (client *gocloak) GetComponents(token string, realm string) (*[]Component, error) {
 	var result []Component
@@ -606,54 +544,6 @@ func (client *gocloak) GetComponents(token string, realm string) (*[]Component,
 	return &result, nil
 }
 
-// GetUsers get all users in realm
-func (client *gocloak) GetUsers(token string, realm string, params GetUsersParams) (*[]User, error) {
-	var result []User
-	queryParams, err := GetQueryParams(params)
-	if err != nil {
-		return nil, err
-	}
-
-	resp, err := getRequestWithBearerAuth(token).
-		SetResult(&result).
-		SetQueryParams(queryParams).
-		Get(client.getAdminRealmURL(realm, "users"))
-
-	if err := checkForError(resp, err); err != nil {
-		return nil, err
-	}
-
-	return &result, nil
-}
-
-// GetUserCount gets the user count in the realm
-func (client *gocloak) GetUserCount(token string, realm string) (int, error) {
-	var result int
-	resp, err := getRequestWithBearerAuth(token).
-		SetResult(&result).
-		Get(client.getAdminRealmURL(realm, "users", "count"))
-
-	if err := checkForError(resp, err); err != nil {
-		return -1, err
-	}
-
-	return result, nil
-}
-
-// GetUsergroups get all groups for user
-func (client *gocloak) GetUserGroups(token string, realm string, userID string) (*[]UserGroup, error) {
-	var result []UserGroup
-	resp, err := getRequestWithBearerAuth(token).
-		SetResult(&result).
-		Get(client.getAdminRealmURL(realm, "users", userID, "groups"))
-
-	if err := checkForError(resp, err); err != nil {
-		return nil, err
-	}
-
-	return &result, nil
-}
-
 func (client *gocloak) getRoleMappings(token string, realm string, path string, objectID string) (*MappingsRepresentation, error) {
 	var result MappingsRepresentation
 	resp, err := getRequestWithBearerAuth(token).
@@ -770,20 +660,6 @@ func (client *gocloak) UserAttributeContains(attributes map[string][]string, att
 	return false
 }
 
-// GetUsersByRoleName returns all users have a given role
-func (client *gocloak) GetUsersByRoleName(token string, realm string, roleName string) (*[]User, error) {
-	var result []User
-	resp, err := getRequestWithBearerAuth(token).
-		SetResult(&result).
-		Get(client.getAdminRealmURL(realm, "roles", roleName, "users"))
-
-	if err := checkForError(resp, err); err != nil {
-		return nil, err
-	}
-
-	return &result, nil
-}
-
 // -----------
 // Realm Roles
 // -----------
@@ -929,3 +805,147 @@ func (client *gocloak) CreateRealm(token string, realm RealmRepresentation) erro
 
 	return checkForError(resp, err)
 }
+
+// -----
+// Users
+// -----
+
+// CreateUser creates the given user in the given realm and returns it's userID
+func (client *gocloak) CreateUser(token string, realm string, user User) (*string, error) {
+	resp, err := getRequestWithBearerAuth(token).
+		SetBody(user).
+		Post(client.getAdminRealmURL(realm, "users"))
+
+	if err := checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	userPath := resp.Header().Get("Location")
+	splittedPath := strings.Split(userPath, urlSeparator)
+	userID := splittedPath[len(splittedPath)-1]
+
+	return &userID, nil
+}
+
+// DeleteUser delete a given user
+func (client *gocloak) DeleteUser(token string, realm string, userID string) error {
+	resp, err := getRequestWithBearerAuth(token).
+		Delete(client.getAdminRealmURL(realm, "users", userID))
+
+	return checkForError(resp, err)
+}
+
+// GetUserByID fetches a user from the given realm with the given userID
+func (client *gocloak) GetUserByID(accessToken string, realm string, userID string) (*User, error) {
+	if userID == "" {
+		return nil, errors.New("UserID shall not be empty")
+	}
+
+	var result User
+	resp, err := getRequestWithBearerAuth(accessToken).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "users", userID))
+
+	if err := checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return &result, nil
+}
+
+// GetUserCount gets the user count in the realm
+func (client *gocloak) GetUserCount(token string, realm string) (int, error) {
+	var result int
+	resp, err := getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "users", "count"))
+
+	if err := checkForError(resp, err); err != nil {
+		return -1, err
+	}
+
+	return result, nil
+}
+
+// GetUserGroups get all groups for user
+func (client *gocloak) GetUserGroups(token string, realm string, userID string) (*[]UserGroup, error) {
+	var result []UserGroup
+	resp, err := getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "users", userID, "groups"))
+
+	if err := checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return &result, nil
+}
+
+// GetUsers get all users in realm
+func (client *gocloak) GetUsers(token string, realm string, params GetUsersParams) (*[]User, error) {
+	var result []User
+	queryParams, err := GetQueryParams(params)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := getRequestWithBearerAuth(token).
+		SetResult(&result).
+		SetQueryParams(queryParams).
+		Get(client.getAdminRealmURL(realm, "users"))
+
+	if err := checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return &result, nil
+}
+
+// GetUsersByRoleName returns all users have a given role
+func (client *gocloak) GetUsersByRoleName(token string, realm string, roleName string) (*[]User, error) {
+	var result []User
+	resp, err := getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "roles", roleName, "users"))
+
+	if err := checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return &result, nil
+}
+
+// SetPassword sets a new password for the user with the given id. Needs elevated privileges
+func (client *gocloak) SetPassword(token string, userID string, realm string, password string, temporary bool) error {
+	requestBody := SetPasswordRequest{Password: password, Temporary: temporary, Type: "password"}
+	resp, err := getRequestWithBearerAuth(token).
+		SetBody(requestBody).
+		Put(client.getAdminRealmURL(realm, "users", userID, "reset-password"))
+
+	return checkForError(resp, err)
+}
+
+// UpdateUser creates a new user
+func (client *gocloak) UpdateUser(token string, realm string, user User) error {
+	resp, err := getRequestWithBearerAuth(token).
+		SetBody(user).
+		Put(client.getAdminRealmURL(realm, "users", user.ID))
+
+	return checkForError(resp, err)
+}
+
+// AddUserToGroup puts given user to given group
+func (client *gocloak) AddUserToGroup(token string, realm string, userID string, groupID string) error {
+	resp, err := getRequestWithBearerAuth(token).
+		Put(client.getAdminRealmURL(realm, "users", userID, "groups", groupID))
+
+	return checkForError(resp, err)
+}
+
+// DeleteUserFromGroup deletes given user from given group
+func (client *gocloak) DeleteUserFromGroup(token string, realm string, userID string, groupID string) error {
+	resp, err := getRequestWithBearerAuth(token).
+		Delete(client.getAdminRealmURL(realm, "users", userID, "groups", groupID))
+
+	return checkForError(resp, err)
+}
diff --git a/gocloak.go b/gocloak.go
index 46ebc8f..f52eea4 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -31,14 +31,9 @@ type GoCloak interface {
 	// GetUserInfo gets the user info for the given realm
 	GetUserInfo(accessToken string, realm string) (*UserInfo, error)
 
-	// SetPassword sets a new password for the user with the given id. Needs elevated privileges
-	SetPassword(token string, userID string, realm string, password string, temporary bool) error
-
 	// ExecuteActionsEmail executes an actions email
 	ExecuteActionsEmail(token string, realm string, params ExecuteActionsEmail) error
 
-	// CreateUser creates a new user
-	CreateUser(token string, realm string, user User) (*string, error)
 	// CreateGroup creates a new group
 	CreateGroup(accessToken string, realm string, group Group) error
 	// CreateClientRole creates a new role for a client
@@ -50,8 +45,6 @@ type GoCloak interface {
 	// CreateComponent creates a new component
 	CreateComponent(accessToken string, realm string, component Component) error
 
-	// UpdateUser updates the given user
-	UpdateUser(accessToken string, realm string, user User) error
 	// UpdateGroup updates the given group
 	UpdateGroup(accessToken string, realm string, group Group) error
 	// UpdateRole updates the given role
@@ -61,8 +54,6 @@ type GoCloak interface {
 	// UpdateClientScope updates the given clientScope
 	UpdateClientScope(accessToken string, realm string, scope ClientScope) error
 
-	// DeleteUser deletes the given user
-	DeleteUser(accessToken string, realm, userID string) error
 	// DeleteComponent deletes the given component
 	DeleteComponent(accessToken string, realm, componentID string) error
 	// DeleteGroup deletes the given group
@@ -80,14 +71,6 @@ type GoCloak interface {
 	GetClientSecret(token string, realm string, clientID string) (*CredentialRepresentation, error)
 	// GetKeyStoreConfig gets the keyStoreConfig
 	GetKeyStoreConfig(accessToken string, realm string) (*KeyStoreConfig, error)
-	// GetUserByID gets the user with the given id
-	GetUserByID(accessToken string, realm string, userID string) (*User, error)
-	// GetUser count returns the userCount of the given realm
-	GetUserCount(accessToken string, realm string) (int, error)
-	// GetUsers gets all users of the given realm
-	GetUsers(accessToken string, realm string, params GetUsersParams) (*[]User, error)
-	// GetUserGroups gets the groups of the given user
-	GetUserGroups(accessToken string, realm string, userID string) (*[]UserGroup, error)
 	// GetComponents gets components of the given realm
 	GetComponents(accessToken string, realm string) (*[]Component, error)
 	// GetGroups gets all groups of the given realm
@@ -104,8 +87,6 @@ type GoCloak interface {
 	GetClientRole(token string, realm string, clientID string, roleName string) (*Role, error)
 	// GetClients gets the clients in the realm
 	GetClients(accessToken string, realm string, params GetClientsParams) (*[]Client, error)
-	// GetUsersByRoleName returns all users have a given role
-	GetUsersByRoleName(token string, realm string, roleName string) (*[]User, error)
 
 	// UserAttributeContains checks if the given attribute has the given value
 	UserAttributeContains(attributes map[string][]string, attribute string, value string) bool
@@ -141,4 +122,29 @@ type GoCloak interface {
 	GetRealm(token string, realm string) (*RealmRepresentation, error)
 	// CreateRealm creates a realm
 	CreateRealm(token string, realm RealmRepresentation) error
+
+	// *** Users ***
+	// CreateUser creates a new user
+	CreateUser(token string, realm string, user User) (*string, error)
+	// DeleteUser deletes the given user
+	DeleteUser(accessToken string, realm, userID string) error
+	// GetUserByID gets the user with the given id
+	GetUserByID(accessToken string, realm string, userID string) (*User, error)
+	// GetUser count returns the userCount of the given realm
+	GetUserCount(accessToken string, realm string) (int, error)
+	// GetUsers gets all users of the given realm
+	GetUsers(accessToken string, realm string, params GetUsersParams) (*[]User, error)
+	// GetUserGroups gets the groups of the given user
+	GetUserGroups(accessToken string, realm string, userID string) (*[]UserGroup, error)
+	// GetUsersByRoleName returns all users have a given role
+	GetUsersByRoleName(token string, realm string, roleName string) (*[]User, error)
+	// SetPassword sets a new password for the user with the given id. Needs elevated privileges
+	SetPassword(token string, userID string, realm string, password string, temporary bool) error
+	// UpdateUser updates the given user
+	UpdateUser(accessToken string, realm string, user User) error
+	// AddUserToGroup puts given user to given group
+	AddUserToGroup(token string, realm string, userID string, groupID string) error
+	// DeleteUserFromGroup deletes given user from given group
+	DeleteUserFromGroup(token string, realm string, userID string, groupID string) error
+
 }


Test patch:
diff --git a/client_test.go b/client_test.go
index 3fe9983..abf6f4c 100644
--- a/client_test.go
+++ b/client_test.go
@@ -156,37 +156,6 @@ func GetClientByClientID(t *testing.T, client GoCloak, clientID string) *Client
 	return nil
 }
 
-func CreateUser(t *testing.T, client GoCloak) (func(), string) {
-	cfg := GetConfig(t)
-	token := GetAdminToken(t, client)
-
-	user := User{}
-	user.FirstName = "Klaus"
-	user.LastName = "Peter"
-	user.Email = GetRandomName("trololo") + "@localhost"
-	user.Enabled = true
-	user.Username = user.Email
-	user.Attributes = map[string][]string{}
-	user.Attributes["foo"] = []string{"bar", "alice", "bob", "roflcopter"}
-	user.Attributes["bar"] = []string{"baz"}
-
-	userID, err := client.CreateUser(
-		token.AccessToken,
-		cfg.GoCloak.Realm,
-		user)
-	FailIfErr(t, err, "CreateUser failed")
-	t.Logf("Created user with ID: %s. User: %+v", *userID, user)
-	tearDown := func() {
-		err := client.DeleteUser(
-			token.AccessToken,
-			cfg.GoCloak.Realm,
-			*userID)
-		FailIfErr(t, err, "DeleteUser")
-	}
-
-	return tearDown, *userID
-}
-
 func CreateGroup(t *testing.T, client GoCloak) (func(), string) {
 	cfg := GetConfig(t)
 	token := GetAdminToken(t, client)
@@ -270,7 +239,7 @@ func SetUpTestUser(t *testing.T, client GoCloak) {
 	})
 }
 
-func TestBaseParams_GetQueryParams(t *testing.T) {
+func TestGetQueryParams(t *testing.T) {
 	t.Parallel()
 
 	type TestParams struct {
@@ -303,6 +272,19 @@ func TestBaseParams_GetQueryParams(t *testing.T) {
 // API tests
 // ---------
 
+func TestGocloak_GetUserInfo(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetClientToken(t, client)
+
+	userInfo, err := client.GetUserInfo(
+		token.AccessToken,
+		cfg.GoCloak.Realm)
+	t.Log(userInfo)
+	FailIfErr(t, err, "Failed to fetch userinfo")
+}
+
 func TestGocloak_RequestPermission(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
@@ -375,19 +357,6 @@ func TestGocloak_RetrospectToken_InactiveToken(t *testing.T) {
 
 }
 
-func TestGocloak_GetUserInfo(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-	token := GetClientToken(t, client)
-
-	userInfo, err := client.GetUserInfo(
-		token.AccessToken,
-		cfg.GoCloak.Realm)
-	t.Log(userInfo)
-	FailIfErr(t, err, "Failed to fetch userinfo")
-}
-
 func TestGocloak_RetrospectToken(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
@@ -463,23 +432,6 @@ func TestGocloak_UserAttributeContains(t *testing.T) {
 	FailIf(t, !ok, "UserAttributeContains")
 }
 
-func TestGocloak_GetUserByID(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-	token := GetAdminToken(t, client)
-
-	tearDown, userID := CreateUser(t, client)
-	defer tearDown()
-
-	fetchedUser, err := client.GetUserByID(
-		token.AccessToken,
-		cfg.GoCloak.Realm,
-		userID)
-	t.Log(fetchedUser)
-	FailIfErr(t, err, "GetUserById failed")
-}
-
 func TestGocloak_GetKeyStoreConfig(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
@@ -547,34 +499,6 @@ func TestGocloak_SetPassword(t *testing.T) {
 	FailIfErr(t, err, "Failed to set password")
 }
 
-func TestGocloak_CreateUser(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-
-	tearDown, _ := CreateUser(t, client)
-	defer tearDown()
-}
-
-func TestGocloak_CreateUserCustomAttributes(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-	token := GetAdminToken(t, client)
-
-	tearDown, userID := CreateUser(t, client)
-	defer tearDown()
-
-	fetchedUser, err := client.GetUserByID(token.AccessToken,
-		cfg.GoCloak.Realm,
-		userID)
-	FailIfErr(t, err, "GetUserByID failed")
-	ok := client.UserAttributeContains(fetchedUser.Attributes, "foo", "alice")
-	FailIf(t, !ok, "User doesn't have custom attributes")
-	ok = client.UserAttributeContains(fetchedUser.Attributes, "foo2", "alice")
-	FailIf(t, ok, "User's custom attributes contains unexpected attribute")
-}
-
 func TestGocloak_CreateGroup(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
@@ -629,35 +553,6 @@ func TestGocloak_CreateClient(t *testing.T) {
 		newClient.ID)
 }
 
-func TestGocloak_GetUsers(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-	token := GetAdminToken(t, client)
-
-	users, err := client.GetUsers(
-		token.AccessToken,
-		cfg.GoCloak.Realm,
-		GetUsersParams{
-			Username: cfg.GoCloak.UserName,
-		})
-	t.Log(users)
-	FailIfErr(t, err, "GetUsers failed")
-}
-
-func TestGocloak_GetUserCount(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-	token := GetAdminToken(t, client)
-
-	count, err := client.GetUserCount(
-		token.AccessToken,
-		cfg.GoCloak.Realm)
-	t.Logf("Users in Realm: %d", count)
-	FailIfErr(t, err, "GetUserCount failed")
-}
-
 func TestGocloak_GetGroups(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
@@ -671,22 +566,6 @@ func TestGocloak_GetGroups(t *testing.T) {
 	FailIfErr(t, err, "GetGroups failed")
 }
 
-func TestGocloak_GetUserGroups(t *testing.T) {
-	t.Parallel()
-	cfg := GetConfig(t)
-	client := NewClient(cfg.HostName)
-	token := GetAdminToken(t, client)
-
-	tearDown, userID := CreateUser(t, client)
-	defer tearDown()
-
-	_, err := client.GetUserGroups(
-		token.AccessToken,
-		cfg.GoCloak.Realm,
-		userID)
-	FailIfErr(t, err, "GetUserGroups failed")
-}
-
 func TestGocloak_GetClients(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
@@ -804,6 +683,7 @@ func TestGocloak_GetRealm(t *testing.T) {
 	FailIfErr(t, err, "GetRealm failed")
 }
 
+
 // -----------
 // Realm Roles
 // -----------
@@ -1096,3 +976,268 @@ func TestGocloak_DeleteRealmRoleComposite(t *testing.T) {
 		cfg.GoCloak.Realm, compositeRole, []Role{*roleModel})
 	FailIfErr(t, err, "DeleteRealmRoleComposite failed")
 }
+
+// -----
+// Users
+// -----
+
+func CreateUser(t *testing.T, client GoCloak) (func(), string) {
+	cfg := GetConfig(t)
+	token := GetAdminToken(t, client)
+
+	user := User{
+		FirstName: GetRandomName("FirstName"),
+		LastName: GetRandomName("LastName"),
+		Email: GetRandomName("email")+"@localhost",
+		Enabled: true,
+		Attributes: map[string][]string{
+			"foo": {"bar", "alice", "bob", "roflcopter"},
+			"bar": {"baz"},
+		},
+	}
+	user.Username = user.Email
+
+	userID, err := client.CreateUser(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		user)
+	user.ID = *userID
+	FailIfErr(t, err, "CreateUser failed")
+	t.Logf("Created User: %+v", user)
+	tearDown := func() {
+		err := client.DeleteUser(
+			token.AccessToken,
+			cfg.GoCloak.Realm,
+			user.ID)
+		FailIfErr(t, err, "DeleteUser")
+	}
+
+	return tearDown, user.ID
+}
+
+func TestGocloak_CreateUser(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+
+	tearDown, _ := CreateUser(t, client)
+	defer tearDown()
+}
+
+func TestGocloak_CreateUserCustomAttributes(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	tearDown, userID := CreateUser(t, client)
+	defer tearDown()
+
+	fetchedUser, err := client.GetUserByID(token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID)
+	FailIfErr(t, err, "GetUserByID failed")
+	ok := client.UserAttributeContains(fetchedUser.Attributes, "foo", "alice")
+	FailIf(t, !ok, "User doesn't have custom attributes")
+	ok = client.UserAttributeContains(fetchedUser.Attributes, "foo2", "alice")
+	FailIf(t, ok, "User's custom attributes contains unexpected attribute")
+	t.Log(fetchedUser)
+}
+
+func TestGocloak_GetUserByID(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	tearDown, userID := CreateUser(t, client)
+	defer tearDown()
+
+	fetchedUser, err := client.GetUserByID(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID)
+	FailIfErr(t, err, "GetUserById failed")
+	t.Log(fetchedUser)
+}
+
+func TestGocloak_GetUsers(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	users, err := client.GetUsers(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		GetUsersParams{
+			Username: cfg.GoCloak.UserName,
+		})
+	FailIfErr(t, err, "GetUsers failed")
+	t.Log(users)
+}
+
+func TestGocloak_GetUserCount(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	count, err := client.GetUserCount(
+		token.AccessToken,
+		cfg.GoCloak.Realm)
+	FailIfErr(t, err, "GetUserCount failed")
+	t.Logf("Users in Realm: %d", count)
+}
+
+func TestGocloak_AddUserToGroup(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+	tearDownUser, userID := CreateUser(t, client)
+	defer tearDownUser()
+
+	tearDownGroup, groupID := CreateGroup(t, client)
+	defer tearDownGroup()
+
+	err := client.AddUserToGroup(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID,
+		groupID,
+	)
+	FailIfErr(t, err, "AddUserToGroup failed")
+}
+
+func TestGocloak_DeleteUserFromGroup(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+	tearDownUser, userID := CreateUser(t, client)
+	defer tearDownUser()
+
+	tearDownGroup, groupID := CreateGroup(t, client)
+	defer tearDownGroup()
+	err := client.AddUserToGroup(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID,
+		groupID,
+	)
+	FailIfErr(t, err, "AddUserToGroup failed")
+	err = client.DeleteUserFromGroup(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID,
+		groupID,
+	)
+	FailIfErr(t, err, "DeleteUserFromGroup failed")
+}
+
+func TestGocloak_GetUserGroups(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	tearDownUser, userID := CreateUser(t, client)
+	defer tearDownUser()
+
+	tearDownGroup, groupID := CreateGroup(t, client)
+	defer tearDownGroup()
+
+	err := client.AddUserToGroup(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID,
+		groupID,
+	)
+	FailIfErr(t, err, "AddUserToGroup failed")
+	groups, err := client.GetUserGroups(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID)
+	FailIfErr(t, err, "GetUserGroups failed")
+	FailIf(
+		t,
+		len(*groups) == 0,
+		"User is not in the Group")
+	AssertEquals(
+		t,
+		groupID,
+		(*groups)[0].ID)
+}
+
+func TestGocloak_DeleteUser(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+
+	tearDown, _ := CreateUser(t, client)
+	defer tearDown()
+}
+
+func TestGocloak_UpdateUser(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	tearDown, userID := CreateUser(t, client)
+	defer tearDown()
+	user, err := client.GetUserByID(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID)
+	FailIfErr(t, err, "GetUserByID failed")
+	user.FirstName = GetRandomName("UpdateUserFirstName")
+	err = client.UpdateUser(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		*user)
+	FailIfErr(t, err, "UpdateUser failed")
+}
+
+func TestGocloak_GetUsersByRoleName(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClient(cfg.HostName)
+	token := GetAdminToken(t, client)
+
+	tearDownUser, userID := CreateUser(t, client)
+	defer tearDownUser()
+
+	tearDownRole, roleName := CreateRealmRole(t, client)
+	defer tearDownRole()
+
+	role, err := client.GetRealmRole(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		roleName)
+	FailIfErr(t, err, "GetRealmRole failed")
+	err = client.AddRealmRoleToUser(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		userID,
+		[]Role{
+			*role,
+		})
+	FailIfErr(t, err, "AddRealmRoleToUser failed")
+
+	users, err := client.GetUsersByRoleName(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		roleName)
+	FailIfErr(t, err, "GetUsersByRoleName failed")
+
+	FailIf(
+		t,
+		len(*users) == 0,
+		"User is not in the Group")
+	AssertEquals(
+		t,
+		userID,
+		(*users)[0].ID)
+}