feat: set metadata field in UpdateUser endpoint (#11747)

# Which Problems Are Solved

To be able to update metadata via the `UpdateUser` endpoint.

# How the Problems Are Solved
This is achieved by:
* adding the `Metadata` field to `UpdateUserRequest`
* update the server layer to convert/set metadata fields to domain layer
metadata
* update the command layer to handle metadata updates

# Additional Changes

N/A

# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11369,
https://github.com/zitadel/zitadel/issues/11759
- Follow-up for PR https://github.com/zitadel/zitadel/pull/11719

---------

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Gayathri Vijayan
2026-03-09 10:47:32 +01:00
committed by GitHub
co-authored by Copilot
parent 5b12690757
commit 282b2486d9
14 changed files with 896 additions and 165 deletions
+4 -3
View File
@@ -80,8 +80,8 @@ func setMetadataEntries(metadata []*user.Metadata) []*user.SetMetadataEntry {
return metadataEntries
}
func (s *Server) updateUserTypeHuman(ctx context.Context, humanPb *user.UpdateUserRequest_Human, userId string, userName *string) (*connect.Response[user.UpdateUserResponse], error) {
cmd, err := updateHumanUserToCommand(userId, userName, humanPb)
func (s *Server) updateUserTypeHuman(ctx context.Context, humanPb *user.UpdateUserRequest_Human, userId string, userName *string, reqMetadata []*user.Metadata) (*connect.Response[user.UpdateUserResponse], error) {
cmd, err := updateHumanUserToCommand(userId, userName, humanPb, reqMetadata)
if err != nil {
return nil, err
}
@@ -95,7 +95,7 @@ func (s *Server) updateUserTypeHuman(ctx context.Context, humanPb *user.UpdateUs
}), nil
}
func updateHumanUserToCommand(userId string, userName *string, human *user.UpdateUserRequest_Human) (*command.ChangeHuman, error) {
func updateHumanUserToCommand(userId string, userName *string, human *user.UpdateUserRequest_Human, reqMetadata []*user.Metadata) (*command.ChangeHuman, error) {
phone := human.GetPhone()
if phone != nil && phone.Phone == "" && phone.GetVerification() != nil {
return nil, zerrors.ThrowInvalidArgument(nil, "USERv2-4f3d6", "Errors.User.Phone.VerifyingRemovalIsNotSupported")
@@ -111,6 +111,7 @@ func updateHumanUserToCommand(userId string, userName *string, human *user.Updat
Email: email,
Phone: setHumanPhoneToPhone(human.Phone, true),
Password: setHumanPasswordToPassword(human.Password),
Metadata: setUserMetadataToDomain(reqMetadata),
}, nil
}
+22 -1
View File
@@ -20,6 +20,7 @@ func Test_patchHumanUserToCommand(t *testing.T) {
userId string
userName *string
human *user.UpdateUserRequest_Human
metadata []*user.Metadata
}
tests := []struct {
name string
@@ -81,6 +82,16 @@ func Test_patchHumanUserToCommand(t *testing.T) {
},
},
},
metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
want: &command.ChangeHuman{
ID: "userId",
@@ -106,6 +117,16 @@ func Test_patchHumanUserToCommand(t *testing.T) {
Password: "newPassword",
ChangeRequired: true,
},
Metadata: []*domain.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
wantErr: assert.NoError,
}, {
@@ -242,7 +263,7 @@ func Test_patchHumanUserToCommand(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := updateHumanUserToCommand(tt.args.userId, tt.args.userName, tt.args.human)
got, err := updateHumanUserToCommand(tt.args.userId, tt.args.userName, tt.args.human, tt.args.metadata)
if !tt.wantErr(t, err, fmt.Sprintf("patchHumanUserToCommand(%v, %v, %v)", tt.args.userId, tt.args.userName, tt.args.human)) {
return
}
@@ -4409,146 +4409,405 @@ func TestServer_UpdateUser_And_Compare(t *testing.T) {
}
type testCase struct {
args args
assert func(t *testing.T, getResponse *user.GetUserByIDResponse)
assert func(
t *testing.T,
getResponse *user.GetUserByIDResponse,
getMetadataResponse *user.ListUserMetadataResponse,
)
}
tests := []struct {
name string
testCase func(runId string) testCase
}{{
name: "human remove phone",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
email := username + "@example.com"
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Human_{
Human: &user.CreateUserRequest_Human{
Profile: &user.SetHumanProfile{
GivenName: "Donald",
FamilyName: "Duck",
}{
{
name: "human remove phone",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
email := username + "@example.com"
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Human_{
Human: &user.CreateUserRequest_Human{
Profile: &user.SetHumanProfile{
GivenName: "Donald",
FamilyName: "Duck",
},
Email: &user.SetHumanEmail{
Email: email,
},
Phone: &user.SetHumanPhone{
Phone: "+1234567890",
},
},
Email: &user.SetHumanEmail{
Email: email,
},
Phone: &user.SetHumanPhone{
Phone: "+1234567890",
},
},
update: &user.UpdateUserRequest{
UserId: runId,
UserType: &user.UpdateUserRequest_Human_{
Human: &user.UpdateUserRequest_Human{
Phone: &user.SetHumanPhone{},
},
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
UserType: &user.UpdateUserRequest_Human_{
Human: &user.UpdateUserRequest_Human{
Phone: &user.SetHumanPhone{},
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, _ *user.ListUserMetadataResponse) {
assert.Empty(t, getResponse.GetUser().GetHuman().GetPhone().GetPhone(), "phone is not empty")
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse) {
assert.Empty(t, getResponse.GetUser().GetHuman().GetPhone().GetPhone(), "phone is not empty")
},
}
}
},
},
}, {
name: "human username",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
email := username + "@example.com"
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Human_{
Human: &user.CreateUserRequest_Human{
Profile: &user.SetHumanProfile{
GivenName: "Donald",
FamilyName: "Duck",
{
name: "human username",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
email := username + "@example.com"
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Human_{
Human: &user.CreateUserRequest_Human{
Profile: &user.SetHumanProfile{
GivenName: "Donald",
FamilyName: "Duck",
},
Email: &user.SetHumanEmail{
Email: email,
},
},
Email: &user.SetHumanEmail{
Email: email,
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Human_{
Human: &user.UpdateUserRequest_Human{},
},
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, _ *user.ListUserMetadataResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
},
}
},
},
{
name: "service accountname",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "Donald",
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{},
},
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, _ *user.ListUserMetadataResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
},
}
},
},
{
name: "machine accessTokenType",
testCase: func(runId string) testCase {
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "Donald",
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{
AccessTokenType: gu.Ptr(user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT),
},
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Human_{
Human: &user.UpdateUserRequest_Human{},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, _ *user.ListUserMetadataResponse) {
assert.Equal(t, user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, getResponse.GetUser().GetMachine().GetAccessTokenType())
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
},
}
}
},
},
}, {
name: "service accountname",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "Donald",
{
name: "human metadata",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
email := username + "@example.com"
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Human_{
Human: &user.CreateUserRequest_Human{
Profile: &user.SetHumanProfile{
GivenName: "Donald",
FamilyName: "Duck",
},
Email: &user.SetHumanEmail{
Email: email,
},
},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Human_{
Human: &user.UpdateUserRequest_Human{},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("updated_value1"), // updating key1
},
{
Key: "key3",
Value: []byte("value3"), // adding key3
},
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, listMetadataResponse *user.ListUserMetadataResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
expectedMetadata := []*metadata.Metadata{
{Key: "key1", Value: []byte("updated_value1")},
{Key: "key2", Value: []byte("value2")},
{Key: "key3", Value: []byte("value3")},
}
assertMetadataEquals(t, expectedMetadata, listMetadataResponse.GetMetadata())
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
},
}
}
},
},
}, {
name: "machine accessTokenType",
testCase: func(runId string) testCase {
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "Donald",
{
name: "human metadata - update and delete, ok",
testCase: func(runId string) testCase {
username := fmt.Sprintf("donald.duck+%s", runId)
email := username + "@example.com"
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Human_{
Human: &user.CreateUserRequest_Human{
Profile: &user.SetHumanProfile{
GivenName: "Donald",
FamilyName: "Duck",
},
Email: &user.SetHumanEmail{
Email: email,
},
},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Human_{
Human: &user.UpdateUserRequest_Human{},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("updated_value1"), // updating key1
},
{
Key: "key2", // removing key2
},
{
Key: "key3", // removing a non-existing key
},
{
Key: "key4", // adding a new key
Value: []byte("value4"),
},
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{
AccessTokenType: gu.Ptr(user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT),
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, listMetadataResponse *user.ListUserMetadataResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
expectedMetadata := []*metadata.Metadata{
{Key: "key1", Value: []byte("updated_value1")},
{Key: "key4", Value: []byte("value4")},
}
assertMetadataEquals(t, expectedMetadata, listMetadataResponse.GetMetadata())
},
}
},
},
{
name: "service account metadata",
testCase: func(runId string) testCase {
username := fmt.Sprintf("service.account+%s", runId)
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "service_account",
AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT,
},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("updated_value1"), // updating key1
},
{
Key: "key3",
Value: []byte("value3"), // adding key3
},
},
},
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse) {
assert.Equal(t, user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT, getResponse.GetUser().GetMachine().GetAccessTokenType())
},
}
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, listMetadataResponse *user.ListUserMetadataResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
expectedMetadata := []*metadata.Metadata{
{Key: "key1", Value: []byte("updated_value1")},
{Key: "key2", Value: []byte("value2")},
{Key: "key3", Value: []byte("value3")},
}
assertMetadataEquals(t, expectedMetadata, listMetadataResponse.GetMetadata())
},
}
},
},
}}
{
name: "service account metadata - update and delete, ok",
testCase: func(runId string) testCase {
username := fmt.Sprintf("service.account+%s", runId)
return testCase{
args: args{
ctx: OrgCTX,
create: &user.CreateUserRequest{
OrganizationId: Instance.DefaultOrg.Id,
UserId: &runId,
UserType: &user.CreateUserRequest_Machine_{
Machine: &user.CreateUserRequest_Machine{
Name: "service_account",
AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT,
},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
update: &user.UpdateUserRequest{
UserId: runId,
Username: &username,
UserType: &user.UpdateUserRequest_Machine_{
Machine: &user.UpdateUserRequest_Machine{},
},
Metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("updated_value1"), // updating key1
},
{
Key: "key2", // removing key2
},
{
Key: "key3", // removing a non-existing key
},
{
Key: "key4", // adding a new key
Value: []byte("value4"),
},
},
},
},
assert: func(t *testing.T, getResponse *user.GetUserByIDResponse, listMetadataResponse *user.ListUserMetadataResponse) {
assert.Equal(t, username, getResponse.GetUser().GetUsername())
expectedMetadata := []*metadata.Metadata{
{Key: "key1", Value: []byte("updated_value1")},
{Key: "key4", Value: []byte("value4")},
}
assertMetadataEquals(t, expectedMetadata, listMetadataResponse.GetMetadata())
},
}
},
},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
now := time.Now()
@@ -4563,7 +4822,11 @@ func TestServer_UpdateUser_And_Compare(t *testing.T) {
UserId: createResponse.GetId(),
})
require.NoError(t, err)
test.assert(t, getResponse)
gotMetadataResponse, err := Client.ListUserMetadata(test.args.ctx, &user.ListUserMetadataRequest{
UserId: createResponse.GetId(),
})
require.NoError(t, err)
test.assert(t, getResponse, gotMetadataResponse)
})
}
}
+4 -3
View File
@@ -47,8 +47,8 @@ func (s *Server) createUserTypeMachine(ctx context.Context, machinePb *user.Crea
}), nil
}
func (s *Server) updateUserTypeMachine(ctx context.Context, machinePb *user.UpdateUserRequest_Machine, userId string, userName *string) (*connect.Response[user.UpdateUserResponse], error) {
cmd := updateMachineUserToCommand(userId, userName, machinePb)
func (s *Server) updateUserTypeMachine(ctx context.Context, machinePb *user.UpdateUserRequest_Machine, userId string, userName *string, reqMetadata []*user.Metadata) (*connect.Response[user.UpdateUserResponse], error) {
cmd := updateMachineUserToCommand(userId, userName, machinePb, reqMetadata)
err := s.command.ChangeUserMachine(ctx, cmd)
if err != nil {
return nil, err
@@ -58,7 +58,7 @@ func (s *Server) updateUserTypeMachine(ctx context.Context, machinePb *user.Upda
}), nil
}
func updateMachineUserToCommand(userId string, userName *string, machine *user.UpdateUserRequest_Machine) *command.ChangeMachine {
func updateMachineUserToCommand(userId string, userName *string, machine *user.UpdateUserRequest_Machine, reqMetadata []*user.Metadata) *command.ChangeMachine {
var accessTokenType *domain.OIDCTokenType
if machine.AccessTokenType != nil {
tokenType := accessTokenTypeToDomain(*machine.AccessTokenType)
@@ -70,6 +70,7 @@ func updateMachineUserToCommand(userId string, userName *string, machine *user.U
Name: machine.Name,
Description: machine.Description,
AccessTokenType: accessTokenType,
Metadata: setUserMetadataToDomain(reqMetadata),
}
}
+22 -1
View File
@@ -18,6 +18,7 @@ func Test_patchMachineUserToCommand(t *testing.T) {
userId string
userName *string
machine *user.UpdateUserRequest_Machine
metadata []*user.Metadata
}
tests := []struct {
name string
@@ -45,6 +46,16 @@ func Test_patchMachineUserToCommand(t *testing.T) {
Description: gu.Ptr("description"),
AccessTokenType: gu.Ptr(user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT),
},
metadata: []*user.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
want: &command.ChangeMachine{
ID: "userId",
@@ -52,11 +63,21 @@ func Test_patchMachineUserToCommand(t *testing.T) {
Name: gu.Ptr("name"),
Description: gu.Ptr("description"),
AccessTokenType: gu.Ptr(domain.OIDCTokenTypeJWT),
Metadata: []*domain.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
{
Key: "key2",
Value: []byte("value2"),
},
},
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := updateMachineUserToCommand(tt.args.userId, tt.args.userName, tt.args.machine)
got := updateMachineUserToCommand(tt.args.userId, tt.args.userName, tt.args.machine, tt.args.metadata)
if diff := cmp.Diff(tt.want, got, cmpopts.EquateComparable(language.Tag{})); diff != "" {
t.Errorf("patchMachineUserToCommand() mismatch (-want +got):\n%s", diff)
}
+11 -8
View File
@@ -49,7 +49,7 @@ func (s *Server) listUserMetadataRequestToModel(req *user.ListUserMetadataReques
}
func (s *Server) SetUserMetadata(ctx context.Context, req *connect.Request[user.SetUserMetadataRequest]) (*connect.Response[user.SetUserMetadataResponse], error) {
result, err := s.command.BulkSetUserMetadata(ctx, req.Msg.UserId, "", s.command.NewPermissionCheckUserWrite(ctx, false), setUserMetadataToDomain(req.Msg)...)
result, err := s.command.BulkSetUserMetadata(ctx, req.Msg.UserId, "", s.command.NewPermissionCheckUserWrite(ctx, false), setUserMetadataToDomain(req.Msg.GetMetadata())...)
if err != nil {
return nil, err
}
@@ -58,15 +58,18 @@ func (s *Server) SetUserMetadata(ctx context.Context, req *connect.Request[user.
}), nil
}
func setUserMetadataToDomain(req *user.SetUserMetadataRequest) []*domain.Metadata {
metadata := make([]*domain.Metadata, len(req.Metadata))
for i, data := range req.Metadata {
metadata[i] = &domain.Metadata{
Key: data.Key,
Value: data.Value,
func setUserMetadataToDomain(reqMetadata []*user.Metadata) []*domain.Metadata {
if len(reqMetadata) == 0 {
return nil
}
metadataEntries := make([]*domain.Metadata, len(reqMetadata))
for i, data := range reqMetadata {
metadataEntries[i] = &domain.Metadata{
Key: data.GetKey(),
Value: data.GetValue(),
}
}
return metadata
return metadataEntries
}
func (s *Server) DeleteUserMetadata(ctx context.Context, req *connect.Request[user.DeleteUserMetadataRequest]) (*connect.Response[user.DeleteUserMetadataResponse], error) {
+2 -2
View File
@@ -425,9 +425,9 @@ func (s *Server) CreateUser(ctx context.Context, req *connect.Request[user.Creat
func (s *Server) UpdateUser(ctx context.Context, req *connect.Request[user.UpdateUserRequest]) (*connect.Response[user.UpdateUserResponse], error) {
switch userType := req.Msg.GetUserType().(type) {
case *user.UpdateUserRequest_Human_:
return s.updateUserTypeHuman(ctx, userType.Human, req.Msg.GetUserId(), req.Msg.Username)
return s.updateUserTypeHuman(ctx, userType.Human, req.Msg.GetUserId(), req.Msg.Username, req.Msg.GetMetadata())
case *user.UpdateUserRequest_Machine_:
return s.updateUserTypeMachine(ctx, userType.Machine, req.Msg.GetUserId(), req.Msg.Username)
return s.updateUserTypeMachine(ctx, userType.Machine, req.Msg.GetUserId(), req.Msg.Username, req.Msg.GetMetadata())
default:
return nil, zerrors.ThrowUnimplemented(nil, "", "user type is not implemented")
}