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

This commit is contained in:
Iraq Jaber
2025-05-03 12:38:45 +02:00
parent 9dbcfc255d
commit 3e482e501e
5 changed files with 622 additions and 247 deletions

View File

@@ -2,9 +2,8 @@ package org
import (
"context"
"time"
"github.com/zitadel/zitadel/internal/api/authz"
metadata "github.com/zitadel/zitadel/internal/api/grpc/metadata/v2beta"
v2beta_object "github.com/zitadel/zitadel/internal/api/grpc/object/v2beta"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
@@ -17,8 +16,6 @@ import (
v2beta_org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
v2beta "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
"google.golang.org/protobuf/types/known/timestamppb"
)
// NOTE: most of this code is copied from `internal/api/grpc/admin/*`, as we will eventually axe the previous versons of the API,
@@ -47,7 +44,7 @@ func OrganizationViewToPb(org *query.Org) *v2beta_org.Organization {
State: OrgStateToPb(org.State),
Name: org.Name,
PrimaryDomain: org.Domain,
Details: ToViewDetailsPb(
Details: v2beta_object.ToViewDetailsPb(
org.Sequence,
org.CreationDate,
org.ChangeDate,
@@ -67,25 +64,6 @@ func OrgStateToPb(state domain.OrgState) v2beta_org.OrgState {
}
}
func ToViewDetailsPb(
sequence uint64,
creationDate,
changeDate time.Time,
resourceOwner string,
) *v2beta.Details {
details := &v2beta.Details{
Sequence: sequence,
ResourceOwner: resourceOwner,
}
if !creationDate.IsZero() {
details.CreationDate = timestamppb.New(creationDate)
}
if !changeDate.IsZero() {
details.ChangeDate = timestamppb.New(changeDate)
}
return details
}
func createdOrganizationToPb(createdOrg *command.CreatedOrg) (_ *org.CreateOrganizationResponse, err error) {
admins := make([]*org.CreateOrganizationResponse_CreatedAdmin, len(createdOrg.CreatedAdmins))
for i, admin := range createdOrg.CreatedAdmins {
@@ -166,7 +144,7 @@ func OrgViewToPb(org *query.Org) *v2beta_org.Organization {
State: OrgStateToPb(org.State),
Name: org.Name,
PrimaryDomain: org.Domain,
Details: ToViewDetailsPb(
Details: v2beta_object.ToViewDetailsPb(
org.Sequence,
org.CreationDate,
org.ChangeDate,
@@ -243,8 +221,35 @@ func GenerateOrgDomainValidationRequestToDomain(ctx context.Context, req *v2beta
func ValidateOrgDomainRequestToDomain(ctx context.Context, req *v2beta_org.VerifyOrganizationDomainRequest) *domain.OrgDomain {
return &domain.OrgDomain{
ObjectRoot: models.ObjectRoot{
AggregateID: authz.GetCtxData(ctx).OrgID,
AggregateID: req.OrganizationId,
},
Domain: req.Domain,
}
}
func BulkSetOrgMetadataToDomain(req *v2beta_org.SetOrganizationMetadataRequest) []*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,
}
}
return metadata
}
func ListOrgMetadataToDomain(request *v2beta_org.ListOrganizationMetadataRequest) (*query.OrgMetadataSearchQueries, error) {
offset, limit, asc := v2beta_object.ListQueryToModel(request.Query)
queries, err := metadata.OrgMetadataQueriesToQuery(request.Queries)
if err != nil {
return nil, err
}
return &query.OrgMetadataSearchQueries{
SearchRequest: query.SearchRequest{
Offset: offset,
Limit: limit,
Asc: asc,
},
Queries: queries,
}, nil
}

View File

@@ -4,6 +4,7 @@ package org_test
import (
"context"
"errors"
"fmt"
"os"
"testing"
@@ -16,6 +17,7 @@ import (
gofakeit "github.com/brianvoe/gofakeit/v6"
"github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/admin"
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"
@@ -23,10 +25,11 @@ import (
)
var (
CTX context.Context
Instance *integration.Instance
Client v2beta_org.OrganizationServiceClient
User *user.AddHumanUserResponse
CTX context.Context
Instance *integration.Instance
Client v2beta_org.OrganizationServiceClient
AdminClient admin.AdminServiceClient
User *user.AddHumanUserResponse
)
func TestMain(m *testing.M) {
@@ -36,6 +39,7 @@ func TestMain(m *testing.M) {
Instance = integration.NewInstance(ctx)
Client = Instance.Client.OrgV2beta
AdminClient = Instance.Client.Admin
CTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner)
CTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner)
@@ -567,7 +571,6 @@ func TestServer_AddOListDeleterganizationDomain(t *testing.T) {
Domain: domain,
})
require.NoError(t, err)
// check details
assert.NotZero(t, addOrgDomainRes.GetDetails().GetSequence())
gotCD := addOrgDomainRes.GetDetails().GetChangeDate().AsTime()
@@ -671,6 +674,407 @@ func TestServer_AddOListDeleterganizationDomain(t *testing.T) {
require.False(t, found, "deleted domain found")
}
func TestServer_ValidateOrganizationDomain(t *testing.T) {
orgs, _, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create org")
}
orgId := orgs[0].OrganizationId
_, err = AdminClient.UpdateDomainPolicy(CTX, &admin.UpdateDomainPolicyRequest{
ValidateOrgDomains: true,
})
require.NoError(t, err)
domain := "www.domainnn.com"
_, err = Client.AddOrganizationDomain(CTX, &v2beta_org.AddOrganizationDomainRequest{
OrganizationId: orgId,
Domain: domain,
})
require.NoError(t, err)
tests := []struct {
name string
ctx context.Context
req *v2beta_org.GenerateOrganizationDomainValidationRequest
err error
}{
{
name: "validate org http happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &v2beta_org.GenerateOrganizationDomainValidationRequest{
OrganizationId: orgId,
Domain: domain,
Type: org.DomainValidationType_DOMAIN_VALIDATION_TYPE_HTTP,
},
},
{
name: "validate org http non existnetn org id",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &v2beta_org.GenerateOrganizationDomainValidationRequest{
OrganizationId: "non existent org id",
Domain: domain,
Type: org.DomainValidationType_DOMAIN_VALIDATION_TYPE_HTTP,
},
// BUG: this should be 'organization does not exist'
err: errors.New("Domain doesn't exist on organization"),
},
{
name: "validate org http non existnetn domain",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
req: &v2beta_org.GenerateOrganizationDomainValidationRequest{
OrganizationId: orgId,
Domain: "non existent domain",
Type: org.DomainValidationType_DOMAIN_VALIDATION_TYPE_HTTP,
},
err: errors.New("Domain doesn't exist on organization"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.GenerateOrganizationDomainValidation(tt.ctx, tt.req)
if tt.err != nil {
require.Contains(t, err.Error(), tt.err.Error())
return
}
require.NoError(t, err)
require.NotEmpty(t, got.Token)
require.Contains(t, got.Url, domain)
})
}
}
func TestServer_SetOrganizationMetadata(t *testing.T) {
orgs, _, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create org")
}
orgId := orgs[0].OrganizationId
tests := []struct {
name string
ctx context.Context
setupFunc func()
orgId string
key string
value string
err error
}{
{
name: "set org metadata",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
orgId: orgId,
key: "key1",
value: "value1",
},
{
name: "set org metadata on non existant org",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
orgId: "non existant orgid",
key: "key2",
value: "value2",
err: errors.New("Organisation not found"),
},
{
name: "update org metadata",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
setupFunc: func() {
_, err := Client.SetOrganizationMetadata(CTX, &v2beta_org.SetOrganizationMetadataRequest{
Id: orgId,
Metadata: []*v2beta_org.Metadata{
{
Key: "key3",
Value: []byte("value3"),
},
},
})
require.NoError(t, err)
},
orgId: orgId,
key: "key4",
value: "value4",
},
{
name: "update org metadata with same value",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
setupFunc: func() {
_, err := Client.SetOrganizationMetadata(CTX, &v2beta_org.SetOrganizationMetadataRequest{
Id: orgId,
Metadata: []*v2beta_org.Metadata{
{
Key: "key5",
Value: []byte("value5"),
},
},
})
require.NoError(t, err)
},
orgId: orgId,
key: "key5",
value: "value5",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.setupFunc != nil {
tt.setupFunc()
}
got, err := Client.SetOrganizationMetadata(tt.ctx, &v2beta_org.SetOrganizationMetadataRequest{
Id: tt.orgId,
Metadata: []*v2beta_org.Metadata{
{
Key: tt.key,
Value: []byte(tt.value),
},
},
})
if tt.err != nil {
require.Contains(t, err.Error(), tt.err.Error())
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())
// check metadata
listMetadataRes, err := Client.ListOrganizationMetadata(tt.ctx, &v2beta_org.ListOrganizationMetadataRequest{
Id: orgId,
})
require.NoError(t, err)
foundMetadata := false
foundMetadataKeyCount := 0
for _, res := range listMetadataRes.Result {
if res.Key == tt.key {
foundMetadataKeyCount += 1
}
if res.Key == tt.key &&
string(res.Value) == tt.value {
foundMetadata = true
}
}
require.True(t, foundMetadata, "unable to find added metadata")
require.Equal(t, 1, foundMetadataKeyCount, "same metadata key found multiple times")
})
}
}
func TestServer_ListOrganizationMetadata(t *testing.T) {
orgs, _, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create org")
}
orgId := orgs[0].OrganizationId
tests := []struct {
name string
ctx context.Context
setupFunc func()
orgId string
keyValuPars []struct {
key string
value string
}
}{
{
name: "list org metadata happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
setupFunc: func() {
_, err := Client.SetOrganizationMetadata(CTX, &v2beta_org.SetOrganizationMetadataRequest{
Id: orgId,
Metadata: []*v2beta_org.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
},
})
require.NoError(t, err)
},
orgId: orgId,
keyValuPars: []struct{ key, value string }{
{
key: "key1",
value: "value1",
},
},
},
{
name: "list multiple org metadata happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
setupFunc: func() {
_, err := Client.SetOrganizationMetadata(CTX, &v2beta_org.SetOrganizationMetadataRequest{
Id: orgId,
Metadata: []*v2beta_org.Metadata{
{
Key: "key2",
Value: []byte("value2"),
},
{
Key: "key3",
Value: []byte("value3"),
},
{
Key: "key4",
Value: []byte("value4"),
},
},
})
require.NoError(t, err)
},
orgId: orgId,
keyValuPars: []struct{ key, value string }{
{
key: "key2",
value: "value2",
},
{
key: "key3",
value: "value3",
},
{
key: "key4",
value: "value4",
},
},
},
{
name: "list org metadata for non existent org",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
orgId: "non existent orgid",
keyValuPars: []struct{ key, value string }{
// {
// key: "key1",
// value: "value1",
// },
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.setupFunc != nil {
tt.setupFunc()
}
got, err := Client.ListOrganizationMetadata(tt.ctx, &v2beta_org.ListOrganizationMetadataRequest{
Id: tt.orgId,
})
// if tt.err != nil {
// require.Contains(t, err.Error(), tt.err.Error())
// return
// }
require.NoError(t, err)
foundMetadataCount := 0
for _, kv := range tt.keyValuPars {
for _, res := range got.Result {
if res.Key == kv.key &&
string(res.Value) == kv.value {
foundMetadataCount += 1
}
}
}
require.Equal(t, len(tt.keyValuPars), foundMetadataCount)
})
}
}
func TestServer_DeleteOrganizationMetadata(t *testing.T) {
orgs, _, err := createOrgs(1)
if err != nil {
assert.Fail(t, "unable to create org")
}
orgId := orgs[0].OrganizationId
tests := []struct {
name string
ctx context.Context
setupFunc func()
orgId string
keyValuPars []struct {
key string
value string
}
err error
}{
{
name: "delete org metadata happy path",
ctx: Instance.WithAuthorization(context.Background(), integration.UserTypeIAMOwner),
setupFunc: func() {
_, err := Client.SetOrganizationMetadata(CTX, &v2beta_org.SetOrganizationMetadataRequest{
Id: orgId,
Metadata: []*v2beta_org.Metadata{
{
Key: "key1",
Value: []byte("value1"),
},
},
})
require.NoError(t, err)
},
orgId: orgId,
keyValuPars: []struct{ key, value string }{
{
key: "key1",
value: "value1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.setupFunc != nil {
tt.setupFunc()
}
// check metadata exists
listOrgMetadataRes, err := Client.ListOrganizationMetadata(tt.ctx, &v2beta_org.ListOrganizationMetadataRequest{
Id: tt.orgId,
})
require.NoError(t, err)
foundMetadataCount := 0
for _, kv := range tt.keyValuPars {
for _, res := range listOrgMetadataRes.Result {
if res.Key == kv.key &&
string(res.Value) == kv.value {
foundMetadataCount += 1
}
}
}
require.Equal(t, len(tt.keyValuPars), foundMetadataCount)
// run delete
_, err = Client.DeleteOrganizationMetadata(tt.ctx, &v2beta_org.DeleteOrganizationMetadataRequest{
Id: tt.orgId,
})
if tt.err != nil {
require.Contains(t, err.Error(), tt.err.Error())
return
}
require.NoError(t, err)
// check metadata was definitely deleted
listOrgMetadataRes, err = Client.ListOrganizationMetadata(tt.ctx, &v2beta_org.ListOrganizationMetadataRequest{
Id: tt.orgId,
})
require.NoError(t, err)
foundMetadataCount = 0
for _, kv := range tt.keyValuPars {
for _, res := range listOrgMetadataRes.Result {
if res.Key == kv.key &&
string(res.Value) == kv.value {
foundMetadataCount += 1
}
}
}
})
}
}
func assertCreatedAdmin(t *testing.T, expected, got *v2beta_org.CreateOrganizationResponse_CreatedAdmin) {
if expected.GetUserId() != "" {
assert.NotEmpty(t, got.GetUserId())

View File

@@ -3,6 +3,7 @@ package org
import (
"context"
metadata "github.com/zitadel/zitadel/internal/api/grpc/metadata/v2beta"
object "github.com/zitadel/zitadel/internal/api/grpc/object/v2beta"
user "github.com/zitadel/zitadel/internal/api/grpc/user/v2beta"
"github.com/zitadel/zitadel/internal/command"
@@ -70,6 +71,41 @@ func (s *Server) DeleteOrganization(ctx context.Context, request *v2beta_org.Del
}, nil
}
func (s *Server) SetOrganizationMetadata(ctx context.Context, request *v2beta_org.SetOrganizationMetadataRequest) (*v2beta_org.SetOrganizationMetadataResponse, error) {
result, err := s.command.BulkSetOrgMetadata(ctx, request.Id, BulkSetOrgMetadataToDomain(request)...)
if err != nil {
return nil, err
}
return &org.SetOrganizationMetadataResponse{
Details: object.DomainToDetailsPb(result),
}, nil
}
func (s *Server) ListOrganizationMetadata(ctx context.Context, request *v2beta_org.ListOrganizationMetadataRequest) (*v2beta_org.ListOrganizationMetadataResponse, error) {
metadataQueries, err := ListOrgMetadataToDomain(request)
if err != nil {
return nil, err
}
res, err := s.query.SearchOrgMetadata(ctx, true, request.Id, metadataQueries, false)
if err != nil {
return nil, err
}
return &v2beta_org.ListOrganizationMetadataResponse{
Result: metadata.OrgMetadataListToPb(res.Metadata),
Details: object.ToListDetails(res.SearchResponse),
}, nil
}
func (s *Server) DeleteOrganizationMetadata(ctx context.Context, request *v2beta_org.DeleteOrganizationMetadataRequest) (*v2beta_org.DeleteOrganizationMetadataResponse, error) {
result, err := s.command.BulkRemoveOrgMetadata(ctx, request.Id, request.Keys...)
if err != nil {
return nil, err
}
return &v2beta_org.DeleteOrganizationMetadataResponse{
Details: object.DomainToChangeDetailsPb(result),
}, 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 {

View File

@@ -42,6 +42,7 @@ func (c *Commands) prepareAddOrgDomain(a *org.Aggregate, addDomain string, userI
return nil, err
}
events := []eventstore.Command{org.NewDomainAddedEvent(ctx, &a.Aggregate, addDomain)}
fmt.Printf("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> domainPolicy = %+v\n", domainPolicy)
if !domainPolicy.ValidateOrgDomains {
events = append(events, org.NewDomainVerifiedEvent(ctx, &a.Aggregate, addDomain))
for _, userID := range userIDs {
@@ -133,7 +134,9 @@ func (c *Commands) AddOrgDomain(ctx context.Context, orgID, domain string, claim
if err != nil {
return nil, err
}
fmt.Printf("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> cmds[0] = %+v\n", cmds[0])
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
fmt.Printf("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> pushedEvents = %+v\n", pushedEvents[0])
if err != nil {
return nil, err
}

View File

@@ -7,6 +7,7 @@ import "zitadel/object/v2beta/object.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/user/v2beta/auth.proto";
import "zitadel/org/v2beta/org.proto";
import "zitadel/metadata/v2beta/metadata.proto";
import "zitadel/user/v2beta/user_service.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
@@ -266,9 +267,9 @@ service OrganizationService {
};
}
rpc DeactivateOrganization(DeactivateOrganizationRequest) returns (DeactivateOrganizationResponse) {
rpc SetOrganizationMetadata(SetOrganizationMetadataRequest) returns (SetOrganizationMetadataResponse) {
option (google.api.http) = {
post: "/v2beta/organization/_deactivate"
post: "/v2beta/organization/metadata"
body: "*"
};
@@ -283,8 +284,9 @@ service OrganizationService {
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."
tags: "Organization Metadata";
summary: "Set Organization Metadata";
description: "This endpoint either adds or updates a metadata value for the requested key. Make sure the value is base64 encoded."
parameters: {
headers: {
name: "x-zitadel-orgid";
@@ -296,12 +298,41 @@ service OrganizationService {
};
}
rpc ReactivateOrganization(ReactivateOrganizationRequest) returns (ReactivateOrganizationResponse) {
rpc ListOrganizationMetadata(ListOrganizationMetadataRequest) returns (ListOrganizationMetadataResponse ) {
option (google.api.http) = {
post: "/v2beta/organization/_reactivate"
post: "/v2beta/organization/metadata/_search"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = { auth_option: {
permission: "org.read"
}
http_response: {
success_code: 200
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "Organizations";
tags: "Organization Metadata";
summary: "Search Organization Metadata";
description: "List metadata of an organization filtered by your query."
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 DeleteOrganizationMetadata(DeleteOrganizationMetadataRequest) returns (DeleteOrganizationMetadataResponse) {
option (google.api.http) = {
delete: "/v2beta/organization/metadata"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "org.write"
@@ -313,8 +344,9 @@ service OrganizationService {
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."
tags: "Organization Metadata";
summary: "Delete Organization Metadata By Key";
description: "Delete metadata object from an organization with a specific key."
parameters: {
headers: {
name: "x-zitadel-orgid";
@@ -326,190 +358,6 @@ service OrganizationService {
};
}
// rpc SetOrganizationMetadata(SetOrganizationMetadataRequest) returns (SetOrganizationMetadataResponse) {
// option (google.api.http) = {
// post: "/v2beta/organization//metadata/{key}"
// 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";
// tags: "Organization Metadata";
// summary: "Set Organization Metadata";
// description: "This endpoint either adds or updates a metadata value for the requested key. Make sure the value is base64 encoded."
// 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 BulkSetOrganizationMetadata(BulkSetOrganizationMetadataRequest) returns (BulkSetOrganizationMetadataResponse) {
// option (google.api.http) = {
// post: "/metadata/_bulk"
// body: "*"
// };
// option (zitadel.v1.auth_option) = {
// permission: "org.write"
// };
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
// tags: "Organizations";
// tags: "Organization Metadata";
// summary: "Bulk Set Organization Metadata";
// description: "This endpoint sets a list of metadata to the organization. Make sure the values are base64 encoded."
// 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 ListOrgMetadata(ListOrgMetadataRequest) returns (ListOrgMetadataResponse) {
// option (google.api.http) = {
// post: "/metadata/_search"
// body: "*"
// };
// option (zitadel.v1.auth_option) = {
// permission: "org.read"
// };
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
// tags: "Organizations";
// tags: "Organization Metadata";
// summary: "Search Organization Metadata";
// description: "Get the metadata of an organization filtered by your query."
// 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 GetOrgMetadata(GetOrgMetadataRequest) returns (GetOrgMetadataResponse) {
// option (google.api.http) = {
// get: "/metadata/{key}"
// };
// option (zitadel.v1.auth_option) = {
// permission: "org.read"
// };
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
// tags: "Organizations";
// tags: "Organization Metadata";
// summary: "Get Organization Metadata By Key";
// description: "Get a metadata object from an organization by a specific key."
// 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 RemoveOrgMetadata(RemoveOrgMetadataRequest) returns (RemoveOrgMetadataResponse) {
// option (google.api.http) = {
// delete: "/metadata/{key}"
// };
// option (zitadel.v1.auth_option) = {
// permission: "org.write"
// };
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
// tags: "Organizations";
// tags: "Organization Metadata";
// summary: "Delete Organization Metadata By Key";
// description: "Remove a metadata object from an organization with a specific key."
// 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 BulkRemoveOrgMetadata(BulkRemoveOrgMetadataRequest) returns (BulkRemoveOrgMetadataResponse) {
// option (google.api.http) = {
// delete: "/metadata/_bulk"
// body: "*"
// };
// option (zitadel.v1.auth_option) = {
// permission: "org.write"
// };
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
// tags: "Organizations";
// tags: "Organization Metadata";
// summary: "Bulk Delete Metadata";
// description: "Remove a list of metadata objects from an organization with a list of keys."
// parameters: {
// headers: {
// name: "x-zitadel-orgid";
// description: "The default is always the organization of the requesting user. If you like to get/set a result of another organization include the header. Make sure the user has permission to access the requested data.";
// type: STRING,
// required: false;
// };
// };
// };
// }
// rpc ListOrganizationDomains(ListOrganizationDomainsRequest) returns (ListOrganizationDomainsResponse) {
// option (google.api.http) = {
// post: "/orgs/me/domains/_search"
// body: "*"
// };
// option (zitadel.v1.auth_option) = {
// permission: "org.read"
// };
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
// tags: "Organizations";
// summary: "Search Domains";
// description: "Returns the list of registered domains of an organization. The domains are used to identify to which organization a user belongs."
// parameters: {
// headers: {
// name: "x-zitadel-orgid";
// description: "The default is always the organization of the requesting user. If you like to get/set a result of another organization include the header. Make sure the user has permission to access the requested data.";
// type: STRING,
// required: false;
// };
// };
// };
// }
rpc AddOrganizationDomain(AddOrganizationDomainRequest) returns (AddOrganizationDomainResponse) {
option (google.api.http) = {
post: "/v2beta/organization/domains"
@@ -659,6 +507,66 @@ service OrganizationService {
};
}
rpc DeactivateOrganization(DeactivateOrganizationRequest) returns (DeactivateOrganizationResponse) {
option (google.api.http) = {
post: "/v2beta/organization/_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: "/v2beta/organization/_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{
@@ -813,30 +721,6 @@ message ReactivateOrganizationResponse {
zitadel.object.v2beta.Details details = 1;
}
// message SetOrganizationMetadataRequest {
// string key = 1 [
// (validate.rules).string = {min_len: 1, max_len: 200},
// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
// example: "\"key1\"";
// min_length: 1,
// max_length: 200;
// }
// ];
// bytes value = 2 [
// (validate.rules).bytes = {min_len: 1, max_len: 500000},
// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
// description: "The value has to be base64 encoded.";
// example: "\"VGhpcyBpcyBteSB0ZXN0IHZhbHVl\"";
// min_length: 1,
// max_length: 500000;
// }
// ];
// }
// message SetOrganizationMetadataResponse {
// zitadel.v1.ObjectDetails details = 1;
// }
message AddOrganizationDomainRequest {
string organization_id = 1;
string domain = 2 [
@@ -927,3 +811,46 @@ message VerifyOrganizationDomainRequest {
message VerifyOrganizationDomainResponse {
zitadel.object.v2beta.Details details = 1;
}
message Metadata {
string key = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
bytes value = 2 [(validate.rules).bytes = {min_len: 1, max_len: 500000}];
}
message SetOrganizationMetadataRequest{
string id = 1;
repeated Metadata metadata = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
title: "Medata (Key/Value)"
description: "The values have to be base64 encoded.";
example: "[{\"key\": \"test1\", \"value\": \"VGhpcyBpcyBteSBmaXJzdCB2YWx1ZQ==\"}, {\"key\": \"test2\", \"value\": \"VGhpcyBpcyBteSBzZWNvbmQgdmFsdWU=\"}]"
}
];
}
message SetOrganizationMetadataResponse{
zitadel.object.v2beta.Details details = 1;
}
message ListOrganizationMetadataRequest {
string id = 1;
zitadel.object.v2beta.ListQuery query = 2;
repeated zitadel.metadata.v2beta.MetadataQuery queries = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
title: "Medata Query"
description: "Metadata object-specific queries."
}];
}
message ListOrganizationMetadataResponse {
zitadel.object.v2beta.ListDetails details = 1;
repeated zitadel.metadata.v2beta.Metadata result = 2;
}
message DeleteOrganizationMetadataRequest {
string id = 1;
repeated string keys = 2 [(validate.rules).repeated.items.string = {min_len: 1, max_len: 200}];
}
message DeleteOrganizationMetadataResponse{
zitadel.object.v2beta.Details details = 1;
}