func (as *authorizerService) AssignGlobalRoleToUser(
	ctx context.Context,
	userID string,
	roleName string,
) error {
	return as.assignRoleToUser(ctx, userID, roleName, nil)
}
AssignGlobalRoleToUser assigns a previously created global role to a user.
package authorizer
import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"github.com/pusher/chatkit-server-go/internal/common"
	"github.com/pusher/pusher-platform-go/client"
	"github.com/pusher/pusher-platform-go/instance"
)
const (
	scopeGlobal = "global"
	scopeRoom   = "room"
)
type Service interface {
	GetRoles(ctx context.Context) ([]Role, error)
	CreateGlobalRole(ctx context.Context, options CreateRoleOptions) error
	CreateRoomRole(ctx context.Context, options CreateRoleOptions) error
	DeleteGlobalRole(ctx context.Context, roleName string) error
	DeleteRoomRole(ctx context.Context, roleName string) error
	GetPermissionsForGlobalRole(ctx context.Context, roleName string) ([]string, error)
	GetPermissionsForRoomRole(ctx context.Context, roleName string) ([]string, error)
	UpdatePermissionsForGlobalRole(
		ctx context.Context,
		roleName string,
		options UpdateRolePermissionsOptions,
	) error
	UpdatePermissionsForRoomRole(
		ctx context.Context,
		roleName string,
		options UpdateRolePermissionsOptions,
	) error
	GetUserRoles(ctx context.Context, userID string) ([]Role, error)
	AssignGlobalRoleToUser(ctx context.Context, userID string, roleName string) error
	AssignRoomRoleToUser(ctx context.Context, userID string, roomID string, roleName string) error
	RemoveGlobalRoleForUser(ctx context.Context, userID string) error
	RemoveRoomRoleForUser(ctx context.Context, userID string, roomID string) error
	Request(ctx context.Context, options client.RequestOptions) (*http.Response, error)
}
type authorizerService struct {
	underlyingInstance instance.Instance
}
func NewService(platformInstance instance.Instance) Service {
	return &authorizerService{
		underlyingInstance: platformInstance,
	}
}
func (as *authorizerService) GetRoles(ctx context.Context) ([]Role, error) {
	response, err := common.RequestWithSuToken(as.underlyingInstance, ctx, client.RequestOptions{
		Method: http.MethodGet,
		Path:   "/roles",
	})
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	var roles []Role
	err = common.DecodeResponseBody(response.Body, &roles)
	if err != nil {
		return nil, err
	}
	return roles, nil
}
func (as *authorizerService) CreateGlobalRole(ctx context.Context, options CreateRoleOptions) error {
	return as.createRole(ctx, Role{
		Name:        options.Name,
		Permissions: options.Permissions,
		Scope:       scopeGlobal,
	})
}
func (as *authorizerService) CreateRoomRole(ctx context.Context, options CreateRoleOptions) error {
	return as.createRole(ctx, Role{
		Name:        options.Name,
		Permissions: options.Permissions,
		Scope:       scopeRoom,
	})
}
func (as *authorizerService) createRole(ctx context.Context, role Role) error {
	if role.Name == "" {
		return errors.New("You must provide a name for the role")
	}
	if role.Permissions == nil {
		return errors.New("You must provide permissions of the role")
	}
	requestBody, err := common.CreateRequestBody(&role)
	if err != nil {
		return err
	}
	response, err := common.RequestWithSuToken(as.underlyingInstance, ctx, client.RequestOptions{
		Method: http.MethodPost,
		Path:   "/roles",
		Body:   requestBody,
	})
	if err != nil {
		return err
	}
	defer response.Body.Close()
	return nil
}
func (as *authorizerService) DeleteGlobalRole(ctx context.Context, roleName string) error {
	return as.deleteRole(ctx, roleName, scopeGlobal)
}
func (as *authorizerService) DeleteRoomRole(ctx context.Context, roleName string) error {
	return as.deleteRole(ctx, roleName, scopeRoom)
}
func (as *authorizerService) deleteRole(ctx context.Context, roleName string, scope string) error {
	response, err := common.RequestWithSuToken(as.underlyingInstance, ctx, client.RequestOptions{
		Method: http.MethodDelete,
		Path:   fmt.Sprintf("/roles/%s/scope/%s", roleName, scope),
	})
	if err != nil {
		return err
	}
	defer response.Body.Close()
	return nil
}
func (as *authorizerService) GetPermissionsForGlobalRole(
	ctx context.Context,
	roleName string,
) ([]string, error) {
	return as.getPermissions(ctx, roleName, scopeGlobal)
}
func (as *authorizerService) GetPermissionsForRoomRole(
	ctx context.Context,
	roleName string,
) ([]string, error) {
	return as.getPermissions(ctx, roleName, scopeRoom)
}
func (as *authorizerService) getPermissions(
	ctx context.Context,
	roleName string,
	scope string,
) ([]string, error) {
	response, err := common.RequestWithSuToken(as.underlyingInstance, ctx, client.RequestOptions{
		Method: http.MethodGet,
		Path:   fmt.Sprintf("/roles/%s/scope/%s/permissions", roleName, scope),
	})
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	var rolePermissions []string
	err = common.DecodeResponseBody(response.Body, &rolePermissions)
	if err != nil {
		return nil, err
	}
	return rolePermissions, nil
}
func (as *authorizerService) UpdatePermissionsForGlobalRole(
	ctx context.Context,
	roleName string,
	options UpdateRolePermissionsOptions,
) error {
	return as.updatePermissions(ctx, roleName, options, scopeGlobal)
}
func (as *authorizerService) UpdatePermissionsForRoomRole(
	ctx context.Context,
	roleName string,
	options UpdateRolePermissionsOptions,
) error {
	return as.updatePermissions(ctx, roleName, options, scopeRoom)
}
func (as *authorizerService) updatePermissions(
	ctx context.Context,
	roleName string,
	options UpdateRolePermissionsOptions,
	scope string,
) error {
	if (options.PermissionsToAdd == nil || len(options.PermissionsToAdd) == 0) &&
		(options.PermissionsToRemove == nil || len(options.PermissionsToRemove) == 0) {
		return errors.New("PermissionsToAdd and PermissionsToRemove cannot both be empty")
	}
	requestBody, err := common.CreateRequestBody(&options)
	if err != nil {
		return err
	}
	response, err := common.RequestWithSuToken(as.underlyingInstance, ctx, client.RequestOptions{
		Method: http.MethodPut,
		Path:   fmt.Sprintf("/roles/%s/scope/%s/permissions", roleName, scope),
		Body:   requestBody,
	})
	if err != nil {
		return err
	}
	defer response.Body.Close()
	return nil
}
func (as *authorizerService) GetUserRoles(ctx context.Context, userID string) ([]Role, error) {
	if userID == "" {
		return nil, errors.New("You must provide the ID of the user whose roles you want to fetch")
	}
	response, err := common.RequestWithSuToken(as.underlyingInstance, ctx, client.RequestOptions{
		Method: http.MethodGet,
		Path:   fmt.Sprintf("/users/%s/roles", userID),
	})
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	var roles []Role
	err = common.DecodeResponseBody(response.Body, &roles)
	if err != nil {
		return nil, err
	}
	return roles, nil
}