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