From c9985b56bcd3ade4beecc1f52278e9e573df3a4b Mon Sep 17 00:00:00 2001 From: Karan Balani <29383381+balanikaran@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:44:14 +0530 Subject: [PATCH] feat: add org id support in root user config (#10418) * feat: add org id support in root user config * chore: address review comments * fix: use zero value uuid for org id in example.conf --- conf/example.yaml | 1 + pkg/modules/user/config.go | 3 ++- pkg/modules/user/impluser/service.go | 37 ++++++++++++++++++++++++++++ pkg/types/organization.go | 15 +++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/conf/example.yaml b/conf/example.yaml index 90473624be..dbe5af3688 100644 --- a/conf/example.yaml +++ b/conf/example.yaml @@ -320,3 +320,4 @@ user: # The name of the organization to create or look up for the root user. org: name: default + id: 00000000-0000-0000-0000-000000000000 diff --git a/pkg/modules/user/config.go b/pkg/modules/user/config.go index 8cad422bf1..487ae5e687 100644 --- a/pkg/modules/user/config.go +++ b/pkg/modules/user/config.go @@ -22,7 +22,8 @@ type RootConfig struct { } type OrgConfig struct { - Name string `mapstructure:"name"` + ID valuer.UUID `mapstructure:"id"` + Name string `mapstructure:"name"` } type PasswordConfig struct { diff --git a/pkg/modules/user/impluser/service.go b/pkg/modules/user/impluser/service.go index 65bfe84b1a..6f345f0a18 100644 --- a/pkg/modules/user/impluser/service.go +++ b/pkg/modules/user/impluser/service.go @@ -78,6 +78,43 @@ func (s *service) Stop(ctx context.Context) error { } func (s *service) reconcile(ctx context.Context) error { + if !s.config.Org.ID.IsZero() { + return s.reconcileWithOrgID(ctx) + } + + return s.reconcileByName(ctx) +} + +func (s *service) reconcileWithOrgID(ctx context.Context) error { + org, err := s.orgGetter.Get(ctx, s.config.Org.ID) + if err != nil { + if !errors.Ast(err, errors.TypeNotFound) { + return err // something really went wrong + } + + // org was not found using id check if we can find an org using name + + existingOrgByName, nameErr := s.orgGetter.GetByName(ctx, s.config.Org.Name) + if nameErr != nil && !errors.Ast(nameErr, errors.TypeNotFound) { + return nameErr // something really went wrong + } + + // we found an org using name + if existingOrgByName != nil { + // the existing org has the same name as config but org id is different inform user with actionable message + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "organization with name %q already exists with a different ID %s (expected %s)", s.config.Org.Name, existingOrgByName.ID.StringValue(), s.config.Org.ID.StringValue()) + } + + // default - we did not found any org using id and name both - create a new org + newOrg := types.NewOrganizationWithID(s.config.Org.ID, s.config.Org.Name, s.config.Org.Name) + _, err = s.module.CreateFirstUser(ctx, newOrg, s.config.Email.String(), s.config.Email, s.config.Password) + return err + } + + return s.reconcileRootUser(ctx, org.ID) +} + +func (s *service) reconcileByName(ctx context.Context) error { org, err := s.orgGetter.GetByName(ctx, s.config.Org.Name) if err != nil { if errors.Ast(err, errors.TypeNotFound) { diff --git a/pkg/types/organization.go b/pkg/types/organization.go index 867234d478..be4ae47eb1 100644 --- a/pkg/types/organization.go +++ b/pkg/types/organization.go @@ -41,6 +41,21 @@ func NewOrganization(displayName string, name string) *Organization { } } +func NewOrganizationWithID(id valuer.UUID, displayName string, name string) *Organization { + return &Organization{ + Identifiable: Identifiable{ + ID: id, + }, + TimeAuditable: TimeAuditable{ + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + Name: name, + DisplayName: displayName, + Key: NewOrganizationKey(id), + } +} + func NewOrganizationKey(orgID valuer.UUID) uint32 { hasher := fnv.New32a()