mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-23 03:57:18 +00:00
# Which Problems Are Solved As part of our efforts to simplify the structure and versions of our APIs, were moving all existing v2beta endpoints to v2 and deprecate them. They will be removed in Zitadel V5. # How the Problems Are Solved - This PR moves the remaining organization v2beta service endpoints to a corresponding v2 version. The v2beta service and all endpoints are deprecated. - The v2beta endpoints are removed from the docs. - The comments and have been improved and, where not already done, moved from swagger annotations to proto. - When listing Organizations can now be sorted by creation date as well. - The custom `org_id` parameter in the `AddOrganizationRequest` message has been deprecated in favor of `organization_id` # Additional Changes None # Additional Context - relates to #10772 - Directly targeting v4.x since main needs to be cleaned up first with the relation table and permission checks.
260 lines
9.9 KiB
Go
260 lines
9.9 KiB
Go
package org
|
|
|
|
import (
|
|
"context"
|
|
|
|
"connectrpc.com/connect"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
|
"github.com/zitadel/zitadel/internal/api/grpc/user/v2"
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
"github.com/zitadel/zitadel/pkg/grpc/org/v2"
|
|
)
|
|
|
|
func (s *Server) AddOrganization(ctx context.Context, request *connect.Request[org.AddOrganizationRequest]) (*connect.Response[org.AddOrganizationResponse], error) {
|
|
orgSetup, err := addOrganizationRequestToCommand(request.Msg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
createdOrg, err := s.command.SetUpOrg(ctx, orgSetup, false, s.command.CheckPermissionOrganizationCreate)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return createdOrganizationToPb(createdOrg)
|
|
}
|
|
|
|
func (s *Server) UpdateOrganization(ctx context.Context, request *connect.Request[org.UpdateOrganizationRequest]) (*connect.Response[org.UpdateOrganizationResponse], error) {
|
|
organization, err := s.command.ChangeOrg(ctx, request.Msg.GetOrganizationId(), request.Msg.GetName(), s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return connect.NewResponse(&org.UpdateOrganizationResponse{
|
|
ChangeDate: timestamppb.New(organization.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) DeleteOrganization(ctx context.Context, request *connect.Request[org.DeleteOrganizationRequest]) (*connect.Response[org.DeleteOrganizationResponse], error) {
|
|
details, err := s.command.RemoveOrg(ctx, request.Msg.GetOrganizationId(), s.command.CheckPermissionOrganizationDelete, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.DeleteOrganizationResponse{
|
|
DeletionDate: timestamppb.New(details.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) SetOrganizationMetadata(ctx context.Context, request *connect.Request[org.SetOrganizationMetadataRequest]) (*connect.Response[org.SetOrganizationMetadataResponse], error) {
|
|
result, err := s.command.BulkSetOrgMetadata(ctx, request.Msg.GetOrganizationId(), s.command.CheckPermissionOrganizationWrite, bulkSetOrgMetadataToDomain(request.Msg)...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.SetOrganizationMetadataResponse{
|
|
SetDate: timestamppb.New(result.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) DeleteOrganizationMetadata(ctx context.Context, request *connect.Request[org.DeleteOrganizationMetadataRequest]) (*connect.Response[org.DeleteOrganizationMetadataResponse], error) {
|
|
result, err := s.command.BulkRemoveOrgMetadata(ctx, request.Msg.GetOrganizationId(), s.command.CheckPermissionOrganizationWrite, request.Msg.Keys...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.DeleteOrganizationMetadataResponse{
|
|
DeletionDate: timestamppb.New(result.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) DeactivateOrganization(ctx context.Context, request *connect.Request[org.DeactivateOrganizationRequest]) (*connect.Response[org.DeactivateOrganizationResponse], error) {
|
|
objectDetails, err := s.command.DeactivateOrg(ctx, request.Msg.GetOrganizationId(), s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.DeactivateOrganizationResponse{
|
|
ChangeDate: timestamppb.New(objectDetails.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) ActivateOrganization(ctx context.Context, request *connect.Request[org.ActivateOrganizationRequest]) (*connect.Response[org.ActivateOrganizationResponse], error) {
|
|
objectDetails, err := s.command.ReactivateOrg(ctx, request.Msg.GetOrganizationId(), s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.ActivateOrganizationResponse{
|
|
ChangeDate: timestamppb.New(objectDetails.EventDate),
|
|
}), err
|
|
}
|
|
|
|
func (s *Server) AddOrganizationDomain(ctx context.Context, request *connect.Request[org.AddOrganizationDomainRequest]) (*connect.Response[org.AddOrganizationDomainResponse], error) {
|
|
userIDs, err := s.getClaimedUserIDsOfOrgDomain(ctx, request.Msg.GetDomain(), request.Msg.GetOrganizationId())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
details, err := s.command.AddOrgDomain(ctx, request.Msg.GetOrganizationId(), request.Msg.GetDomain(), userIDs, s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.AddOrganizationDomainResponse{
|
|
CreationDate: timestamppb.New(details.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) DeleteOrganizationDomain(ctx context.Context, req *connect.Request[org.DeleteOrganizationDomainRequest]) (*connect.Response[org.DeleteOrganizationDomainResponse], error) {
|
|
details, err := s.command.RemoveOrgDomain(ctx, removeOrgDomainRequestToDomain(req.Msg), s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.DeleteOrganizationDomainResponse{
|
|
DeletionDate: timestamppb.New(details.EventDate),
|
|
}), err
|
|
}
|
|
|
|
func (s *Server) GenerateOrganizationDomainValidation(ctx context.Context, req *connect.Request[org.GenerateOrganizationDomainValidationRequest]) (*connect.Response[org.GenerateOrganizationDomainValidationResponse], error) {
|
|
token, url, err := s.command.GenerateOrgDomainValidation(ctx, generateOrgDomainValidationRequestToDomain(req.Msg), s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.GenerateOrganizationDomainValidationResponse{
|
|
Token: token,
|
|
Url: url,
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) VerifyOrganizationDomain(ctx context.Context, request *connect.Request[org.VerifyOrganizationDomainRequest]) (*connect.Response[org.VerifyOrganizationDomainResponse], error) {
|
|
userIDs, err := s.getClaimedUserIDsOfOrgDomain(ctx, request.Msg.GetDomain(), request.Msg.GetOrganizationId())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
details, err := s.command.ValidateOrgDomain(ctx, validateOrgDomainRequestToDomain(request.Msg), userIDs, s.command.CheckPermissionOrganizationWrite)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connect.NewResponse(&org.VerifyOrganizationDomainResponse{
|
|
ChangeDate: timestamppb.New(details.EventDate),
|
|
}), nil
|
|
}
|
|
|
|
func addOrganizationRequestToCommand(request *org.AddOrganizationRequest) (*command.OrgSetup, error) {
|
|
admins, err := addOrganizationRequestAdminsToCommand(request.GetAdmins())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &command.OrgSetup{
|
|
Name: request.GetName(),
|
|
CustomDomain: "",
|
|
Admins: admins,
|
|
OrgID: request.GetOrgId(),
|
|
}, nil
|
|
}
|
|
|
|
func addOrganizationRequestAdminsToCommand(requestAdmins []*org.AddOrganizationRequest_Admin) (admins []*command.OrgSetupAdmin, err error) {
|
|
admins = make([]*command.OrgSetupAdmin, len(requestAdmins))
|
|
for i, admin := range requestAdmins {
|
|
admins[i], err = addOrganizationRequestAdminToCommand(admin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return admins, nil
|
|
}
|
|
|
|
func addOrganizationRequestAdminToCommand(admin *org.AddOrganizationRequest_Admin) (*command.OrgSetupAdmin, error) {
|
|
switch a := admin.GetUserType().(type) {
|
|
case *org.AddOrganizationRequest_Admin_UserId:
|
|
return &command.OrgSetupAdmin{
|
|
ID: a.UserId,
|
|
Roles: admin.GetRoles(),
|
|
}, nil
|
|
case *org.AddOrganizationRequest_Admin_Human:
|
|
human, err := user.AddUserRequestToAddHuman(a.Human)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &command.OrgSetupAdmin{
|
|
Human: human,
|
|
Roles: admin.GetRoles(),
|
|
}, nil
|
|
default:
|
|
return nil, zerrors.ThrowUnimplementedf(nil, "ORGv2-SD2r1", "userType oneOf %T in method AddOrganization not implemented", a)
|
|
}
|
|
}
|
|
|
|
func createdOrganizationToPb(createdOrg *command.CreatedOrg) (_ *connect.Response[org.AddOrganizationResponse], err error) {
|
|
admins := make([]*org.AddOrganizationResponse_CreatedAdmin, 0, len(createdOrg.OrgAdmins))
|
|
for _, admin := range createdOrg.OrgAdmins {
|
|
admin, ok := admin.(*command.CreatedOrgAdmin)
|
|
if ok {
|
|
admins = append(admins, &org.AddOrganizationResponse_CreatedAdmin{
|
|
UserId: admin.GetID(),
|
|
EmailCode: admin.EmailCode,
|
|
PhoneCode: admin.PhoneCode,
|
|
})
|
|
}
|
|
}
|
|
return connect.NewResponse(&org.AddOrganizationResponse{
|
|
Details: object.DomainToDetailsPb(createdOrg.ObjectDetails),
|
|
OrganizationId: createdOrg.ObjectDetails.ResourceOwner,
|
|
CreatedAdmins: admins,
|
|
}), nil
|
|
}
|
|
|
|
func (s *Server) getClaimedUserIDsOfOrgDomain(ctx context.Context, orgDomain, orgID string) ([]string, error) {
|
|
return s.query.SearchClaimedUserIDsOfOrgDomain(ctx, orgDomain, orgID)
|
|
}
|
|
|
|
func bulkSetOrgMetadataToDomain(req *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 removeOrgDomainRequestToDomain(req *org.DeleteOrganizationDomainRequest) *domain.OrgDomain {
|
|
return &domain.OrgDomain{
|
|
ObjectRoot: models.ObjectRoot{
|
|
AggregateID: req.OrganizationId,
|
|
},
|
|
Domain: req.Domain,
|
|
}
|
|
}
|
|
|
|
func generateOrgDomainValidationRequestToDomain(req *org.GenerateOrganizationDomainValidationRequest) *domain.OrgDomain {
|
|
return &domain.OrgDomain{
|
|
ObjectRoot: models.ObjectRoot{
|
|
AggregateID: req.OrganizationId,
|
|
},
|
|
Domain: req.Domain,
|
|
ValidationType: domainValidationTypeToDomain(req.Type),
|
|
}
|
|
}
|
|
|
|
func domainValidationTypeToDomain(validationType org.DomainValidationType) domain.OrgDomainValidationType {
|
|
switch validationType {
|
|
case org.DomainValidationType_DOMAIN_VALIDATION_TYPE_HTTP:
|
|
return domain.OrgDomainValidationTypeHTTP
|
|
case org.DomainValidationType_DOMAIN_VALIDATION_TYPE_DNS:
|
|
return domain.OrgDomainValidationTypeDNS
|
|
case org.DomainValidationType_DOMAIN_VALIDATION_TYPE_UNSPECIFIED:
|
|
return domain.OrgDomainValidationTypeUnspecified
|
|
default:
|
|
return domain.OrgDomainValidationTypeUnspecified
|
|
}
|
|
}
|
|
|
|
func validateOrgDomainRequestToDomain(req *org.VerifyOrganizationDomainRequest) *domain.OrgDomain {
|
|
return &domain.OrgDomain{
|
|
ObjectRoot: models.ObjectRoot{
|
|
AggregateID: req.OrganizationId,
|
|
},
|
|
Domain: req.Domain,
|
|
}
|
|
}
|