github.com/cloudfoundry/cli@v7.1.0+incompatible/api/uaa/user.go (about)

     1  package uaa
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  
    10  	"code.cloudfoundry.org/cli/actor/actionerror"
    11  	"code.cloudfoundry.org/cli/api/uaa/internal"
    12  )
    13  
    14  // User represents an UAA user account.
    15  type User struct {
    16  	ID     string
    17  	Origin string
    18  }
    19  
    20  // newUserRequestBody represents the body of the request.
    21  type newUserRequestBody struct {
    22  	Username string   `json:"userName"`
    23  	Password string   `json:"password"`
    24  	Origin   string   `json:"origin"`
    25  	Name     userName `json:"name"`
    26  	Emails   []email  `json:"emails"`
    27  }
    28  
    29  type userName struct {
    30  	FamilyName string `json:"familyName"`
    31  	GivenName  string `json:"givenName"`
    32  }
    33  
    34  type email struct {
    35  	Value   string `json:"value"`
    36  	Primary bool   `json:"primary"`
    37  }
    38  
    39  // newUserResponse represents the HTTP JSON response.
    40  type newUserResponse struct {
    41  	ID     string `json:"id"`
    42  	Origin string `json:"origin"`
    43  }
    44  
    45  type paginatedUsersResponse struct {
    46  	Resources []newUserResponse `json:"resources"`
    47  }
    48  
    49  // CreateUser creates a new UAA user account with the provided password.
    50  func (client *Client) CreateUser(user string, password string, origin string) (User, error) {
    51  	userRequest := newUserRequestBody{
    52  		Username: user,
    53  		Password: password,
    54  		Origin:   origin,
    55  		Name: userName{
    56  			FamilyName: user,
    57  			GivenName:  user,
    58  		},
    59  		Emails: []email{
    60  			{
    61  				Value:   user,
    62  				Primary: true,
    63  			},
    64  		},
    65  	}
    66  
    67  	bodyBytes, err := json.Marshal(userRequest)
    68  	if err != nil {
    69  		return User{}, err
    70  	}
    71  
    72  	request, err := client.newRequest(requestOptions{
    73  		RequestName: internal.PostUserRequest,
    74  		Header: http.Header{
    75  			"Content-Type": {"application/json"},
    76  		},
    77  		Body: bytes.NewBuffer(bodyBytes),
    78  	})
    79  	if err != nil {
    80  		return User{}, err
    81  	}
    82  
    83  	var userResponse newUserResponse
    84  	response := Response{
    85  		Result: &userResponse,
    86  	}
    87  
    88  	err = client.connection.Make(request, &response)
    89  	if err != nil {
    90  		return User{}, err
    91  	}
    92  
    93  	return User(userResponse), nil
    94  }
    95  
    96  func (client *Client) DeleteUser(userGuid string) (User, error) {
    97  	deleteRequest, err := client.newRequest(requestOptions{
    98  		RequestName: internal.DeleteUserRequest,
    99  		Header: http.Header{
   100  			"Content-Type": {"application/json"},
   101  		},
   102  		URIParams: map[string]string{"user_guid": userGuid},
   103  	})
   104  
   105  	if err != nil {
   106  		return User{}, err
   107  	}
   108  
   109  	var deleteUserResponse newUserResponse
   110  	deleteResponse := Response{
   111  		Result: &deleteUserResponse,
   112  	}
   113  
   114  	err = client.connection.Make(deleteRequest, &deleteResponse)
   115  	if err != nil {
   116  		return User{}, err
   117  	}
   118  
   119  	return User(deleteUserResponse), nil
   120  }
   121  
   122  // ListUsers gets a list of users from UAA with the given username and (if provided) origin.
   123  // NOTE: that this is a paginated response and we are only currently returning the first page
   124  // of users. This will mean, if no origin is passed and there are more than 100 users with
   125  // the given username, only the first 100 will be returned. For our current purposes, this is
   126  // more than enough, but it would be a problem if we ever need to get all users with a username.
   127  func (client Client) ListUsers(userName, origin string) ([]User, error) {
   128  	filter := fmt.Sprintf(`userName eq "%s"`, userName)
   129  
   130  	if origin != "" {
   131  		filter = fmt.Sprintf(`%s and origin eq "%s"`, filter, origin)
   132  	}
   133  
   134  	request, err := client.newRequest(requestOptions{
   135  		RequestName: internal.ListUsersRequest,
   136  		Header: http.Header{
   137  			"Content-Type": {"application/json"},
   138  		},
   139  		Query: url.Values{
   140  			"filter": {filter},
   141  		},
   142  	})
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	var usersResponse paginatedUsersResponse
   148  	response := Response{
   149  		Result: &usersResponse,
   150  	}
   151  
   152  	err = client.connection.Make(request, &response)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	var users []User
   158  	for _, user := range usersResponse.Resources {
   159  		users = append(users, User(user))
   160  	}
   161  
   162  	return users, nil
   163  }
   164  
   165  func (client *Client) UpdatePassword(userGUID string, oldPassword string, newPassword string) error {
   166  	requestBody := map[string]interface{}{
   167  		"oldPassword": oldPassword,
   168  		"password":    newPassword,
   169  	}
   170  
   171  	bodyBytes, err := json.Marshal(requestBody)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	request, err := client.newRequest(requestOptions{
   177  		RequestName: internal.UpdatePasswordRequest,
   178  		Header:      http.Header{"Content-Type": {"application/json"}},
   179  		URIParams:   map[string]string{"user_guid": userGUID},
   180  		Body:        bytes.NewBuffer(bodyBytes),
   181  	})
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	return client.connection.Make(request, &Response{})
   187  }
   188  
   189  func (client Client) ValidateClientUser(clientID string) error {
   190  	request, err := client.newRequest(requestOptions{
   191  		RequestName: internal.GetClientUser,
   192  		Header: http.Header{
   193  			"Content-Type": {"application/json"},
   194  		},
   195  		URIParams: map[string]string{"client_id": clientID},
   196  	})
   197  	if err != nil {
   198  		return err
   199  	}
   200  	err = client.connection.Make(request, &Response{})
   201  
   202  	if errType, ok := err.(RawHTTPStatusError); ok {
   203  		switch errType.StatusCode {
   204  		case http.StatusNotFound:
   205  			return actionerror.UserNotFoundError{Username: clientID}
   206  		case http.StatusForbidden:
   207  			return InsufficientScopeError{}
   208  		}
   209  	}
   210  
   211  	return err
   212  }