diff --git a/api/roles/custom.go b/api/roles/custom.go new file mode 100644 index 0000000000..4f340f0fd4 --- /dev/null +++ b/api/roles/custom.go @@ -0,0 +1,107 @@ +package roles + +import ( + "context" + "fmt" + + "github.com/hashicorp/watchtower/api" +) + +func (s Role) AddPrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) { + if s.Client == nil { + return nil, nil, fmt.Errorf("nil client in AddPrincipals request") + } + // We assume that the client provided has the org and optionally the project id of the request. + + body := map[string]interface{}{ + "group_ids": groups, + "user_ids": users, + "version": s.Version, + } + + req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:add-principals", s.Id), body) + if err != nil { + return nil, nil, fmt.Errorf("error creating AddPrincipals request: %w", err) + } + + resp, err := s.Client.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("error performing client request during AddPrincipals call: %w", err) + } + + target := new(Role) + apiErr, err := resp.Decode(target) + if err != nil { + return nil, nil, fmt.Errorf("error decoding AddPrincipals repsonse: %w", err) + } + + target.Client = s.Client + + return target, apiErr, nil +} + +func (s Role) SetPrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) { + if s.Client == nil { + return nil, nil, fmt.Errorf("nil client in SetPrincipals request") + } + // We assume that the client provided has the org and optionally the project id of the request. + + body := map[string]interface{}{ + "group_ids": groups, + "user_ids": users, + "version": s.Version, + } + + req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:set-principals", s.Id), body) + if err != nil { + return nil, nil, fmt.Errorf("error creating SetPrincipals request: %w", err) + } + + resp, err := s.Client.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("error performing client request during SetPrincipals call: %w", err) + } + + target := new(Role) + apiErr, err := resp.Decode(target) + if err != nil { + return nil, nil, fmt.Errorf("error decoding SetPrincipals repsonse: %w", err) + } + + target.Client = s.Client + + return target, apiErr, nil +} + +func (s Role) RemovePrincipals(ctx context.Context, groups, users []string) (*Role, *api.Error, error) { + if s.Client == nil { + return nil, nil, fmt.Errorf("nil client in RemovePrincipals request") + } + // We assume that the client provided has the org and optionally the project id of the request. + + body := map[string]interface{}{ + "group_ids": groups, + "user_ids": users, + "version": s.Version, + } + + req, err := s.Client.NewRequest(ctx, "POST", fmt.Sprintf("roles/%s:remove-principals", s.Id), body) + if err != nil { + return nil, nil, fmt.Errorf("error creating RemovePrincipals request: %w", err) + } + + resp, err := s.Client.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("error performing client request during RemovePrincipals call: %w", err) + } + + target := new(Role) + apiErr, err := resp.Decode(target) + if err != nil { + return nil, nil, fmt.Errorf("error decoding RemovePrincipals repsonse: %w", err) + } + + target.Client = s.Client + + return target, apiErr, nil +} diff --git a/api/roles/role.gen.go b/api/roles/role.gen.go index 4b73efde51..048909ec39 100644 --- a/api/roles/role.gen.go +++ b/api/roles/role.gen.go @@ -31,6 +31,18 @@ type Role struct { UpdatedTime time.Time `json:"updated_time,omitempty"` // Whether the resource is disabled Disabled *bool `json:"disabled,omitempty"` + // The version can be used in subsiquent write requests to ensure this resource + // has not changed and to fail the write if it has. + // Output only. + Version *uint32 `json:"version,omitempty"` + // The principals that are assigned this role. + // Output only. + UserIds []string `json:"user_ids,omitempty"` + // Output only. + GroupIds []string `json:"group_ids,omitempty"` + // The grants that this role provides for it's principals. + // Output only. + Grants []string `json:"grants,omitempty"` } func (s *Role) SetDefault(key string) { diff --git a/api/roles/role_test.go b/api/roles/role_test.go index 3082982692..2be07f7837 100644 --- a/api/roles/role_test.go +++ b/api/roles/role_test.go @@ -7,8 +7,10 @@ import ( "testing" "github.com/hashicorp/watchtower/api" + "github.com/hashicorp/watchtower/api/groups" "github.com/hashicorp/watchtower/api/roles" "github.com/hashicorp/watchtower/api/scopes" + "github.com/hashicorp/watchtower/api/users" "github.com/hashicorp/watchtower/internal/iam" "github.com/hashicorp/watchtower/internal/servers/controller" "github.com/stretchr/testify/assert" @@ -16,6 +18,7 @@ import ( ) type roleCrud interface { + CreateGroup(context.Context, *groups.Group) (*groups.Group, *api.Error, error) CreateRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error) ReadRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error) UpdateRole(context.Context, *roles.Role) (*roles.Role, *api.Error, error) @@ -23,6 +26,83 @@ type roleCrud interface { ListRoles(ctx context.Context) ([]*roles.Role, *api.Error, error) } +func TestCustom(t *testing.T) { + tc := controller.NewTestController(t, nil) + defer tc.Shutdown() + + client := tc.Client() + org := &scopes.Organization{ + Client: client, + } + proj, apiErr, err := org.CreateProject(context.Background(), &scopes.Project{}) + require.NoError(t, err) + require.Nil(t, apiErr) + + user, apiErr, err := org.CreateUser(context.Background(), &users.User{}) + require.NoError(t, err) + require.Nil(t, apiErr) + + cases := []struct { + name string + scope roleCrud + }{ + { + name: "org", + scope: org, + }, + { + name: "proj", + scope: proj, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + require := require.New(t) + ctx := context.Background() + g, apiErr, err := tc.scope.CreateGroup(ctx, &groups.Group{}) + require.NoError(err) + require.Nil(apiErr) + require.NotNil(g) + + r, apiErr, err := tc.scope.CreateRole(ctx, &roles.Role{Name: api.String("foo")}) + require.NoError(err) + require.Nil(apiErr) + require.NotNil(r) + + updatedRole, apiErr, err := r.AddPrincipals(ctx, []string{g.Id}, nil) + require.NoError(err) + require.Nil(apiErr, "Got error ", errorMessage(apiErr)) + assert.Equal(t, *updatedRole.Version, (*r.Version)+1) + assert.Contains(t, updatedRole.GroupIds, g.Id) + assert.Empty(t, updatedRole.UserIds) + + r = updatedRole + updatedRole, apiErr, err = r.SetPrincipals(ctx, nil, []string{user.Id}) + require.NoError(err) + require.Nil(apiErr, "Got error ", errorMessage(apiErr)) + assert.Equal(t, *updatedRole.Version, (*r.Version)+1) + assert.Empty(t, updatedRole.GroupIds) + assert.Contains(t, updatedRole.UserIds, user.Id) + + r = updatedRole + updatedRole, apiErr, err = r.RemovePrincipals(ctx, nil, []string{user.Id}) + require.NoError(err) + require.Nil(apiErr, "Got error ", errorMessage(apiErr)) + assert.Equal(t, *updatedRole.Version, (*r.Version)+1) + assert.Empty(t, updatedRole.GroupIds) + assert.Empty(t, updatedRole.UserIds) + }) + } +} + +func errorMessage(in *api.Error) string { + if in == nil { + return "" + } + return *in.Message +} + func TestRole_List(t *testing.T) { assert := assert.New(t) tc := controller.NewTestController(t, nil) diff --git a/internal/db/option.go b/internal/db/option.go index 4c688ba866..aed0cd4c7f 100644 --- a/internal/db/option.go +++ b/internal/db/option.go @@ -33,7 +33,7 @@ type Options struct { newOplogMsgs *[]*oplog.Message // WithVersion must be accessible from other packages - WithVersion int + WithVersion uint32 withSkipVetForWrite bool } @@ -121,7 +121,7 @@ func WithLimit(limit int) Option { } // WithVersion provides an option version number for update operations. -func WithVersion(version int) Option { +func WithVersion(version uint32) Option { return func(o *Options) { o.WithVersion = version } diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index adafca7d28..0dc94b7158 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -2199,6 +2199,141 @@ ] } }, + "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:add-principals": { + "post": { + "summary": "Adds Users and/or Groups to a Role", + "operationId": "RoleService_AddRolePrincipals2", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "project_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.AddRolePrincipalsRequest" + } + } + ], + "tags": [ + "controller.api.services.v1.RoleService" + ] + } + }, + "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:remove-principals": { + "post": { + "summary": "Removes the specified Users and/or Groups from a Role.", + "operationId": "RoleService_RemoveRolePrincipals2", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "project_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.RemoveRolePrincipalsRequest" + } + } + ], + "tags": [ + "controller.api.services.v1.RoleService" + ] + } + }, + "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:set-principals": { + "post": { + "summary": "Set Users and/or Groups to a Role, removing any principals that are not specified in the request.", + "operationId": "RoleService_SetRolePrincipals2", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "project_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.SetRolePrincipalsRequest" + } + } + ], + "tags": [ + "controller.api.services.v1.RoleService" + ] + } + }, "/v1/orgs/{org_id}/roles": { "get": { "summary": "Lists all Roles", @@ -2382,6 +2517,123 @@ ] } }, + "/v1/orgs/{org_id}/roles/{role_id}:add-principals": { + "post": { + "summary": "Adds Users and/or Groups to a Role", + "operationId": "RoleService_AddRolePrincipals", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.AddRolePrincipalsRequest" + } + } + ], + "tags": [ + "controller.api.services.v1.RoleService" + ] + } + }, + "/v1/orgs/{org_id}/roles/{role_id}:remove-principals": { + "post": { + "summary": "Removes the specified Users and/or Groups from a Role.", + "operationId": "RoleService_RemoveRolePrincipals", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.RemoveRolePrincipalsRequest" + } + } + ], + "tags": [ + "controller.api.services.v1.RoleService" + ] + } + }, + "/v1/orgs/{org_id}/roles/{role_id}:set-principals": { + "post": { + "summary": "Set Users and/or Groups to a Role, removing any principals that are not specified in the request.", + "operationId": "RoleService_SetRolePrincipals", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.SetRolePrincipalsRequest" + } + } + ], + "tags": [ + "controller.api.services.v1.RoleService" + ] + } + }, "/v1/orgs/{org_id}/users": { "get": { "summary": "Lists all Users", @@ -2867,6 +3119,36 @@ "type": "boolean", "format": "boolean", "title": "Whether the resource is disabled" + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The version can be used in subsiquent write requests to ensure this resource\nhas not changed and to fail the write if it has.\nOutput only.", + "readOnly": true + }, + "user_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The principals that are assigned this role.\nOutput only.", + "readOnly": true + }, + "group_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only.", + "readOnly": true + }, + "grants": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The grants that this role provides for it's principals.\nOutput only.", + "readOnly": true } }, "title": "Role contains all fields related to a Role resource" @@ -2974,6 +3256,45 @@ }, "title": "User contains all fields related to a User resource" }, + "controller.api.services.v1.AddRolePrincipalsRequest": { + "type": "object", + "properties": { + "org_id": { + "type": "string" + }, + "project_id": { + "type": "string" + }, + "role_id": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail." + }, + "user_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "group_ids": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "controller.api.services.v1.AddRolePrincipalsResponse": { + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, "controller.api.services.v1.AddToHostSetResponse": { "type": "object" }, @@ -3313,6 +3634,84 @@ "controller.api.services.v1.RemoveFromHostSetResponse": { "type": "object" }, + "controller.api.services.v1.RemoveRolePrincipalsRequest": { + "type": "object", + "properties": { + "org_id": { + "type": "string" + }, + "project_id": { + "type": "string" + }, + "role_id": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail." + }, + "user_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "group_ids": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "controller.api.services.v1.RemoveRolePrincipalsResponse": { + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, + "controller.api.services.v1.SetRolePrincipalsRequest": { + "type": "object", + "properties": { + "org_id": { + "type": "string" + }, + "project_id": { + "type": "string" + }, + "role_id": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The version ensures the role hasn't changed since it was last retrieved and if\nit has the request will fail." + }, + "user_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "group_ids": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "controller.api.services.v1.SetRolePrincipalsResponse": { + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.roles.v1.Role" + } + } + }, "controller.api.services.v1.UpdateGroupResponse": { "type": "object", "properties": { diff --git a/internal/gen/controller/api/resources/roles/role.pb.go b/internal/gen/controller/api/resources/roles/role.pb.go index 9c864b322c..53d834fa11 100644 --- a/internal/gen/controller/api/resources/roles/role.pb.go +++ b/internal/gen/controller/api/resources/roles/role.pb.go @@ -48,6 +48,18 @@ type Role struct { UpdatedTime *timestamp.Timestamp `protobuf:"bytes,5,opt,name=updated_time,proto3" json:"updated_time,omitempty"` // Whether the resource is disabled Disabled *wrappers.BoolValue `protobuf:"bytes,6,opt,name=disabled,proto3" json:"disabled,omitempty"` + // The version can be used in subsiquent write requests to ensure this resource + // has not changed and to fail the write if it has. + // Output only. + Version uint32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"` + // The principals that are assigned this role. + // Output only. + UserIds []string `protobuf:"bytes,8,rep,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + // Output only. + GroupIds []string `protobuf:"bytes,9,rep,name=group_ids,json=groupIds,proto3" json:"group_ids,omitempty"` + // The grants that this role provides for it's principals. + // Output only. + Grants []string `protobuf:"bytes,10,rep,name=grants,proto3" json:"grants,omitempty"` } func (x *Role) Reset() { @@ -124,6 +136,34 @@ func (x *Role) GetDisabled() *wrappers.BoolValue { return nil } +func (x *Role) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *Role) GetUserIds() []string { + if x != nil { + return x.UserIds + } + return nil +} + +func (x *Role) GetGroupIds() []string { + if x != nil { + return x.GroupIds + } + return nil +} + +func (x *Role) GetGrants() []string { + if x != nil { + return x.Grants + } + return nil +} + var File_controller_api_resources_roles_v1_role_proto protoreflect.FileDescriptor var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{ @@ -136,7 +176,7 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{ 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0xc0, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x74, 0x6f, 0x22, 0xaa, 0x03, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, @@ -156,13 +196,19 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{ 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, - 0x74, 0x63, 0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, - 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, + 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74, 0x6f, 0x77, + 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x72, + 0x6f, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/services/role_service.pb.go b/internal/gen/controller/api/services/role_service.pb.go index 8270b0c6aa..18f4a9d6f7 100644 --- a/internal/gen/controller/api/services/role_service.pb.go +++ b/internal/gen/controller/api/services/role_service.pb.go @@ -9,6 +9,7 @@ package services import ( context "context" proto "github.com/golang/protobuf/proto" + wrappers "github.com/golang/protobuf/ptypes/wrappers" _ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options" roles "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/roles" _ "google.golang.org/genproto/googleapis/api/annotations" @@ -379,6 +380,7 @@ func (x *CreateRoleResponse) GetItem() *roles.Role { return nil } +// TODO: Add versions to Update and Delete role requests. type UpdateRoleRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -615,6 +617,414 @@ func (x *DeleteRoleResponse) GetExisted() bool { return false } +type AddRolePrincipalsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + ProjectId string `protobuf:"bytes,2,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"` + RoleId string `protobuf:"bytes,3,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` + // The version ensures the role hasn't changed since it was last retrieved and if + // it has the request will fail. + Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + UserIds []string `protobuf:"bytes,5,rep,name=user_ids,proto3" json:"user_ids,omitempty"` + GroupIds []string `protobuf:"bytes,6,rep,name=group_ids,proto3" json:"group_ids,omitempty"` +} + +func (x *AddRolePrincipalsRequest) Reset() { + *x = AddRolePrincipalsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddRolePrincipalsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddRolePrincipalsRequest) ProtoMessage() {} + +func (x *AddRolePrincipalsRequest) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddRolePrincipalsRequest.ProtoReflect.Descriptor instead. +func (*AddRolePrincipalsRequest) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{10} +} + +func (x *AddRolePrincipalsRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *AddRolePrincipalsRequest) GetProjectId() string { + if x != nil { + return x.ProjectId + } + return "" +} + +func (x *AddRolePrincipalsRequest) GetRoleId() string { + if x != nil { + return x.RoleId + } + return "" +} + +func (x *AddRolePrincipalsRequest) GetVersion() *wrappers.UInt32Value { + if x != nil { + return x.Version + } + return nil +} + +func (x *AddRolePrincipalsRequest) GetUserIds() []string { + if x != nil { + return x.UserIds + } + return nil +} + +func (x *AddRolePrincipalsRequest) GetGroupIds() []string { + if x != nil { + return x.GroupIds + } + return nil +} + +type AddRolePrincipalsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *roles.Role `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *AddRolePrincipalsResponse) Reset() { + *x = AddRolePrincipalsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddRolePrincipalsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddRolePrincipalsResponse) ProtoMessage() {} + +func (x *AddRolePrincipalsResponse) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddRolePrincipalsResponse.ProtoReflect.Descriptor instead. +func (*AddRolePrincipalsResponse) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{11} +} + +func (x *AddRolePrincipalsResponse) GetItem() *roles.Role { + if x != nil { + return x.Item + } + return nil +} + +type SetRolePrincipalsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + ProjectId string `protobuf:"bytes,2,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"` + RoleId string `protobuf:"bytes,3,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` + // The version ensures the role hasn't changed since it was last retrieved and if + // it has the request will fail. + Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + UserIds []string `protobuf:"bytes,5,rep,name=user_ids,proto3" json:"user_ids,omitempty"` + GroupIds []string `protobuf:"bytes,6,rep,name=group_ids,proto3" json:"group_ids,omitempty"` +} + +func (x *SetRolePrincipalsRequest) Reset() { + *x = SetRolePrincipalsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetRolePrincipalsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetRolePrincipalsRequest) ProtoMessage() {} + +func (x *SetRolePrincipalsRequest) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetRolePrincipalsRequest.ProtoReflect.Descriptor instead. +func (*SetRolePrincipalsRequest) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{12} +} + +func (x *SetRolePrincipalsRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *SetRolePrincipalsRequest) GetProjectId() string { + if x != nil { + return x.ProjectId + } + return "" +} + +func (x *SetRolePrincipalsRequest) GetRoleId() string { + if x != nil { + return x.RoleId + } + return "" +} + +func (x *SetRolePrincipalsRequest) GetVersion() *wrappers.UInt32Value { + if x != nil { + return x.Version + } + return nil +} + +func (x *SetRolePrincipalsRequest) GetUserIds() []string { + if x != nil { + return x.UserIds + } + return nil +} + +func (x *SetRolePrincipalsRequest) GetGroupIds() []string { + if x != nil { + return x.GroupIds + } + return nil +} + +type SetRolePrincipalsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *roles.Role `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *SetRolePrincipalsResponse) Reset() { + *x = SetRolePrincipalsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetRolePrincipalsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetRolePrincipalsResponse) ProtoMessage() {} + +func (x *SetRolePrincipalsResponse) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetRolePrincipalsResponse.ProtoReflect.Descriptor instead. +func (*SetRolePrincipalsResponse) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{13} +} + +func (x *SetRolePrincipalsResponse) GetItem() *roles.Role { + if x != nil { + return x.Item + } + return nil +} + +type RemoveRolePrincipalsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrgId string `protobuf:"bytes,1,opt,name=org_id,json=orgId,proto3" json:"org_id,omitempty"` + ProjectId string `protobuf:"bytes,2,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"` + RoleId string `protobuf:"bytes,3,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` + // The version ensures the role hasn't changed since it was last retrieved and if + // it has the request will fail. + Version *wrappers.UInt32Value `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + UserIds []string `protobuf:"bytes,5,rep,name=user_ids,proto3" json:"user_ids,omitempty"` + GroupIds []string `protobuf:"bytes,6,rep,name=group_ids,proto3" json:"group_ids,omitempty"` +} + +func (x *RemoveRolePrincipalsRequest) Reset() { + *x = RemoveRolePrincipalsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveRolePrincipalsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveRolePrincipalsRequest) ProtoMessage() {} + +func (x *RemoveRolePrincipalsRequest) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveRolePrincipalsRequest.ProtoReflect.Descriptor instead. +func (*RemoveRolePrincipalsRequest) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{14} +} + +func (x *RemoveRolePrincipalsRequest) GetOrgId() string { + if x != nil { + return x.OrgId + } + return "" +} + +func (x *RemoveRolePrincipalsRequest) GetProjectId() string { + if x != nil { + return x.ProjectId + } + return "" +} + +func (x *RemoveRolePrincipalsRequest) GetRoleId() string { + if x != nil { + return x.RoleId + } + return "" +} + +func (x *RemoveRolePrincipalsRequest) GetVersion() *wrappers.UInt32Value { + if x != nil { + return x.Version + } + return nil +} + +func (x *RemoveRolePrincipalsRequest) GetUserIds() []string { + if x != nil { + return x.UserIds + } + return nil +} + +func (x *RemoveRolePrincipalsRequest) GetGroupIds() []string { + if x != nil { + return x.GroupIds + } + return nil +} + +type RemoveRolePrincipalsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *roles.Role `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *RemoveRolePrincipalsResponse) Reset() { + *x = RemoveRolePrincipalsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveRolePrincipalsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveRolePrincipalsResponse) ProtoMessage() {} + +func (x *RemoveRolePrincipalsResponse) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_role_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveRolePrincipalsResponse.ProtoReflect.Descriptor instead. +func (*RemoveRolePrincipalsResponse) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_role_service_proto_rawDescGZIP(), []int{15} +} + +func (x *RemoveRolePrincipalsResponse) GetItem() *roles.Role { + if x != nil { + return x.Item + } + return nil +} + var File_controller_api_services_v1_role_service_proto protoreflect.FileDescriptor var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{ @@ -629,7 +1039,9 @@ var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{ 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, - 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, + 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x52, 0x6f, @@ -697,85 +1109,211 @@ var file_controller_api_services_v1_role_service_proto_rawDesc = []byte{ 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x32, 0x88, 0x09, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xe1, 0x01, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, - 0x6f, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x60, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, - 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x5a, 0x3a, 0x12, 0x32, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, - 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, - 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x14, 0x12, 0x12, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, - 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xce, 0x01, 0x0a, 0x09, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0xdb, 0x01, 0x0a, 0x18, 0x41, 0x64, 0x64, 0x52, + 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, + 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, + 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, + 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, + 0xdb, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, + 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, + 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, + 0x67, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, + 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x12, + 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x58, 0x0a, + 0x19, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, + 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, + 0x65, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xde, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, + 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x6f, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, + 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x5b, 0x0a, 0x1c, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xb0, 0x11, 0x0a, 0x0b, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xe1, 0x01, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, + 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, + 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x60, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, + 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x5a, 0x3a, 0x12, 0x32, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, + 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x92, 0x41, 0x14, 0x12, 0x12, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xce, 0x01, 0x0a, 0x09, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4a, 0x12, 0x17, - 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, - 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5a, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4a, 0x12, 0x17, 0x2f, 0x76, + 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5a, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, + 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x92, 0x41, 0x11, 0x12, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x73, + 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xf0, 0x01, 0x0a, 0x0a, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x62, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x5a, 0x3b, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, + 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, + 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, + 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xf3, 0x01, + 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x85, 0x01, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x6c, 0x32, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, + 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x40, 0x32, 0x32, 0x2f, 0x76, 0x31, 0x2f, + 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x92, 0x41, 0x10, 0x12, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52, + 0x6f, 0x6c, 0x65, 0x12, 0xda, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, + 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x6d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x54, 0x2a, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, + 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x34, 0x2a, 0x32, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, - 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x92, 0x41, 0x11, 0x12, 0x0f, 0x4c, 0x69, 0x73, - 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xf0, 0x01, 0x0a, - 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, - 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, - 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x62, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, - 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, - 0x65, 0x6d, 0x5a, 0x3b, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, + 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x10, + 0x12, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, + 0x12, 0xbf, 0x02, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, + 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, + 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x6c, + 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xbc, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e, 0x01, 0x22, 0x30, 0x2f, + 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, + 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, + 0x01, 0x2a, 0x5a, 0x51, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, - 0x6c, 0x65, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, - 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, - 0xf3, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, + 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, + 0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x62, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22, + 0x41, 0x64, 0x64, 0x73, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, + 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x52, 0x6f, + 0x6c, 0x65, 0x12, 0xfe, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, + 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, + 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x85, 0x01, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x6c, 0x32, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, - 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x40, 0x32, 0x32, 0x2f, 0x76, - 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, - 0x65, 0x6d, 0x92, 0x41, 0x10, 0x12, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, - 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0xda, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x54, 0x2a, 0x1c, 0x2f, 0x76, 0x31, - 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, - 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x34, 0x2a, 0x32, 0x2f, 0x76, 0x31, - 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, - 0x41, 0x10, 0x12, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x52, 0x6f, - 0x6c, 0x65, 0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, - 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, - 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, + 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xfb, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e, 0x01, 0x22, + 0x30, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, + 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, + 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, + 0x73, 0x3a, 0x01, 0x2a, 0x5a, 0x51, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, + 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, + 0x73, 0x65, 0x74, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, + 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x63, + 0x12, 0x61, 0x53, 0x65, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x2f, + 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x52, + 0x6f, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x12, 0xe2, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, + 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x37, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x6f, 0x6c, 0x65, 0x50, 0x72, 0x69, + 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xd6, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x94, 0x01, 0x22, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x6f, + 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, + 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, + 0x2a, 0x5a, 0x54, 0x22, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x67, 0x73, 0x2f, 0x7b, 0x6f, + 0x72, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, + 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, + 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x3a, 0x01, + 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x38, + 0x12, 0x36, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, + 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x55, 0x73, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, + 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, + 0x20, 0x61, 0x20, 0x52, 0x6f, 0x6c, 0x65, 0x2e, 0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -790,44 +1328,63 @@ func file_controller_api_services_v1_role_service_proto_rawDescGZIP() []byte { return file_controller_api_services_v1_role_service_proto_rawDescData } -var file_controller_api_services_v1_role_service_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_controller_api_services_v1_role_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_controller_api_services_v1_role_service_proto_goTypes = []interface{}{ - (*GetRoleRequest)(nil), // 0: controller.api.services.v1.GetRoleRequest - (*GetRoleResponse)(nil), // 1: controller.api.services.v1.GetRoleResponse - (*ListRolesRequest)(nil), // 2: controller.api.services.v1.ListRolesRequest - (*ListRolesResponse)(nil), // 3: controller.api.services.v1.ListRolesResponse - (*CreateRoleRequest)(nil), // 4: controller.api.services.v1.CreateRoleRequest - (*CreateRoleResponse)(nil), // 5: controller.api.services.v1.CreateRoleResponse - (*UpdateRoleRequest)(nil), // 6: controller.api.services.v1.UpdateRoleRequest - (*UpdateRoleResponse)(nil), // 7: controller.api.services.v1.UpdateRoleResponse - (*DeleteRoleRequest)(nil), // 8: controller.api.services.v1.DeleteRoleRequest - (*DeleteRoleResponse)(nil), // 9: controller.api.services.v1.DeleteRoleResponse - (*roles.Role)(nil), // 10: controller.api.resources.roles.v1.Role - (*field_mask.FieldMask)(nil), // 11: google.protobuf.FieldMask + (*GetRoleRequest)(nil), // 0: controller.api.services.v1.GetRoleRequest + (*GetRoleResponse)(nil), // 1: controller.api.services.v1.GetRoleResponse + (*ListRolesRequest)(nil), // 2: controller.api.services.v1.ListRolesRequest + (*ListRolesResponse)(nil), // 3: controller.api.services.v1.ListRolesResponse + (*CreateRoleRequest)(nil), // 4: controller.api.services.v1.CreateRoleRequest + (*CreateRoleResponse)(nil), // 5: controller.api.services.v1.CreateRoleResponse + (*UpdateRoleRequest)(nil), // 6: controller.api.services.v1.UpdateRoleRequest + (*UpdateRoleResponse)(nil), // 7: controller.api.services.v1.UpdateRoleResponse + (*DeleteRoleRequest)(nil), // 8: controller.api.services.v1.DeleteRoleRequest + (*DeleteRoleResponse)(nil), // 9: controller.api.services.v1.DeleteRoleResponse + (*AddRolePrincipalsRequest)(nil), // 10: controller.api.services.v1.AddRolePrincipalsRequest + (*AddRolePrincipalsResponse)(nil), // 11: controller.api.services.v1.AddRolePrincipalsResponse + (*SetRolePrincipalsRequest)(nil), // 12: controller.api.services.v1.SetRolePrincipalsRequest + (*SetRolePrincipalsResponse)(nil), // 13: controller.api.services.v1.SetRolePrincipalsResponse + (*RemoveRolePrincipalsRequest)(nil), // 14: controller.api.services.v1.RemoveRolePrincipalsRequest + (*RemoveRolePrincipalsResponse)(nil), // 15: controller.api.services.v1.RemoveRolePrincipalsResponse + (*roles.Role)(nil), // 16: controller.api.resources.roles.v1.Role + (*field_mask.FieldMask)(nil), // 17: google.protobuf.FieldMask + (*wrappers.UInt32Value)(nil), // 18: google.protobuf.UInt32Value } var file_controller_api_services_v1_role_service_proto_depIdxs = []int32{ - 10, // 0: controller.api.services.v1.GetRoleResponse.item:type_name -> controller.api.resources.roles.v1.Role - 10, // 1: controller.api.services.v1.ListRolesResponse.items:type_name -> controller.api.resources.roles.v1.Role - 10, // 2: controller.api.services.v1.CreateRoleRequest.item:type_name -> controller.api.resources.roles.v1.Role - 10, // 3: controller.api.services.v1.CreateRoleResponse.item:type_name -> controller.api.resources.roles.v1.Role - 10, // 4: controller.api.services.v1.UpdateRoleRequest.item:type_name -> controller.api.resources.roles.v1.Role - 11, // 5: controller.api.services.v1.UpdateRoleRequest.update_mask:type_name -> google.protobuf.FieldMask - 10, // 6: controller.api.services.v1.UpdateRoleResponse.item:type_name -> controller.api.resources.roles.v1.Role - 0, // 7: controller.api.services.v1.RoleService.GetRole:input_type -> controller.api.services.v1.GetRoleRequest - 2, // 8: controller.api.services.v1.RoleService.ListRoles:input_type -> controller.api.services.v1.ListRolesRequest - 4, // 9: controller.api.services.v1.RoleService.CreateRole:input_type -> controller.api.services.v1.CreateRoleRequest - 6, // 10: controller.api.services.v1.RoleService.UpdateRole:input_type -> controller.api.services.v1.UpdateRoleRequest - 8, // 11: controller.api.services.v1.RoleService.DeleteRole:input_type -> controller.api.services.v1.DeleteRoleRequest - 1, // 12: controller.api.services.v1.RoleService.GetRole:output_type -> controller.api.services.v1.GetRoleResponse - 3, // 13: controller.api.services.v1.RoleService.ListRoles:output_type -> controller.api.services.v1.ListRolesResponse - 5, // 14: controller.api.services.v1.RoleService.CreateRole:output_type -> controller.api.services.v1.CreateRoleResponse - 7, // 15: controller.api.services.v1.RoleService.UpdateRole:output_type -> controller.api.services.v1.UpdateRoleResponse - 9, // 16: controller.api.services.v1.RoleService.DeleteRole:output_type -> controller.api.services.v1.DeleteRoleResponse - 12, // [12:17] is the sub-list for method output_type - 7, // [7:12] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 16, // 0: controller.api.services.v1.GetRoleResponse.item:type_name -> controller.api.resources.roles.v1.Role + 16, // 1: controller.api.services.v1.ListRolesResponse.items:type_name -> controller.api.resources.roles.v1.Role + 16, // 2: controller.api.services.v1.CreateRoleRequest.item:type_name -> controller.api.resources.roles.v1.Role + 16, // 3: controller.api.services.v1.CreateRoleResponse.item:type_name -> controller.api.resources.roles.v1.Role + 16, // 4: controller.api.services.v1.UpdateRoleRequest.item:type_name -> controller.api.resources.roles.v1.Role + 17, // 5: controller.api.services.v1.UpdateRoleRequest.update_mask:type_name -> google.protobuf.FieldMask + 16, // 6: controller.api.services.v1.UpdateRoleResponse.item:type_name -> controller.api.resources.roles.v1.Role + 18, // 7: controller.api.services.v1.AddRolePrincipalsRequest.version:type_name -> google.protobuf.UInt32Value + 16, // 8: controller.api.services.v1.AddRolePrincipalsResponse.item:type_name -> controller.api.resources.roles.v1.Role + 18, // 9: controller.api.services.v1.SetRolePrincipalsRequest.version:type_name -> google.protobuf.UInt32Value + 16, // 10: controller.api.services.v1.SetRolePrincipalsResponse.item:type_name -> controller.api.resources.roles.v1.Role + 18, // 11: controller.api.services.v1.RemoveRolePrincipalsRequest.version:type_name -> google.protobuf.UInt32Value + 16, // 12: controller.api.services.v1.RemoveRolePrincipalsResponse.item:type_name -> controller.api.resources.roles.v1.Role + 0, // 13: controller.api.services.v1.RoleService.GetRole:input_type -> controller.api.services.v1.GetRoleRequest + 2, // 14: controller.api.services.v1.RoleService.ListRoles:input_type -> controller.api.services.v1.ListRolesRequest + 4, // 15: controller.api.services.v1.RoleService.CreateRole:input_type -> controller.api.services.v1.CreateRoleRequest + 6, // 16: controller.api.services.v1.RoleService.UpdateRole:input_type -> controller.api.services.v1.UpdateRoleRequest + 8, // 17: controller.api.services.v1.RoleService.DeleteRole:input_type -> controller.api.services.v1.DeleteRoleRequest + 10, // 18: controller.api.services.v1.RoleService.AddRolePrincipals:input_type -> controller.api.services.v1.AddRolePrincipalsRequest + 12, // 19: controller.api.services.v1.RoleService.SetRolePrincipals:input_type -> controller.api.services.v1.SetRolePrincipalsRequest + 14, // 20: controller.api.services.v1.RoleService.RemoveRolePrincipals:input_type -> controller.api.services.v1.RemoveRolePrincipalsRequest + 1, // 21: controller.api.services.v1.RoleService.GetRole:output_type -> controller.api.services.v1.GetRoleResponse + 3, // 22: controller.api.services.v1.RoleService.ListRoles:output_type -> controller.api.services.v1.ListRolesResponse + 5, // 23: controller.api.services.v1.RoleService.CreateRole:output_type -> controller.api.services.v1.CreateRoleResponse + 7, // 24: controller.api.services.v1.RoleService.UpdateRole:output_type -> controller.api.services.v1.UpdateRoleResponse + 9, // 25: controller.api.services.v1.RoleService.DeleteRole:output_type -> controller.api.services.v1.DeleteRoleResponse + 11, // 26: controller.api.services.v1.RoleService.AddRolePrincipals:output_type -> controller.api.services.v1.AddRolePrincipalsResponse + 13, // 27: controller.api.services.v1.RoleService.SetRolePrincipals:output_type -> controller.api.services.v1.SetRolePrincipalsResponse + 15, // 28: controller.api.services.v1.RoleService.RemoveRolePrincipals:output_type -> controller.api.services.v1.RemoveRolePrincipalsResponse + 21, // [21:29] is the sub-list for method output_type + 13, // [13:21] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_controller_api_services_v1_role_service_proto_init() } @@ -956,6 +1513,78 @@ func file_controller_api_services_v1_role_service_proto_init() { return nil } } + file_controller_api_services_v1_role_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddRolePrincipalsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_role_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddRolePrincipalsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_role_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetRolePrincipalsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_role_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetRolePrincipalsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_role_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveRolePrincipalsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_role_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveRolePrincipalsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -963,7 +1592,7 @@ func file_controller_api_services_v1_role_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_services_v1_role_service_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, @@ -1020,6 +1649,23 @@ type RoleServiceClient interface { // specifies if the resource existed before the DeleteRole request was // received. DeleteRole(ctx context.Context, in *DeleteRoleRequest, opts ...grpc.CallOption) (*DeleteRoleResponse, error) + // AddRolePrincipals adds users and/or groups to a role. The provided request must include + // the org id and the role id which the users and/or groups will be added to. If the + // org id is missing, malformed or references a non existing organization, + // an error is returned. + AddRolePrincipals(ctx context.Context, in *AddRolePrincipalsRequest, opts ...grpc.CallOption) (*AddRolePrincipalsResponse, error) + // SetRolePrincipals sets the role's users and/or groups. Any existing principals on + // the role are deleted if they are not included in this request. The provided + // request must include the org id and the role id which the users and/or groups + // will be set to. If the org id is missing, malformed or references a non + // existing organization, an error is returned. + SetRolePrincipals(ctx context.Context, in *SetRolePrincipalsRequest, opts ...grpc.CallOption) (*SetRolePrincipalsResponse, error) + // RemoveRolePrincipals removes the users and/or groups from the specified role. + // The provided request must include the org id and the role id which the users + // and/or groups will be removed from. If the org id is missing, malformed or references a non + // existing organization, an error is returned. It is not an error to have duplicate + // user/group ids. + RemoveRolePrincipals(ctx context.Context, in *RemoveRolePrincipalsRequest, opts ...grpc.CallOption) (*RemoveRolePrincipalsResponse, error) } type roleServiceClient struct { @@ -1075,6 +1721,33 @@ func (c *roleServiceClient) DeleteRole(ctx context.Context, in *DeleteRoleReques return out, nil } +func (c *roleServiceClient) AddRolePrincipals(ctx context.Context, in *AddRolePrincipalsRequest, opts ...grpc.CallOption) (*AddRolePrincipalsResponse, error) { + out := new(AddRolePrincipalsResponse) + err := c.cc.Invoke(ctx, "/controller.api.services.v1.RoleService/AddRolePrincipals", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *roleServiceClient) SetRolePrincipals(ctx context.Context, in *SetRolePrincipalsRequest, opts ...grpc.CallOption) (*SetRolePrincipalsResponse, error) { + out := new(SetRolePrincipalsResponse) + err := c.cc.Invoke(ctx, "/controller.api.services.v1.RoleService/SetRolePrincipals", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *roleServiceClient) RemoveRolePrincipals(ctx context.Context, in *RemoveRolePrincipalsRequest, opts ...grpc.CallOption) (*RemoveRolePrincipalsResponse, error) { + out := new(RemoveRolePrincipalsResponse) + err := c.cc.Invoke(ctx, "/controller.api.services.v1.RoleService/RemoveRolePrincipals", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // RoleServiceServer is the server API for RoleService service. type RoleServiceServer interface { // GetRole returns a stored Role if present. The provided request @@ -1108,6 +1781,23 @@ type RoleServiceServer interface { // specifies if the resource existed before the DeleteRole request was // received. DeleteRole(context.Context, *DeleteRoleRequest) (*DeleteRoleResponse, error) + // AddRolePrincipals adds users and/or groups to a role. The provided request must include + // the org id and the role id which the users and/or groups will be added to. If the + // org id is missing, malformed or references a non existing organization, + // an error is returned. + AddRolePrincipals(context.Context, *AddRolePrincipalsRequest) (*AddRolePrincipalsResponse, error) + // SetRolePrincipals sets the role's users and/or groups. Any existing principals on + // the role are deleted if they are not included in this request. The provided + // request must include the org id and the role id which the users and/or groups + // will be set to. If the org id is missing, malformed or references a non + // existing organization, an error is returned. + SetRolePrincipals(context.Context, *SetRolePrincipalsRequest) (*SetRolePrincipalsResponse, error) + // RemoveRolePrincipals removes the users and/or groups from the specified role. + // The provided request must include the org id and the role id which the users + // and/or groups will be removed from. If the org id is missing, malformed or references a non + // existing organization, an error is returned. It is not an error to have duplicate + // user/group ids. + RemoveRolePrincipals(context.Context, *RemoveRolePrincipalsRequest) (*RemoveRolePrincipalsResponse, error) } // UnimplementedRoleServiceServer can be embedded to have forward compatible implementations. @@ -1129,6 +1819,15 @@ func (*UnimplementedRoleServiceServer) UpdateRole(context.Context, *UpdateRoleRe func (*UnimplementedRoleServiceServer) DeleteRole(context.Context, *DeleteRoleRequest) (*DeleteRoleResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteRole not implemented") } +func (*UnimplementedRoleServiceServer) AddRolePrincipals(context.Context, *AddRolePrincipalsRequest) (*AddRolePrincipalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddRolePrincipals not implemented") +} +func (*UnimplementedRoleServiceServer) SetRolePrincipals(context.Context, *SetRolePrincipalsRequest) (*SetRolePrincipalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetRolePrincipals not implemented") +} +func (*UnimplementedRoleServiceServer) RemoveRolePrincipals(context.Context, *RemoveRolePrincipalsRequest) (*RemoveRolePrincipalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveRolePrincipals not implemented") +} func RegisterRoleServiceServer(s *grpc.Server, srv RoleServiceServer) { s.RegisterService(&_RoleService_serviceDesc, srv) @@ -1224,6 +1923,60 @@ func _RoleService_DeleteRole_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _RoleService_AddRolePrincipals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddRolePrincipalsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RoleServiceServer).AddRolePrincipals(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/controller.api.services.v1.RoleService/AddRolePrincipals", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoleServiceServer).AddRolePrincipals(ctx, req.(*AddRolePrincipalsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _RoleService_SetRolePrincipals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetRolePrincipalsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RoleServiceServer).SetRolePrincipals(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/controller.api.services.v1.RoleService/SetRolePrincipals", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoleServiceServer).SetRolePrincipals(ctx, req.(*SetRolePrincipalsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _RoleService_RemoveRolePrincipals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveRolePrincipalsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RoleServiceServer).RemoveRolePrincipals(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/controller.api.services.v1.RoleService/RemoveRolePrincipals", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoleServiceServer).RemoveRolePrincipals(ctx, req.(*RemoveRolePrincipalsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _RoleService_serviceDesc = grpc.ServiceDesc{ ServiceName: "controller.api.services.v1.RoleService", HandlerType: (*RoleServiceServer)(nil), @@ -1248,6 +2001,18 @@ var _RoleService_serviceDesc = grpc.ServiceDesc{ MethodName: "DeleteRole", Handler: _RoleService_DeleteRole_Handler, }, + { + MethodName: "AddRolePrincipals", + Handler: _RoleService_AddRolePrincipals_Handler, + }, + { + MethodName: "SetRolePrincipals", + Handler: _RoleService_SetRolePrincipals_Handler, + }, + { + MethodName: "RemoveRolePrincipals", + Handler: _RoleService_RemoveRolePrincipals_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "controller/api/services/v1/role_service.proto", diff --git a/internal/gen/controller/api/services/role_service.pb.gw.go b/internal/gen/controller/api/services/role_service.pb.gw.go index 2e88ac104a..11a1529efd 100644 --- a/internal/gen/controller/api/services/role_service.pb.gw.go +++ b/internal/gen/controller/api/services/role_service.pb.gw.go @@ -1053,6 +1053,624 @@ func local_request_RoleService_DeleteRole_1(ctx context.Context, marshaler runti } +func request_RoleService_AddRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := client.AddRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RoleService_AddRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := server.AddRolePrincipals(ctx, &protoReq) + return msg, metadata, err + +} + +func request_RoleService_AddRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["project_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id") + } + + protoReq.ProjectId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := client.AddRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RoleService_AddRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["project_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id") + } + + protoReq.ProjectId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := server.AddRolePrincipals(ctx, &protoReq) + return msg, metadata, err + +} + +func request_RoleService_SetRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := client.SetRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RoleService_SetRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := server.SetRolePrincipals(ctx, &protoReq) + return msg, metadata, err + +} + +func request_RoleService_SetRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["project_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id") + } + + protoReq.ProjectId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := client.SetRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RoleService_SetRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["project_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id") + } + + protoReq.ProjectId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := server.SetRolePrincipals(ctx, &protoReq) + return msg, metadata, err + +} + +func request_RoleService_RemoveRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemoveRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := client.RemoveRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RoleService_RemoveRolePrincipals_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemoveRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := server.RemoveRolePrincipals(ctx, &protoReq) + return msg, metadata, err + +} + +func request_RoleService_RemoveRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemoveRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["project_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id") + } + + protoReq.ProjectId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := client.RemoveRolePrincipals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RoleService_RemoveRolePrincipals_1(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemoveRolePrincipalsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["org_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "org_id") + } + + protoReq.OrgId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err) + } + + val, ok = pathParams["project_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "project_id") + } + + protoReq.ProjectId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err) + } + + val, ok = pathParams["role_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "role_id") + } + + protoReq.RoleId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "role_id", err) + } + + msg, err := server.RemoveRolePrincipals(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterRoleServiceHandlerServer registers the http handlers for service RoleService to "mux". // UnaryRPC :call RoleServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1258,6 +1876,126 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_RoleService_AddRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RoleService_AddRolePrincipals_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_AddRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_AddRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RoleService_AddRolePrincipals_1(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_AddRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_SetRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RoleService_SetRolePrincipals_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_SetRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_SetRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RoleService_SetRolePrincipals_1(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_SetRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RoleService_RemoveRolePrincipals_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_RemoveRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RoleService_RemoveRolePrincipals_1(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_RemoveRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1499,6 +2237,126 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_RoleService_AddRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RoleService_AddRolePrincipals_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_AddRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_AddRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RoleService_AddRolePrincipals_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_AddRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_AddRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_SetRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RoleService_SetRolePrincipals_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_SetRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_SetRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RoleService_SetRolePrincipals_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_SetRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_SetRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RoleService_RemoveRolePrincipals_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_RemoveRolePrincipals_0(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RoleService_RemoveRolePrincipals_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RoleService_RemoveRolePrincipals_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_RoleService_RemoveRolePrincipals_1(ctx, mux, outboundMarshaler, w, req, response_RoleService_RemoveRolePrincipals_1{resp}, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1556,6 +2414,60 @@ func (m response_RoleService_UpdateRole_1) XXX_ResponseBody() interface{} { return response.Item } +type response_RoleService_AddRolePrincipals_0 struct { + proto.Message +} + +func (m response_RoleService_AddRolePrincipals_0) XXX_ResponseBody() interface{} { + response := m.Message.(*AddRolePrincipalsResponse) + return response.Item +} + +type response_RoleService_AddRolePrincipals_1 struct { + proto.Message +} + +func (m response_RoleService_AddRolePrincipals_1) XXX_ResponseBody() interface{} { + response := m.Message.(*AddRolePrincipalsResponse) + return response.Item +} + +type response_RoleService_SetRolePrincipals_0 struct { + proto.Message +} + +func (m response_RoleService_SetRolePrincipals_0) XXX_ResponseBody() interface{} { + response := m.Message.(*SetRolePrincipalsResponse) + return response.Item +} + +type response_RoleService_SetRolePrincipals_1 struct { + proto.Message +} + +func (m response_RoleService_SetRolePrincipals_1) XXX_ResponseBody() interface{} { + response := m.Message.(*SetRolePrincipalsResponse) + return response.Item +} + +type response_RoleService_RemoveRolePrincipals_0 struct { + proto.Message +} + +func (m response_RoleService_RemoveRolePrincipals_0) XXX_ResponseBody() interface{} { + response := m.Message.(*RemoveRolePrincipalsResponse) + return response.Item +} + +type response_RoleService_RemoveRolePrincipals_1 struct { + proto.Message +} + +func (m response_RoleService_RemoveRolePrincipals_1) XXX_ResponseBody() interface{} { + response := m.Message.(*RemoveRolePrincipalsResponse) + return response.Item +} + var ( pattern_RoleService_GetRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "id"}, "", runtime.AssumeColonVerbOpt(true))) @@ -1576,6 +2488,18 @@ var ( pattern_RoleService_DeleteRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "id"}, "", runtime.AssumeColonVerbOpt(true))) pattern_RoleService_DeleteRole_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "id"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_RoleService_AddRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "role_id"}, "add-principals", runtime.AssumeColonVerbOpt(true))) + + pattern_RoleService_AddRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "role_id"}, "add-principals", runtime.AssumeColonVerbOpt(true))) + + pattern_RoleService_SetRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "role_id"}, "set-principals", runtime.AssumeColonVerbOpt(true))) + + pattern_RoleService_SetRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "role_id"}, "set-principals", runtime.AssumeColonVerbOpt(true))) + + pattern_RoleService_RemoveRolePrincipals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "orgs", "org_id", "roles", "role_id"}, "remove-principals", runtime.AssumeColonVerbOpt(true))) + + pattern_RoleService_RemoveRolePrincipals_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"v1", "orgs", "org_id", "projects", "project_id", "roles", "role_id"}, "remove-principals", runtime.AssumeColonVerbOpt(true))) ) var ( @@ -1598,4 +2522,16 @@ var ( forward_RoleService_DeleteRole_0 = runtime.ForwardResponseMessage forward_RoleService_DeleteRole_1 = runtime.ForwardResponseMessage + + forward_RoleService_AddRolePrincipals_0 = runtime.ForwardResponseMessage + + forward_RoleService_AddRolePrincipals_1 = runtime.ForwardResponseMessage + + forward_RoleService_SetRolePrincipals_0 = runtime.ForwardResponseMessage + + forward_RoleService_SetRolePrincipals_1 = runtime.ForwardResponseMessage + + forward_RoleService_RemoveRolePrincipals_0 = runtime.ForwardResponseMessage + + forward_RoleService_RemoveRolePrincipals_1 = runtime.ForwardResponseMessage ) diff --git a/internal/iam/repository_principal_role.go b/internal/iam/repository_principal_role.go index d0d756f130..a0b806ca4a 100644 --- a/internal/iam/repository_principal_role.go +++ b/internal/iam/repository_principal_role.go @@ -13,7 +13,7 @@ import ( // roleVersion or an error will be returned. The roles and groups must be in // the same scope. User can only be added to roles which are within the user's // organization, or the role is within a project within the user's organization. -func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleVersion int, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, error) { +func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, error) { // NOTE - we are intentionally not going to check that the scopes are // correct for the userIds and groupIds, given the roleId. We are going to // rely on the database constraints and triggers to maintain the integrity @@ -64,7 +64,7 @@ func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleV } updatedRole := allocRole() updatedRole.PublicId = roleId - updatedRole.Version = uint32(roleVersion) + 1 + updatedRole.Version = roleVersion + 1 var roleOplogMsg oplog.Message rowsUpdated, err := w.Update(ctx, &updatedRole, []string{"Version"}, nil, db.NewOplogMsg(&roleOplogMsg), db.WithVersion(roleVersion)) if err != nil { @@ -117,7 +117,7 @@ func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleV // principals as need to reconcile the existing principals with the principals // requested. If both userIds and groupIds are empty, the principal roles will // be cleared. -func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleVersion int, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, int, error) { +func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) ([]PrincipalRole, int, error) { // NOTE - we are intentionally not going to check that the scopes are // correct for the userIds and groupIds, given the roleId. We are going to // rely on the database constraints and triggers to maintain the integrity @@ -179,7 +179,7 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV } updatedRole := allocRole() updatedRole.PublicId = roleId - updatedRole.Version = uint32(roleVersion) + 1 + updatedRole.Version = roleVersion + 1 var roleOplogMsg oplog.Message rowsUpdated, err := w.Update(ctx, &updatedRole, []string{"Version"}, nil, db.NewOplogMsg(&roleOplogMsg), db.WithVersion(roleVersion)) if err != nil { @@ -262,7 +262,7 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV // DeletePrincipalRoles principals (userIds and/or groupIds) from a role // (roleId). The role's current db version must match the roleVersion or an // error will be returned. -func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, roleVersion int, userIds, groupIds []string, opt ...Option) (int, error) { +func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, roleVersion uint32, userIds, groupIds []string, opt ...Option) (int, error) { if roleId == "" { return db.NoRowsAffected, fmt.Errorf("delete principal roles: missing role id: %w", db.ErrInvalidParameter) } @@ -305,7 +305,7 @@ func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, ro } updatedRole := allocRole() updatedRole.PublicId = roleId - updatedRole.Version = uint32(roleVersion) + 1 + updatedRole.Version = roleVersion + 1 var roleOplogMsg oplog.Message rowsUpdated, err := w.Update(ctx, &updatedRole, []string{"Version"}, nil, db.NewOplogMsg(&roleOplogMsg), db.WithVersion(roleVersion)) if err != nil { diff --git a/internal/iam/repository_principal_role_test.go b/internal/iam/repository_principal_role_test.go index 3ba6d42ca1..7ab97faeaa 100644 --- a/internal/iam/repository_principal_role_test.go +++ b/internal/iam/repository_principal_role_test.go @@ -40,7 +40,7 @@ func TestRepository_AddPrincipalRoles(t *testing.T) { } type args struct { roleId string - roleVersion int + roleVersion uint32 userIds []string groupIds []string opt []Option @@ -231,7 +231,7 @@ func TestRepository_ListPrincipalRoles(t *testing.T) { g := TestGroup(t, conn, tt.createScopeId) groupRoles = append(groupRoles, g.PublicId) } - testRoles, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, int(role.Version), userRoles, groupRoles, tt.args.opt...) + testRoles, err := repo.AddPrincipalRoles(context.Background(), role.PublicId, role.Version, userRoles, groupRoles, tt.args.opt...) require.NoError(err) assert.Equal(tt.createCnt, len(testRoles)) @@ -452,7 +452,7 @@ func TestRepository_SetPrincipalRoles(t *testing.T) { } type args struct { role *Role - roleVersion int + roleVersion uint32 userIds []string groupIds []string addToOrigUsers bool diff --git a/internal/iam/repository_role.go b/internal/iam/repository_role.go index f5884ac664..576e03c9a9 100644 --- a/internal/iam/repository_role.go +++ b/internal/iam/repository_role.go @@ -86,16 +86,36 @@ func (r *Repository) UpdateRole(ctx context.Context, role *Role, fieldMaskPaths // LookupRole will look up a role in the repository. If the role is not // found, it will return nil, nil. -func (r *Repository) LookupRole(ctx context.Context, withPublicId string, opt ...Option) (*Role, error) { +func (r *Repository) LookupRole(ctx context.Context, withPublicId string, opt ...Option) (*Role, []PrincipalRole, error) { if withPublicId == "" { - return nil, fmt.Errorf("lookup role: missing public id %w", db.ErrNilParameter) + return nil, nil, fmt.Errorf("lookup role: missing public id %w", db.ErrNilParameter) } role := allocRole() role.PublicId = withPublicId - if err := r.reader.LookupByPublicId(ctx, &role); err != nil { - return nil, fmt.Errorf("lookup role: failed %w for %s", err, withPublicId) + var pr []PrincipalRole + _, err := r.writer.DoTx( + ctx, + db.StdRetryCnt, + db.ExpBackoff{}, + func(read db.Reader, w db.Writer) error { + if err := read.LookupByPublicId(ctx, &role); err != nil { + return fmt.Errorf("lookup role: failed %w for %s", err, withPublicId) + } + repo, err := NewRepository(read, w, r.wrapper) + if err != nil { + return fmt.Errorf("lookup role: failed creating inner repo: %w for %s", err, withPublicId) + } + pr, err = repo.ListPrincipalRoles(ctx, withPublicId) + if err != nil { + return fmt.Errorf("lookup role: listing principal roles: %w for %s", err, withPublicId) + } + return nil + }, + ) + if err != nil { + return nil, nil, err } - return &role, nil + return &role, pr, nil } // DeleteRole will delete a role from the repository. diff --git a/internal/iam/repository_role_test.go b/internal/iam/repository_role_test.go index 6a96e87286..43ff771316 100644 --- a/internal/iam/repository_role_test.go +++ b/internal/iam/repository_role_test.go @@ -160,7 +160,7 @@ func TestRepository_CreateRole(t *testing.T) { assert.NotNil(grp.CreateTime) assert.NotNil(grp.UpdateTime) - foundGrp, err := repo.LookupRole(context.Background(), grp.PublicId) + foundGrp, _, err := repo.LookupRole(context.Background(), grp.PublicId) assert.NoError(err) assert.True(proto.Equal(foundGrp, grp)) @@ -421,7 +421,7 @@ func TestRepository_UpdateRole(t *testing.T) { default: assert.NotEqual(r.UpdateTime, roleAfterUpdate.UpdateTime) } - foundRole, err := repo.LookupRole(context.Background(), r.PublicId) + foundRole, _, err := repo.LookupRole(context.Background(), r.PublicId) assert.NoError(err) assert.True(proto.Equal(roleAfterUpdate, foundRole)) dbassert := dbassert.New(t, rw) @@ -511,7 +511,7 @@ func TestRepository_DeleteRole(t *testing.T) { } assert.NoError(err) assert.Equal(tt.wantRowsDeleted, deletedRows) - foundRole, err := repo.LookupRole(context.Background(), tt.args.role.PublicId) + foundRole, _, err := repo.LookupRole(context.Background(), tt.args.role.PublicId) assert.Error(err) assert.Nil(foundRole) assert.True(errors.Is(err, db.ErrRecordNotFound)) diff --git a/internal/proto/local/controller/api/resources/roles/v1/role.proto b/internal/proto/local/controller/api/resources/roles/v1/role.proto index e66c4d0400..199791b690 100644 --- a/internal/proto/local/controller/api/resources/roles/v1/role.proto +++ b/internal/proto/local/controller/api/resources/roles/v1/role.proto @@ -29,4 +29,19 @@ message Role { // Whether the resource is disabled google.protobuf.BoolValue disabled = 6; + + // The version can be used in subsiquent write requests to ensure this resource + // has not changed and to fail the write if it has. + // Output only. + uint32 version = 7; + + // The principals that are assigned this role. + // Output only. + repeated string user_ids = 8; + // Output only. + repeated string group_ids = 9; + + // The grants that this role provides for it's principals. + // Output only. + repeated string grants = 10; } diff --git a/internal/proto/local/controller/api/services/v1/role_service.proto b/internal/proto/local/controller/api/services/v1/role_service.proto index 9226ec0fb3..6e99876b9c 100644 --- a/internal/proto/local/controller/api/services/v1/role_service.proto +++ b/internal/proto/local/controller/api/services/v1/role_service.proto @@ -7,6 +7,7 @@ option go_package = "github.com/hashicorp/watchtower/internal/gen/controller/api import "protoc-gen-swagger/options/annotations.proto"; import "google/api/annotations.proto"; import "google/protobuf/field_mask.proto"; +import "google/protobuf/wrappers.proto"; import "controller/api/resources/roles/v1/role.proto"; service RoleService { @@ -106,6 +107,68 @@ service RoleService { summary: "Deletes a Role" }; } + + // AddRolePrincipals adds users and/or groups to a role. The provided request must include + // the org id and the role id which the users and/or groups will be added to. If the + // org id is missing, malformed or references a non existing organization, + // an error is returned. + rpc AddRolePrincipals(AddRolePrincipalsRequest) returns (AddRolePrincipalsResponse) { + option (google.api.http) = { + post: "/v1/orgs/{org_id}/roles/{role_id}:add-principals" + body: "*" + response_body: "item" + additional_bindings { + post: "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:add-principals" + body: "*" + response_body: "item" + } + }; + option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { + summary: "Adds Users and/or Groups to a Role" + }; + } + + // SetRolePrincipals sets the role's users and/or groups. Any existing principals on + // the role are deleted if they are not included in this request. The provided + // request must include the org id and the role id which the users and/or groups + // will be set to. If the org id is missing, malformed or references a non + // existing organization, an error is returned. + rpc SetRolePrincipals(SetRolePrincipalsRequest) returns (SetRolePrincipalsResponse) { + option (google.api.http) = { + post: "/v1/orgs/{org_id}/roles/{role_id}:set-principals" + body: "*" + response_body: "item" + additional_bindings { + post: "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:set-principals" + body: "*" + response_body: "item" + } + }; + option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { + summary: "Set Users and/or Groups to a Role, removing any principals that are not specified in the request." + }; + } + + // RemoveRolePrincipals removes the users and/or groups from the specified role. + // The provided request must include the org id and the role id which the users + // and/or groups will be removed from. If the org id is missing, malformed or references a non + // existing organization, an error is returned. It is not an error to have duplicate + // user/group ids. + rpc RemoveRolePrincipals(RemoveRolePrincipalsRequest) returns (RemoveRolePrincipalsResponse) { + option (google.api.http) = { + post: "/v1/orgs/{org_id}/roles/{role_id}:remove-principals" + body: "*" + response_body: "item" + additional_bindings { + post: "/v1/orgs/{org_id}/projects/{project_id}/roles/{role_id}:remove-principals" + body: "*" + response_body: "item" + } + }; + option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { + summary: "Removes the specified Users and/or Groups from a Role." + }; + } } message GetRoleRequest { @@ -140,6 +203,7 @@ message CreateRoleResponse { resources.roles.v1.Role item = 2; } +// TODO: Add versions to Update and Delete role requests. message UpdateRoleRequest { string org_id = 1; string project_id = 2; @@ -161,3 +225,48 @@ message DeleteRoleRequest { message DeleteRoleResponse { bool existed = 1; } + +message AddRolePrincipalsRequest { + string org_id = 1; + string project_id = 2; + string role_id = 3; + // The version ensures the role hasn't changed since it was last retrieved and if + // it has the request will fail. + google.protobuf.UInt32Value version = 4; + repeated string user_ids = 5 [json_name="user_ids"]; + repeated string group_ids = 6 [json_name="group_ids"]; +} + +message AddRolePrincipalsResponse { + resources.roles.v1.Role item = 1; +} + +message SetRolePrincipalsRequest { + string org_id = 1; + string project_id = 2; + string role_id = 3; + // The version ensures the role hasn't changed since it was last retrieved and if + // it has the request will fail. + google.protobuf.UInt32Value version = 4; + repeated string user_ids = 5 [json_name="user_ids"]; + repeated string group_ids = 6 [json_name="group_ids"]; +} + +message SetRolePrincipalsResponse { + resources.roles.v1.Role item = 1; +} + +message RemoveRolePrincipalsRequest { + string org_id = 1; + string project_id = 2; + string role_id = 3; + // The version ensures the role hasn't changed since it was last retrieved and if + // it has the request will fail. + google.protobuf.UInt32Value version = 4; + repeated string user_ids = 5 [json_name="user_ids"]; + repeated string group_ids = 6 [json_name="group_ids"]; +} + +message RemoveRolePrincipalsResponse { + resources.roles.v1.Role item = 1; +} \ No newline at end of file diff --git a/internal/servers/controller/handler_test.go b/internal/servers/controller/handler_test.go index db6ceb372b..a4a14976ef 100644 --- a/internal/servers/controller/handler_test.go +++ b/internal/servers/controller/handler_test.go @@ -119,6 +119,47 @@ func TestGrpcGatewayRouting(t *testing.T) { } } +func TestGrpcGatewayRouting_CustomActions(t *testing.T) { + ctx := context.Background() + // The unimplemented result indicates the grpc routing is happening successfully otherwise it would return NotFound. + routed := http.StatusNotImplemented + + cases := []struct { + name string + setup func(mux *runtime.ServeMux) + post_urls []string + }{ + { + name: "roles", + setup: func(mux *runtime.ServeMux) { + require.NoError(t, services.RegisterRoleServiceHandlerServer(ctx, mux, &services.UnimplementedRoleServiceServer{})) + }, + post_urls: []string{ + "v1/orgs/someid/roles/r_anotherid:add-principals", + "v1/orgs/someid/roles/r_anotherid:set-principals", + "v1/orgs/someid/roles/r_anotherid:remove-principals", + "v1/orgs/someid/projects/p_something/roles/r_anotherid:add-principals", + "v1/orgs/someid/projects/p_something/roles/r_anotherid:set-principals", + "v1/orgs/someid/projects/p_something/roles/r_anotherid:remove-principals", + }, + }, + } + + for _, tc := range cases { + for _, url := range tc.post_urls { + t.Run(tc.name+"_"+url, func(t *testing.T) { + mux := runtime.NewServeMux() + tc.setup(mux) + + req := httptest.NewRequest("POST", fmt.Sprintf("http://localhost/%s", url), nil) + resp := httptest.NewRecorder() + mux.ServeHTTP(resp, req) + assert.Equal(t, routed, resp.Result().StatusCode, "Got response %v", resp) + }) + } + } +} + func TestHandleGrpcGateway(t *testing.T) { c := NewTestController(t, nil) defer c.Shutdown() diff --git a/internal/servers/controller/handlers/roles/role_service.go b/internal/servers/controller/handlers/roles/role_service.go index 47599d2e3d..c7be9b2d94 100644 --- a/internal/servers/controller/handlers/roles/role_service.go +++ b/internal/servers/controller/handlers/roles/role_service.go @@ -121,22 +121,64 @@ func (s Service) DeleteRole(ctx context.Context, req *pbs.DeleteRoleRequest) (*p return &pbs.DeleteRoleResponse{Existed: existed}, nil } +// AddRolePrincipals implements the interface pbs.RoleServiceServer. +func (s Service) AddRolePrincipals(ctx context.Context, req *pbs.AddRolePrincipalsRequest) (*pbs.AddRolePrincipalsResponse, error) { + auth := handlers.ToTokenMetadata(ctx) + _ = auth + if err := validateAddRolePrincipalsRequest(req); err != nil { + return nil, err + } + r, err := s.addPrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue()) + if err != nil { + return nil, err + } + return &pbs.AddRolePrincipalsResponse{Item: r}, nil +} + +// SetRolePrincipals implements the interface pbs.RoleServiceServer. +func (s Service) SetRolePrincipals(ctx context.Context, req *pbs.SetRolePrincipalsRequest) (*pbs.SetRolePrincipalsResponse, error) { + auth := handlers.ToTokenMetadata(ctx) + _ = auth + if err := validateSetRolePrincipalsRequest(req); err != nil { + return nil, err + } + r, err := s.setPrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue()) + if err != nil { + return nil, err + } + return &pbs.SetRolePrincipalsResponse{Item: r}, nil +} + +// RemoveRolePrincipals implements the interface pbs.RoleServiceServer. +func (s Service) RemoveRolePrincipals(ctx context.Context, req *pbs.RemoveRolePrincipalsRequest) (*pbs.RemoveRolePrincipalsResponse, error) { + auth := handlers.ToTokenMetadata(ctx) + _ = auth + if err := validateRemoveRolePrincipalsRequest(req); err != nil { + return nil, err + } + r, err := s.removePrinciplesInRepo(ctx, req.GetRoleId(), req.GetUserIds(), req.GetGroupIds(), req.GetVersion().GetValue()) + if err != nil { + return nil, err + } + return &pbs.RemoveRolePrincipalsResponse{Item: r}, nil +} + func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Role, error) { repo, err := s.repoFn() if err != nil { return nil, err } - u, err := repo.LookupRole(ctx, id) + out, pr, err := repo.LookupRole(ctx, id) if err != nil { if errors.Is(err, db.ErrRecordNotFound) { return nil, handlers.NotFoundErrorf("Role %q doesn't exist.", id) } return nil, err } - if u == nil { + if out == nil { return nil, handlers.NotFoundErrorf("Role %q doesn't exist.", id) } - return toProto(u), nil + return toProto(out, pr), nil } func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Role) (*pb.Role, error) { @@ -162,7 +204,7 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Role if out == nil { return nil, status.Error(codes.Internal, "Unable to create role but no error returned from repository.") } - return toProto(out), nil + return toProto(out, nil), nil } func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []string, item *pb.Role) (*pb.Role, error) { @@ -196,7 +238,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st if rowsUpdated == 0 { return nil, handlers.NotFoundErrorf("Role %q doesn't exist.", id) } - return toProto(out), nil + return toProto(out, nil), nil } func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) { @@ -225,11 +267,59 @@ func (s Service) listFromRepo(ctx context.Context, scopeId string) ([]*pb.Role, } var outRl []*pb.Role for _, g := range rl { - outRl = append(outRl, toProto(g)) + outRl = append(outRl, toProto(g, nil)) } return outRl, nil } +func (s Service) addPrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) { + repo, err := s.repoFn() + if err != nil { + return nil, err + } + _, err = repo.AddPrincipalRoles(ctx, roleId, version, userIds, groupIds) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to add principles to role: %v.", err) + } + out, pr, err := repo.LookupRole(ctx, roleId) + if out == nil { + return nil, status.Error(codes.Internal, "Unable to lookup role after adding principles to it.") + } + return toProto(out, pr), nil +} + +func (s Service) setPrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) { + repo, err := s.repoFn() + if err != nil { + return nil, err + } + _, _, err = repo.SetPrincipalRoles(ctx, roleId, version, userIds, groupIds) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to set principles on role: %v.", err) + } + out, pr, err := repo.LookupRole(ctx, roleId) + if out == nil { + return nil, status.Error(codes.Internal, "Unable to lookup role after setting principles for it.") + } + return toProto(out, pr), nil +} + +func (s Service) removePrinciplesInRepo(ctx context.Context, roleId string, userIds []string, groupIds []string, version uint32) (*pb.Role, error) { + repo, err := s.repoFn() + if err != nil { + return nil, err + } + _, err = repo.DeletePrincipalRoles(ctx, roleId, version, userIds, groupIds) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to remove principles from role: %v.", err) + } + out, pr, err := repo.LookupRole(ctx, roleId) + if out == nil { + return nil, status.Error(codes.Internal, "Unable to lookup role after removing principles from it.") + } + return toProto(out, pr), nil +} + // toDbUpdateMask converts the wire format's FieldMask into a list of strings containing FieldMask paths used func toDbUpdateMask(paths []string) ([]string, error) { var dbPaths []string @@ -249,11 +339,12 @@ func toDbUpdateMask(paths []string) ([]string, error) { return dbPaths, nil } -func toProto(in *iam.Role) *pb.Role { +func toProto(in *iam.Role, principals []iam.PrincipalRole) *pb.Role { out := pb.Role{ Id: in.GetPublicId(), CreatedTime: in.GetCreateTime().GetTimestamp(), UpdatedTime: in.GetUpdateTime().GetTimestamp(), + Version: in.GetVersion(), } if in.GetDescription() != "" { out.Description = &wrapperspb.StringValue{Value: in.GetDescription()} @@ -261,6 +352,14 @@ func toProto(in *iam.Role) *pb.Role { if in.GetName() != "" { out.Name = &wrapperspb.StringValue{Value: in.GetName()} } + for _, p := range principals { + switch p.GetType() { + case iam.UserRoleType.String(): + out.UserIds = append(out.UserIds, p.GetPrincipalId()) + case iam.GroupRoleType.String(): + out.GroupIds = append(out.GroupIds, p.GetPrincipalId()) + } + } return &out } @@ -348,6 +447,60 @@ func validateListRequest(req *pbs.ListRolesRequest) error { return nil } +func validateAddRolePrincipalsRequest(req *pbs.AddRolePrincipalsRequest) error { + badFields := validateAncestors(req) + if !validId(req.GetRoleId(), iam.RolePrefix+"_") { + badFields["id"] = "Incorrectly formatted identifier." + } + if req.GetVersion() == nil { + badFields["version"] = "Required field." + } + if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 { + badFields["user_ids"] = "Either user_ids or group_ids must be non empty." + badFields["group_ids"] = "Either user_ids or group_ids must be non empty." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields) + } + return nil +} + +func validateSetRolePrincipalsRequest(req *pbs.SetRolePrincipalsRequest) error { + badFields := validateAncestors(req) + if !validId(req.GetRoleId(), iam.RolePrefix+"_") { + badFields["id"] = "Incorrectly formatted identifier." + } + if req.GetVersion() == nil { + badFields["version"] = "Required field." + } + if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 { + badFields["user_ids"] = "Either user_ids or group_ids must be non empty." + badFields["group_ids"] = "Either user_ids or group_ids must be non empty." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields) + } + return nil +} + +func validateRemoveRolePrincipalsRequest(req *pbs.RemoveRolePrincipalsRequest) error { + badFields := validateAncestors(req) + if !validId(req.GetRoleId(), iam.RolePrefix+"_") { + badFields["id"] = "Incorrectly formatted identifier." + } + if req.GetVersion() == nil { + badFields["version"] = "Required field." + } + if len(req.GetGroupIds()) == 0 && len(req.GetUserIds()) == 0 { + badFields["user_ids"] = "Either user_ids or group_ids must be non empty." + badFields["group_ids"] = "Either user_ids or group_ids must be non empty." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields) + } + return nil +} + func validId(id, prefix string) bool { if !strings.HasPrefix(id, prefix) { return false diff --git a/internal/servers/controller/handlers/roles/role_service_test.go b/internal/servers/controller/handlers/roles/role_service_test.go index 12d236bd1e..a381ee9fb0 100644 --- a/internal/servers/controller/handlers/roles/role_service_test.go +++ b/internal/servers/controller/handlers/roles/role_service_test.go @@ -3,10 +3,12 @@ package roles_test import ( "context" "fmt" + "sort" "strings" "testing" "github.com/golang/protobuf/ptypes" + "github.com/google/go-cmp/cmp" "github.com/hashicorp/watchtower/internal/db" pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/roles" pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services" @@ -17,6 +19,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/stretchr/testify/assert" @@ -53,6 +56,7 @@ func TestGet(t *testing.T) { Description: &wrapperspb.StringValue{Value: or.GetDescription()}, CreatedTime: or.CreateTime.GetTimestamp(), UpdatedTime: or.UpdateTime.GetTimestamp(), + Version: or.GetVersion(), } wantProjRole := &pb.Role{ @@ -61,6 +65,7 @@ func TestGet(t *testing.T) { Description: &wrapperspb.StringValue{Value: pr.GetDescription()}, CreatedTime: pr.CreateTime.GetTimestamp(), UpdatedTime: pr.UpdateTime.GetTimestamp(), + Version: pr.GetVersion(), } cases := []struct { @@ -151,12 +156,14 @@ func TestList(t *testing.T) { Id: or.GetPublicId(), CreatedTime: or.GetCreateTime().GetTimestamp(), UpdatedTime: or.GetUpdateTime().GetTimestamp(), + Version: or.GetVersion(), }) pr := iam.TestRole(t, conn, pWithRoles.GetPublicId()) wantProjRoles = append(wantProjRoles, &pb.Role{ Id: pr.GetPublicId(), CreatedTime: pr.GetCreateTime().GetTimestamp(), UpdatedTime: pr.GetUpdateTime().GetTimestamp(), + Version: pr.GetVersion(), }) } @@ -408,6 +415,7 @@ func TestCreate(t *testing.T) { Item: &pb.Role{ Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, }, }, errCode: codes.OK, @@ -426,6 +434,7 @@ func TestCreate(t *testing.T) { Item: &pb.Role{ Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, }, }, errCode: codes.OK, @@ -773,8 +782,713 @@ func TestUpdate(t *testing.T) { // Clear all values which are hard to compare against. got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil + + // TODO: Figure out the best way to test versions when updating roles + got.GetItem().Version = 0 } assert.True(proto.Equal(got, tc.res), "UpdateRole(%q) got response %q, wanted %q", req, got, tc.res) }) } } + +func TestAddPrincipal(t *testing.T) { + conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) + wrap := db.TestWrapper(t) + repoFn := func() (*iam.Repository, error) { + return iam.NewRepository(rw, rw, wrap) + } + o, p := iam.TestScopes(t, conn) + + orUserEmpty := iam.TestRole(t, conn, o.GetPublicId()) + prUserEmpty := iam.TestRole(t, conn, p.GetPublicId()) + orGroupEmpty := iam.TestRole(t, conn, o.GetPublicId()) + prGroupEmpty := iam.TestRole(t, conn, p.GetPublicId()) + + orWithUser := iam.TestRole(t, conn, o.GetPublicId()) + assignedUser := iam.TestUser(t, conn, o.GetPublicId()) + _ = iam.TestUserRole(t, conn, o.GetPublicId(), orWithUser.GetPublicId(), assignedUser.GetPublicId()) + + ou1 := iam.TestUser(t, conn, o.GetPublicId()) + ou2 := iam.TestUser(t, conn, o.GetPublicId()) + + orWithGroup := iam.TestRole(t, conn, o.GetPublicId()) + assignedOG := iam.TestGroup(t, conn, o.GetPublicId()) + _ = iam.TestGroupRole(t, conn, o.GetPublicId(), orWithGroup.GetPublicId(), assignedOG.GetPublicId()) + + og1 := iam.TestGroup(t, conn, o.GetPublicId()) + og2 := iam.TestGroup(t, conn, o.GetPublicId()) + + prWithUser := iam.TestRole(t, conn, p.GetPublicId()) + _ = iam.TestUserRole(t, conn, p.GetPublicId(), prWithUser.GetPublicId(), assignedUser.GetPublicId()) + + prWithGroup := iam.TestRole(t, conn, p.GetPublicId()) + assignedPG := iam.TestGroup(t, conn, p.GetPublicId()) + _ = iam.TestGroupRole(t, conn, p.GetPublicId(), prWithGroup.GetPublicId(), assignedPG.GetPublicId()) + + pg1 := iam.TestGroup(t, conn, p.GetPublicId()) + pg2 := iam.TestGroup(t, conn, p.GetPublicId()) + + s, err := roles.NewService(repoFn) + require.NoError(t, err, "Error when getting new role service.") + + cases := []struct { + name string + req *pbs.AddRolePrincipalsRequest + res *pbs.AddRolePrincipalsResponse + errCode codes.Code + }{ + { + name: "Add User Empty Org Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: orUserEmpty.GetScopeId(), + RoleId: orUserEmpty.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orUserEmpty.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orUserEmpty.GetPublicId(), + CreatedTime: orUserEmpty.GetCreateTime().GetTimestamp(), + Version: orUserEmpty.GetVersion() + 1, + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add User Populated Org Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: orWithUser.GetScopeId(), + RoleId: orWithUser.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orWithUser.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orWithUser.GetPublicId(), + CreatedTime: orWithUser.GetCreateTime().GetTimestamp(), + Version: orWithUser.GetVersion() + 1, + UserIds: []string{assignedUser.GetPublicId(), ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add User Empty Project Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prUserEmpty.GetScopeId(), + RoleId: prUserEmpty.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prUserEmpty.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prUserEmpty.GetPublicId(), + CreatedTime: prUserEmpty.GetCreateTime().GetTimestamp(), + Version: prUserEmpty.GetVersion() + 1, + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add User Populated Project Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prWithUser.GetScopeId(), + RoleId: prWithUser.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithUser.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prWithUser.GetPublicId(), + CreatedTime: prWithUser.GetCreateTime().GetTimestamp(), + Version: prWithUser.GetVersion() + 1, + UserIds: []string{assignedUser.GetPublicId(), ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add Group Empty Org Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: orGroupEmpty.GetScopeId(), + RoleId: orGroupEmpty.GetPublicId(), + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orGroupEmpty.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orGroupEmpty.GetPublicId(), + CreatedTime: orGroupEmpty.GetCreateTime().GetTimestamp(), + Version: orGroupEmpty.GetVersion() + 1, + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add Group Populated Org Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: orWithGroup.GetScopeId(), + RoleId: orWithGroup.GetPublicId(), + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orWithGroup.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orWithGroup.GetPublicId(), + CreatedTime: orWithGroup.GetCreateTime().GetTimestamp(), + Version: orWithGroup.GetVersion() + 1, + GroupIds: []string{assignedOG.GetPublicId(), og1.GetPublicId(), og2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add Group Empty Project Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prGroupEmpty.GetScopeId(), + RoleId: prGroupEmpty.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prGroupEmpty.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prGroupEmpty.GetPublicId(), + CreatedTime: prGroupEmpty.GetCreateTime().GetTimestamp(), + Version: prGroupEmpty.GetVersion() + 1, + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Add Group Populated Project Role", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prWithGroup.GetScopeId(), + RoleId: prWithGroup.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: &pbs.AddRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prWithGroup.GetPublicId(), + CreatedTime: prWithGroup.GetCreateTime().GetTimestamp(), + Version: prWithGroup.GetVersion() + 1, + GroupIds: []string{assignedPG.GetPublicId(), pg1.GetPublicId(), pg2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Bad Org Id", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: "", + ProjectId: prWithGroup.GetScopeId(), + RoleId: prWithGroup.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Bad Project Id", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: "bad id", + RoleId: prWithGroup.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Bad Role Id", + req: &pbs.AddRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prWithGroup.GetScopeId(), + RoleId: "bad id", + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert := assert.New(t) + got, gErr := s.AddRolePrincipals(context.Background(), tc.req) + assert.Equal(tc.errCode, status.Code(gErr), "AddRolePrincipals(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode) + + if tc.res == nil { + require.Nil(t, got) + return + } + got.Item.UpdatedTime = nil + sort.Strings(got.Item.UserIds) + sort.Strings(got.Item.GroupIds) + sort.Strings(tc.res.Item.UserIds) + sort.Strings(tc.res.Item.GroupIds) + assert.Emptyf(cmp.Diff(tc.res, got, protocmp.Transform()), + "AddRolePrincipals(%+v) got response %v, wanted %v", tc.req, got, tc.res) + }) + } +} + +func TestSetPrincipal(t *testing.T) { + conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) + wrap := db.TestWrapper(t) + repoFn := func() (*iam.Repository, error) { + return iam.NewRepository(rw, rw, wrap) + } + o, p := iam.TestScopes(t, conn) + + orUserEmpty := iam.TestRole(t, conn, o.GetPublicId()) + prUserEmpty := iam.TestRole(t, conn, p.GetPublicId()) + orGroupEmpty := iam.TestRole(t, conn, o.GetPublicId()) + prGroupEmpty := iam.TestRole(t, conn, p.GetPublicId()) + + orWithUser := iam.TestRole(t, conn, o.GetPublicId()) + assignedUser := iam.TestUser(t, conn, o.GetPublicId()) + _ = iam.TestUserRole(t, conn, o.GetPublicId(), orWithUser.GetPublicId(), assignedUser.GetPublicId()) + + ou1 := iam.TestUser(t, conn, o.GetPublicId()) + ou2 := iam.TestUser(t, conn, o.GetPublicId()) + + orWithGroup := iam.TestRole(t, conn, o.GetPublicId()) + assignedOG := iam.TestGroup(t, conn, o.GetPublicId()) + _ = iam.TestGroupRole(t, conn, o.GetPublicId(), orWithGroup.GetPublicId(), assignedOG.GetPublicId()) + + og1 := iam.TestGroup(t, conn, o.GetPublicId()) + og2 := iam.TestGroup(t, conn, o.GetPublicId()) + + prWithUser := iam.TestRole(t, conn, p.GetPublicId()) + _ = iam.TestUserRole(t, conn, p.GetPublicId(), prWithUser.GetPublicId(), assignedUser.GetPublicId()) + + prWithGroup := iam.TestRole(t, conn, p.GetPublicId()) + assignedPG := iam.TestGroup(t, conn, p.GetPublicId()) + _ = iam.TestGroupRole(t, conn, p.GetPublicId(), prWithGroup.GetPublicId(), assignedPG.GetPublicId()) + + pg1 := iam.TestGroup(t, conn, p.GetPublicId()) + pg2 := iam.TestGroup(t, conn, p.GetPublicId()) + + s, err := roles.NewService(repoFn) + require.NoError(t, err, "Error when getting new role service.") + + cases := []struct { + name string + req *pbs.SetRolePrincipalsRequest + res *pbs.SetRolePrincipalsResponse + errCode codes.Code + }{ + { + name: "Set User Empty Org Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: orUserEmpty.GetScopeId(), + RoleId: orUserEmpty.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orUserEmpty.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orUserEmpty.GetPublicId(), + CreatedTime: orUserEmpty.GetCreateTime().GetTimestamp(), + Version: orUserEmpty.GetVersion() + 1, + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set User Populated Org Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: orWithUser.GetScopeId(), + RoleId: orWithUser.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orWithUser.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orWithUser.GetPublicId(), + CreatedTime: orWithUser.GetCreateTime().GetTimestamp(), + Version: orWithUser.GetVersion() + 1, + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set User Empty Project Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prUserEmpty.GetScopeId(), + RoleId: prUserEmpty.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prUserEmpty.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prUserEmpty.GetPublicId(), + CreatedTime: prUserEmpty.GetCreateTime().GetTimestamp(), + Version: prUserEmpty.GetVersion() + 1, + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set User Populated Project Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prWithUser.GetScopeId(), + RoleId: prWithUser.GetPublicId(), + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithUser.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prWithUser.GetPublicId(), + CreatedTime: prWithUser.GetCreateTime().GetTimestamp(), + Version: prWithUser.GetVersion() + 1, + UserIds: []string{ou1.GetPublicId(), ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set Group Empty Org Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: orGroupEmpty.GetScopeId(), + RoleId: orGroupEmpty.GetPublicId(), + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orGroupEmpty.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orGroupEmpty.GetPublicId(), + CreatedTime: orGroupEmpty.GetCreateTime().GetTimestamp(), + Version: orGroupEmpty.GetVersion() + 1, + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set Group Populated Org Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: orWithGroup.GetScopeId(), + RoleId: orWithGroup.GetPublicId(), + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orWithGroup.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orWithGroup.GetPublicId(), + CreatedTime: orWithGroup.GetCreateTime().GetTimestamp(), + Version: orWithGroup.GetVersion() + 1, + GroupIds: []string{og1.GetPublicId(), og2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set Group Empty Project Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prGroupEmpty.GetScopeId(), + RoleId: prGroupEmpty.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prGroupEmpty.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prGroupEmpty.GetPublicId(), + CreatedTime: prGroupEmpty.GetCreateTime().GetTimestamp(), + Version: prGroupEmpty.GetVersion() + 1, + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Set Group Populated Project Role", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prWithGroup.GetScopeId(), + RoleId: prWithGroup.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: &pbs.SetRolePrincipalsResponse{ + Item: &pb.Role{ + Id: prWithGroup.GetPublicId(), + CreatedTime: prWithGroup.GetCreateTime().GetTimestamp(), + Version: prWithGroup.GetVersion() + 1, + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Bad Org Id", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: "", + ProjectId: prWithGroup.GetScopeId(), + RoleId: prWithGroup.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Bad Project Id", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: "bad id", + RoleId: prWithGroup.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Bad Role Id", + req: &pbs.SetRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: prWithGroup.GetScopeId(), + RoleId: "bad id", + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: prWithGroup.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert := assert.New(t) + got, gErr := s.SetRolePrincipals(context.Background(), tc.req) + assert.Equal(tc.errCode, status.Code(gErr), "AddRolePrincipals(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode) + + if tc.res == nil { + require.Nil(t, got) + return + } + got.Item.UpdatedTime = nil + sort.Strings(got.Item.UserIds) + sort.Strings(got.Item.GroupIds) + sort.Strings(tc.res.Item.UserIds) + sort.Strings(tc.res.Item.GroupIds) + assert.Emptyf(cmp.Diff(tc.res, got, protocmp.Transform()), + "AddRolePrincipals(%+v) got response %v, wanted %v", tc.req, got, tc.res) + }) + } +} + +func TestRemovePrincipal(t *testing.T) { + conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) + wrap := db.TestWrapper(t) + repoFn := func() (*iam.Repository, error) { + return iam.NewRepository(rw, rw, wrap) + } + o, p := iam.TestScopes(t, conn) + + orgEmptyRole := iam.TestRole(t, conn, o.GetPublicId()) + orgUserRoles := iam.TestRole(t, conn, o.GetPublicId()) + orgGroupRoles := iam.TestRole(t, conn, o.GetPublicId()) + projEmptyRole := iam.TestRole(t, conn, p.GetPublicId()) + projUserRoles := iam.TestRole(t, conn, p.GetPublicId()) + projGroupRoles := iam.TestRole(t, conn, p.GetPublicId()) + + ou1 := iam.TestUser(t, conn, o.GetPublicId()) + ou2 := iam.TestUser(t, conn, o.GetPublicId()) + _ = iam.TestUserRole(t, conn, o.GetPublicId(), orgUserRoles.GetPublicId(), ou1.GetPublicId()) + _ = iam.TestUserRole(t, conn, o.GetPublicId(), orgUserRoles.GetPublicId(), ou2.GetPublicId()) + _ = iam.TestUserRole(t, conn, p.GetPublicId(), projUserRoles.GetPublicId(), ou1.GetPublicId()) + _ = iam.TestUserRole(t, conn, p.GetPublicId(), projUserRoles.GetPublicId(), ou2.GetPublicId()) + + og1 := iam.TestGroup(t, conn, o.GetPublicId()) + og2 := iam.TestGroup(t, conn, o.GetPublicId()) + _ = iam.TestGroupRole(t, conn, o.GetPublicId(), orgGroupRoles.GetPublicId(), og1.GetPublicId()) + _ = iam.TestGroupRole(t, conn, o.GetPublicId(), orgGroupRoles.GetPublicId(), og2.GetPublicId()) + + pg1 := iam.TestGroup(t, conn, p.GetPublicId()) + pg2 := iam.TestGroup(t, conn, p.GetPublicId()) + _ = iam.TestGroupRole(t, conn, p.GetPublicId(), projGroupRoles.GetPublicId(), pg1.GetPublicId()) + _ = iam.TestGroupRole(t, conn, p.GetPublicId(), projGroupRoles.GetPublicId(), pg2.GetPublicId()) + + s, err := roles.NewService(repoFn) + require.NoError(t, err, "Error when getting new role service.") + + cases := []struct { + name string + req *pbs.RemoveRolePrincipalsRequest + res *pbs.RemoveRolePrincipalsResponse + errCode codes.Code + }{ + { + name: "Remove User From Org Role", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: orgUserRoles.GetScopeId(), + RoleId: orgUserRoles.GetPublicId(), + UserIds: []string{ou1.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orgUserRoles.GetVersion()}, + }, + res: &pbs.RemoveRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orgUserRoles.GetPublicId(), + CreatedTime: orgUserRoles.GetCreateTime().GetTimestamp(), + Version: orgUserRoles.GetVersion() + 1, + UserIds: []string{ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Remove User From Proj Role", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: projUserRoles.GetScopeId(), + RoleId: projUserRoles.GetPublicId(), + UserIds: []string{ou1.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: projUserRoles.GetVersion()}, + }, + res: &pbs.RemoveRolePrincipalsResponse{ + Item: &pb.Role{ + Id: projUserRoles.GetPublicId(), + CreatedTime: projUserRoles.GetCreateTime().GetTimestamp(), + Version: projUserRoles.GetVersion() + 1, + UserIds: []string{ou2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Remove Group From Org Role", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: orgGroupRoles.GetScopeId(), + RoleId: orgGroupRoles.GetPublicId(), + GroupIds: []string{og1.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orgGroupRoles.GetVersion()}, + }, + res: &pbs.RemoveRolePrincipalsResponse{ + Item: &pb.Role{ + Id: orgGroupRoles.GetPublicId(), + CreatedTime: orgGroupRoles.GetCreateTime().GetTimestamp(), + Version: orgGroupRoles.GetVersion() + 1, + GroupIds: []string{og2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + { + name: "Remove Group From Proj Role", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: projGroupRoles.GetScopeId(), + RoleId: projGroupRoles.GetPublicId(), + GroupIds: []string{pg1.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()}, + }, + res: &pbs.RemoveRolePrincipalsResponse{ + Item: &pb.Role{ + Id: projGroupRoles.GetPublicId(), + CreatedTime: projGroupRoles.GetCreateTime().GetTimestamp(), + Version: projGroupRoles.GetVersion() + 1, + GroupIds: []string{pg2.GetPublicId()}, + }, + }, + errCode: codes.OK, + }, + // TODO: Should it be a silent noop to remove a principal from a role when the principal isn't on the role? + { + name: "Remove From Empty Org Role", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + RoleId: orgEmptyRole.GetPublicId(), + UserIds: []string{ou1.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: orgEmptyRole.GetVersion()}, + }, + errCode: codes.Internal, + }, + { + name: "Remove From Empty Project Role", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: projEmptyRole.GetScopeId(), + RoleId: projEmptyRole.GetPublicId(), + UserIds: []string{ou1.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: projEmptyRole.GetVersion()}, + }, + errCode: codes.Internal, + }, + { + name: "Bad Org Id", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: "", + ProjectId: projGroupRoles.GetScopeId(), + RoleId: projGroupRoles.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Bad Project Id", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: "bad id", + RoleId: projGroupRoles.GetPublicId(), + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Bad Role Id", + req: &pbs.RemoveRolePrincipalsRequest{ + OrgId: o.GetPublicId(), + ProjectId: projGroupRoles.GetScopeId(), + RoleId: "bad id", + GroupIds: []string{pg1.GetPublicId(), pg2.GetPublicId()}, + Version: &wrapperspb.UInt32Value{Value: projGroupRoles.GetVersion()}, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert := assert.New(t) + got, gErr := s.RemoveRolePrincipals(context.Background(), tc.req) + assert.Equal(tc.errCode, status.Code(gErr), "AddRolePrincipals(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode) + + if tc.res == nil { + require.Nil(t, got) + return + } + got.Item.UpdatedTime = nil + sort.Strings(got.Item.UserIds) + sort.Strings(got.Item.GroupIds) + sort.Strings(tc.res.Item.UserIds) + sort.Strings(tc.res.Item.GroupIds) + assert.Emptyf(cmp.Diff(tc.res, got, protocmp.Transform()), + "AddRolePrincipals(%+v) got response %v, wanted %v", tc.req, got, tc.res) + }) + } +}