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  }