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 }