Repository: Nerzal/gocloak (go)

Issue:
Don't use pointers for interface{} types
**Describe the bug**
In the recent refactor of all types to points you have two places where you use interfaces as pointers.

https://github.com/Nerzal/gocloak/blob/master/models.go#L605
https://github.com/Nerzal/gocloak/blob/master/models.go#L662

Because of this I can no longer set those values. It's possible there is an easy way to do it but I haven't figured it out. If so let me know and perhaps this isn't actually a bug.

When trying to set `RealmRepresentation.Roles` I get an error like:

~~~
./organization.go:149:3: cannot use roles (type *map[string]interface {}) as type *interface {} in field value:
	*interface {} is pointer to interface, not interface
~~~

I believe reverting back to `interface{}` will solve the issue. If the value isn't set then the JSON representation would be `null`.

**To Reproduce**
Set `RealmRepresentation.Roles` to any pointer value.

**Expected behavior**
I can set `RealmRepresentation.Roles`.


Pull request:
Replace *interface{} to interface{} in models
Fix #187 

Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 6016310..21d03d6 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -16,10 +16,10 @@ jobs:
         uses: golangci/golangci-lint-action@v1
         with:
           version: v1.27
-      - name: nancy
-        uses: sonatype-nexus-community/nancy-github-action@master
-        with:
-          target: go.sum
+      # - name: nancy
+      #   uses: sonatype-nexus-community/nancy-github-action@master
+      #   with:
+      #     target: go.sum
       - name: Run Keycloak
         run: |
           docker pull jboss/keycloak:latest
diff --git a/models.go b/models.go
index 12f49e2..98a959f 100644
--- a/models.go
+++ b/models.go
@@ -579,101 +579,107 @@ type UserInfo struct {
 	UpdatedAt           *int             `json:"updated_at,omitempty"`
 }
 
-// RealmRepresentation represent a realm
+// RolesRepresentation represents the roles of a realm
+type RolesRepresentation struct {
+	Client *map[string][]Role `json:"client,omitempty"`
+	Realm  *[]Role            `json:"realm,omitempty"`
+}
+
+// RealmRepresentation represents a realm
 type RealmRepresentation struct {
-	AccessCodeLifespan                  *int               `json:"accessCodeLifespan,omitempty"`
-	AccessCodeLifespanLogin             *int               `json:"accessCodeLifespanLogin,omitempty"`
-	AccessCodeLifespanUserAction        *int               `json:"accessCodeLifespanUserAction,omitempty"`
-	AccessTokenLifespan                 *int               `json:"accessTokenLifespan,omitempty"`
-	AccessTokenLifespanForImplicitFlow  *int               `json:"accessTokenLifespanForImplicitFlow,omitempty"`
-	AccountTheme                        *string            `json:"accountTheme,omitempty"`
-	ActionTokenGeneratedByAdminLifespan *int               `json:"actionTokenGeneratedByAdminLifespan,omitempty"`
-	ActionTokenGeneratedByUserLifespan  *int               `json:"actionTokenGeneratedByUserLifespan,omitempty"`
-	AdminEventsDetailsEnabled           *bool              `json:"adminEventsDetailsEnabled"`
-	AdminEventsEnabled                  *bool              `json:"adminEventsEnabled"`
-	AdminTheme                          *string            `json:"adminTheme,omitempty"`
-	Attributes                          *map[string]string `json:"attributes,omitempty"`
-	AuthenticationFlows                 *[]interface{}     `json:"authenticationFlows,omitempty"`
-	AuthenticatorConfig                 *[]interface{}     `json:"authenticatorConfig,omitempty"`
-	BrowserFlow                         *string            `json:"browserFlow,omitempty"`
-	BrowserSecurityHeaders              *map[string]string `json:"browserSecurityHeaders,omitempty"`
-	BruteForceProtected                 *bool              `json:"bruteForceProtected"`
-	ClientAuthenticationFlow            *string            `json:"clientAuthenticationFlow,omitempty"`
-	ClientScopeMappings                 *map[string]string `json:"clientScopeMappings,omitempty"`
-	ClientScopes                        *[]ClientScope     `json:"clientScopes,omitempty"`
-	Clients                             *[]Client          `json:"clients,omitempty"`
-	Components                          *interface{}       `json:"components,omitempty"`
-	DefaultDefaultClientScopes          *[]string          `json:"defaultDefaultClientScopes,omitempty"`
-	DefaultGroups                       *[]string          `json:"defaultGroups,omitempty"`
-	DefaultLocale                       *string            `json:"defaultLocale,omitempty"`
-	DefaultOptionalClientScopes         *[]string          `json:"defaultOptionalClientScopes,omitempty"`
-	DefaultRoles                        *[]string          `json:"defaultRoles,omitempty"`
-	DefaultSignatureAlgorithm           *string            `json:"defaultSignatureAlgorithm,omitempty"`
-	DirectGrantFlow                     *string            `json:"directGrantFlow,omitempty"`
-	DisplayName                         *string            `json:"displayName,omitempty"`
-	DisplayNameHTML                     *string            `json:"displayNameHtml,omitempty"`
-	DockerAuthenticationFlow            *string            `json:"dockerAuthenticationFlow,omitempty"`
-	DuplicateEmailsAllowed              *bool              `json:"duplicateEmailsAllowed"`
-	EditUsernameAllowed                 *bool              `json:"editUsernameAllowed"`
-	EmailTheme                          *string            `json:"emailTheme,omitempty"`
-	Enabled                             *bool              `json:"enabled"`
-	EnabledEventTypes                   *[]string          `json:"enabledEventTypes,omitempty"`
-	EventsEnabled                       *bool              `json:"eventsEnabled"`
-	EventsExpiration                    *int64             `json:"eventsExpiration,omitempty"`
-	EventsListeners                     *[]string          `json:"eventsListeners,omitempty"`
-	FailureFactor                       *int               `json:"failureFactor,omitempty"`
-	FederatedUsers                      *[]interface{}     `json:"federatedUsers,omitempty"`
-	Groups                              *[]interface{}     `json:"groups,omitempty"`
-	ID                                  *string            `json:"id,omitempty"`
-	IdentityProviderMappers             *[]interface{}     `json:"identityProviderMappers,omitempty"`
-	IdentityProviders                   *[]interface{}     `json:"identityProviders,omitempty"`
-	InternationalizationEnabled         *bool              `json:"internationalizationEnabled"`
-	KeycloakVersion                     *string            `json:"keycloakVersion,omitempty"`
-	LoginTheme                          *string            `json:"loginTheme,omitempty"`
-	LoginWithEmailAllowed               *bool              `json:"loginWithEmailAllowed"`
-	MaxDeltaTimeSeconds                 *int               `json:"maxDeltaTimeSeconds,omitempty"`
-	MaxFailureWaitSeconds               *int               `json:"maxFailureWaitSeconds,omitempty"`
-	MinimumQuickLoginWaitSeconds        *int               `json:"minimumQuickLoginWaitSeconds,omitempty"`
-	NotBefore                           *int               `json:"notBefore,omitempty"`
-	OfflineSessionIdleTimeout           *int               `json:"offlineSessionIdleTimeout,omitempty"`
-	OfflineSessionMaxLifespan           *int               `json:"offlineSessionMaxLifespan,omitempty"`
-	OfflineSessionMaxLifespanEnabled    *bool              `json:"offlineSessionMaxLifespanEnabled"`
-	OtpPolicyAlgorithm                  *string            `json:"otpPolicyAlgorithm,omitempty"`
-	OtpPolicyDigits                     *int               `json:"otpPolicyDigits,omitempty"`
-	OtpPolicyInitialCounter             *int               `json:"otpPolicyInitialCounter,omitempty"`
-	OtpPolicyLookAheadWindow            *int               `json:"otpPolicyLookAheadWindow,omitempty"`
-	OtpPolicyPeriod                     *int               `json:"otpPolicyPeriod,omitempty"`
-	OtpPolicyType                       *string            `json:"otpPolicyType,omitempty"`
-	OtpSupportedApplications            *[]string          `json:"otpSupportedApplications,omitempty"`
-	PasswordPolicy                      *string            `json:"passwordPolicy,omitempty"`
-	PermanentLockout                    *bool              `json:"permanentLockout"`
-	ProtocolMappers                     *[]interface{}     `json:"protocolMappers,omitempty"`
-	QuickLoginCheckMilliSeconds         *int64             `json:"quickLoginCheckMilliSeconds,omitempty"`
-	Realm                               *string            `json:"realm,omitempty"`
-	RefreshTokenMaxReuse                *int               `json:"refreshTokenMaxReuse,omitempty"`
-	RegistrationAllowed                 *bool              `json:"registrationAllowed"`
-	RegistrationEmailAsUsername         *bool              `json:"registrationEmailAsUsername"`
-	RegistrationFlow                    *string            `json:"registrationFlow,omitempty"`
-	RememberMe                          *bool              `json:"rememberMe"`
-	RequiredActions                     *[]interface{}     `json:"requiredActions,omitempty"`
-	ResetCredentialsFlow                *string            `json:"resetCredentialsFlow,omitempty"`
-	ResetPasswordAllowed                *bool              `json:"resetPasswordAllowed"`
-	RevokeRefreshToken                  *bool              `json:"revokeRefreshToken"`
-	Roles                               *interface{}       `json:"roles,omitempty"`
-	ScopeMappings                       *[]interface{}     `json:"scopeMappings,omitempty"`
-	SMTPServer                          *map[string]string `json:"smtpServer,omitempty"`
-	SslRequired                         *string            `json:"sslRequired,omitempty"`
-	SsoSessionIdleTimeout               *int               `json:"ssoSessionIdleTimeout,omitempty"`
-	SsoSessionIdleTimeoutRememberMe     *int               `json:"ssoSessionIdleTimeoutRememberMe,omitempty"`
-	SsoSessionMaxLifespan               *int               `json:"ssoSessionMaxLifespan,omitempty"`
-	SsoSessionMaxLifespanRememberMe     *int               `json:"ssoSessionMaxLifespanRememberMe,omitempty"`
-	SupportedLocales                    *[]string          `json:"supportedLocales,omitempty"`
-	UserFederationMappers               *[]interface{}     `json:"userFederationMappers,omitempty"`
-	UserFederationProviders             *[]interface{}     `json:"userFederationProviders,omitempty"`
-	UserManagedAccessAllowed            *bool              `json:"userManagedAccessAllowed"`
-	Users                               *[]User            `json:"users,omitempty"`
-	VerifyEmail                         *bool              `json:"verifyEmail"`
-	WaitIncrementSeconds                *int               `json:"waitIncrementSeconds,omitempty"`
+	AccessCodeLifespan                  *int                 `json:"accessCodeLifespan,omitempty"`
+	AccessCodeLifespanLogin             *int                 `json:"accessCodeLifespanLogin,omitempty"`
+	AccessCodeLifespanUserAction        *int                 `json:"accessCodeLifespanUserAction,omitempty"`
+	AccessTokenLifespan                 *int                 `json:"accessTokenLifespan,omitempty"`
+	AccessTokenLifespanForImplicitFlow  *int                 `json:"accessTokenLifespanForImplicitFlow,omitempty"`
+	AccountTheme                        *string              `json:"accountTheme,omitempty"`
+	ActionTokenGeneratedByAdminLifespan *int                 `json:"actionTokenGeneratedByAdminLifespan,omitempty"`
+	ActionTokenGeneratedByUserLifespan  *int                 `json:"actionTokenGeneratedByUserLifespan,omitempty"`
+	AdminEventsDetailsEnabled           *bool                `json:"adminEventsDetailsEnabled"`
+	AdminEventsEnabled                  *bool                `json:"adminEventsEnabled"`
+	AdminTheme                          *string              `json:"adminTheme,omitempty"`
+	Attributes                          *map[string]string   `json:"attributes,omitempty"`
+	AuthenticationFlows                 *[]interface{}       `json:"authenticationFlows,omitempty"`
+	AuthenticatorConfig                 *[]interface{}       `json:"authenticatorConfig,omitempty"`
+	BrowserFlow                         *string              `json:"browserFlow,omitempty"`
+	BrowserSecurityHeaders              *map[string]string   `json:"browserSecurityHeaders,omitempty"`
+	BruteForceProtected                 *bool                `json:"bruteForceProtected"`
+	ClientAuthenticationFlow            *string              `json:"clientAuthenticationFlow,omitempty"`
+	ClientScopeMappings                 *map[string]string   `json:"clientScopeMappings,omitempty"`
+	ClientScopes                        *[]ClientScope       `json:"clientScopes,omitempty"`
+	Clients                             *[]Client            `json:"clients,omitempty"`
+	Components                          interface{}          `json:"components,omitempty"`
+	DefaultDefaultClientScopes          *[]string            `json:"defaultDefaultClientScopes,omitempty"`
+	DefaultGroups                       *[]string            `json:"defaultGroups,omitempty"`
+	DefaultLocale                       *string              `json:"defaultLocale,omitempty"`
+	DefaultOptionalClientScopes         *[]string            `json:"defaultOptionalClientScopes,omitempty"`
+	DefaultRoles                        *[]string            `json:"defaultRoles,omitempty"`
+	DefaultSignatureAlgorithm           *string              `json:"defaultSignatureAlgorithm,omitempty"`
+	DirectGrantFlow                     *string              `json:"directGrantFlow,omitempty"`
+	DisplayName                         *string              `json:"displayName,omitempty"`
+	DisplayNameHTML                     *string              `json:"displayNameHtml,omitempty"`
+	DockerAuthenticationFlow            *string              `json:"dockerAuthenticationFlow,omitempty"`
+	DuplicateEmailsAllowed              *bool                `json:"duplicateEmailsAllowed"`
+	EditUsernameAllowed                 *bool                `json:"editUsernameAllowed"`
+	EmailTheme                          *string              `json:"emailTheme,omitempty"`
+	Enabled                             *bool                `json:"enabled"`
+	EnabledEventTypes                   *[]string            `json:"enabledEventTypes,omitempty"`
+	EventsEnabled                       *bool                `json:"eventsEnabled"`
+	EventsExpiration                    *int64               `json:"eventsExpiration,omitempty"`
+	EventsListeners                     *[]string            `json:"eventsListeners,omitempty"`
+	FailureFactor                       *int                 `json:"failureFactor,omitempty"`
+	FederatedUsers                      *[]interface{}       `json:"federatedUsers,omitempty"`
+	Groups                              *[]interface{}       `json:"groups,omitempty"`
+	ID                                  *string              `json:"id,omitempty"`
+	IdentityProviderMappers             *[]interface{}       `json:"identityProviderMappers,omitempty"`
+	IdentityProviders                   *[]interface{}       `json:"identityProviders,omitempty"`
+	InternationalizationEnabled         *bool                `json:"internationalizationEnabled"`
+	KeycloakVersion                     *string              `json:"keycloakVersion,omitempty"`
+	LoginTheme                          *string              `json:"loginTheme,omitempty"`
+	LoginWithEmailAllowed               *bool                `json:"loginWithEmailAllowed"`
+	MaxDeltaTimeSeconds                 *int                 `json:"maxDeltaTimeSeconds,omitempty"`
+	MaxFailureWaitSeconds               *int                 `json:"maxFailureWaitSeconds,omitempty"`
+	MinimumQuickLoginWaitSeconds        *int                 `json:"minimumQuickLoginWaitSeconds,omitempty"`
+	NotBefore                           *int                 `json:"notBefore,omitempty"`
+	OfflineSessionIdleTimeout           *int                 `json:"offlineSessionIdleTimeout,omitempty"`
+	OfflineSessionMaxLifespan           *int                 `json:"offlineSessionMaxLifespan,omitempty"`
+	OfflineSessionMaxLifespanEnabled    *bool                `json:"offlineSessionMaxLifespanEnabled"`
+	OtpPolicyAlgorithm                  *string              `json:"otpPolicyAlgorithm,omitempty"`
+	OtpPolicyDigits                     *int                 `json:"otpPolicyDigits,omitempty"`
+	OtpPolicyInitialCounter             *int                 `json:"otpPolicyInitialCounter,omitempty"`
+	OtpPolicyLookAheadWindow            *int                 `json:"otpPolicyLookAheadWindow,omitempty"`
+	OtpPolicyPeriod                     *int                 `json:"otpPolicyPeriod,omitempty"`
+	OtpPolicyType                       *string              `json:"otpPolicyType,omitempty"`
+	OtpSupportedApplications            *[]string            `json:"otpSupportedApplications,omitempty"`
+	PasswordPolicy                      *string              `json:"passwordPolicy,omitempty"`
+	PermanentLockout                    *bool                `json:"permanentLockout"`
+	ProtocolMappers                     *[]interface{}       `json:"protocolMappers,omitempty"`
+	QuickLoginCheckMilliSeconds         *int64               `json:"quickLoginCheckMilliSeconds,omitempty"`
+	Realm                               *string              `json:"realm,omitempty"`
+	RefreshTokenMaxReuse                *int                 `json:"refreshTokenMaxReuse,omitempty"`
+	RegistrationAllowed                 *bool                `json:"registrationAllowed"`
+	RegistrationEmailAsUsername         *bool                `json:"registrationEmailAsUsername"`
+	RegistrationFlow                    *string              `json:"registrationFlow,omitempty"`
+	RememberMe                          *bool                `json:"rememberMe"`
+	RequiredActions                     *[]interface{}       `json:"requiredActions,omitempty"`
+	ResetCredentialsFlow                *string              `json:"resetCredentialsFlow,omitempty"`
+	ResetPasswordAllowed                *bool                `json:"resetPasswordAllowed"`
+	RevokeRefreshToken                  *bool                `json:"revokeRefreshToken"`
+	Roles                               *RolesRepresentation `json:"roles,omitempty"`
+	ScopeMappings                       *[]interface{}       `json:"scopeMappings,omitempty"`
+	SMTPServer                          *map[string]string   `json:"smtpServer,omitempty"`
+	SslRequired                         *string              `json:"sslRequired,omitempty"`
+	SsoSessionIdleTimeout               *int                 `json:"ssoSessionIdleTimeout,omitempty"`
+	SsoSessionIdleTimeoutRememberMe     *int                 `json:"ssoSessionIdleTimeoutRememberMe,omitempty"`
+	SsoSessionMaxLifespan               *int                 `json:"ssoSessionMaxLifespan,omitempty"`
+	SsoSessionMaxLifespanRememberMe     *int                 `json:"ssoSessionMaxLifespanRememberMe,omitempty"`
+	SupportedLocales                    *[]string            `json:"supportedLocales,omitempty"`
+	UserFederationMappers               *[]interface{}       `json:"userFederationMappers,omitempty"`
+	UserFederationProviders             *[]interface{}       `json:"userFederationProviders,omitempty"`
+	UserManagedAccessAllowed            *bool                `json:"userManagedAccessAllowed"`
+	Users                               *[]User              `json:"users,omitempty"`
+	VerifyEmail                         *bool                `json:"verifyEmail"`
+	WaitIncrementSeconds                *int                 `json:"waitIncrementSeconds,omitempty"`
 }
 
 // MultiValuedHashMap represents something


Test patch:
diff --git a/client_test.go b/client_test.go
index 871a53c..fb5d322 100644
--- a/client_test.go
+++ b/client_test.go
@@ -1740,6 +1740,20 @@ func CreateRealm(t *testing.T, client gocloak.GoCloak) (func(), string) {
 		token.AccessToken,
 		gocloak.RealmRepresentation{
 			Realm: &realmName,
+			Roles: &gocloak.RolesRepresentation{
+				Realm: &[]gocloak.Role{
+					{
+						Name: GetRandomNameP("Role"),
+					},
+				},
+				Client: &map[string][]gocloak.Role{
+					"account": {
+						{
+							Name: GetRandomNameP("Role"),
+						},
+					},
+				},
+			},
 		})
 	require.NoError(t, err, "CreateRealm failed")
 	require.Equal(t, realmID, realmName)