fix: process org remove event in domain verified writemodel (#8790)

# Which Problems Are Solved

Domains are processed as still verified in the domain verified
writemodel even if the org is removed.

# How the Problems Are Solved

Handle the org removed event in the writemodel.

# Additional Changes

None

# Additional Context

Closes #8514

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz 2024-11-28 18:09:00 +01:00 committed by GitHub
parent de7e0f8408
commit ed42dde463
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 326 additions and 1 deletions

View File

@ -202,6 +202,8 @@ func (wm *OrgDomainVerifiedWriteModel) AppendEvents(events ...eventstore.Event)
continue continue
} }
wm.WriteModel.AppendEvents(e) wm.WriteModel.AppendEvents(e)
case *org.OrgRemovedEvent:
wm.WriteModel.AppendEvents(e)
} }
} }
} }
@ -214,6 +216,11 @@ func (wm *OrgDomainVerifiedWriteModel) Reduce() error {
wm.ResourceOwner = e.Aggregate().ResourceOwner wm.ResourceOwner = e.Aggregate().ResourceOwner
case *org.DomainRemovedEvent: case *org.DomainRemovedEvent:
wm.Verified = false wm.Verified = false
case *org.OrgRemovedEvent:
if wm.ResourceOwner != e.Aggregate().ID {
continue
}
wm.Verified = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()
@ -225,6 +232,7 @@ func (wm *OrgDomainVerifiedWriteModel) Query() *eventstore.SearchQueryBuilder {
AggregateTypes(org.AggregateType). AggregateTypes(org.AggregateType).
EventTypes( EventTypes(
org.OrgDomainVerifiedEventType, org.OrgDomainVerifiedEventType,
org.OrgDomainRemovedEventType). org.OrgDomainRemovedEventType,
org.OrgRemovedEventType).
Builder() Builder()
} }

View File

@ -1725,6 +1725,323 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
wantID: "user1", wantID: "user1",
}, },
}, },
{
name: "register human (validate domain), already verified",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(context.Background(),
&org.NewAggregate("existing").Aggregate,
"example.com",
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &AddHuman{
Username: "username@example.com",
FirstName: "firstname",
LastName: "lastname",
Email: Email{
Address: "email@example.com",
},
PreferredLanguage: language.English,
Register: true,
UserAgentID: "userAgentID",
AuthRequestID: "authRequestID",
},
secretGenerator: GetMockSecretGenerator(t),
allowInitMail: true,
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-SFd21", "Errors.User.DomainNotAllowedAsUsername"))
},
},
},
{
name: "register human (validate domain), ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(context.Background(),
&org.NewAggregate(userAgg.ResourceOwner).Aggregate,
"example.com",
),
),
),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
"username@example.com",
"firstname",
"lastname",
"",
"firstname lastname",
language.English,
domain.GenderUnspecified,
"email@example.com",
false,
"userAgentID",
),
user.NewHumanInitialCodeAddedEvent(context.Background(),
&userAgg.Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("userinit"),
},
time.Hour*1,
"authRequestID",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &AddHuman{
Username: "username@example.com",
FirstName: "firstname",
LastName: "lastname",
Email: Email{
Address: "email@example.com",
},
PreferredLanguage: language.English,
Register: true,
UserAgentID: "userAgentID",
AuthRequestID: "authRequestID",
},
secretGenerator: GetMockSecretGenerator(t),
allowInitMail: true,
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
wantID: "user1",
},
},
{
name: "register human (validate domain, domain removed), ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(context.Background(),
&org.NewAggregate("existing").Aggregate,
"example.com",
),
),
eventFromEventPusher(
org.NewDomainRemovedEvent(context.Background(),
&org.NewAggregate("existing").Aggregate,
"example.com",
true,
),
),
),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
"username@example.com",
"firstname",
"lastname",
"",
"firstname lastname",
language.English,
domain.GenderUnspecified,
"email@example.com",
false,
"userAgentID",
),
user.NewHumanInitialCodeAddedEvent(context.Background(),
&userAgg.Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("userinit"),
},
time.Hour*1,
"authRequestID",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &AddHuman{
Username: "username@example.com",
FirstName: "firstname",
LastName: "lastname",
Email: Email{
Address: "email@example.com",
},
PreferredLanguage: language.English,
Register: true,
UserAgentID: "userAgentID",
AuthRequestID: "authRequestID",
},
secretGenerator: GetMockSecretGenerator(t),
allowInitMail: true,
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
wantID: "user1",
},
},
{
name: "register human (validate domain, org removed), ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(context.Background(),
&org.NewAggregate("existing").Aggregate,
"example.com",
),
),
eventFromEventPusher(
org.NewOrgRemovedEvent(context.Background(),
&org.NewAggregate("existing").Aggregate,
"org",
[]string{},
false,
[]string{},
[]*domain.UserIDPLink{},
[]string{},
),
),
),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
"username@example.com",
"firstname",
"lastname",
"",
"firstname lastname",
language.English,
domain.GenderUnspecified,
"email@example.com",
false,
"userAgentID",
),
user.NewHumanInitialCodeAddedEvent(context.Background(),
&userAgg.Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("userinit"),
},
time.Hour*1,
"authRequestID",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &AddHuman{
Username: "username@example.com",
FirstName: "firstname",
LastName: "lastname",
Email: Email{
Address: "email@example.com",
},
PreferredLanguage: language.English,
Register: true,
UserAgentID: "userAgentID",
AuthRequestID: "authRequestID",
},
secretGenerator: GetMockSecretGenerator(t),
allowInitMail: true,
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
wantID: "user1",
},
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {