github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/identity/v3/users/requests.go (about) 1 package users 2 3 import ( 4 "context" 5 "net/url" 6 "strings" 7 8 "github.com/vnpaycloud-console/gophercloud/v2" 9 "github.com/vnpaycloud-console/gophercloud/v2/openstack/identity/v3/groups" 10 "github.com/vnpaycloud-console/gophercloud/v2/openstack/identity/v3/projects" 11 "github.com/vnpaycloud-console/gophercloud/v2/pagination" 12 ) 13 14 // Option is a specific option defined at the API to enable features 15 // on a user account. 16 type Option string 17 18 const ( 19 IgnoreChangePasswordUponFirstUse Option = "ignore_change_password_upon_first_use" 20 IgnorePasswordExpiry Option = "ignore_password_expiry" 21 IgnoreLockoutFailureAttempts Option = "ignore_lockout_failure_attempts" 22 MultiFactorAuthRules Option = "multi_factor_auth_rules" 23 MultiFactorAuthEnabled Option = "multi_factor_auth_enabled" 24 ) 25 26 // ListOptsBuilder allows extensions to add additional parameters to 27 // the List request 28 type ListOptsBuilder interface { 29 ToUserListQuery() (string, error) 30 } 31 32 // ListOpts provides options to filter the List results. 33 type ListOpts struct { 34 // DomainID filters the response by a domain ID. 35 DomainID string `q:"domain_id"` 36 37 // Enabled filters the response by enabled users. 38 Enabled *bool `q:"enabled"` 39 40 // IdpID filters the response by an Identity Provider ID. 41 IdPID string `q:"idp_id"` 42 43 // Name filters the response by username. 44 Name string `q:"name"` 45 46 // PasswordExpiresAt filters the response based on expiring passwords. 47 PasswordExpiresAt string `q:"password_expires_at"` 48 49 // ProtocolID filters the response by protocol ID. 50 ProtocolID string `q:"protocol_id"` 51 52 // UniqueID filters the response by unique ID. 53 UniqueID string `q:"unique_id"` 54 55 // Filters filters the response by custom filters such as 56 // 'name__contains=foo' 57 Filters map[string]string `q:"-"` 58 } 59 60 // ToUserListQuery formats a ListOpts into a query string. 61 func (opts ListOpts) ToUserListQuery() (string, error) { 62 q, err := gophercloud.BuildQueryString(opts) 63 if err != nil { 64 return "", err 65 } 66 67 params := q.Query() 68 for k, v := range opts.Filters { 69 i := strings.Index(k, "__") 70 if i > 0 && i < len(k)-2 { 71 params.Add(k, v) 72 } else { 73 return "", InvalidListFilter{FilterName: k} 74 } 75 } 76 77 q = &url.URL{RawQuery: params.Encode()} 78 return q.String(), err 79 } 80 81 // List enumerates the Users to which the current token has access. 82 func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 83 url := listURL(client) 84 if opts != nil { 85 query, err := opts.ToUserListQuery() 86 if err != nil { 87 return pagination.Pager{Err: err} 88 } 89 url += query 90 } 91 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 92 return UserPage{pagination.LinkedPageBase{PageResult: r}} 93 }) 94 } 95 96 // Get retrieves details on a single user, by ID. 97 func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) { 98 resp, err := client.Get(ctx, getURL(client, id), &r.Body, nil) 99 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 100 return 101 } 102 103 // CreateOptsBuilder allows extensions to add additional parameters to 104 // the Create request. 105 type CreateOptsBuilder interface { 106 ToUserCreateMap() (map[string]any, error) 107 } 108 109 // CreateOpts provides options used to create a user. 110 type CreateOpts struct { 111 // Name is the name of the new user. 112 Name string `json:"name" required:"true"` 113 114 // DefaultProjectID is the ID of the default project of the user. 115 DefaultProjectID string `json:"default_project_id,omitempty"` 116 117 // Description is a description of the user. 118 Description string `json:"description,omitempty"` 119 120 // DomainID is the ID of the domain the user belongs to. 121 DomainID string `json:"domain_id,omitempty"` 122 123 // Enabled sets the user status to enabled or disabled. 124 Enabled *bool `json:"enabled,omitempty"` 125 126 // Extra is free-form extra key/value pairs to describe the user. 127 Extra map[string]any `json:"-"` 128 129 // Options are defined options in the API to enable certain features. 130 Options map[Option]any `json:"options,omitempty"` 131 132 // Password is the password of the new user. 133 Password string `json:"password,omitempty"` 134 } 135 136 // ToUserCreateMap formats a CreateOpts into a create request. 137 func (opts CreateOpts) ToUserCreateMap() (map[string]any, error) { 138 b, err := gophercloud.BuildRequestBody(opts, "user") 139 if err != nil { 140 return nil, err 141 } 142 143 if opts.Extra != nil { 144 if v, ok := b["user"].(map[string]any); ok { 145 for key, value := range opts.Extra { 146 v[key] = value 147 } 148 } 149 } 150 151 return b, nil 152 } 153 154 // Create creates a new User. 155 func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 156 b, err := opts.ToUserCreateMap() 157 if err != nil { 158 r.Err = err 159 return 160 } 161 resp, err := client.Post(ctx, createURL(client), &b, &r.Body, &gophercloud.RequestOpts{ 162 OkCodes: []int{201}, 163 }) 164 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 165 return 166 } 167 168 // UpdateOptsBuilder allows extensions to add additional parameters to 169 // the Update request. 170 type UpdateOptsBuilder interface { 171 ToUserUpdateMap() (map[string]any, error) 172 } 173 174 // UpdateOpts provides options for updating a user account. 175 type UpdateOpts struct { 176 // Name is the name of the new user. 177 Name string `json:"name,omitempty"` 178 179 // DefaultProjectID is the ID of the default project of the user. 180 DefaultProjectID string `json:"default_project_id,omitempty"` 181 182 // Description is a description of the user. 183 Description *string `json:"description,omitempty"` 184 185 // DomainID is the ID of the domain the user belongs to. 186 DomainID string `json:"domain_id,omitempty"` 187 188 // Enabled sets the user status to enabled or disabled. 189 Enabled *bool `json:"enabled,omitempty"` 190 191 // Extra is free-form extra key/value pairs to describe the user. 192 Extra map[string]any `json:"-"` 193 194 // Options are defined options in the API to enable certain features. 195 Options map[Option]any `json:"options,omitempty"` 196 197 // Password is the password of the new user. 198 Password string `json:"password,omitempty"` 199 } 200 201 // ToUserUpdateMap formats a UpdateOpts into an update request. 202 func (opts UpdateOpts) ToUserUpdateMap() (map[string]any, error) { 203 b, err := gophercloud.BuildRequestBody(opts, "user") 204 if err != nil { 205 return nil, err 206 } 207 208 if opts.Extra != nil { 209 if v, ok := b["user"].(map[string]any); ok { 210 for key, value := range opts.Extra { 211 v[key] = value 212 } 213 } 214 } 215 216 return b, nil 217 } 218 219 // Update updates an existing User. 220 func Update(ctx context.Context, client *gophercloud.ServiceClient, userID string, opts UpdateOptsBuilder) (r UpdateResult) { 221 b, err := opts.ToUserUpdateMap() 222 if err != nil { 223 r.Err = err 224 return 225 } 226 resp, err := client.Patch(ctx, updateURL(client, userID), &b, &r.Body, &gophercloud.RequestOpts{ 227 OkCodes: []int{200}, 228 }) 229 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 230 return 231 } 232 233 // ChangePasswordOptsBuilder allows extensions to add additional parameters to 234 // the ChangePassword request. 235 type ChangePasswordOptsBuilder interface { 236 ToUserChangePasswordMap() (map[string]any, error) 237 } 238 239 // ChangePasswordOpts provides options for changing password for a user. 240 type ChangePasswordOpts struct { 241 // OriginalPassword is the original password of the user. 242 OriginalPassword string `json:"original_password"` 243 244 // Password is the new password of the user. 245 Password string `json:"password"` 246 } 247 248 // ToUserChangePasswordMap formats a ChangePasswordOpts into a ChangePassword request. 249 func (opts ChangePasswordOpts) ToUserChangePasswordMap() (map[string]any, error) { 250 b, err := gophercloud.BuildRequestBody(opts, "user") 251 if err != nil { 252 return nil, err 253 } 254 255 return b, nil 256 } 257 258 // ChangePassword changes password for a user. 259 func ChangePassword(ctx context.Context, client *gophercloud.ServiceClient, userID string, opts ChangePasswordOptsBuilder) (r ChangePasswordResult) { 260 b, err := opts.ToUserChangePasswordMap() 261 if err != nil { 262 r.Err = err 263 return 264 } 265 266 resp, err := client.Post(ctx, changePasswordURL(client, userID), &b, nil, &gophercloud.RequestOpts{ 267 OkCodes: []int{204}, 268 }) 269 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 270 return 271 } 272 273 // Delete deletes a user. 274 func Delete(ctx context.Context, client *gophercloud.ServiceClient, userID string) (r DeleteResult) { 275 resp, err := client.Delete(ctx, deleteURL(client, userID), nil) 276 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 277 return 278 } 279 280 // ListGroups enumerates groups user belongs to. 281 func ListGroups(client *gophercloud.ServiceClient, userID string) pagination.Pager { 282 url := listGroupsURL(client, userID) 283 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 284 return groups.GroupPage{LinkedPageBase: pagination.LinkedPageBase{PageResult: r}} 285 }) 286 } 287 288 // AddToGroup adds a user to a group. 289 func AddToGroup(ctx context.Context, client *gophercloud.ServiceClient, groupID, userID string) (r AddToGroupResult) { 290 url := addToGroupURL(client, groupID, userID) 291 resp, err := client.Put(ctx, url, nil, nil, &gophercloud.RequestOpts{ 292 OkCodes: []int{204}, 293 }) 294 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 295 return 296 } 297 298 // IsMemberOfGroup checks whether a user belongs to a group. 299 func IsMemberOfGroup(ctx context.Context, client *gophercloud.ServiceClient, groupID, userID string) (r IsMemberOfGroupResult) { 300 url := isMemberOfGroupURL(client, groupID, userID) 301 resp, err := client.Head(ctx, url, &gophercloud.RequestOpts{ 302 OkCodes: []int{204, 404}, 303 }) 304 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 305 if r.Err == nil { 306 if resp.StatusCode == 204 { 307 r.isMember = true 308 } 309 } 310 return 311 } 312 313 // RemoveFromGroup removes a user from a group. 314 func RemoveFromGroup(ctx context.Context, client *gophercloud.ServiceClient, groupID, userID string) (r RemoveFromGroupResult) { 315 url := removeFromGroupURL(client, groupID, userID) 316 resp, err := client.Delete(ctx, url, &gophercloud.RequestOpts{ 317 OkCodes: []int{204}, 318 }) 319 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 320 return 321 } 322 323 // ListProjects enumerates groups user belongs to. 324 func ListProjects(client *gophercloud.ServiceClient, userID string) pagination.Pager { 325 url := listProjectsURL(client, userID) 326 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 327 return projects.ProjectPage{LinkedPageBase: pagination.LinkedPageBase{PageResult: r}} 328 }) 329 } 330 331 // ListInGroup enumerates users that belong to a group. 332 func ListInGroup(client *gophercloud.ServiceClient, groupID string, opts ListOptsBuilder) pagination.Pager { 333 url := listInGroupURL(client, groupID) 334 if opts != nil { 335 query, err := opts.ToUserListQuery() 336 if err != nil { 337 return pagination.Pager{Err: err} 338 } 339 url += query 340 } 341 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 342 return UserPage{pagination.LinkedPageBase{PageResult: r}} 343 }) 344 }