github.com/aiven/aiven-go-client@v1.36.0/service_user.go (about)

     1  package aiven
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  )
     9  
    10  const (
    11  	UpdateOperationResetCredentials = "reset-credentials"
    12  	UpdateOperationSetAccessControl = "set-access-control"
    13  )
    14  
    15  type (
    16  	// ServiceUser is the representation of a Service User in the Aiven API.
    17  	ServiceUser struct {
    18  		Username                    string        `json:"username"`
    19  		Password                    string        `json:"password"`
    20  		Type                        string        `json:"type"`
    21  		AccessCert                  string        `json:"access_cert"`
    22  		AccessKey                   string        `json:"access_key"`
    23  		AccessCertNotValidAfterTime string        `json:"access_cert_not_valid_after_time"`
    24  		AccessControl               AccessControl `json:"access_control,omitempty"`
    25  	}
    26  
    27  	AccessControl struct {
    28  		M3Group                  *string  `json:"m3_group"`
    29  		RedisACLCategories       []string `json:"redis_acl_categories"`
    30  		RedisACLCommands         []string `json:"redis_acl_commands"`
    31  		RedisACLKeys             []string `json:"redis_acl_keys"`
    32  		RedisACLChannels         []string `json:"redis_acl_channels"`
    33  		PostgresAllowReplication *bool    `json:"pg_allow_replication"`
    34  	}
    35  
    36  	// ServiceUsersHandler is the client that interacts with the ServiceUsers
    37  	// endpoints.
    38  	ServiceUsersHandler struct {
    39  		client *Client
    40  	}
    41  
    42  	// CreateServiceUserRequest are the parameters required to create a
    43  	// ServiceUser.
    44  	CreateServiceUserRequest struct {
    45  		Username       string         `json:"username"`
    46  		Authentication *string        `json:"authentication,omitempty"`
    47  		AccessControl  *AccessControl `json:"access_control,omitempty"`
    48  	}
    49  
    50  	// ModifyServiceUserRequest params required to modify a ServiceUser
    51  	ModifyServiceUserRequest struct {
    52  		Operation      *string        `json:"operation"`
    53  		Authentication *string        `json:"authentication,omitempty"`
    54  		NewPassword    *string        `json:"new_password,omitempty"`
    55  		AccessControl  *AccessControl `json:"access_control,omitempty"`
    56  	}
    57  
    58  	// ServiceUserResponse represents the response after creating a ServiceUser.
    59  	ServiceUserResponse struct {
    60  		APIResponse
    61  		User *ServiceUser `json:"user"`
    62  	}
    63  )
    64  
    65  // MarshalJSON implements a custom marshalling process for AccessControl where only null fields are omitted
    66  func (ac AccessControl) MarshalJSON() ([]byte, error) {
    67  	out := make(map[string]interface{})
    68  
    69  	fields := reflect.TypeOf(ac)
    70  	values := reflect.ValueOf(ac)
    71  
    72  	for i := 0; i < fields.NumField(); i++ {
    73  		field := fields.Field(i)
    74  		value := values.Field(i)
    75  
    76  		switch value.Kind() {
    77  		case reflect.Pointer, reflect.Slice: // *string, *bool, []string
    78  			if !value.IsNil() {
    79  				jsonName := field.Tag.Get("json")
    80  				out[jsonName] = value.Interface()
    81  			}
    82  		}
    83  	}
    84  	return json.Marshal(out)
    85  }
    86  
    87  // Create creates the given User on Aiven.
    88  func (h *ServiceUsersHandler) Create(project, service string, req CreateServiceUserRequest) (*ServiceUser, error) {
    89  	path := buildPath("project", project, "service", service, "user")
    90  	bts, err := h.client.doPostRequest(path, req)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	var r ServiceUserResponse
    96  	errR := checkAPIResponse(bts, &r)
    97  
    98  	return r.User, errR
    99  }
   100  
   101  // List Service Users for given service in Aiven.
   102  func (h *ServiceUsersHandler) List(project, serviceName string) ([]*ServiceUser, error) {
   103  	// Aiven API does not provide list operation for service users, need to get them via service info instead
   104  	service, err := h.client.Services.Get(project, serviceName)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	return service.Users, nil
   110  }
   111  
   112  // Get specific Service User in Aiven.
   113  func (h *ServiceUsersHandler) Get(project, serviceName, username string) (*ServiceUser, error) {
   114  	// Aiven API does not provide get operation for service users, need to get them via list instead
   115  	users, err := h.List(project, serviceName)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	for _, user := range users {
   120  		if user.Username == username {
   121  			return user, nil
   122  		}
   123  	}
   124  
   125  	err = Error{Message: fmt.Sprintf("Service user with username %v not found", username), Status: 404}
   126  	return nil, err
   127  }
   128  
   129  // Update modifies the given Service User in Aiven.
   130  func (h *ServiceUsersHandler) Update(project, service, username string, update ModifyServiceUserRequest) (*ServiceUser, error) {
   131  	var DefaultOperation = UpdateOperationResetCredentials
   132  	if update.Operation == nil {
   133  		update.Operation = &DefaultOperation
   134  	}
   135  
   136  	if update.AccessControl != nil && *update.Operation != UpdateOperationSetAccessControl {
   137  		return nil, errors.New("wrong operation for updating access control")
   138  	}
   139  
   140  	if (update.NewPassword != nil || update.Authentication != nil) && *update.Operation != UpdateOperationResetCredentials {
   141  		return nil, errors.New("wrong operation for updating credentials")
   142  	}
   143  	path := buildPath("project", project, "service", service, "user", username)
   144  	svc, err := h.client.doPutRequest(path, update)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	var r ServiceResponse
   150  	errR := checkAPIResponse(svc, &r)
   151  	if errR == nil {
   152  		for _, user := range r.Service.Users {
   153  			if user.Username == username {
   154  				return user, nil
   155  			}
   156  		}
   157  		return nil, errors.New("user not found")
   158  	}
   159  
   160  	return nil, errR
   161  }
   162  
   163  // Delete deletes the given Service User in Aiven.
   164  func (h *ServiceUsersHandler) Delete(project, service, user string) error {
   165  	path := buildPath("project", project, "service", service, "user", user)
   166  	bts, err := h.client.doDeleteRequest(path, nil)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	return checkAPIResponse(bts, nil)
   172  }