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  }