mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:37:31 +00:00
feat: set up org (#1157)
* add setup steps * refactoring * omitempty * cleanup * begin org * create org * setup org * setup org * merge * fixes * fixes * fixes
This commit is contained in:
@@ -15,6 +15,7 @@ type CommandSide struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
iamID string
|
||||
iamDomain string
|
||||
|
||||
idpConfigSecretCrypto crypto.Crypto
|
||||
|
||||
@@ -37,6 +38,7 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
||||
eventstore: config.Eventstore,
|
||||
idGenerator: id.SonyFlakeGenerator,
|
||||
iamID: config.SystemDefaults.IamID,
|
||||
iamDomain: config.SystemDefaults.Domain,
|
||||
}
|
||||
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
//TODO: private
|
||||
func (r *CommandSide) GetIAM(ctx context.Context, aggregateID string) (*domain.IAM, error) {
|
||||
iamWriteModel := NewIAMWriteModel(aggregateID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, iamWriteModel)
|
||||
|
@@ -25,9 +25,9 @@ func writeModelToIAM(wm *IAMWriteModel) *domain.IAM {
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToMember(writeModel *IAMMemberWriteModel) *domain.IAMMember {
|
||||
return &domain.IAMMember{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.MemberWriteModel.WriteModel),
|
||||
func memberWriteModelToMember(writeModel *MemberWriteModel) *domain.Member {
|
||||
return &domain.Member{
|
||||
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
|
||||
Roles: writeModel.Roles,
|
||||
UserID: writeModel.UserID,
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ import (
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.IAMMember) (*domain.IAMMember, error) {
|
||||
func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
@@ -35,11 +35,11 @@ func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.IAMMember
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToMember(addedMember), nil
|
||||
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
//ChangeIAMMember updates an existing member
|
||||
func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.IAMMember) (*domain.IAMMember, error) {
|
||||
func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
@@ -67,7 +67,7 @@ func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *domain.IAMMem
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToMember(existingMember), nil
|
||||
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveIAMMember(ctx context.Context, userID string) error {
|
||||
|
@@ -8,17 +8,6 @@ import (
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
func (r *CommandSide) GetDefaultOrgIAMPolicy(ctx context.Context) (*domain.OrgIAMPolicy, error) {
|
||||
policyWriteModel := NewIAMOrgIAMPolicyWriteModel(r.iamID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := writeModelToOrgIAMPolicy(policyWriteModel)
|
||||
policy.Default = true
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddDefaultOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
policy.AggregateID = r.iamID
|
||||
addedPolicy := NewIAMOrgIAMPolicyWriteModel(policy.AggregateID)
|
||||
@@ -75,6 +64,16 @@ func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *dom
|
||||
return writeModelToOrgIAMPolicy(existingPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getDefaultOrgIAMPolicy(ctx context.Context) (*domain.OrgIAMPolicy, error) {
|
||||
policyWriteModel, err := r.defaultOrgIAMPolicyWriteModelByID(ctx, r.iamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy := writeModelToOrgIAMPolicy(policyWriteModel)
|
||||
policy.Default = true
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) defaultOrgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMOrgIAMPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
72
internal/v2/command/org.go
Normal file
72
internal/v2/command/org.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||
)
|
||||
|
||||
func (r *CommandSide) SetUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.User) error {
|
||||
orgAgg, userAgg, orgMemberAgg, err := r.setUpOrg(ctx, organisation, admin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.eventstore.PushAggregates(ctx, orgAgg, userAgg, orgMemberAgg)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) setUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.User) (*org.Aggregate, *user.Aggregate, *org.Aggregate, error) {
|
||||
orgAgg, _, err := r.addOrg(ctx, organisation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
userAgg, _, err := r.addHuman(ctx, orgAgg.ID(), admin.UserName, admin.Human)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
addedMember := NewOrgMemberWriteModel(orgAgg.ID(), userAgg.ID())
|
||||
orgMemberAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
|
||||
err = r.addOrgMember(ctx, orgMemberAgg, addedMember, domain.NewMember(orgMemberAgg.ID(), userAgg.ID(), domain.OrgOwnerRole)) //TODO: correct?
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return orgAgg, userAgg, orgMemberAgg, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrg(ctx context.Context, organisation *domain.Org) (_ *org.Aggregate, _ *OrgWriteModel, err error) {
|
||||
if organisation == nil || !organisation.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMM-deLSk", "Errors.Org.Invalid")
|
||||
}
|
||||
|
||||
organisation.AggregateID, err = r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, nil, caos_errs.ThrowInternal(err, "COMMA-OwciI", "Errors.Internal")
|
||||
}
|
||||
organisation.AddIAMDomain(r.iamDomain)
|
||||
addedOrg := NewOrgWriteModel(organisation.AggregateID)
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedOrg.WriteModel)
|
||||
//TODO: uniqueness org name
|
||||
orgAgg.PushEvents(org.NewOrgAddedEvent(ctx, organisation.Name))
|
||||
for _, orgDomain := range organisation.Domains {
|
||||
if err := r.addOrgDomain(ctx, orgAgg, NewOrgDomainWriteModel(orgAgg.ID(), orgDomain.Domain), orgDomain); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return orgAgg, addedOrg, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getOrgWriteModelByID(ctx context.Context, orgID string) (*OrgWriteModel, error) {
|
||||
orgWriteModel := NewOrgWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, orgWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgWriteModel, nil
|
||||
}
|
@@ -4,6 +4,14 @@ import (
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
func orgWriteModelToOrg(wm *OrgWriteModel) *domain.Org {
|
||||
return &domain.Org{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
Name: wm.Name,
|
||||
State: wm.State,
|
||||
}
|
||||
}
|
||||
|
||||
func orgWriteModelToOrgIAMPolicy(wm *ORGOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
||||
return &domain.OrgIAMPolicy{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
||||
@@ -21,3 +29,14 @@ func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWrit
|
||||
HasSymbol: wm.HasSymbol,
|
||||
}
|
||||
}
|
||||
|
||||
func orgDomainWriteModelToOrgDomain(wm *OrgDomainWriteModel) *domain.OrgDomain {
|
||||
return &domain.OrgDomain{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
Domain: wm.Domain,
|
||||
Primary: wm.Primary,
|
||||
Verified: wm.Verified,
|
||||
ValidationType: wm.ValidationType,
|
||||
ValidationCode: wm.ValidationCode,
|
||||
}
|
||||
}
|
||||
|
43
internal/v2/command/org_domain.go
Normal file
43
internal/v2/command/org_domain.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) (*domain.OrgDomain, error) {
|
||||
domainWriteModel := NewOrgDomainWriteModel(orgDomain.AggregateID, orgDomain.Domain)
|
||||
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
|
||||
err := r.addOrgDomain(ctx, orgAgg, domainWriteModel, orgDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orgDomainWriteModelToOrgDomain(domainWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *org.Aggregate, addedDomain *OrgDomainWriteModel, orgDomain *domain.OrgDomain) error {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if addedDomain.State == domain.OrgDomainStateActive {
|
||||
return caos_errs.ThrowAlreadyExists(nil, "COMMA-Bd2jj", "Errors.Org.Domain.AlreadyExists")
|
||||
}
|
||||
orgAgg.PushEvents(org.NewDomainAddedEvent(ctx, orgDomain.Domain))
|
||||
if orgDomain.Verified {
|
||||
//TODO: uniqueness verified domain
|
||||
//TODO: users with verified domain -> domain claimed
|
||||
orgAgg.PushEvents(org.NewDomainVerifiedEvent(ctx, orgDomain.Domain))
|
||||
}
|
||||
if orgDomain.Primary {
|
||||
orgAgg.PushEvents(org.NewDomainPrimarySetEvent(ctx, orgDomain.Domain))
|
||||
}
|
||||
return nil
|
||||
}
|
90
internal/v2/command/org_domain_model.go
Normal file
90
internal/v2/command/org_domain_model.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgDomainWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Domain string
|
||||
ValidationType domain.OrgDomainValidationType
|
||||
ValidationCode *crypto.CryptoValue
|
||||
Primary bool
|
||||
Verified bool
|
||||
|
||||
State domain.OrgDomainState
|
||||
}
|
||||
|
||||
func NewOrgDomainWriteModel(orgID string, domain string) *OrgDomainWriteModel {
|
||||
return &OrgDomainWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
},
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgDomainWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.DomainAddedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainVerificationAddedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainVerificationFailedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainVerifiedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainPrimarySetEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
case *org.DomainRemovedEvent:
|
||||
if e.Domain != wm.Domain {
|
||||
continue
|
||||
}
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgDomainWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *org.DomainAddedEvent:
|
||||
wm.Domain = e.Domain
|
||||
wm.State = domain.OrgDomainStateActive
|
||||
case *org.DomainVerificationAddedEvent:
|
||||
wm.ValidationType = e.ValidationType
|
||||
wm.ValidationCode = e.ValidationCode
|
||||
case *org.DomainVerificationFailedEvent:
|
||||
//TODO: not handled in v1
|
||||
case *org.DomainVerifiedEvent:
|
||||
wm.Verified = true
|
||||
case *org.DomainPrimarySetEvent:
|
||||
wm.Primary = e.Domain == wm.Domain
|
||||
case *org.DomainRemovedEvent:
|
||||
wm.State = domain.OrgDomainStateRemoved
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wm *OrgDomainWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID)
|
||||
}
|
112
internal/v2/command/org_member.go
Normal file
112
internal/v2/command/org_member.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddOrgMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
addedMember := NewOrgMemberWriteModel(member.AggregateID, member.UserID)
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
|
||||
err := r.addOrgMember(ctx, orgAgg, addedMember, member)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = r.eventstore.PushAggregate(ctx, addedMember, orgAgg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToMember(&addedMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrgMember(ctx context.Context, orgAgg *org.Aggregate, addedMember *OrgMemberWriteModel, member *domain.Member) error {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "Org-W8m4l", "Errors.Org.MemberInvalid")
|
||||
}
|
||||
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedMember)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if addedMember.State == domain.MemberStateActive {
|
||||
return errors.ThrowAlreadyExists(nil, "Org-PtXi1", "Errors.Org.Member.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg.PushEvents(org.NewMemberAddedEvent(ctx, member.UserID, member.Roles...))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//ChangeOrgMember updates an existing member
|
||||
func (r *CommandSide) ChangeOrgMember(ctx context.Context, member *domain.Member) (*domain.Member, error) {
|
||||
//TODO: check if roles valid
|
||||
|
||||
if !member.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-LiaZi", "Errors.Org.MemberInvalid")
|
||||
}
|
||||
|
||||
existingMember, err := r.orgMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-LiaZi", "Errors.Org.Member.RolesNotChanged")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
|
||||
orgAgg.PushEvents(org.NewMemberChangedEvent(ctx, member.UserID, member.Roles...))
|
||||
|
||||
events, err := r.eventstore.PushAggregates(ctx, orgAgg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingMember.AppendEvents(events...)
|
||||
if err = existingMember.Reduce(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberWriteModelToMember(&existingMember.MemberWriteModel), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveOrgMember(ctx context.Context, orgID, userID string) error {
|
||||
m, err := r.orgMemberWriteModelByID(ctx, orgID, userID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
|
||||
orgAgg.PushEvents(org.NewMemberRemovedEvent(ctx, userID))
|
||||
|
||||
return r.eventstore.PushAggregate(ctx, m, orgAgg)
|
||||
}
|
||||
|
||||
func (r *CommandSide) orgMemberWriteModelByID(ctx context.Context, orgID, userID string) (member *OrgMemberWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewOrgMemberWriteModel(orgID, userID)
|
||||
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||
return nil, errors.ThrowNotFound(nil, "Org-D8JxR", "Errors.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
@@ -1,5 +1,52 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
type OrgMemberWriteModel struct {
|
||||
MemberWriteModel
|
||||
}
|
||||
|
||||
func NewOrgMemberWriteModel(orgID, userID string) *OrgMemberWriteModel {
|
||||
return &OrgMemberWriteModel{
|
||||
MemberWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
},
|
||||
UserID: userID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.MemberAddedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
|
||||
case *org.MemberChangedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
|
||||
case *org.MemberRemovedEvent:
|
||||
if e.UserID != wm.MemberWriteModel.UserID {
|
||||
continue
|
||||
}
|
||||
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgMemberWriteModel) Reduce() error {
|
||||
return wm.MemberWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *OrgMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.MemberWriteModel.AggregateID)
|
||||
}
|
||||
|
@@ -2,10 +2,56 @@ package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func ORGAggregateFromWriteModel(wm *eventstore.WriteModel) *org.Aggregate {
|
||||
type OrgWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Name string
|
||||
State domain.OrgState
|
||||
}
|
||||
|
||||
func NewOrgWriteModel(orgID string) *OrgWriteModel {
|
||||
return &OrgWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
wm.WriteModel.AppendEvents(events...)
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.OrgAddedEvent,
|
||||
*iam.LabelPolicyChangedEvent:
|
||||
wm.WriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *OrgWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *org.OrgAddedEvent:
|
||||
wm.Name = e.Name
|
||||
wm.State = domain.OrgStateActive
|
||||
case *org.OrgChangedEvent:
|
||||
wm.Name = e.Name
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wm *OrgWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID)
|
||||
}
|
||||
|
||||
func OrgAggregateFromWriteModel(wm *eventstore.WriteModel) *org.Aggregate {
|
||||
return &org.Aggregate{
|
||||
Aggregate: *eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion),
|
||||
}
|
||||
|
@@ -5,32 +5,20 @@ import (
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
func (r *CommandSide) GetOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error) {
|
||||
policy := NewORGOrgIAMPolicyWriteModel(orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policy.State == domain.PolicyStateActive {
|
||||
return orgWriteModelToOrgIAMPolicy(policy), nil
|
||||
}
|
||||
return r.GetDefaultOrgIAMPolicy(ctx)
|
||||
}
|
||||
|
||||
func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
addedPolicy := NewORGOrgIAMPolicyWriteModel(policy.AggregateID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
err := r.addOrgIAMPolicy(ctx, orgAgg, addedPolicy, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||
}
|
||||
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
orgAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||
orgAgg.PushEvents(org.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||
|
||||
err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg)
|
||||
if err != nil {
|
||||
@@ -40,6 +28,18 @@ func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAM
|
||||
return orgWriteModelToOrgIAMPolicy(addedPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addOrgIAMPolicy(ctx context.Context, orgAgg *org.Aggregate, addedPolicy *ORGOrgIAMPolicyWriteModel, policy *domain.OrgIAMPolicy) error {
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||
}
|
||||
orgAgg.PushEvents(org.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAMPolicy) (*domain.OrgIAMPolicy, error) {
|
||||
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
|
||||
if err != nil {
|
||||
@@ -54,7 +54,7 @@ func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.Org
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
||||
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||
orgAgg.PushEvents(changedEvent)
|
||||
|
||||
err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg)
|
||||
@@ -65,6 +65,17 @@ func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.Org
|
||||
return orgWriteModelToOrgIAMPolicy(existingPolicy), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) getOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error) {
|
||||
policy, err := r.orgIAMPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policy.State == domain.PolicyStateActive {
|
||||
return orgWriteModelToOrgIAMPolicy(policy), nil
|
||||
}
|
||||
return r.getDefaultOrgIAMPolicy(ctx)
|
||||
}
|
||||
|
||||
func (r *CommandSide) orgIAMPolicyWriteModelByID(ctx context.Context, orgID string) (policy *ORGOrgIAMPolicyWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
@@ -48,8 +49,7 @@ type Org struct {
|
||||
Name string
|
||||
Domain string
|
||||
OrgIamPolicy bool
|
||||
Users []User
|
||||
Owners []string
|
||||
Owner User
|
||||
Projects []Project
|
||||
}
|
||||
|
||||
@@ -84,25 +84,60 @@ func (r *CommandSide) SetupStep1(ctx context.Context, iamID string, step1 *Step1
|
||||
return err
|
||||
}
|
||||
//create orgs
|
||||
//create projects
|
||||
//create applications
|
||||
aggregates := make([]eventstore.Aggregater, 0)
|
||||
for _, organisation := range step1.Orgs {
|
||||
orgAgg, userAgg, orgMemberAgg, err := r.setUpOrg(ctx,
|
||||
&domain.Org{
|
||||
Name: organisation.Name,
|
||||
Domains: []*domain.OrgDomain{{Domain: organisation.Domain}},
|
||||
},
|
||||
&domain.User{
|
||||
UserName: organisation.Owner.UserName,
|
||||
Human: &domain.Human{
|
||||
Profile: &domain.Profile{
|
||||
FirstName: organisation.Owner.FirstName,
|
||||
LastName: organisation.Owner.LastName,
|
||||
},
|
||||
Password: &domain.Password{
|
||||
SecretString: organisation.Owner.Password,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: organisation.Owner.Email,
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if organisation.OrgIamPolicy {
|
||||
err = r.addOrgIAMPolicy(ctx, orgAgg, NewORGOrgIAMPolicyWriteModel(orgAgg.ID()), &domain.OrgIAMPolicy{UserLoginMustBeDomain: false})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
aggregates = append(aggregates, orgAgg, userAgg, orgMemberAgg)
|
||||
//projects
|
||||
//create applications
|
||||
}
|
||||
|
||||
//set iam owners
|
||||
//set global org
|
||||
//set iam project id
|
||||
|
||||
/*aggregates:
|
||||
iam:
|
||||
default login policy
|
||||
iam owner
|
||||
org:
|
||||
default
|
||||
caos
|
||||
zitadel
|
||||
iam:
|
||||
default login policy
|
||||
iam owner
|
||||
org:
|
||||
default
|
||||
caos
|
||||
zitadel
|
||||
|
||||
*/
|
||||
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
|
||||
|
||||
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
|
||||
_, err = r.eventstore.PushAggregates(ctx, append(aggregates, iamAgg)...)
|
||||
if err != nil {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Gr2hh", "Setup Step1 failed")
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ func (r *CommandSide) ChangeUsername(ctx context.Context, orgID, userID, userNam
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.UsernameNotChanged")
|
||||
}
|
||||
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -2,37 +2,51 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||
)
|
||||
|
||||
func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, human *domain.Human) (*domain.Human, error) {
|
||||
userAgg, addedHuman, err := r.addHuman(ctx, orgID, username, human)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToHuman(addedHuman), nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) addHuman(ctx context.Context, orgID, username string, human *domain.Human) (*user.Aggregate, *HumanWriteModel, error) {
|
||||
if !human.IsValid() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
|
||||
}
|
||||
userID, err := r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
human.AggregateID = userID
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
addedHuman := NewHumanWriteModel(human.AggregateID)
|
||||
//TODO: Check Unique Username
|
||||
if err := human.CheckOrgIAMPolicy(username, orgIAMPolicy); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
human.SetNamesAsDisplayname()
|
||||
if err := human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||
@@ -66,7 +80,7 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma
|
||||
if human.IsInitialState() {
|
||||
initCode, err := domain.NewInitUserCode(r.initializeUserCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry)
|
||||
}
|
||||
@@ -76,19 +90,14 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma
|
||||
if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified {
|
||||
phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry)
|
||||
} else if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
|
||||
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
|
||||
}
|
||||
|
||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToHuman(addedHuman), nil
|
||||
return userAgg, addedHuman, nil
|
||||
}
|
||||
|
||||
func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string, human *domain.Human, externalIDP *domain.ExternalIDP) (*domain.Human, error) {
|
||||
@@ -100,7 +109,7 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string,
|
||||
return nil, err
|
||||
}
|
||||
human.AggregateID = userID
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ func (r *CommandSide) AddMachine(ctx context.Context, orgID, username string, ma
|
||||
}
|
||||
//TODO: Check Unique username
|
||||
machine.AggregateID = userID
|
||||
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -15,6 +15,12 @@ type Password struct {
|
||||
ChangeRequired bool
|
||||
}
|
||||
|
||||
func NewPassword(password string) *Password {
|
||||
return &Password{
|
||||
SecretString: password,
|
||||
}
|
||||
}
|
||||
|
||||
type PasswordCode struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
|
@@ -11,7 +11,7 @@ type IAM struct {
|
||||
IAMProjectID string
|
||||
SetUpDone Step
|
||||
SetUpStarted Step
|
||||
Members []*IAMMember
|
||||
Members []*Member
|
||||
IDPs []*IDPConfig
|
||||
DefaultLoginPolicy *LoginPolicy
|
||||
DefaultLabelPolicy *LabelPolicy
|
||||
|
@@ -4,14 +4,24 @@ import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type IAMMember struct {
|
||||
type Member struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
UserID string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
func (i *IAMMember) IsValid() bool {
|
||||
func NewMember(aggregateID, userID string, roles ...string) *Member {
|
||||
return &Member{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: aggregateID,
|
||||
},
|
||||
UserID: userID,
|
||||
Roles: roles,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Member) IsValid() bool {
|
||||
return i.AggregateID != "" && i.UserID != "" && len(i.Roles) != 0
|
||||
}
|
||||
|
43
internal/v2/domain/org.go
Normal file
43
internal/v2/domain/org.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type Org struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State OrgState
|
||||
Name string
|
||||
|
||||
Domains []*OrgDomain
|
||||
Members []*Member
|
||||
OrgIamPolicy *OrgIAMPolicy
|
||||
LoginPolicy *LoginPolicy
|
||||
LabelPolicy *LabelPolicy
|
||||
PasswordComplexityPolicy *PasswordComplexityPolicy
|
||||
PasswordAgePolicy *PasswordAgePolicy
|
||||
PasswordLockoutPolicy *PasswordLockoutPolicy
|
||||
IDPs []*IDPConfig
|
||||
}
|
||||
|
||||
func (o *Org) IsValid() bool {
|
||||
return o.Name != ""
|
||||
}
|
||||
|
||||
func (o *Org) AddIAMDomain(iamDomain string) {
|
||||
o.Domains = append(o.Domains, &OrgDomain{Domain: o.nameForDomain(iamDomain), Verified: true, Primary: true})
|
||||
}
|
||||
|
||||
func (o *Org) nameForDomain(iamDomain string) string {
|
||||
return strings.ToLower(strings.ReplaceAll(o.Name, " ", "-") + "." + iamDomain)
|
||||
}
|
||||
|
||||
type OrgState int32
|
||||
|
||||
const (
|
||||
OrgStateActive OrgState = iota
|
||||
OrgStateInactive
|
||||
)
|
38
internal/v2/domain/org_domain.go
Normal file
38
internal/v2/domain/org_domain.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type OrgDomain struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Domain string
|
||||
Primary bool
|
||||
Verified bool
|
||||
ValidationType OrgDomainValidationType
|
||||
ValidationCode *crypto.CryptoValue
|
||||
}
|
||||
|
||||
type OrgDomainValidationType int32
|
||||
|
||||
const (
|
||||
OrgDomainValidationTypeUnspecified OrgDomainValidationType = iota
|
||||
OrgDomainValidationTypeHTTP
|
||||
OrgDomainValidationTypeDNS
|
||||
)
|
||||
|
||||
type OrgDomainState int32
|
||||
|
||||
const (
|
||||
OrgDomainStateUnspecified OrgDomainState = iota
|
||||
OrgDomainStateActive
|
||||
OrgDomainStateRemoved
|
||||
|
||||
orgDomainStateCount
|
||||
)
|
||||
|
||||
func (f OrgDomainState) Valid() bool {
|
||||
return f >= 0 && f < orgDomainStateCount
|
||||
}
|
5
internal/v2/domain/roles.go
Normal file
5
internal/v2/domain/roles.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package domain
|
||||
|
||||
const (
|
||||
OrgOwnerRole = "ORG_OWNER"
|
||||
)
|
222
internal/v2/repository/org/domain.go
Normal file
222
internal/v2/repository/org/domain.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
domainEventPrefix = orgEventTypePrefix + "domain."
|
||||
OrgDomainAdded = domainEventPrefix + "added"
|
||||
OrgDomainVerificationAdded = domainEventPrefix + "verification.added"
|
||||
OrgDomainVerificationFailed = domainEventPrefix + "verification.failed"
|
||||
OrgDomainVerified = domainEventPrefix + "verified"
|
||||
OrgDomainPrimarySet = domainEventPrefix + "primary.set"
|
||||
OrgDomainRemoved = domainEventPrefix + "removed"
|
||||
)
|
||||
|
||||
type DomainAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
func (e *DomainAddedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewDomainAddedEvent(ctx context.Context, domain string) *DomainAddedEvent {
|
||||
return &DomainAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgDomainAdded,
|
||||
),
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func DomainAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgDomainAdded := &DomainAddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgDomainAdded)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-GBr52", "unable to unmarshal org domain added")
|
||||
}
|
||||
|
||||
return orgDomainAdded, nil
|
||||
}
|
||||
|
||||
type DomainVerificationAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Domain string `json:"domain,omitempty"`
|
||||
ValidationType domain.OrgDomainValidationType `json:"validationType,omitempty"`
|
||||
ValidationCode *crypto.CryptoValue `json:"validationCode,omitempty"`
|
||||
}
|
||||
|
||||
func (e *DomainVerificationAddedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewDomainVerificationAddedEvent(
|
||||
ctx context.Context,
|
||||
domain string,
|
||||
validationType domain.OrgDomainValidationType,
|
||||
validationCode *crypto.CryptoValue) *DomainVerificationAddedEvent {
|
||||
return &DomainVerificationAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgDomainVerificationAdded,
|
||||
),
|
||||
Domain: domain,
|
||||
ValidationType: validationType,
|
||||
ValidationCode: validationCode,
|
||||
}
|
||||
}
|
||||
|
||||
func DomainVerificationAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgDomainVerificationAdded := &DomainVerificationAddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgDomainVerificationAdded)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-NRN32", "unable to unmarshal org domain verification added")
|
||||
}
|
||||
|
||||
return orgDomainVerificationAdded, nil
|
||||
}
|
||||
|
||||
type DomainVerificationFailedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
func (e *DomainVerificationFailedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewDomainVerificationFailedEvent(ctx context.Context, domain string) *DomainVerificationFailedEvent {
|
||||
return &DomainVerificationFailedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgDomainVerificationFailed,
|
||||
),
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func DomainVerificationFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgDomainVerificationFailed := &DomainVerificationFailedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgDomainVerificationFailed)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-Bhm37", "unable to unmarshal org domain verification failed")
|
||||
}
|
||||
|
||||
return orgDomainVerificationFailed, nil
|
||||
}
|
||||
|
||||
type DomainVerifiedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
func (e *DomainVerifiedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewDomainVerifiedEvent(ctx context.Context, domain string) *DomainVerifiedEvent {
|
||||
return &DomainVerifiedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgDomainVerified,
|
||||
),
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func DomainVerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgDomainVerified := &DomainVerifiedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgDomainVerified)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-BFSwt", "unable to unmarshal org domain verified")
|
||||
}
|
||||
|
||||
return orgDomainVerified, nil
|
||||
}
|
||||
|
||||
type DomainPrimarySetEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
func (e *DomainPrimarySetEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewDomainPrimarySetEvent(ctx context.Context, domain string) *DomainPrimarySetEvent {
|
||||
return &DomainPrimarySetEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgDomainPrimarySet,
|
||||
),
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func DomainPrimarySetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgDomainPrimarySet := &DomainPrimarySetEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgDomainPrimarySet)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-N5787", "unable to unmarshal org domain primary set")
|
||||
}
|
||||
|
||||
return orgDomainPrimarySet, nil
|
||||
}
|
||||
|
||||
type DomainRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
func (e *DomainRemovedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewDomainRemovedEvent(ctx context.Context, domain string) *DomainRemovedEvent {
|
||||
return &DomainRemovedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgDomainRemoved,
|
||||
),
|
||||
Domain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
func DomainRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgDomainRemoved := &DomainRemovedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgDomainRemoved)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-BngB2", "unable to unmarshal org domain removed")
|
||||
}
|
||||
|
||||
return orgDomainRemoved, nil
|
||||
}
|
19
internal/v2/repository/org/eventstore.go
Normal file
19
internal/v2/repository/org/eventstore.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
)
|
||||
|
||||
func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
es.RegisterFilterEventMapper(OrgAdded, OrgAddedEventMapper).
|
||||
RegisterFilterEventMapper(OrgChanged, OrgChangedEventMapper).
|
||||
//RegisterFilterEventMapper(OrgDeactivated, OrgChangedEventMapper). TODO: !
|
||||
//RegisterFilterEventMapper(OrgReactivated, OrgChangedEventMapper).
|
||||
//RegisterFilterEventMapper(OrgRemoved, OrgChangedEventMapper).
|
||||
RegisterFilterEventMapper(OrgDomainAdded, DomainAddedEventMapper).
|
||||
RegisterFilterEventMapper(OrgDomainVerificationAdded, DomainVerificationAddedEventMapper).
|
||||
RegisterFilterEventMapper(OrgDomainVerificationFailed, DomainVerificationFailedEventMapper).
|
||||
RegisterFilterEventMapper(OrgDomainVerified, DomainVerifiedEventMapper).
|
||||
RegisterFilterEventMapper(OrgDomainPrimarySet, DomainPrimarySetEventMapper).
|
||||
RegisterFilterEventMapper(OrgDomainRemoved, DomainRemovedEventMapper)
|
||||
}
|
82
internal/v2/repository/org/org.go
Normal file
82
internal/v2/repository/org/org.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
OrgAdded = orgEventTypePrefix + "added"
|
||||
OrgChanged = orgEventTypePrefix + "changed"
|
||||
OrgDeactivated = orgEventTypePrefix + "deactivated"
|
||||
OrgReactivated = orgEventTypePrefix + "reactivated"
|
||||
OrgRemoved = orgEventTypePrefix + "removed"
|
||||
)
|
||||
|
||||
type OrgAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (e *OrgAddedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewOrgAddedEvent(ctx context.Context, name string) *OrgAddedEvent {
|
||||
return &OrgAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgAdded,
|
||||
),
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func OrgAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgAdded := &OrgAddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgAdded)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-Bren2", "unable to unmarshal org added")
|
||||
}
|
||||
|
||||
return orgAdded, nil
|
||||
}
|
||||
|
||||
type OrgChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (e *OrgChangedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func NewOrgChangedEvent(ctx context.Context, name string) *OrgChangedEvent {
|
||||
return &OrgChangedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgChanged,
|
||||
),
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func OrgChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
orgChanged := &OrgChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, orgChanged)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "ORG-Bren2", "unable to unmarshal org added")
|
||||
}
|
||||
|
||||
return orgChanged, nil
|
||||
}
|
@@ -8,14 +8,38 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
OrgIAMPolicyAddedEventType = orgEventTypePrefix + policy.OrgIAMPolicyAddedEventType
|
||||
OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType
|
||||
//TODO: enable when possible
|
||||
//OrgIAMPolicyAddedEventType = orgEventTypePrefix + policy.OrgIAMPolicyAddedEventType
|
||||
//OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType
|
||||
OrgIAMPolicyAddedEventType = orgEventTypePrefix + "iam.policy.added"
|
||||
OrgIAMPolicyChangedEventType = orgEventTypePrefix + "iam.policy.changed"
|
||||
)
|
||||
|
||||
type OrgIAMPolicyAddedEvent struct {
|
||||
policy.OrgIAMPolicyAddedEvent
|
||||
}
|
||||
|
||||
func NewOrgIAMPolicyAddedEvent(
|
||||
ctx context.Context,
|
||||
userLoginMustBeDomain bool,
|
||||
) *OrgIAMPolicyAddedEvent {
|
||||
return &OrgIAMPolicyAddedEvent{
|
||||
OrgIAMPolicyAddedEvent: *policy.NewOrgIAMPolicyAddedEvent(
|
||||
eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyAddedEventType),
|
||||
userLoginMustBeDomain,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func OrgIAMPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
e, err := policy.OrgIAMPolicyAddedEventMapper(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &OrgIAMPolicyAddedEvent{OrgIAMPolicyAddedEvent: *e.(*policy.OrgIAMPolicyAddedEvent)}, nil
|
||||
}
|
||||
|
||||
type OrgIAMPolicyChangedEvent struct {
|
||||
policy.OrgIAMPolicyChangedEvent
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
//TODO: use for org events as suffix (when possible)
|
||||
OrgIAMPolicyAddedEventType = "policy.org.iam.added"
|
||||
OrgIAMPolicyChangedEventType = "policy.org.iam.changed"
|
||||
)
|
||||
|
Reference in New Issue
Block a user