From 56bacaf809b7f4eb5eb41d8d21c8a6eec32b32d3 Mon Sep 17 00:00:00 2001 From: Iraq Jaber Date: Fri, 25 Apr 2025 14:30:40 +0200 Subject: [PATCH] fixup! fixup! refactor(api): moving organization API resourced based added updateOrganization --- internal/api/grpc/management/org.go | 2 +- .../org/v2beta/integration_test/org_test.go | 69 +++++++++++++++++++ internal/api/grpc/org/v2beta/org.go | 11 +++ internal/command/org.go | 2 +- internal/command/org_test.go | 2 +- proto/zitadel/org/v2beta/org_service.proto | 40 +++++++---- 6 files changed, 111 insertions(+), 15 deletions(-) diff --git a/internal/api/grpc/management/org.go b/internal/api/grpc/management/org.go index 70f509a4d7..dc5b3be8b4 100644 --- a/internal/api/grpc/management/org.go +++ b/internal/api/grpc/management/org.go @@ -98,7 +98,7 @@ func (s *Server) AddOrg(ctx context.Context, req *mgmt_pb.AddOrgRequest) (*mgmt_ func (s *Server) UpdateOrg(ctx context.Context, req *mgmt_pb.UpdateOrgRequest) (*mgmt_pb.UpdateOrgResponse, error) { ctxData := authz.GetCtxData(ctx) - org, err := s.command.ChangeOrg(ctx, ctxData.OrgID, req.Name) + org, err := s.command.UpdateOrg(ctx, ctxData.OrgID, req.Name) if err != nil { return nil, err } diff --git a/internal/api/grpc/org/v2beta/integration_test/org_test.go b/internal/api/grpc/org/v2beta/integration_test/org_test.go index 857c137b11..16ae45836c 100644 --- a/internal/api/grpc/org/v2beta/integration_test/org_test.go +++ b/internal/api/grpc/org/v2beta/integration_test/org_test.go @@ -187,6 +187,75 @@ func TestServer_CreateOrganization(t *testing.T) { } } +func TestServer_UpdateOrganization(t *testing.T) { + orgName := "new_org_name" + orgId, err := createOrg(orgName) + if err != nil { + assert.Fail(t, "unable to create org") + } + + tests := []struct { + name string + ctx context.Context + req *org.UpdateOrganizationRequest + want *org.UpdateOrganizationResponse + wantErr bool + }{ + { + name: "update org with same name", + ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeOrgOwner), + req: &org.UpdateOrganizationRequest{ + Id: orgId, + Name: orgName, + }, + }, + { + name: "update org with new name", + ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeOrgOwner), + req: &org.UpdateOrganizationRequest{ + Id: orgId, + Name: "new org name", + }, + }, + { + name: "update org with no id", + ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeOrgOwner), + req: &org.UpdateOrganizationRequest{ + Id: orgId, + // Name: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Client.UpdateOrganization(tt.ctx, tt.req) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + // check details + assert.NotZero(t, got.GetDetails().GetSequence()) + gotCD := got.GetDetails().GetChangeDate().AsTime() + now := time.Now() + assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute)) + assert.NotEmpty(t, got.GetDetails().GetResourceOwner()) + }) + } +} + +func createOrg(orgName string) (string, error) { + org, err := Client.CreateOrganization(CTX, + &org.CreateOrganizationRequest{ + Name: orgName, + }, + ) + + return org.OrganizationId, err +} + func assertCreatedAdmin(t *testing.T, expected, got *org.CreateOrganizationResponse_CreatedAdmin) { if expected.GetUserId() != "" { assert.NotEmpty(t, got.GetUserId()) diff --git a/internal/api/grpc/org/v2beta/org.go b/internal/api/grpc/org/v2beta/org.go index 51cab77d38..ccb001a793 100644 --- a/internal/api/grpc/org/v2beta/org.go +++ b/internal/api/grpc/org/v2beta/org.go @@ -22,6 +22,17 @@ func (s *Server) CreateOrganization(ctx context.Context, request *org.CreateOrga return createdOrganizationToPb(createdOrg) } +func (s *Server) UpdateOrganization(ctx context.Context, request *org.UpdateOrganizationRequest) (*org.UpdateOrganizationResponse, error) { + updated_org, err := s.command.UpdateOrg(ctx, request.Id, request.Name) + if err != nil { + return nil, err + } + + return &org.UpdateOrganizationResponse{ + Details: object.DomainToDetailsPb(updated_org), + }, nil +} + func createOrganizationRequestToCommand(request *org.CreateOrganizationRequest) (*command.OrgSetup, error) { admins, err := createOrganizationRequestAdminsToCommand(request.GetAdmins()) if err != nil { diff --git a/internal/command/org.go b/internal/command/org.go index a018a90c82..68c9ae982e 100644 --- a/internal/command/org.go +++ b/internal/command/org.go @@ -342,7 +342,7 @@ func (c *Commands) addOrgWithIDAndMember(ctx context.Context, name, userID, reso return orgWriteModelToOrg(addedOrg), nil } -func (c *Commands) ChangeOrg(ctx context.Context, orgID, name string) (*domain.ObjectDetails, error) { +func (c *Commands) UpdateOrg(ctx context.Context, orgID, name string) (*domain.ObjectDetails, error) { name = strings.TrimSpace(name) if orgID == "" || name == "" { return nil, zerrors.ThrowInvalidArgument(nil, "EVENT-Mf9sd", "Errors.Org.Invalid") diff --git a/internal/command/org_test.go b/internal/command/org_test.go index 4ec85d61e1..2eec42c5a4 100644 --- a/internal/command/org_test.go +++ b/internal/command/org_test.go @@ -756,7 +756,7 @@ func TestCommandSide_ChangeOrg(t *testing.T) { r := &Commands{ eventstore: tt.fields.eventstore, } - _, err := r.ChangeOrg(tt.args.ctx, tt.args.orgID, tt.args.name) + _, err := r.UpdateOrg(tt.args.ctx, tt.args.orgID, tt.args.name) if tt.res.err == nil { assert.NoError(t, err) } diff --git a/proto/zitadel/org/v2beta/org_service.proto b/proto/zitadel/org/v2beta/org_service.proto index 41e50b02ba..c1cfd10792 100644 --- a/proto/zitadel/org/v2beta/org_service.proto +++ b/proto/zitadel/org/v2beta/org_service.proto @@ -145,8 +145,13 @@ service OrganizationService { body: "*" }; - option (zitadel.v1.auth_option) = { - permission: "org.write" + option (zitadel.protoc_gen_zitadel.v2.options) = { + auth_option: { + permission: "org.write" + } + http_response: { + success_code: 200 + } }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { @@ -198,17 +203,28 @@ message CreateOrganizationResponse{ } message UpdateOrganizationRequest { - string name = 1 [ - (validate.rules).string = {min_len: 1, max_len: 200}, - (google.api.field_behavior) = REQUIRED, - (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { - min_length: 1; - max_length: 200; - example: "\"Customer 1\""; - } - ]; + string id = 1 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (google.api.field_behavior) = REQUIRED, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + min_length: 1; + max_length: 200; + example: "\"69629012906488334\""; + description: "Organization ID of the organization you want to update." + } + ]; + + string name = 2 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (google.api.field_behavior) = REQUIRED, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + min_length: 1; + max_length: 200; + example: "\"Customer 1\""; + } + ]; } message UpdateOrganizationResponse { - zitadel.v1.ObjectDetails details = 1; + zitadel.object.v2beta.Details details = 1; }