fixup! fixup! fixup! fixup! fixup! fixup! fixup! refactor(api): moving organization API resourced based

added Deactivate/ActivateOrg
This commit is contained in:
Iraq Jaber
2025-05-01 12:37:14 +02:00
parent 40de3d462a
commit 96831fb5f5
5 changed files with 308 additions and 98 deletions

View File

@@ -15,7 +15,9 @@ import (
gofakeit "github.com/brianvoe/gofakeit/v6" gofakeit "github.com/brianvoe/gofakeit/v6"
"github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/internal/integration"
org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta" org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
v2beta_org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
"github.com/zitadel/zitadel/pkg/grpc/user/v2" "github.com/zitadel/zitadel/pkg/grpc/user/v2"
user_v2beta "github.com/zitadel/zitadel/pkg/grpc/user/v2beta" user_v2beta "github.com/zitadel/zitadel/pkg/grpc/user/v2beta"
) )
@@ -23,7 +25,7 @@ import (
var ( var (
CTX context.Context CTX context.Context
Instance *integration.Instance Instance *integration.Instance
Client org.OrganizationServiceClient Client v2beta_org.OrganizationServiceClient
User *user.AddHumanUserResponse User *user.AddHumanUserResponse
) )
@@ -42,66 +44,20 @@ func TestMain(m *testing.M) {
}()) }())
} }
func TestServer_GetOrganizationByID(t *testing.T) {
orgs, orgsName, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create org")
}
orgId := orgs[0].OrganizationId
orgName := orgsName[0]
tests := []struct {
name string
ctx context.Context
req *org.GetOrganizationByIDRequest
want *org.GetOrganizationByIDResponse
wantErr bool
}{
{
name: "get organization happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.GetOrganizationByIDRequest{
Id: orgId,
},
},
{
name: "get organization that doesn't exist",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.GetOrganizationByIDRequest{
Id: "non existing organization",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.GetOrganizationByID(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, orgId, got.Organization.Id)
require.Equal(t, orgName, got.Organization.Name)
})
}
}
func TestServer_CreateOrganization(t *testing.T) { func TestServer_CreateOrganization(t *testing.T) {
idpResp := Instance.AddGenericOAuthProvider(CTX, Instance.DefaultOrg.Id) idpResp := Instance.AddGenericOAuthProvider(CTX, Instance.DefaultOrg.Id)
tests := []struct { tests := []struct {
name string name string
ctx context.Context ctx context.Context
req *org.CreateOrganizationRequest req *v2beta_org.CreateOrganizationRequest
want *org.CreateOrganizationResponse want *v2beta_org.CreateOrganizationResponse
wantErr bool wantErr bool
}{ }{
{ {
name: "missing permission", name: "missing permission",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeOrgOwner), ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeOrgOwner),
req: &org.CreateOrganizationRequest{ req: &v2beta_org.CreateOrganizationRequest{
Name: "name", Name: "name",
Admins: nil, Admins: nil,
}, },
@@ -110,7 +66,7 @@ func TestServer_CreateOrganization(t *testing.T) {
{ {
name: "empty name", name: "empty name",
ctx: CTX, ctx: CTX,
req: &org.CreateOrganizationRequest{ req: &v2beta_org.CreateOrganizationRequest{
Name: "", Name: "",
Admins: nil, Admins: nil,
}, },
@@ -119,9 +75,9 @@ func TestServer_CreateOrganization(t *testing.T) {
{ {
name: "invalid admin type", name: "invalid admin type",
ctx: CTX, ctx: CTX,
req: &org.CreateOrganizationRequest{ req: &v2beta_org.CreateOrganizationRequest{
Name: gofakeit.AppName(), Name: gofakeit.AppName(),
Admins: []*org.CreateOrganizationRequest_Admin{ Admins: []*v2beta_org.CreateOrganizationRequest_Admin{
{}, {},
}, },
}, },
@@ -130,11 +86,11 @@ func TestServer_CreateOrganization(t *testing.T) {
{ {
name: "admin with init", name: "admin with init",
ctx: CTX, ctx: CTX,
req: &org.CreateOrganizationRequest{ req: &v2beta_org.CreateOrganizationRequest{
Name: gofakeit.AppName(), Name: gofakeit.AppName(),
Admins: []*org.CreateOrganizationRequest_Admin{ Admins: []*v2beta_org.CreateOrganizationRequest_Admin{
{ {
UserType: &org.CreateOrganizationRequest_Admin_Human{ UserType: &v2beta_org.CreateOrganizationRequest_Admin_Human{
Human: &user_v2beta.AddHumanUserRequest{ Human: &user_v2beta.AddHumanUserRequest{
Profile: &user_v2beta.SetHumanProfile{ Profile: &user_v2beta.SetHumanProfile{
GivenName: "firstname", GivenName: "firstname",
@@ -151,9 +107,9 @@ func TestServer_CreateOrganization(t *testing.T) {
}, },
}, },
}, },
want: &org.CreateOrganizationResponse{ want: &v2beta_org.CreateOrganizationResponse{
OrganizationId: integration.NotEmpty, OrganizationId: integration.NotEmpty,
CreatedAdmins: []*org.CreateOrganizationResponse_CreatedAdmin{ CreatedAdmins: []*v2beta_org.CreateOrganizationResponse_CreatedAdmin{
{ {
UserId: integration.NotEmpty, UserId: integration.NotEmpty,
EmailCode: gu.Ptr(integration.NotEmpty), EmailCode: gu.Ptr(integration.NotEmpty),
@@ -165,14 +121,14 @@ func TestServer_CreateOrganization(t *testing.T) {
{ {
name: "existing user and new human with idp", name: "existing user and new human with idp",
ctx: CTX, ctx: CTX,
req: &org.CreateOrganizationRequest{ req: &v2beta_org.CreateOrganizationRequest{
Name: gofakeit.AppName(), Name: gofakeit.AppName(),
Admins: []*org.CreateOrganizationRequest_Admin{ Admins: []*v2beta_org.CreateOrganizationRequest_Admin{
{ {
UserType: &org.CreateOrganizationRequest_Admin_UserId{UserId: User.GetUserId()}, UserType: &v2beta_org.CreateOrganizationRequest_Admin_UserId{UserId: User.GetUserId()},
}, },
{ {
UserType: &org.CreateOrganizationRequest_Admin_Human{ UserType: &v2beta_org.CreateOrganizationRequest_Admin_Human{
Human: &user_v2beta.AddHumanUserRequest{ Human: &user_v2beta.AddHumanUserRequest{
Profile: &user_v2beta.SetHumanProfile{ Profile: &user_v2beta.SetHumanProfile{
GivenName: "firstname", GivenName: "firstname",
@@ -196,8 +152,8 @@ func TestServer_CreateOrganization(t *testing.T) {
}, },
}, },
}, },
want: &org.CreateOrganizationResponse{ want: &v2beta_org.CreateOrganizationResponse{
CreatedAdmins: []*org.CreateOrganizationResponse_CreatedAdmin{ CreatedAdmins: []*v2beta_org.CreateOrganizationResponse_CreatedAdmin{
// a single admin is expected, because the first provided already exists // a single admin is expected, because the first provided already exists
{ {
UserId: integration.NotEmpty, UserId: integration.NotEmpty,
@@ -246,14 +202,14 @@ func TestServer_UpdateOrganization(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
ctx context.Context ctx context.Context
req *org.UpdateOrganizationRequest req *v2beta_org.UpdateOrganizationRequest
want *org.UpdateOrganizationResponse want *v2beta_org.UpdateOrganizationResponse
wantErr bool wantErr bool
}{ }{
{ {
name: "update org with new name", name: "update org with new name",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner), ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.UpdateOrganizationRequest{ req: &v2beta_org.UpdateOrganizationRequest{
Id: orgId, Id: orgId,
Name: "new org name", Name: "new org name",
}, },
@@ -261,7 +217,7 @@ func TestServer_UpdateOrganization(t *testing.T) {
{ {
name: "update org with same name", name: "update org with same name",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner), ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.UpdateOrganizationRequest{ req: &v2beta_org.UpdateOrganizationRequest{
Id: orgId, Id: orgId,
Name: orgName, Name: orgName,
}, },
@@ -269,7 +225,7 @@ func TestServer_UpdateOrganization(t *testing.T) {
{ {
name: "update org with no id", name: "update org with no id",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner), ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.UpdateOrganizationRequest{ req: &v2beta_org.UpdateOrganizationRequest{
Id: orgId, Id: orgId,
// Name: "", // Name: "",
}, },
@@ -295,6 +251,52 @@ func TestServer_UpdateOrganization(t *testing.T) {
} }
} }
func TestServer_GetOrganizationByID(t *testing.T) {
orgs, orgsName, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create org")
}
orgId := orgs[0].OrganizationId
orgName := orgsName[0]
tests := []struct {
name string
ctx context.Context
req *v2beta_org.GetOrganizationByIDRequest
want *v2beta_org.GetOrganizationByIDResponse
wantErr bool
}{
{
name: "get organization happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &v2beta_org.GetOrganizationByIDRequest{
Id: orgId,
},
},
{
name: "get organization that doesn't exist",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &v2beta_org.GetOrganizationByIDRequest{
Id: "non existing organization",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.GetOrganizationByID(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, orgId, got.Organization.Id)
require.Equal(t, orgName, got.Organization.Name)
})
}
}
// TODO: finish off qyery testing in ListOrganizations // TODO: finish off qyery testing in ListOrganizations
func TestServer_ListOrganization(t *testing.T) { func TestServer_ListOrganization(t *testing.T) {
noOfOrgs := 3 noOfOrgs := 3
@@ -306,15 +308,15 @@ func TestServer_ListOrganization(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
ctx context.Context ctx context.Context
req *org.ListOrganizationsRequest req *v2beta_org.ListOrganizationsRequest
want []*org.Organization want []*v2beta_org.Organization
wantErr bool wantErr bool
}{ }{
{ {
name: "list organizations happy path", name: "list organizations happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner), ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.ListOrganizationsRequest{}, req: &v2beta_org.ListOrganizationsRequest{},
want: []*org.Organization{ want: []*v2beta_org.Organization{
{ {
Id: orgs[0].OrganizationId, Id: orgs[0].OrganizationId,
Name: orgsName[0], Name: orgsName[0],
@@ -370,8 +372,8 @@ func TestServer_DeleteOrganization(t *testing.T) {
name string name string
ctx context.Context ctx context.Context
createOrgFunc func() string createOrgFunc func() string
req *org.DeleteOrganizationRequest req *v2beta_org.DeleteOrganizationRequest
want *org.DeleteOrganizationResponse want *v2beta_org.DeleteOrganizationResponse
err error err error
}{ }{
{ {
@@ -384,12 +386,12 @@ func TestServer_DeleteOrganization(t *testing.T) {
} }
return orgs[0].OrganizationId return orgs[0].OrganizationId
}, },
req: &org.DeleteOrganizationRequest{}, req: &v2beta_org.DeleteOrganizationRequest{},
}, },
{ {
name: "delete non existent org", name: "delete non existent org",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner), ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &org.DeleteOrganizationRequest{ req: &v2beta_org.DeleteOrganizationRequest{
Id: "non existent org id", Id: "non existent org id",
}, },
err: fmt.Errorf("Organisation not found"), err: fmt.Errorf("Organisation not found"),
@@ -415,7 +417,7 @@ func TestServer_DeleteOrganization(t *testing.T) {
assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute)) assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute))
assert.NotEmpty(t, got.GetDetails().GetResourceOwner()) assert.NotEmpty(t, got.GetDetails().GetResourceOwner())
_, err = Client.GetOrganizationByID(tt.ctx, &org.GetOrganizationByIDRequest{ _, err = Client.GetOrganizationByID(tt.ctx, &v2beta_org.GetOrganizationByIDRequest{
Id: tt.req.Id, Id: tt.req.Id,
}) })
require.Contains(t, err.Error(), "Organisation not found") require.Contains(t, err.Error(), "Organisation not found")
@@ -423,16 +425,121 @@ func TestServer_DeleteOrganization(t *testing.T) {
} }
} }
func createOrgs(noOfOrgs int) ([]*org.CreateOrganizationResponse, []string, error) { func TestServer_DeactivateReactivateNonExistentOrganization(t *testing.T) {
ctx := Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner)
// deactivate non existent organization
_, err := Client.DeactivateOrganization(ctx, &v2beta_org.DeactivateOrganizationRequest{
Id: "non existent organization",
})
require.Contains(t, err.Error(), "Organisation not found")
// reactivate non existent organization
_, err = Client.ReactivateOrganization(ctx, &v2beta_org.ReactivateOrganizationRequest{
Id: "non existent organization",
})
require.Contains(t, err.Error(), "Organisation not found")
}
func TestServer_DeactivateReactivateOrganization(t *testing.T) {
// 1. create organization
orgs, _, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create orgs")
}
orgId := orgs[0].OrganizationId
ctx := Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner)
// 2. check inital state of organization
res, err := Client.GetOrganizationByID(ctx, &org.GetOrganizationByIDRequest{
Id: orgId,
})
require.NoError(t, err)
require.Equal(t, v2beta_org.OrganizationState_ORGANIZATION_STATE_ACTIVE, res.Organization.State)
// 3. deactivate organization once
deactivate_res, err := Client.DeactivateOrganization(ctx, &v2beta_org.DeactivateOrganizationRequest{
Id: orgId,
})
require.NoError(t, err)
assert.NotZero(t, deactivate_res.GetDetails().GetSequence())
gotCD := deactivate_res.GetDetails().GetChangeDate().AsTime()
now := time.Now()
assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute))
assert.NotEmpty(t, deactivate_res.GetDetails().GetResourceOwner())
// 4. check organization state is deactivated
res, err = Client.GetOrganizationByID(ctx, &v2beta_org.GetOrganizationByIDRequest{
Id: orgId,
})
require.NoError(t, err)
require.Equal(t, v2beta_org.OrganizationState_ORGANIZATION_STATE_INACTIVE, res.Organization.State)
// 5. repeat deactivate organization once
deactivate_res, err = Client.DeactivateOrganization(ctx, &v2beta_org.DeactivateOrganizationRequest{
Id: orgId,
})
require.NoError(t, err)
assert.NotZero(t, deactivate_res.GetDetails().GetSequence())
gotCD = deactivate_res.GetDetails().GetChangeDate().AsTime()
now = time.Now()
assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute))
assert.NotEmpty(t, deactivate_res.GetDetails().GetResourceOwner())
// 6. repeat check organization state is still deactivated
res, err = Client.GetOrganizationByID(ctx, &v2beta_org.GetOrganizationByIDRequest{
Id: orgId,
})
require.NoError(t, err)
require.Equal(t, v2beta_org.OrganizationState_ORGANIZATION_STATE_INACTIVE, res.Organization.State)
// 7. reactivate organization
reactivate_res, err := Client.ReactivateOrganization(ctx, &v2beta_org.ReactivateOrganizationRequest{
Id: orgId,
})
require.NoError(t, err)
assert.NotZero(t, reactivate_res.GetDetails().GetSequence())
gotCD = reactivate_res.GetDetails().GetChangeDate().AsTime()
now = time.Now()
assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute))
assert.NotEmpty(t, reactivate_res.GetDetails().GetResourceOwner())
// 8. check organization state is active
res, err = Client.GetOrganizationByID(ctx, &v2beta_org.GetOrganizationByIDRequest{
Id: orgId,
})
require.NoError(t, err)
require.Equal(t, v2beta_org.OrganizationState_ORGANIZATION_STATE_ACTIVE, res.Organization.State)
// 9. repeat reactivate organization
reactivate_res, err = Client.ReactivateOrganization(ctx, &v2beta_org.ReactivateOrganizationRequest{
Id: orgId,
})
require.NoError(t, err)
assert.NotZero(t, reactivate_res.GetDetails().GetSequence())
gotCD = reactivate_res.GetDetails().GetChangeDate().AsTime()
now = time.Now()
assert.WithinRange(t, gotCD, now.Add(-time.Minute), now.Add(time.Minute))
assert.NotEmpty(t, reactivate_res.GetDetails().GetResourceOwner())
// 10. repeat check organization state is still active
res, err = Client.GetOrganizationByID(ctx, &v2beta_org.GetOrganizationByIDRequest{
Id: orgId,
})
require.NoError(t, err)
require.Equal(t, v2beta_org.OrganizationState_ORGANIZATION_STATE_ACTIVE, res.Organization.State)
}
func createOrgs(noOfOrgs int) ([]*v2beta_org.CreateOrganizationResponse, []string, error) {
var err error var err error
orgs := make([]*org.CreateOrganizationResponse, noOfOrgs) orgs := make([]*v2beta_org.CreateOrganizationResponse, noOfOrgs)
orgsName := make([]string, noOfOrgs) orgsName := make([]string, noOfOrgs)
for i := range noOfOrgs { for i := range noOfOrgs {
orgName := gofakeit.Name() orgName := gofakeit.Name()
orgsName[i] = orgName orgsName[i] = orgName
orgs[i], err = Client.CreateOrganization(CTX, orgs[i], err = Client.CreateOrganization(CTX,
&org.CreateOrganizationRequest{ &v2beta_org.CreateOrganizationRequest{
Name: orgName, Name: orgName,
}, },
) )
@@ -444,7 +551,7 @@ func createOrgs(noOfOrgs int) ([]*org.CreateOrganizationResponse, []string, erro
return orgs, orgsName, nil return orgs, orgsName, nil
} }
func assertCreatedAdmin(t *testing.T, expected, got *org.CreateOrganizationResponse_CreatedAdmin) { func assertCreatedAdmin(t *testing.T, expected, got *v2beta_org.CreateOrganizationResponse_CreatedAdmin) {
if expected.GetUserId() != "" { if expected.GetUserId() != "" {
assert.NotEmpty(t, got.GetUserId()) assert.NotEmpty(t, got.GetUserId())
} else { } else {

View File

@@ -7,6 +7,7 @@ import (
user "github.com/zitadel/zitadel/internal/api/grpc/user/v2beta" user "github.com/zitadel/zitadel/internal/api/grpc/user/v2beta"
"github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/zerrors" "github.com/zitadel/zitadel/internal/zerrors"
org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
v2beta_org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta" v2beta_org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
) )
@@ -68,6 +69,26 @@ func (s *Server) DeleteOrganization(ctx context.Context, request *v2beta_org.Del
}, nil }, nil
} }
func (s *Server) DeactivateOrganization(ctx context.Context, request *org.DeactivateOrganizationRequest) (*org.DeactivateOrganizationResponse, error) {
objectDetails, err := s.command.DeactivateOrg(ctx, request.Id)
if err != nil {
return nil, err
}
return &org.DeactivateOrganizationResponse{
Details: object.DomainToDetailsPb(objectDetails),
}, nil
}
func (s *Server) ReactivateOrganization(ctx context.Context, request *org.ReactivateOrganizationRequest) (*org.ReactivateOrganizationResponse, error) {
objectDetails, err := s.command.ReactivateOrg(ctx, request.Id)
if err != nil {
return nil, err
}
return &org.ReactivateOrganizationResponse{
Details: object.DomainToDetailsPb(objectDetails),
}, err
}
func createOrganizationRequestToCommand(request *v2beta_org.CreateOrganizationRequest) (*command.OrgSetup, error) { func createOrganizationRequestToCommand(request *v2beta_org.CreateOrganizationRequest) (*command.OrgSetup, error) {
admins, err := createOrganizationRequestAdminsToCommand(request.GetAdmins()) admins, err := createOrganizationRequestAdminsToCommand(request.GetAdmins())
if err != nil { if err != nil {

View File

@@ -353,7 +353,7 @@ func (c *Commands) UpdateOrg(ctx context.Context, orgID, name string) (*domain.O
return nil, err return nil, err
} }
if !isOrgStateExists(orgWriteModel.State) { if !isOrgStateExists(orgWriteModel.State) {
return nil, zerrors.ThrowNotFound(nil, "ORG-1MRds", "Errors.Org.NotFound") return writeModelToObjectDetails(&orgWriteModel.WriteModel), nil
} }
if orgWriteModel.Name == name { if orgWriteModel.Name == name {
return writeModelToObjectDetails(&orgWriteModel.WriteModel), nil return writeModelToObjectDetails(&orgWriteModel.WriteModel), nil
@@ -388,7 +388,7 @@ func (c *Commands) DeactivateOrg(ctx context.Context, orgID string) (*domain.Obj
return nil, zerrors.ThrowNotFound(nil, "ORG-oL9nT", "Errors.Org.NotFound") return nil, zerrors.ThrowNotFound(nil, "ORG-oL9nT", "Errors.Org.NotFound")
} }
if orgWriteModel.State == domain.OrgStateInactive { if orgWriteModel.State == domain.OrgStateInactive {
return nil, zerrors.ThrowPreconditionFailed(nil, "EVENT-Dbs2g", "Errors.Org.AlreadyDeactivated") return writeModelToObjectDetails(&orgWriteModel.WriteModel), nil
} }
orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel) orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel)
pushedEvents, err := c.eventstore.Push(ctx, org.NewOrgDeactivatedEvent(ctx, orgAgg)) pushedEvents, err := c.eventstore.Push(ctx, org.NewOrgDeactivatedEvent(ctx, orgAgg))
@@ -411,7 +411,7 @@ func (c *Commands) ReactivateOrg(ctx context.Context, orgID string) (*domain.Obj
return nil, zerrors.ThrowNotFound(nil, "ORG-Dgf3g", "Errors.Org.NotFound") return nil, zerrors.ThrowNotFound(nil, "ORG-Dgf3g", "Errors.Org.NotFound")
} }
if orgWriteModel.State == domain.OrgStateActive { if orgWriteModel.State == domain.OrgStateActive {
return nil, zerrors.ThrowPreconditionFailed(nil, "EVENT-bfnrh", "Errors.Org.AlreadyActive") return writeModelToObjectDetails(&orgWriteModel.WriteModel), nil
} }
orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel) orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel)
pushedEvents, err := c.eventstore.Push(ctx, org.NewOrgReactivatedEvent(ctx, orgAgg)) pushedEvents, err := c.eventstore.Push(ctx, org.NewOrgReactivatedEvent(ctx, orgAgg))

View File

@@ -32,6 +32,7 @@ message Organization {
]; ];
} }
// TODO rename to OrgState
enum OrganizationState { enum OrganizationState {
ORGANIZATION_STATE_UNSPECIFIED = 0; ORGANIZATION_STATE_UNSPECIFIED = 0;
ORGANIZATION_STATE_ACTIVE = 1; ORGANIZATION_STATE_ACTIVE = 1;
@@ -80,7 +81,7 @@ message OrgDomainQuery {
} }
message OrgStateQuery { message OrgStateQuery {
OrgState state = 1 [ OrganizationState state = 1 [
(validate.rules).enum.defined_only = true, (validate.rules).enum.defined_only = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "current state of the organization"; description: "current state of the organization";
@@ -97,14 +98,3 @@ message OrgIDQuery {
]; ];
} }
enum OrgState {
ORG_STATE_UNSPECIFIED = 0;
ORG_STATE_ACTIVE = 1;
ORG_STATE_INACTIVE = 2;
ORG_STATE_REMOVED = 3;
}
enum OrgFieldName {
ORG_FIELD_NAME_UNSPECIFIED = 0;
ORG_FIELD_NAME_NAME = 1;
}

View File

@@ -249,7 +249,7 @@ service OrganizationService {
responses: { responses: {
key: "200"; key: "200";
value: { value: {
description: "org removed successfully"; description: "org deleted successfully";
}; };
}; };
responses: { responses: {
@@ -266,6 +266,66 @@ service OrganizationService {
}; };
} }
rpc DeactivateOrganization(DeactivateOrganizationRequest) returns (DeactivateOrganizationResponse) {
option (google.api.http) = {
post: "/v2beta/_deactivate"
body: "*"
};
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) = {
tags: "Organizations";
summary: "Deactivate Organization";
description: "Sets the state of my organization to deactivated. Users of this organization will not be able to log in."
parameters: {
headers: {
name: "x-zitadel-orgid";
description: "The default is always the organization of the requesting user. If you like to get users of another organization include the header. Make sure the user has permission to access the requested data.";
type: STRING,
required: false;
};
};
};
}
rpc ReactivateOrganization(ReactivateOrganizationRequest) returns (ReactivateOrganizationResponse) {
option (google.api.http) = {
post: "/orgs/me/_reactivate"
body: "*"
};
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) = {
tags: "Organizations";
summary: "Reactivate Organization";
description: "Set the state of my organization to active. The state of the organization has to be deactivated to perform the request. Users of this organization will be able to log in again."
parameters: {
headers: {
name: "x-zitadel-orgid";
description: "The default is always the organization of the requesting user. If you like to get users of another organization include the header. Make sure the user has permission to access the requested data.";
type: STRING,
required: false;
};
};
};
}
} }
message CreateOrganizationRequest{ message CreateOrganizationRequest{
@@ -387,3 +447,35 @@ message DeleteOrganizationRequest {
message DeleteOrganizationResponse { message DeleteOrganizationResponse {
zitadel.object.v2beta.Details details = 1; zitadel.object.v2beta.Details details = 1;
} }
//This is an empty request
message DeactivateOrganizationRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
min_length: 1;
max_length: 200;
}
];
}
message DeactivateOrganizationResponse {
zitadel.object.v2beta.Details details = 1;
}
//This is an empty request
message ReactivateOrganizationRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
min_length: 1;
max_length: 200;
}
];
}
message ReactivateOrganizationResponse {
zitadel.object.v2beta.Details details = 1;
}