github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/identity/v3/roles/requests.go (about) 1 package roles 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/pagination" 10 ) 11 12 // ListOptsBuilder allows extensions to add additional parameters to 13 // the List request 14 type ListOptsBuilder interface { 15 ToRoleListQuery() (string, error) 16 } 17 18 // ListOpts provides options to filter the List results. 19 type ListOpts struct { 20 // DomainID filters the response by a domain ID. 21 DomainID string `q:"domain_id"` 22 23 // Name filters the response by role name. 24 Name string `q:"name"` 25 26 // Filters filters the response by custom filters such as 27 // 'name__contains=foo' 28 Filters map[string]string `q:"-"` 29 } 30 31 // ToRoleListQuery formats a ListOpts into a query string. 32 func (opts ListOpts) ToRoleListQuery() (string, error) { 33 q, err := gophercloud.BuildQueryString(opts) 34 if err != nil { 35 return "", err 36 } 37 38 params := q.Query() 39 for k, v := range opts.Filters { 40 i := strings.Index(k, "__") 41 if i > 0 && i < len(k)-2 { 42 params.Add(k, v) 43 } else { 44 return "", InvalidListFilter{FilterName: k} 45 } 46 } 47 48 q = &url.URL{RawQuery: params.Encode()} 49 return q.String(), err 50 } 51 52 // List enumerates the roles to which the current token has access. 53 func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 54 url := listURL(client) 55 if opts != nil { 56 query, err := opts.ToRoleListQuery() 57 if err != nil { 58 return pagination.Pager{Err: err} 59 } 60 url += query 61 } 62 63 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 64 return RolePage{pagination.LinkedPageBase{PageResult: r}} 65 }) 66 } 67 68 // Get retrieves details on a single role, by ID. 69 func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) { 70 resp, err := client.Get(ctx, getURL(client, id), &r.Body, nil) 71 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 72 return 73 } 74 75 // CreateOptsBuilder allows extensions to add additional parameters to 76 // the Create request. 77 type CreateOptsBuilder interface { 78 ToRoleCreateMap() (map[string]any, error) 79 } 80 81 // CreateOpts provides options used to create a role. 82 type CreateOpts struct { 83 // Name is the name of the new role. 84 Name string `json:"name" required:"true"` 85 86 // DomainID is the ID of the domain the role belongs to. 87 DomainID string `json:"domain_id,omitempty"` 88 89 // Extra is free-form extra key/value pairs to describe the role. 90 Extra map[string]any `json:"-"` 91 } 92 93 // ToRoleCreateMap formats a CreateOpts into a create request. 94 func (opts CreateOpts) ToRoleCreateMap() (map[string]any, error) { 95 b, err := gophercloud.BuildRequestBody(opts, "role") 96 if err != nil { 97 return nil, err 98 } 99 100 if opts.Extra != nil { 101 if v, ok := b["role"].(map[string]any); ok { 102 for key, value := range opts.Extra { 103 v[key] = value 104 } 105 } 106 } 107 108 return b, nil 109 } 110 111 // Create creates a new Role. 112 func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 113 b, err := opts.ToRoleCreateMap() 114 if err != nil { 115 r.Err = err 116 return 117 } 118 resp, err := client.Post(ctx, createURL(client), &b, &r.Body, &gophercloud.RequestOpts{ 119 OkCodes: []int{201}, 120 }) 121 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 122 return 123 } 124 125 // UpdateOptsBuilder allows extensions to add additional parameters to 126 // the Update request. 127 type UpdateOptsBuilder interface { 128 ToRoleUpdateMap() (map[string]any, error) 129 } 130 131 // UpdateOpts provides options for updating a role. 132 type UpdateOpts struct { 133 // Name is the name of the new role. 134 Name string `json:"name,omitempty"` 135 136 // Extra is free-form extra key/value pairs to describe the role. 137 Extra map[string]any `json:"-"` 138 } 139 140 // ToRoleUpdateMap formats a UpdateOpts into an update request. 141 func (opts UpdateOpts) ToRoleUpdateMap() (map[string]any, error) { 142 b, err := gophercloud.BuildRequestBody(opts, "role") 143 if err != nil { 144 return nil, err 145 } 146 147 if opts.Extra != nil { 148 if v, ok := b["role"].(map[string]any); ok { 149 for key, value := range opts.Extra { 150 v[key] = value 151 } 152 } 153 } 154 155 return b, nil 156 } 157 158 // Update updates an existing Role. 159 func Update(ctx context.Context, client *gophercloud.ServiceClient, roleID string, opts UpdateOptsBuilder) (r UpdateResult) { 160 b, err := opts.ToRoleUpdateMap() 161 if err != nil { 162 r.Err = err 163 return 164 } 165 resp, err := client.Patch(ctx, updateURL(client, roleID), &b, &r.Body, &gophercloud.RequestOpts{ 166 OkCodes: []int{200}, 167 }) 168 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 169 return 170 } 171 172 // Delete deletes a role. 173 func Delete(ctx context.Context, client *gophercloud.ServiceClient, roleID string) (r DeleteResult) { 174 resp, err := client.Delete(ctx, deleteURL(client, roleID), nil) 175 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 176 return 177 } 178 179 // ListAssignmentsOptsBuilder allows extensions to add additional parameters to 180 // the ListAssignments request. 181 type ListAssignmentsOptsBuilder interface { 182 ToRolesListAssignmentsQuery() (string, error) 183 } 184 185 // ListAssignmentsOpts allows you to query the ListAssignments method. 186 // Specify one of or a combination of GroupId, RoleId, ScopeDomainId, 187 // ScopeProjectId, and/or UserId to search for roles assigned to corresponding 188 // entities. 189 type ListAssignmentsOpts struct { 190 // GroupID is the group ID to query. 191 GroupID string `q:"group.id"` 192 193 // RoleID is the specific role to query assignments to. 194 RoleID string `q:"role.id"` 195 196 // ScopeDomainID filters the results by the given domain ID. 197 ScopeDomainID string `q:"scope.domain.id"` 198 199 // ScopeProjectID filters the results by the given Project ID. 200 ScopeProjectID string `q:"scope.project.id"` 201 202 // UserID filterst he results by the given User ID. 203 UserID string `q:"user.id"` 204 205 // Effective lists effective assignments at the user, project, and domain 206 // level, allowing for the effects of group membership. 207 Effective *bool `q:"effective"` 208 209 // IncludeNames indicates whether to include names of any returned entities. 210 // Requires microversion 3.6 or later. 211 IncludeNames *bool `q:"include_names"` 212 213 // IncludeSubtree indicates whether to include relevant assignments in the project hierarchy below the project 214 // specified in the ScopeProjectID. Specify DomainID in ScopeProjectID to get a list for all projects in the domain. 215 // Requires microversion 3.6 or later. 216 IncludeSubtree *bool `q:"include_subtree"` 217 } 218 219 // ToRolesListAssignmentsQuery formats a ListAssignmentsOpts into a query string. 220 func (opts ListAssignmentsOpts) ToRolesListAssignmentsQuery() (string, error) { 221 q, err := gophercloud.BuildQueryString(opts) 222 return q.String(), err 223 } 224 225 // ListAssignments enumerates the roles assigned to a specified resource. 226 func ListAssignments(client *gophercloud.ServiceClient, opts ListAssignmentsOptsBuilder) pagination.Pager { 227 url := listAssignmentsURL(client) 228 if opts != nil { 229 query, err := opts.ToRolesListAssignmentsQuery() 230 if err != nil { 231 return pagination.Pager{Err: err} 232 } 233 url += query 234 } 235 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 236 return RoleAssignmentPage{pagination.LinkedPageBase{PageResult: r}} 237 }) 238 } 239 240 // ListAssignmentsOnResourceOpts provides options to list role assignments 241 // for a user/group on a project/domain 242 type ListAssignmentsOnResourceOpts struct { 243 // UserID is the ID of a user to assign a role 244 // Note: exactly one of UserID or GroupID must be provided 245 UserID string `xor:"GroupID"` 246 247 // GroupID is the ID of a group to assign a role 248 // Note: exactly one of UserID or GroupID must be provided 249 GroupID string `xor:"UserID"` 250 251 // ProjectID is the ID of a project to assign a role on 252 // Note: exactly one of ProjectID or DomainID must be provided 253 ProjectID string `xor:"DomainID"` 254 255 // DomainID is the ID of a domain to assign a role on 256 // Note: exactly one of ProjectID or DomainID must be provided 257 DomainID string `xor:"ProjectID"` 258 } 259 260 // AssignOpts provides options to assign a role 261 type AssignOpts struct { 262 // UserID is the ID of a user to assign a role 263 // Note: exactly one of UserID or GroupID must be provided 264 UserID string `xor:"GroupID"` 265 266 // GroupID is the ID of a group to assign a role 267 // Note: exactly one of UserID or GroupID must be provided 268 GroupID string `xor:"UserID"` 269 270 // ProjectID is the ID of a project to assign a role on 271 // Note: exactly one of ProjectID or DomainID must be provided 272 ProjectID string `xor:"DomainID"` 273 274 // DomainID is the ID of a domain to assign a role on 275 // Note: exactly one of ProjectID or DomainID must be provided 276 DomainID string `xor:"ProjectID"` 277 } 278 279 // UnassignOpts provides options to unassign a role 280 type UnassignOpts struct { 281 // UserID is the ID of a user to unassign a role 282 // Note: exactly one of UserID or GroupID must be provided 283 UserID string `xor:"GroupID"` 284 285 // GroupID is the ID of a group to unassign a role 286 // Note: exactly one of UserID or GroupID must be provided 287 GroupID string `xor:"UserID"` 288 289 // ProjectID is the ID of a project to unassign a role on 290 // Note: exactly one of ProjectID or DomainID must be provided 291 ProjectID string `xor:"DomainID"` 292 293 // DomainID is the ID of a domain to unassign a role on 294 // Note: exactly one of ProjectID or DomainID must be provided 295 DomainID string `xor:"ProjectID"` 296 } 297 298 // ListAssignmentsOnResource is the operation responsible for listing role 299 // assignments for a user/group on a project/domain. 300 func ListAssignmentsOnResource(client *gophercloud.ServiceClient, opts ListAssignmentsOnResourceOpts) pagination.Pager { 301 // Check xor conditions 302 _, err := gophercloud.BuildRequestBody(opts, "") 303 if err != nil { 304 return pagination.Pager{Err: err} 305 } 306 307 // Get corresponding URL 308 var targetID string 309 var targetType string 310 if opts.ProjectID != "" { 311 targetID = opts.ProjectID 312 targetType = "projects" 313 } else { 314 targetID = opts.DomainID 315 targetType = "domains" 316 } 317 318 var actorID string 319 var actorType string 320 if opts.UserID != "" { 321 actorID = opts.UserID 322 actorType = "users" 323 } else { 324 actorID = opts.GroupID 325 actorType = "groups" 326 } 327 328 url := listAssignmentsOnResourceURL(client, targetType, targetID, actorType, actorID) 329 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 330 return RolePage{pagination.LinkedPageBase{PageResult: r}} 331 }) 332 } 333 334 // Assign is the operation responsible for assigning a role 335 // to a user/group on a project/domain. 336 func Assign(ctx context.Context, client *gophercloud.ServiceClient, roleID string, opts AssignOpts) (r AssignmentResult) { 337 // Check xor conditions 338 _, err := gophercloud.BuildRequestBody(opts, "") 339 if err != nil { 340 r.Err = err 341 return 342 } 343 344 // Get corresponding URL 345 var targetID string 346 var targetType string 347 if opts.ProjectID != "" { 348 targetID = opts.ProjectID 349 targetType = "projects" 350 } else { 351 targetID = opts.DomainID 352 targetType = "domains" 353 } 354 355 var actorID string 356 var actorType string 357 if opts.UserID != "" { 358 actorID = opts.UserID 359 actorType = "users" 360 } else { 361 actorID = opts.GroupID 362 actorType = "groups" 363 } 364 365 resp, err := client.Put(ctx, assignURL(client, targetType, targetID, actorType, actorID, roleID), nil, nil, &gophercloud.RequestOpts{ 366 OkCodes: []int{204}, 367 }) 368 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 369 return 370 } 371 372 // Unassign is the operation responsible for unassigning a role 373 // from a user/group on a project/domain. 374 func Unassign(ctx context.Context, client *gophercloud.ServiceClient, roleID string, opts UnassignOpts) (r UnassignmentResult) { 375 // Check xor conditions 376 _, err := gophercloud.BuildRequestBody(opts, "") 377 if err != nil { 378 r.Err = err 379 return 380 } 381 382 // Get corresponding URL 383 var targetID string 384 var targetType string 385 if opts.ProjectID != "" { 386 targetID = opts.ProjectID 387 targetType = "projects" 388 } else { 389 targetID = opts.DomainID 390 targetType = "domains" 391 } 392 393 var actorID string 394 var actorType string 395 if opts.UserID != "" { 396 actorID = opts.UserID 397 actorType = "users" 398 } else { 399 actorID = opts.GroupID 400 actorType = "groups" 401 } 402 403 resp, err := client.Delete(ctx, assignURL(client, targetType, targetID, actorType, actorID, roleID), &gophercloud.RequestOpts{ 404 OkCodes: []int{204}, 405 }) 406 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 407 return 408 } 409 410 func CreateRoleInferenceRule(ctx context.Context, client *gophercloud.ServiceClient, priorRoleID, impliedRoleID string) (r CreateImpliedRoleResult) { 411 resp, err := client.Put(ctx, createRoleInferenceRuleURL(client, priorRoleID, impliedRoleID), nil, &r.Body, &gophercloud.RequestOpts{ 412 OkCodes: []int{201}, 413 }) 414 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 415 return 416 } 417 418 func GetRoleInferenceRule(ctx context.Context, client *gophercloud.ServiceClient, priorRoleID, impliedRoleID string) (r CreateImpliedRoleResult) { 419 resp, err := client.Get(ctx, getRoleInferenceRuleURL(client, priorRoleID, impliedRoleID), &r.Body, &gophercloud.RequestOpts{ 420 OkCodes: []int{200}, 421 }) 422 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 423 return 424 } 425 426 func DeleteRoleInferenceRule(ctx context.Context, client *gophercloud.ServiceClient, priorRoleID, impliedRoleID string) (r DeleteImpliedRoleResult) { 427 resp, err := client.Delete(ctx, deleteRoleInferenceRuleURL(client, priorRoleID, impliedRoleID), &gophercloud.RequestOpts{ 428 OkCodes: []int{204}, 429 }) 430 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 431 return 432 } 433 434 func ListRoleInferenceRules(ctx context.Context, client *gophercloud.ServiceClient) (r ListImpliedRolesResult) { 435 resp, err := client.Get(ctx, listRoleInferenceRulesURL(client), &r.Body, &gophercloud.RequestOpts{ 436 OkCodes: []int{200}, 437 }) 438 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 439 return 440 }