Files
zitadel/internal/api/grpc/admin/org.go
Silvan 1470ae08fc fix: query organization directly from event store (#10463)
Querying an organization by id allowed to trigger the org projection.
This could lead to performance impacts if the projection gets triggered
too often.

Instead of executing the trigger the organization by id query is now
always executed on the eventstore and reduces all event types required
of the organization requested.

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
2025-08-12 11:47:00 +02:00

108 lines
3.5 KiB
Go

package admin
import (
"context"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/grpc/object"
org_grpc "github.com/zitadel/zitadel/internal/api/grpc/org"
http_utils "github.com/zitadel/zitadel/internal/api/http"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
)
func (s *Server) IsOrgUnique(ctx context.Context, req *admin_pb.IsOrgUniqueRequest) (*admin_pb.IsOrgUniqueResponse, error) {
isUnique, err := s.query.IsOrgUnique(ctx, req.Name, req.Domain)
return &admin_pb.IsOrgUniqueResponse{IsUnique: isUnique}, err
}
func (s *Server) SetDefaultOrg(ctx context.Context, req *admin_pb.SetDefaultOrgRequest) (*admin_pb.SetDefaultOrgResponse, error) {
details, err := s.command.SetDefaultOrg(ctx, req.OrgId)
if err != nil {
return nil, err
}
return &admin_pb.SetDefaultOrgResponse{
Details: object.DomainToChangeDetailsPb(details),
}, nil
}
func (s *Server) RemoveOrg(ctx context.Context, req *admin_pb.RemoveOrgRequest) (*admin_pb.RemoveOrgResponse, error) {
details, err := s.command.RemoveOrg(ctx, req.OrgId)
if err != nil {
return nil, err
}
return &admin_pb.RemoveOrgResponse{
Details: object.DomainToChangeDetailsPb(details),
}, nil
}
func (s *Server) GetDefaultOrg(ctx context.Context, _ *admin_pb.GetDefaultOrgRequest) (*admin_pb.GetDefaultOrgResponse, error) {
org, err := s.query.OrgByID(ctx, authz.GetInstance(ctx).DefaultOrganisationID())
if err != nil {
return nil, err
}
return &admin_pb.GetDefaultOrgResponse{Org: org_grpc.OrgToPb(org)}, nil
}
func (s *Server) GetOrgByID(ctx context.Context, req *admin_pb.GetOrgByIDRequest) (*admin_pb.GetOrgByIDResponse, error) {
org, err := s.query.OrgByID(ctx, req.Id)
if err != nil {
return nil, err
}
return &admin_pb.GetOrgByIDResponse{Org: org_grpc.OrgViewToPb(org)}, nil
}
func (s *Server) ListOrgs(ctx context.Context, req *admin_pb.ListOrgsRequest) (*admin_pb.ListOrgsResponse, error) {
queries, err := listOrgRequestToModel(req)
if err != nil {
return nil, err
}
orgs, err := s.query.SearchOrgs(ctx, queries, nil)
if err != nil {
return nil, err
}
return &admin_pb.ListOrgsResponse{
Result: org_grpc.OrgViewsToPb(orgs.Orgs),
Details: object.ToListDetails(orgs.Count, orgs.Sequence, orgs.LastRun),
}, nil
}
func (s *Server) SetUpOrg(ctx context.Context, req *admin_pb.SetUpOrgRequest) (*admin_pb.SetUpOrgResponse, error) {
orgDomain, err := domain.NewIAMDomainName(req.Org.Name, http_utils.DomainContext(ctx).RequestedDomain())
if err != nil {
return nil, err
}
userIDs, err := s.getClaimedUserIDsOfOrgDomain(ctx, orgDomain)
if err != nil {
return nil, err
}
human := setUpOrgHumanToCommand(req.User.(*admin_pb.SetUpOrgRequest_Human_).Human) // TODO: handle machine
createdOrg, err := s.command.SetUpOrg(ctx, &command.OrgSetup{
Name: req.Org.Name,
CustomDomain: req.Org.Domain,
Admins: []*command.OrgSetupAdmin{
{
Human: human,
Roles: req.Roles,
},
},
}, true, userIDs...)
if err != nil {
return nil, err
}
var userID string
if len(createdOrg.OrgAdmins) == 1 {
userID = createdOrg.OrgAdmins[0].GetID()
}
return &admin_pb.SetUpOrgResponse{
Details: object.DomainToAddDetailsPb(createdOrg.ObjectDetails),
OrgId: createdOrg.ObjectDetails.ResourceOwner,
UserId: userID,
}, nil
}
func (s *Server) getClaimedUserIDsOfOrgDomain(ctx context.Context, orgDomain string) ([]string, error) {
return s.query.SearchClaimedUserIDsOfOrgDomain(ctx, orgDomain, "")
}