feat: user events (#1062)

* feat: user new eventstore

* feat: rename query builder

* feat: human events

* feat: human events

* feat: events

* feat: phone events

* feat: phone events

* feat: profile, address events

* feat: mfa, otp

* feat: webauthn events

* feat: webauthn events

* feat: webauthn events

* feat: enums

* feat: new events

* feat: user events

* feat: domain events

* feat: all v2 events

* feat: all v1 events

* feat: pkg structure

* feat: change events

* feat: better naming

* feat: better naming
This commit is contained in:
Fabi 2020-12-10 16:18:52 +01:00 committed by GitHub
parent 5dd60f01e0
commit 31ea9d1acd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 3237 additions and 3 deletions

View File

@ -52,9 +52,6 @@ const (
MFAInitSkipped models.EventType = "user.mfa.init.skipped"
SignedOut models.EventType = "user.signed.out"
DomainClaimed models.EventType = "user.domain.claimed"
DomainClaimedSent models.EventType = "user.domain.claimed.sent"
)
//the following consts are for user(v2)
@ -69,6 +66,9 @@ const (
UserRemoved models.EventType = "user.removed"
UserTokenAdded models.EventType = "user.token.added"
DomainClaimed models.EventType = "user.domain.claimed"
DomainClaimedSent models.EventType = "user.domain.claimed.sent"
)
// the following consts are for user(v2).human

View File

@ -0,0 +1,49 @@
package user
import (
"github.com/caos/zitadel/internal/eventstore/v2"
)
const (
AggregateType = "user"
AggregateVersion = "v2"
)
type Aggregate struct {
eventstore.Aggregate
}
func NewAggregate(
id,
resourceOwner string,
previousSequence uint64,
) *Aggregate {
return &Aggregate{
Aggregate: *eventstore.NewAggregate(
id,
AggregateType,
resourceOwner,
AggregateVersion,
previousSequence,
),
}
}
func AggregateFromWriteModel(wm *eventstore.WriteModel) *Aggregate {
return &Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, AggregateType, AggregateVersion),
}
}
func AggregateFromReadModel(rm *ReadModel) *Aggregate {
return &Aggregate{
Aggregate: *eventstore.NewAggregate(
rm.AggregateID,
AggregateType,
rm.ResourceOwner,
AggregateVersion,
rm.ProcessedSequence,
),
}
}

View File

@ -0,0 +1,321 @@
package user
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"
"time"
)
const (
userEventTypePrefix = eventstore.EventType("user.")
UserLockedType = userEventTypePrefix + "locked"
UserUnlockedType = userEventTypePrefix + "unlocked"
UserDeactivatedType = userEventTypePrefix + "deactivated"
UserReactivatedType = userEventTypePrefix + "reactivated"
UserRemovedType = userEventTypePrefix + "removed"
UserTokenAddedType = userEventTypePrefix + "token.added"
UserDomainClaimedType = userEventTypePrefix + "domain.claimed"
UserDomainClaimedSentType = userEventTypePrefix + "domain.claimed.sent"
UserUserNameChangedType = userEventTypePrefix + "username.changed"
)
type LockedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *LockedEvent) CheckPrevious() bool {
return true
}
func (e *LockedEvent) Data() interface{} {
return nil
}
func NewLockedEvent(ctx context.Context) *LockedEvent {
return &LockedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserLockedType,
),
}
}
func LockedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &LockedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type UnlockedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *UnlockedEvent) CheckPrevious() bool {
return true
}
func (e *UnlockedEvent) Data() interface{} {
return nil
}
func NewUnlockedEvent(ctx context.Context) *UnlockedEvent {
return &UnlockedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserUnlockedType,
),
}
}
func UnlockedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &UnlockedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type DeactivatedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *DeactivatedEvent) CheckPrevious() bool {
return true
}
func (e *DeactivatedEvent) Data() interface{} {
return nil
}
func NewDeactivatedEvent(ctx context.Context) *DeactivatedEvent {
return &DeactivatedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserDeactivatedType,
),
}
}
func DeactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &DeactivatedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type ReactivatedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *ReactivatedEvent) CheckPrevious() bool {
return true
}
func (e *ReactivatedEvent) Data() interface{} {
return nil
}
func NewReactivatedEvent(ctx context.Context) *ReactivatedEvent {
return &ReactivatedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserReactivatedType,
),
}
}
func ReactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &ReactivatedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type RemovedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *RemovedEvent) CheckPrevious() bool {
return true
}
func (e *RemovedEvent) Data() interface{} {
return nil
}
func NewRemovedEvent(ctx context.Context) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserRemovedType,
),
}
}
func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &RemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type TokenAddedEvent struct {
eventstore.BaseEvent `json:"-"`
TokenID string `json:"tokenId"`
ApplicationID string `json:"applicationId"`
UserAgentID string `json:"userAgentId"`
Audience []string `json:"audience"`
Scopes []string `json:"scopes""`
Expiration time.Time `json:"expiration"`
PreferredLanguage string `json:"preferredLanguage"`
}
func (e *TokenAddedEvent) CheckPrevious() bool {
return false
}
func (e *TokenAddedEvent) Data() interface{} {
return e
}
func NewTokenAddedEvent(
ctx context.Context,
tokenID,
applicationID,
userAgentID,
preferredLanguage string,
audience,
scopes []string,
expiration time.Time,
) *TokenAddedEvent {
return &TokenAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserTokenAddedType,
),
TokenID: tokenID,
ApplicationID: applicationID,
UserAgentID: userAgentID,
Audience: audience,
Scopes: scopes,
Expiration: expiration,
}
}
func TokenAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
tokenAdded := &TokenAddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, tokenAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-7M9sd", "unable to unmarshal token added")
}
return tokenAdded, nil
}
type DomainClaimedEvent struct {
eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
}
func (e *DomainClaimedEvent) CheckPrevious() bool {
return false
}
func (e *DomainClaimedEvent) Data() interface{} {
return e
}
func NewDomainClaimedEvent(
ctx context.Context,
userName string,
) *DomainClaimedEvent {
return &DomainClaimedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserDomainClaimedType,
),
UserName: userName,
}
}
func DomainClaimedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
domainClaimed := &DomainClaimedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, domainClaimed)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-aR8jc", "unable to unmarshal domain claimed")
}
return domainClaimed, nil
}
type DomainClaimedSentEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *DomainClaimedSentEvent) CheckPrevious() bool {
return false
}
func (e *DomainClaimedSentEvent) Data() interface{} {
return nil
}
func NewDomainClaimedSentEvent(
ctx context.Context,
) *DomainClaimedSentEvent {
return &DomainClaimedSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserDomainClaimedSentType,
),
}
}
func DomainClaimedSentEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &DomainClaimedSentEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type UsernameChangedEvent struct {
eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
}
func (e *UsernameChangedEvent) CheckPrevious() bool {
return false
}
func (e *UsernameChangedEvent) Data() interface{} {
return e
}
func NewUsernameChangedEvent(
ctx context.Context,
userName string,
) *UsernameChangedEvent {
return &UsernameChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserUserNameChangedType,
),
UserName: userName,
}
}
func UsernameChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
domainClaimed := &UsernameChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, domainClaimed)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-4Bm9s", "unable to unmarshal username changed")
}
return domainClaimed, nil
}

View File

@ -0,0 +1,114 @@
package user
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/user/human"
"github.com/caos/zitadel/internal/v2/repository/user/human/address"
"github.com/caos/zitadel/internal/v2/repository/user/human/email"
"github.com/caos/zitadel/internal/v2/repository/user/human/external_idp"
"github.com/caos/zitadel/internal/v2/repository/user/human/mfa"
"github.com/caos/zitadel/internal/v2/repository/user/human/mfa/otp"
"github.com/caos/zitadel/internal/v2/repository/user/human/mfa/web_auth_n"
"github.com/caos/zitadel/internal/v2/repository/user/human/password"
"github.com/caos/zitadel/internal/v2/repository/user/human/phone"
"github.com/caos/zitadel/internal/v2/repository/user/human/profile"
"github.com/caos/zitadel/internal/v2/repository/user/machine"
"github.com/caos/zitadel/internal/v2/repository/user/machine/keys"
"github.com/caos/zitadel/internal/v2/repository/user/v1"
)
func RegisterEventMappers(es *eventstore.Eventstore) {
es.RegisterFilterEventMapper(v1.UserV1AddedType, human.AddedEventMapper).
RegisterFilterEventMapper(v1.UserV1RegisteredType, human.RegisteredEventMapper).
RegisterFilterEventMapper(v1.UserV1InitialCodeAddedType, human.InitialCodeAddedEventMapper).
RegisterFilterEventMapper(v1.UserV1InitialCodeSentType, human.InitialCodeSentEventMapper).
RegisterFilterEventMapper(v1.UserV1InitializedCheckSucceededType, human.InitializedCheckSucceededEventMapper).
RegisterFilterEventMapper(v1.UserV1InitializedCheckFailedType, human.InitializedCheckFailedEventMapper).
RegisterFilterEventMapper(v1.UserV1SignedOutType, human.SignedOutEventMapper).
RegisterFilterEventMapper(v1.UserV1PasswordChangedType, password.ChangedEventMapper).
RegisterFilterEventMapper(v1.UserV1PasswordCodeAddedType, password.CodeAddedEventMapper).
RegisterFilterEventMapper(v1.UserV1PasswordCodeSentType, password.CodeSentEventMapper).
RegisterFilterEventMapper(v1.UserV1PasswordCheckSucceededType, password.CheckSucceededEventMapper).
RegisterFilterEventMapper(v1.UserV1PasswordCheckFailedType, password.CheckFailedEventMapper).
RegisterFilterEventMapper(v1.UserV1EmailChangedType, email.ChangedEventMapper).
RegisterFilterEventMapper(v1.UserV1EmailVerifiedType, email.VerifiedEventMapper).
RegisterFilterEventMapper(v1.UserV1EmailVerificationFailedType, email.VerificationFailedEventMapper).
RegisterFilterEventMapper(v1.UserV1EmailCodeAddedType, email.CodeAddedEventMapper).
RegisterFilterEventMapper(v1.UserV1EmailCodeSentType, email.CodeSentEventMapper).
RegisterFilterEventMapper(v1.UserV1PhoneChangedType, phone.ChangedEventMapper).
RegisterFilterEventMapper(v1.UserV1PhoneRemovedType, phone.RemovedEventMapper).
RegisterFilterEventMapper(v1.UserV1PhoneVerifiedType, phone.VerifiedEventMapper).
RegisterFilterEventMapper(v1.UserV1PhoneVerificationFailedType, phone.VerificationFailedEventMapper).
RegisterFilterEventMapper(v1.UserV1PhoneCodeAddedType, phone.CodeAddedEventMapper).
RegisterFilterEventMapper(v1.UserV1PhoneCodeSentType, phone.CodeSentEventMapper).
RegisterFilterEventMapper(v1.UserV1ProfileChangedType, profile.ChangedEventMapper).
RegisterFilterEventMapper(v1.UserV1AddressChangedType, address.ChangedEventMapper).
RegisterFilterEventMapper(v1.UserV1MFAInitSkippedType, mfa.InitSkippedEventMapper).
RegisterFilterEventMapper(v1.UserV1MFAOTPAddedType, otp.AddedEventMapper).
RegisterFilterEventMapper(v1.UserV1MFAOTPVerifiedType, otp.VerifiedEventMapper).
RegisterFilterEventMapper(v1.UserV1MFAOTPRemovedType, otp.RemovedEventMapper).
RegisterFilterEventMapper(v1.UserV1MFAOTPCheckSucceededType, otp.CheckSucceededEventMapper).
RegisterFilterEventMapper(v1.UserV1MFAOTPCheckFailedType, otp.CheckFailedEventMapper).
RegisterFilterEventMapper(UserLockedType, LockedEventMapper).
RegisterFilterEventMapper(UserUnlockedType, LockedEventMapper).
RegisterFilterEventMapper(UserDeactivatedType, DeactivatedEventMapper).
RegisterFilterEventMapper(UserReactivatedType, ReactivatedEventMapper).
RegisterFilterEventMapper(UserRemovedType, RemovedEventMapper).
RegisterFilterEventMapper(UserTokenAddedType, TokenAddedEventMapper).
RegisterFilterEventMapper(UserDomainClaimedType, DomainClaimedEventMapper).
RegisterFilterEventMapper(UserDomainClaimedSentType, DomainClaimedEventMapper).
RegisterFilterEventMapper(UserUserNameChangedType, UsernameChangedEventMapper).
RegisterFilterEventMapper(human.HumanAddedType, human.AddedEventMapper).
RegisterFilterEventMapper(human.HumanRegisteredType, human.RegisteredEventMapper).
RegisterFilterEventMapper(human.HumanInitialCodeAddedType, human.InitialCodeAddedEventMapper).
RegisterFilterEventMapper(human.HumanInitialCodeSentType, human.InitialCodeSentEventMapper).
RegisterFilterEventMapper(human.HumanInitializedCheckSucceededType, human.InitializedCheckSucceededEventMapper).
RegisterFilterEventMapper(human.HumanInitializedCheckFailedType, human.InitializedCheckFailedEventMapper).
RegisterFilterEventMapper(human.HumanSignedOutType, human.SignedOutEventMapper).
RegisterFilterEventMapper(password.HumanPasswordChangedType, password.ChangedEventMapper).
RegisterFilterEventMapper(password.HumanPasswordCodeAddedType, password.CodeAddedEventMapper).
RegisterFilterEventMapper(password.HumanPasswordCodeSentType, password.CodeSentEventMapper).
RegisterFilterEventMapper(password.HumanPasswordCheckSucceededType, password.CheckSucceededEventMapper).
RegisterFilterEventMapper(password.HumanPasswordCheckFailedType, password.CheckFailedEventMapper).
RegisterFilterEventMapper(external_idp.HumanExternalIDPAddedType, external_idp.AddedEventMapper).
RegisterFilterEventMapper(external_idp.HumanExternalIDPRemovedType, external_idp.RemovedEventMapper).
RegisterFilterEventMapper(external_idp.HumanExternalIDPCascadeRemovedType, external_idp.CascadeRemovedEventMapper).
RegisterFilterEventMapper(external_idp.HumanExternalLoginCheckSucceededType, external_idp.CheckSucceededEventMapper).
RegisterFilterEventMapper(email.HumanEmailChangedType, email.ChangedEventMapper).
RegisterFilterEventMapper(email.HumanEmailVerifiedType, email.VerifiedEventMapper).
RegisterFilterEventMapper(email.HumanEmailVerificationFailedType, email.VerificationFailedEventMapper).
RegisterFilterEventMapper(email.HumanEmailCodeAddedType, email.CodeAddedEventMapper).
RegisterFilterEventMapper(email.HumanEmailCodeSentType, email.CodeSentEventMapper).
RegisterFilterEventMapper(phone.HumanPhoneChangedType, phone.ChangedEventMapper).
RegisterFilterEventMapper(phone.HumanPhoneRemovedType, phone.RemovedEventMapper).
RegisterFilterEventMapper(phone.HumanPhoneVerifiedType, phone.VerifiedEventMapper).
RegisterFilterEventMapper(phone.HumanPhoneVerificationFailedType, phone.VerificationFailedEventMapper).
RegisterFilterEventMapper(phone.HumanPhoneCodeAddedType, phone.CodeAddedEventMapper).
RegisterFilterEventMapper(phone.HumanPhoneCodeSentType, phone.CodeSentEventMapper).
RegisterFilterEventMapper(profile.HumanProfileChangedType, profile.ChangedEventMapper).
RegisterFilterEventMapper(address.HumanAddressChangedType, address.ChangedEventMapper).
RegisterFilterEventMapper(mfa.HumanMFAInitSkippedType, mfa.InitSkippedEventMapper).
RegisterFilterEventMapper(otp.HumanMFAOTPAddedType, otp.AddedEventMapper).
RegisterFilterEventMapper(otp.HumanMFAOTPVerifiedType, otp.VerifiedEventMapper).
RegisterFilterEventMapper(otp.HumanMFAOTPRemovedType, otp.RemovedEventMapper).
RegisterFilterEventMapper(otp.HumanMFAOTPCheckSucceededType, otp.CheckSucceededEventMapper).
RegisterFilterEventMapper(otp.HumanMFAOTPCheckFailedType, otp.CheckFailedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenAddedType, web_auth_n.AddedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenVerifiedType, web_auth_n.VerifiedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenSignCountChangedType, web_auth_n.SignCountChangedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenRemovedType, web_auth_n.RemovedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenBeginLoginType, web_auth_n.BeginLoginEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenCheckSucceededType, web_auth_n.CheckSucceededEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanU2FTokenCheckFailedType, web_auth_n.CheckFailedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenAddedType, web_auth_n.AddedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenVerifiedType, web_auth_n.VerifiedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenSignCountChangedType, web_auth_n.SignCountChangedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenRemovedType, web_auth_n.RemovedEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenBeginLoginType, web_auth_n.BeginLoginEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenCheckSucceededType, web_auth_n.CheckSucceededEventMapper).
RegisterFilterEventMapper(web_auth_n.HumanPasswordlessTokenCheckFailedType, web_auth_n.CheckFailedEventMapper).
RegisterFilterEventMapper(machine.MachineAddedEventType, machine.AddedEventMapper).
RegisterFilterEventMapper(machine.MachineChangedEventType, machine.ChangedEventMapper).
RegisterFilterEventMapper(keys.MachineKeyAddedEventType, keys.AddedEventMapper).
RegisterFilterEventMapper(keys.MachineKeyRemovedEventType, keys.RemovedEventMapper)
}

View File

@ -0,0 +1,79 @@
package address
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 (
addressEventPrefix = eventstore.EventType("user.human.address.")
HumanAddressChangedType = addressEventPrefix + "changed"
)
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
Country string `json:"country,omitempty"`
Locality string `json:"locality,omitempty"`
PostalCode string `json:"postalCode,omitempty"`
Region string `json:"region,omitempty"`
StreetAddress string `json:"streetAddress,omitempty"`
}
func (e *ChangedEvent) CheckPrevious() bool {
return true
}
func (e *ChangedEvent) Data() interface{} {
return e
}
func NewChangedEvent(
ctx context.Context,
current *WriteModel,
country,
locality,
postalCode,
region,
streetAddress string,
) *ChangedEvent {
e := &ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanAddressChangedType,
),
}
if current.Country != country {
e.Country = country
}
if current.Locality != locality {
e.Locality = locality
}
if current.PostalCode != postalCode {
e.PostalCode = postalCode
}
if current.Region != region {
e.Region = region
}
if current.StreetAddress != streetAddress {
e.StreetAddress = streetAddress
}
return e
}
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
addressChanged := &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, addressChanged)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5M0pd", "unable to unmarshal human address changed")
}
return addressChanged, nil
}

View File

@ -0,0 +1,13 @@
package address
import "github.com/caos/zitadel/internal/eventstore/v2"
type WriteModel struct {
eventstore.WriteModel
Country string
Locality string
PostalCode string
Region string
StreetAddress string
}

View File

@ -0,0 +1,189 @@
package email
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"
"time"
)
const (
emailEventPrefix = eventstore.EventType("user.human.email.")
HumanEmailChangedType = emailEventPrefix + "changed"
HumanEmailVerifiedType = emailEventPrefix + "verified"
HumanEmailVerificationFailedType = emailEventPrefix + "verification.failed"
HumanEmailCodeAddedType = emailEventPrefix + "code.added"
HumanEmailCodeSentType = emailEventPrefix + "code.sent"
)
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
EmailAddress string `json:"email,omitempty"`
}
func (e *ChangedEvent) CheckPrevious() bool {
return true
}
func (e *ChangedEvent) Data() interface{} {
return e
}
func NewChangedEvent(
ctx context.Context,
current *WriteModel,
emailAddress string,
) *ChangedEvent {
e := &ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanEmailChangedType,
),
}
if current.Email != emailAddress {
e.EmailAddress = emailAddress
}
return e
}
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
emailChangedEvent := &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, emailChangedEvent)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-4M0sd", "unable to unmarshal human password changed")
}
return emailChangedEvent, nil
}
type VerifiedEvent struct {
eventstore.BaseEvent `json:"-"`
IsEmailVerified bool `json:"-"`
}
func (e *VerifiedEvent) CheckPrevious() bool {
return true
}
func (e *VerifiedEvent) Data() interface{} {
return nil
}
func NewVerifiedEvent(ctx context.Context) *VerifiedEvent {
return &VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanEmailVerifiedType,
),
}
}
func VerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
emailVerified := &VerifiedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
IsEmailVerified: true,
}
return emailVerified, nil
}
type VerificationFailedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *VerificationFailedEvent) CheckPrevious() bool {
return false
}
func (e *VerificationFailedEvent) Data() interface{} {
return nil
}
func NewVerificationFailedEvent(ctx context.Context) *VerificationFailedEvent {
return &VerificationFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanEmailVerificationFailedType,
),
}
}
func VerificationFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &VerificationFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type CodeAddedEvent struct {
eventstore.BaseEvent `json:"-"`
Code *crypto.CryptoValue `json:"code,omitempty"`
Expiry time.Duration `json:"expiry,omitempty"`
}
func (e *CodeAddedEvent) CheckPrevious() bool {
return true
}
func (e *CodeAddedEvent) Data() interface{} {
return e
}
func NewCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration) *CodeAddedEvent {
return &CodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanEmailCodeAddedType,
),
Code: code,
Expiry: expiry,
}
}
func CodeAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
codeAdded := &CodeAddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, codeAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-3M0sd", "unable to unmarshal human email code added")
}
return codeAdded, nil
}
type CodeSentEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CodeSentEvent) CheckPrevious() bool {
return true
}
func (e *CodeSentEvent) Data() interface{} {
return nil
}
func NewCodeSentEvent(ctx context.Context) *CodeSentEvent {
return &CodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanEmailCodeSentType,
),
}
}
func CodeSentEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CodeSentEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,9 @@
package email
import "github.com/caos/zitadel/internal/eventstore/v2"
type WriteModel struct {
eventstore.WriteModel
Email string
}

View File

@ -0,0 +1,336 @@
package human
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"
"golang.org/x/text/language"
"time"
)
const (
humanEventPrefix = eventstore.EventType("user.human.")
HumanAddedType = humanEventPrefix + "added"
HumanRegisteredType = humanEventPrefix + "selfregistered"
HumanInitialCodeAddedType = humanEventPrefix + "initialization.code.added"
HumanInitialCodeSentType = humanEventPrefix + "initialization.code.sent"
HumanInitializedCheckSucceededType = humanEventPrefix + "initialization.check.succeeded"
HumanInitializedCheckFailedType = humanEventPrefix + "initialization.check.failed"
HumanSignedOutType = humanEventPrefix + "signed.out"
)
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
NickName string `json:"nickName,omitempty"`
DisplayName string `json:"displayName,omitempty"`
PreferredLanguage language.Tag `json:"preferredLanguage,omitempty"`
Gender Gender `json:"gender,omitempty"`
EmailAddress string `json:"email,omitempty"`
PhoneNumber string `json:"phone,omitempty"`
Country string `json:"country,omitempty"`
Locality string `json:"locality,omitempty"`
PostalCode string `json:"postalCode,omitempty"`
Region string `json:"region,omitempty"`
StreetAddress string `json:"streetAddress,omitempty"`
}
func (e *AddedEvent) CheckPrevious() bool {
return false
}
func (e *AddedEvent) Data() interface{} {
return e
}
func NewAddedEvent(
ctx context.Context,
userName,
firstName,
lastName,
nickName,
displayName string,
preferredLanguage language.Tag,
gender Gender,
emailAddress,
phoneNumber,
country,
locality,
postalCode,
region,
streetAddress string,
) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanAddedType,
),
UserName: userName,
FirstName: firstName,
LastName: lastName,
NickName: nickName,
DisplayName: displayName,
PreferredLanguage: preferredLanguage,
Gender: gender,
EmailAddress: emailAddress,
PhoneNumber: phoneNumber,
Country: country,
Locality: locality,
PostalCode: postalCode,
Region: region,
StreetAddress: streetAddress,
}
}
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
humanAdded := &AddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, humanAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5Gm9s", "unable to unmarshal human added")
}
return humanAdded, nil
}
type RegisteredEvent struct {
eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
NickName string `json:"nickName,omitempty"`
DisplayName string `json:"displayName,omitempty"`
PreferredLanguage language.Tag `json:"preferredLanguage,omitempty"`
Gender int32 `json:"gender,omitempty"`
EmailAddress string `json:"email,omitempty"`
PhoneNumber string `json:"phone,omitempty"`
Country string `json:"country,omitempty"`
Locality string `json:"locality,omitempty"`
PostalCode string `json:"postalCode,omitempty"`
Region string `json:"region,omitempty"`
StreetAddress string `json:"streetAddress,omitempty"`
}
func (e *RegisteredEvent) CheckPrevious() bool {
return false
}
func (e *RegisteredEvent) Data() interface{} {
return e
}
func NewRegisteredEvent(
ctx context.Context,
userName,
firstName,
lastName,
nickName,
displayName string,
preferredLanguage language.Tag,
gender int32,
emailAddress,
phoneNumber,
country,
locality,
postalCode,
region,
streetAddress string,
) *RegisteredEvent {
return &RegisteredEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanRegisteredType,
),
UserName: userName,
FirstName: firstName,
LastName: lastName,
NickName: nickName,
DisplayName: displayName,
PreferredLanguage: preferredLanguage,
Gender: gender,
EmailAddress: emailAddress,
PhoneNumber: phoneNumber,
Country: country,
Locality: locality,
PostalCode: postalCode,
Region: region,
StreetAddress: streetAddress,
}
}
func RegisteredEventMapper(event *repository.Event) (eventstore.EventReader, error) {
humanRegistered := &RegisteredEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, humanRegistered)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-3Vm9s", "unable to unmarshal human registered")
}
return humanRegistered, nil
}
type InitialCodeAddedEvent struct {
eventstore.BaseEvent `json:"-"`
Code *crypto.CryptoValue `json:"code,omitempty"`
Expiry time.Duration `json:"expiry,omitempty"`
}
func (e *InitialCodeAddedEvent) CheckPrevious() bool {
return true
}
func (e *InitialCodeAddedEvent) Data() interface{} {
return e
}
func NewInitialCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
) *InitialCodeAddedEvent {
return &InitialCodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanInitialCodeAddedType,
),
Code: code,
Expiry: expiry,
}
}
func InitialCodeAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
humanRegistered := &InitialCodeAddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, humanRegistered)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-bM9se", "unable to unmarshal human initial code added")
}
return humanRegistered, nil
}
type InitialCodeSentEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *InitialCodeSentEvent) CheckPrevious() bool {
return false
}
func (e *InitialCodeSentEvent) Data() interface{} {
return nil
}
func NewInitialCodeSentEvent(ctx context.Context) *InitialCodeSentEvent {
return &InitialCodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanInitialCodeSentType,
),
}
}
func InitialCodeSentEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &InitialCodeSentEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type InitializedCheckSucceededEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *InitializedCheckSucceededEvent) CheckPrevious() bool {
return false
}
func (e *InitializedCheckSucceededEvent) Data() interface{} {
return nil
}
func NewInitializedCheckSucceededEvent(ctx context.Context) *InitializedCheckSucceededEvent {
return &InitializedCheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanInitializedCheckSucceededType,
),
}
}
func InitializedCheckSucceededEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &InitializedCheckSucceededEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type InitializedCheckFailedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *InitializedCheckFailedEvent) CheckPrevious() bool {
return false
}
func (e *InitializedCheckFailedEvent) Data() interface{} {
return nil
}
func NewInitializedCheckFailedEvent(ctx context.Context) *InitializedCheckFailedEvent {
return &InitializedCheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanInitializedCheckFailedType,
),
}
}
func InitializedCheckFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &InitializedCheckFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type SignedOutEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *SignedOutEvent) CheckPrevious() bool {
return false
}
func (e *SignedOutEvent) Data() interface{} {
return nil
}
func NewSignedOutEvent(ctx context.Context) *SignedOutEvent {
return &SignedOutEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanSignedOutType,
),
}
}
func SignedOutEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &SignedOutEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,206 @@
package external_idp
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 (
externalIDPEventPrefix = eventstore.EventType("user.human.externalidp.")
externalLoginEventPrefix = eventstore.EventType("user.human.externallogin.")
//TODO: Handle unique Aggregate
HumanExternalIDPReservedType = externalIDPEventPrefix + "reserved"
HumanExternalIDPReleasedType = externalIDPEventPrefix + "released"
HumanExternalIDPAddedType = externalIDPEventPrefix + "added"
HumanExternalIDPRemovedType = externalIDPEventPrefix + "removed"
HumanExternalIDPCascadeRemovedType = externalIDPEventPrefix + "cascade.removed"
HumanExternalLoginCheckSucceededType = externalLoginEventPrefix + "check.succeeded"
)
type ReservedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *ReservedEvent) CheckPrevious() bool {
return true
}
func (e *ReservedEvent) Data() interface{} {
return nil
}
func NewReservedEvent(ctx context.Context) *ReservedEvent {
return &ReservedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanExternalIDPReservedType,
),
}
}
type ReleasedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *ReleasedEvent) CheckPrevious() bool {
return true
}
func (e *ReleasedEvent) Data() interface{} {
return nil
}
func NewReleasedEvent(ctx context.Context) *ReleasedEvent {
return &ReleasedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanExternalIDPReleasedType,
),
}
}
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId,omitempty"`
DisplayName string `json:"displayName,omitempty"`
}
func (e *AddedEvent) CheckPrevious() bool {
return true
}
func (e *AddedEvent) Data() interface{} {
return e
}
func NewAddedEvent(ctx context.Context, idpConfigID, displayName string) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanExternalIDPAddedType,
),
IDPConfigID: idpConfigID,
DisplayName: displayName,
}
}
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &AddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-6M9sd", "unable to unmarshal user external idp added")
}
return e, nil
}
type RemovedEvent struct {
eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId"`
}
func (e *RemovedEvent) CheckPrevious() bool {
return true
}
func (e *RemovedEvent) Data() interface{} {
return e
}
func NewRemovedEvent(ctx context.Context, idpConfigID string) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanExternalIDPRemovedType,
),
IDPConfigID: idpConfigID,
}
}
func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &RemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5Gm9s", "unable to unmarshal user external idp removed")
}
return e, nil
}
type CascadeRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId"`
}
func (e *CascadeRemovedEvent) CheckPrevious() bool {
return false
}
func (e *CascadeRemovedEvent) Data() interface{} {
return e
}
func NewCascadeRemovedEvent(ctx context.Context, idpConfigID string) *CascadeRemovedEvent {
return &CascadeRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanExternalIDPCascadeRemovedType,
),
IDPConfigID: idpConfigID,
}
}
func CascadeRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &CascadeRemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-2M0sd", "unable to unmarshal user external idp cascade removed")
}
return e, nil
}
type CheckSucceededEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CheckSucceededEvent) CheckPrevious() bool {
return false
}
func (e *CheckSucceededEvent) Data() interface{} {
return nil
}
func NewCheckSucceededEvent(ctx context.Context) *CheckSucceededEvent {
return &CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanExternalLoginCheckSucceededType,
),
}
}
func CheckSucceededEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CheckSucceededEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,16 @@
package human
type Gender int32
const (
GenderUnspecified Gender = iota
GenderFemale
GenderMale
GenderDiverse
genderCount
)
func (f Gender) Valid() bool {
return f >= 0 && f < genderCount
}

View File

@ -0,0 +1,39 @@
package mfa
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
)
const (
mfaEventPrefix = eventstore.EventType("user.human.mfa.")
HumanMFAInitSkippedType = mfaEventPrefix + "init.skiped"
)
type InitSkippedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *InitSkippedEvent) CheckPrevious() bool {
return true
}
func (e *InitSkippedEvent) Data() interface{} {
return e
}
func NewInitSkippedEvent(ctx context.Context) *InitSkippedEvent {
return &InitSkippedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanMFAInitSkippedType,
),
}
}
func InitSkippedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &InitSkippedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,15 @@
package mfa
type State int32
const (
StateUnspecified State = iota
StateNotReady
StateReady
stateCount
)
func (f State) Valid() bool {
return f >= 0 && f < stateCount
}

View File

@ -0,0 +1,168 @@
package otp
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/repository/user/human/mfa"
)
const (
otpEventPrefix = eventstore.EventType("user.human.mfa.otp.")
HumanMFAOTPAddedType = otpEventPrefix + "added"
HumanMFAOTPVerifiedType = otpEventPrefix + "verified"
HumanMFAOTPRemovedType = otpEventPrefix + "removed"
HumanMFAOTPCheckSucceededType = otpEventPrefix + "check.succeeded"
HumanMFAOTPCheckFailedType = otpEventPrefix + "check.failed"
)
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
Secret *crypto.CryptoValue `json:"otpSecret,omitempty"`
State mfa.State `json:"-"`
}
func (e *AddedEvent) CheckPrevious() bool {
return true
}
func (e *AddedEvent) Data() interface{} {
return e
}
func NewAddedEvent(ctx context.Context,
secret *crypto.CryptoValue) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanMFAOTPAddedType,
),
Secret: secret,
}
}
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
otpAdded := &AddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
State: mfa.StateNotReady,
}
err := json.Unmarshal(event.Data, otpAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-Ns9df", "unable to unmarshal human otp added")
}
return otpAdded, nil
}
type VerifiedEvent struct {
eventstore.BaseEvent `json:"-"`
State mfa.State `json:"-"`
}
func (e *VerifiedEvent) CheckPrevious() bool {
return true
}
func (e *VerifiedEvent) Data() interface{} {
return nil
}
func NewVerifiedEvent(ctx context.Context) *VerifiedEvent {
return &VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanMFAOTPVerifiedType,
),
}
}
func VerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &VerifiedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
State: mfa.StateReady,
}, nil
}
type RemovedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *RemovedEvent) CheckPrevious() bool {
return true
}
func (e *RemovedEvent) Data() interface{} {
return nil
}
func NewRemovedEvent(ctx context.Context) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanMFAOTPRemovedType,
),
}
}
func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &RemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type CheckSucceededEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CheckSucceededEvent) CheckPrevious() bool {
return false
}
func (e *CheckSucceededEvent) Data() interface{} {
return nil
}
func NewCheckSucceededEvent(ctx context.Context) *CheckSucceededEvent {
return &CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanMFAOTPCheckSucceededType,
),
}
}
func CheckSucceededEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CheckSucceededEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type CheckFailedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CheckFailedEvent) CheckPrevious() bool {
return false
}
func (e *CheckFailedEvent) Data() interface{} {
return nil
}
func NewCheckFailedEvent(ctx context.Context) *CheckFailedEvent {
return &CheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanMFAOTPCheckFailedType,
),
}
}
func CheckFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CheckFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,426 @@
package web_auth_n
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"
"github.com/caos/zitadel/internal/v2/repository/user/human/mfa"
)
const (
u2fEventPrefix = eventstore.EventType("user.human.mfa.u2f.token.")
HumanU2FTokenAddedType = u2fEventPrefix + "added"
HumanU2FTokenVerifiedType = u2fEventPrefix + "verified"
HumanU2FTokenSignCountChangedType = u2fEventPrefix + "signcount.changed"
HumanU2FTokenRemovedType = u2fEventPrefix + "removed"
HumanU2FTokenBeginLoginType = u2fEventPrefix + "begin.login"
HumanU2FTokenCheckSucceededType = u2fEventPrefix + "check.succeeded"
HumanU2FTokenCheckFailedType = u2fEventPrefix + "check.failed"
passwordlessEventPrefix = eventstore.EventType("user.human.mfa.passwordless.token.")
HumanPasswordlessTokenAddedType = passwordlessEventPrefix + "added"
HumanPasswordlessTokenVerifiedType = passwordlessEventPrefix + "verified"
HumanPasswordlessTokenSignCountChangedType = passwordlessEventPrefix + "signcount.changed"
HumanPasswordlessTokenRemovedType = passwordlessEventPrefix + "removed"
HumanPasswordlessTokenBeginLoginType = passwordlessEventPrefix + "begin.login"
HumanPasswordlessTokenCheckSucceededType = passwordlessEventPrefix + "check.succeeded"
HumanPasswordlessTokenCheckFailedType = passwordlessEventPrefix + "check.failed"
)
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
WebAuthNTokenID string `json:"webAuthNTokenId"`
Challenge string `json:"challenge"`
State mfa.State `json:"-"`
}
func (e *AddedEvent) CheckPrevious() bool {
return true
}
func (e *AddedEvent) Data() interface{} {
return e
}
func NewU2FAddedEvent(
ctx context.Context,
webAuthNTokenID,
challenge string,
) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenAddedType,
),
WebAuthNTokenID: webAuthNTokenID,
Challenge: challenge,
}
}
func NewPasswordlessAddedEvent(
ctx context.Context,
webAuthNTokenID,
challenge string,
) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenAddedType,
),
WebAuthNTokenID: webAuthNTokenID,
Challenge: challenge,
}
}
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webAuthNAdded := &AddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
State: mfa.StateNotReady,
}
err := json.Unmarshal(event.Data, webAuthNAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-tB8sf", "unable to unmarshal human webAuthN added")
}
return webAuthNAdded, nil
}
type VerifiedEvent struct {
eventstore.BaseEvent `json:"-"`
WebAuthNTokenID string `json:"webAuthNTokenId"`
KeyID []byte `json:"keyId"`
PublicKey []byte `json:"publicKey"`
AttestationType string `json:"attestationType"`
AAGUID []byte `json:"aaguid"`
SignCount uint32 `json:"signCount"`
WebAuthNTokenName string `json:"webAuthNTokenName"`
State mfa.State `json:"-"`
}
func (e *VerifiedEvent) CheckPrevious() bool {
return true
}
func (e *VerifiedEvent) Data() interface{} {
return e
}
func NewU2FVerifiedEvent(
ctx context.Context,
webAuthNTokenID,
webAuthNTokenName,
attestationType string,
keyID,
publicKey,
aaguid []byte,
signCount uint32,
) *VerifiedEvent {
return &VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenVerifiedType,
),
WebAuthNTokenID: webAuthNTokenID,
KeyID: keyID,
PublicKey: publicKey,
AttestationType: attestationType,
AAGUID: aaguid,
SignCount: signCount,
WebAuthNTokenName: webAuthNTokenName,
}
}
func NewPasswordlessVerifiedEvent(
ctx context.Context,
webAuthNTokenID,
webAuthNTokenName,
attestationType string,
keyID,
publicKey,
aaguid []byte,
signCount uint32,
) *VerifiedEvent {
return &VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenVerifiedType,
),
WebAuthNTokenID: webAuthNTokenID,
KeyID: keyID,
PublicKey: publicKey,
AttestationType: attestationType,
AAGUID: aaguid,
SignCount: signCount,
WebAuthNTokenName: webAuthNTokenName,
}
}
func VerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webauthNVerified := &VerifiedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
State: mfa.StateReady,
}
err := json.Unmarshal(event.Data, webauthNVerified)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-B0zDs", "unable to unmarshal human webAuthN verified")
}
return webauthNVerified, nil
}
type SignCountChangedEvent struct {
eventstore.BaseEvent `json:"-"`
WebAuthNTokenID string `json:"webAuthNTokenId"`
SignCount uint32 `json:"signCount"`
State mfa.State `json:"-"`
}
func (e *SignCountChangedEvent) CheckPrevious() bool {
return true
}
func (e *SignCountChangedEvent) Data() interface{} {
return e
}
func NewU2FSignCountChangedEvent(
ctx context.Context,
webAuthNTokenID string,
signCount uint32,
) *SignCountChangedEvent {
return &SignCountChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenSignCountChangedType,
),
WebAuthNTokenID: webAuthNTokenID,
SignCount: signCount,
}
}
func NewPasswordlessSignCountChangedEvent(
ctx context.Context,
webAuthNTokenID string,
signCount uint32,
) *SignCountChangedEvent {
return &SignCountChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenSignCountChangedType,
),
WebAuthNTokenID: webAuthNTokenID,
SignCount: signCount,
}
}
func SignCountChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webauthNVerified := &SignCountChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, webauthNVerified)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5Gm0s", "unable to unmarshal human webAuthN sign count")
}
return webauthNVerified, nil
}
type RemovedEvent struct {
eventstore.BaseEvent `json:"-"`
WebAuthNTokenID string `json:"webAuthNTokenId"`
State mfa.State `json:"-"`
}
func (e *RemovedEvent) CheckPrevious() bool {
return true
}
func (e *RemovedEvent) Data() interface{} {
return e
}
func NewU2FRemovedEvent(
ctx context.Context,
webAuthNTokenID string,
) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenRemovedType,
),
WebAuthNTokenID: webAuthNTokenID,
}
}
func NewPasswordlessRemovedEvent(
ctx context.Context,
webAuthNTokenID string,
) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenRemovedType,
),
WebAuthNTokenID: webAuthNTokenID,
}
}
func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webauthNVerified := &RemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, webauthNVerified)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-gM9sd", "unable to unmarshal human webAuthN token removed")
}
return webauthNVerified, nil
}
type BeginLoginEvent struct {
eventstore.BaseEvent `json:"-"`
WebAuthNTokenID string `json:"webAuthNTokenId"`
Challenge string `json:"challenge"`
//TODO: Handle Auth Req??
//*AuthRequest
}
func (e *BeginLoginEvent) CheckPrevious() bool {
return true
}
func (e *BeginLoginEvent) Data() interface{} {
return e
}
func NewU2FBeginLoginEvent(
ctx context.Context,
webAuthNTokenID,
challenge string,
) *BeginLoginEvent {
return &BeginLoginEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenRemovedType,
),
WebAuthNTokenID: webAuthNTokenID,
Challenge: challenge,
}
}
func NewPasswordlessBeginLoginEvent(
ctx context.Context,
webAuthNTokenID,
challenge string,
) *BeginLoginEvent {
return &BeginLoginEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenRemovedType,
),
WebAuthNTokenID: webAuthNTokenID,
Challenge: challenge,
}
}
func BeginLoginEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webAuthNAdded := &BeginLoginEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, webAuthNAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-rMb8x", "unable to unmarshal human webAuthN begin login")
}
return webAuthNAdded, nil
}
type CheckSucceededEvent struct {
eventstore.BaseEvent `json:"-"`
//TODO: Handle Auth Req??
//*AuthRequest
}
func (e *CheckSucceededEvent) CheckPrevious() bool {
return true
}
func (e *CheckSucceededEvent) Data() interface{} {
return e
}
func NewU2FCheckSucceededEvent(ctx context.Context) *CheckSucceededEvent {
return &CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenCheckSucceededType,
),
}
}
func NewPasswordlessCheckSucceededEvent(ctx context.Context) *CheckSucceededEvent {
return &CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenCheckSucceededType,
),
}
}
func CheckSucceededEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webAuthNAdded := &CheckSucceededEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, webAuthNAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-2M0fg", "unable to unmarshal human webAuthN check succeeded")
}
return webAuthNAdded, nil
}
type CheckFailedEvent struct {
eventstore.BaseEvent `json:"-"`
//TODO: Handle Auth Req??
//*AuthRequest
}
func (e *CheckFailedEvent) CheckPrevious() bool {
return true
}
func (e *CheckFailedEvent) Data() interface{} {
return e
}
func NewU2FCheckFailedEvent(ctx context.Context) *CheckFailedEvent {
return &CheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanU2FTokenCheckFailedType,
),
}
}
func NewPasswordlessCheckFailedEvent(ctx context.Context) *CheckFailedEvent {
return &CheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordlessTokenCheckFailedType,
),
}
}
func CheckFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
webAuthNAdded := &CheckFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, webAuthNAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-O0dse", "unable to unmarshal human webAuthN check failed")
}
return webAuthNAdded, nil
}

View File

@ -0,0 +1,8 @@
package human
type NotificationType int32
const (
NotificationTypeEmail NotificationType = iota
NotificationTypeSms
)

View File

@ -0,0 +1,189 @@
package password
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/repository/user/human"
"time"
)
const (
passwordEventPrefix = eventstore.EventType("user.human.password.")
HumanPasswordChangedType = passwordEventPrefix + "changed"
HumanPasswordCodeAddedType = passwordEventPrefix + "code.added"
HumanPasswordCodeSentType = passwordEventPrefix + "code.sent"
HumanPasswordCheckSucceededType = passwordEventPrefix + "check.succeeded"
HumanPasswordCheckFailedType = passwordEventPrefix + "check.failed"
)
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
Secret *crypto.CryptoValue `json:"secret,omitempty"`
ChangeRequired bool `json:"changeRequired,omitempty"`
}
func (e *ChangedEvent) CheckPrevious() bool {
return false
}
func (e *ChangedEvent) Data() interface{} {
return e
}
func NewChangedEvent(
ctx context.Context,
secret *crypto.CryptoValue,
changeRequired bool,
) *ChangedEvent {
return &ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordChangedType,
),
Secret: secret,
ChangeRequired: changeRequired,
}
}
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
humanAdded := &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, humanAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-4M0sd", "unable to unmarshal human password changed")
}
return humanAdded, nil
}
type CodeAddedEvent struct {
eventstore.BaseEvent `json:"-"`
Code *crypto.CryptoValue `json:"code,omitempty"`
Expiry time.Duration `json:"expiry,omitempty"`
NotificationType human.NotificationType `json:"notificationType,omitempty"`
}
func (e *CodeAddedEvent) CheckPrevious() bool {
return false
}
func (e *CodeAddedEvent) Data() interface{} {
return e
}
func NewPasswordCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
notificationType human.NotificationType,
) *CodeAddedEvent {
return &CodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordCodeAddedType,
),
Code: code,
Expiry: expiry,
NotificationType: notificationType,
}
}
func CodeAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
humanAdded := &CodeAddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, humanAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-Ms90d", "unable to unmarshal human password code added")
}
return humanAdded, nil
}
type CodeSentEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CodeSentEvent) CheckPrevious() bool {
return false
}
func (e *CodeSentEvent) Data() interface{} {
return nil
}
func NewCodeSentEvent(ctx context.Context) *CodeSentEvent {
return &CodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordCodeSentType,
),
}
}
func CodeSentEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CodeSentEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type CheckSucceededEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CheckSucceededEvent) CheckPrevious() bool {
return false
}
func (e *CheckSucceededEvent) Data() interface{} {
return nil
}
func NewCheckSucceededEvent(ctx context.Context) *CheckSucceededEvent {
return &CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordCheckSucceededType,
),
}
}
func CheckSucceededEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CheckSucceededEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type CheckFailedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CheckFailedEvent) CheckPrevious() bool {
return false
}
func (e *CheckFailedEvent) Data() interface{} {
return nil
}
func NewCheckFailedEvent(ctx context.Context) *CheckFailedEvent {
return &CheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPasswordCheckFailedType,
),
}
}
func CheckFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CheckFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,210 @@
package phone
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"
"time"
)
const (
phoneEventPrefix = eventstore.EventType("user.human.phone.")
HumanPhoneChangedType = phoneEventPrefix + "changed"
HumanPhoneRemovedType = phoneEventPrefix + "removed"
HumanPhoneVerifiedType = phoneEventPrefix + "verified"
HumanPhoneVerificationFailedType = phoneEventPrefix + "verification.failed"
HumanPhoneCodeAddedType = phoneEventPrefix + "code.added"
HumanPhoneCodeSentType = phoneEventPrefix + "code.sent"
)
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
PhoneNumber string `json:"phone,omitempty"`
}
func (e *ChangedEvent) CheckPrevious() bool {
return true
}
func (e *ChangedEvent) Data() interface{} {
return e
}
func NewChangedEvent(ctx context.Context, phone string) *ChangedEvent {
return &ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPhoneChangedType,
),
PhoneNumber: phone,
}
}
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
phoneChangedEvent := &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, phoneChangedEvent)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5M0pd", "unable to unmarshal human phone changed")
}
return phoneChangedEvent, nil
}
type RemovedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *RemovedEvent) CheckPrevious() bool {
return true
}
func (e *RemovedEvent) Data() interface{} {
return nil
}
func NewRemovedEvent(ctx context.Context) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPhoneRemovedType,
),
}
}
func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type VerifiedEvent struct {
eventstore.BaseEvent `json:"-"`
IsPhoneVerified bool `json:"-"`
}
func (e *VerifiedEvent) CheckPrevious() bool {
return true
}
func (e *VerifiedEvent) Data() interface{} {
return nil
}
func NewVerifiedEvent(ctx context.Context) *VerifiedEvent {
return &VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPhoneVerifiedType,
),
}
}
func VerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &VerifiedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
IsPhoneVerified: true,
}, nil
}
type VerificationFailedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *VerificationFailedEvent) CheckPrevious() bool {
return true
}
func (e *VerificationFailedEvent) Data() interface{} {
return nil
}
func NewVerificationFailedEvent(ctx context.Context) *VerificationFailedEvent {
return &VerificationFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPhoneVerificationFailedType,
),
}
}
func VerificationFailedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &VerificationFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}
type CodeAddedEvent struct {
eventstore.BaseEvent `json:"-"`
Code *crypto.CryptoValue `json:"code,omitempty"`
Expiry time.Duration `json:"expiry,omitempty"`
}
func (e *CodeAddedEvent) CheckPrevious() bool {
return true
}
func (e *CodeAddedEvent) Data() interface{} {
return e
}
func NewCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
) *CodeAddedEvent {
return &CodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPhoneCodeAddedType,
),
Code: code,
Expiry: expiry,
}
}
func CodeAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
codeAdded := &CodeAddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, codeAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-6Ms9d", "unable to unmarshal human phone code added")
}
return codeAdded, nil
}
type CodeSentEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *CodeSentEvent) CheckPrevious() bool {
return false
}
func (e *CodeSentEvent) Data() interface{} {
return e
}
func NewCodeSentEvent(ctx context.Context) *CodeSentEvent {
return &CodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanPhoneCodeSentType,
),
}
}
func CodeSentEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &CodeSentEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -0,0 +1,84 @@
package profile
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"
"github.com/caos/zitadel/internal/v2/repository/user/human"
"golang.org/x/text/language"
)
const (
profileEventPrefix = eventstore.EventType("user.human.profile.")
HumanProfileChangedType = profileEventPrefix + "changed"
)
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
NickName string `json:"nickName,omitempty"`
DisplayName string `json:"displayName,omitempty"`
PreferredLanguage language.Tag `json:"preferredLanguage,omitempty"`
Gender human.Gender `json:"gender,omitempty"`
}
func (e *ChangedEvent) CheckPrevious() bool {
return true
}
func (e *ChangedEvent) Data() interface{} {
return e
}
func NewChangedEvent(
ctx context.Context,
current *WriteModel,
firstName,
lastName,
nickName,
displayName string,
preferredLanguage language.Tag,
gender human.Gender,
) *ChangedEvent {
e := &ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
HumanProfileChangedType,
),
}
if current.FirstName != firstName {
e.FirstName = firstName
}
if current.LastName != lastName {
e.LastName = lastName
}
if current.NickName != nickName {
e.NickName = nickName
}
if current.DisplayName != displayName {
e.DisplayName = displayName
}
if current.PreferredLanguage != preferredLanguage {
e.PreferredLanguage = preferredLanguage
}
if current.Gender != gender {
e.Gender = gender
}
return e
}
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
profileChanged := &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, profileChanged)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5M0pd", "unable to unmarshal human profile changed")
}
return profileChanged, nil
}

View File

@ -0,0 +1,18 @@
package profile
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/user/human"
"golang.org/x/text/language"
)
type WriteModel struct {
eventstore.WriteModel
FirstName string
LastName string
NickName string
DisplayName string
PreferredLanguage language.Tag
Gender human.Gender
}

View File

@ -0,0 +1,107 @@
package machine
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 (
machineEventPrefix = eventstore.EventType("user.machine.")
MachineAddedEventType = machineEventPrefix + "added"
MachineChangedEventType = machineEventPrefix + "changed"
)
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
func (e *AddedEvent) CheckPrevious() bool {
return false
}
func (e *AddedEvent) Data() interface{} {
return e
}
func NewAddedEvent(
ctx context.Context,
userName,
name,
description string,
) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
MachineAddedEventType,
),
UserName: userName,
Name: name,
Description: description,
}
}
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
machineAdded := &AddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, machineAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-tMv9s", "unable to unmarshal machine added")
}
return machineAdded, nil
}
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
func (e *ChangedEvent) CheckPrevious() bool {
return false
}
func (e *ChangedEvent) Data() interface{} {
return e
}
func NewChangedEvent(
ctx context.Context,
userName,
name,
description string,
) *ChangedEvent {
return &ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
MachineChangedEventType,
),
UserName: userName,
Name: name,
Description: description,
}
}
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
machineChanged := &ChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, machineChanged)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-4M9ds", "unable to unmarshal machine changed")
}
return machineChanged, nil
}

View File

@ -0,0 +1,103 @@
package keys
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"
"time"
)
const (
machineKeyEventPrefix = eventstore.EventType("user.machine.key.")
MachineKeyAddedEventType = machineKeyEventPrefix + "added"
MachineKeyRemovedEventType = machineKeyEventPrefix + "removed"
)
type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
KeyID string `json:"keyId,omitempty"`
Type MachineKeyType `json:"type,omitempty"`
ExpirationDate time.Time `json:"expirationDate,omitempty"`
PublicKey []byte `json:"publicKey,omitempty"`
}
func (e *AddedEvent) CheckPrevious() bool {
return false
}
func (e *AddedEvent) Data() interface{} {
return e
}
func NewAddedEvent(
ctx context.Context,
keyID string,
keyType MachineKeyType,
expirationDate time.Time,
publicKey []byte,
) *AddedEvent {
return &AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
MachineKeyAddedEventType,
),
KeyID: keyID,
Type: keyType,
ExpirationDate: expirationDate,
PublicKey: publicKey,
}
}
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
machineAdded := &AddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, machineAdded)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-rEs8f", "unable to unmarshal machine key added")
}
return machineAdded, nil
}
type RemovedEvent struct {
eventstore.BaseEvent `json:"-"`
KeyID string `json:"keyId,omitempty"`
}
func (e *RemovedEvent) CheckPrevious() bool {
return false
}
func (e *RemovedEvent) Data() interface{} {
return e
}
func NewRemovedEvent(
ctx context.Context,
keyID string,
) *RemovedEvent {
return &RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
MachineKeyRemovedEventType,
),
KeyID: keyID,
}
}
func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
machineRemoved := &RemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, machineRemoved)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-5Gm9s", "unable to unmarshal machine key removed")
}
return machineRemoved, nil
}

View File

@ -0,0 +1,14 @@
package keys
type MachineKeyType int32
const (
MachineKeyTypeNONE = iota
MachineKeyTypeJSON
keyCount
)
func (f MachineKeyType) Valid() bool {
return f >= 0 && f < keyCount
}

View File

@ -0,0 +1,52 @@
package user
import (
"github.com/caos/zitadel/internal/eventstore/v2"
)
type ReadModel struct {
eventstore.ReadModel
}
func NewReadModel(id string) *ReadModel {
return &ReadModel{
ReadModel: eventstore.ReadModel{
AggregateID: id,
},
}
}
func (rm *ReadModel) AppendEvents(events ...eventstore.EventReader) {
rm.ReadModel.AppendEvents(events...)
for _, event := range events {
switch event.(type) {
// TODO: implement append events
}
}
}
func (rm *ReadModel) Reduce() (err error) {
for _, event := range rm.Events {
switch event.(type) {
//TODO: implement reduce
}
}
for _, reduce := range []func() error{
rm.ReadModel.Reduce,
} {
if err = reduce(); err != nil {
return err
}
}
return nil
}
func (rm *ReadModel) AppendAndReduce(events ...eventstore.EventReader) error {
rm.AppendEvents(events...)
return rm.Reduce()
}
func (rm *ReadModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, AggregateType).AggregateIDs(rm.AggregateID)
}

View File

@ -0,0 +1,469 @@
package v1
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/user/human"
"github.com/caos/zitadel/internal/v2/repository/user/human/address"
"github.com/caos/zitadel/internal/v2/repository/user/human/email"
"github.com/caos/zitadel/internal/v2/repository/user/human/mfa"
"github.com/caos/zitadel/internal/v2/repository/user/human/mfa/otp"
"github.com/caos/zitadel/internal/v2/repository/user/human/password"
"github.com/caos/zitadel/internal/v2/repository/user/human/phone"
"github.com/caos/zitadel/internal/v2/repository/user/human/profile"
"golang.org/x/text/language"
"time"
)
const (
userEventTypePrefix = eventstore.EventType("user.")
UserV1AddedType = userEventTypePrefix + "added"
UserV1RegisteredType = userEventTypePrefix + "selfregistered"
UserV1InitialCodeAddedType = userEventTypePrefix + "initialization.code.added"
UserV1InitialCodeSentType = userEventTypePrefix + "initialization.code.sent"
UserV1InitializedCheckSucceededType = userEventTypePrefix + "initialization.check.succeeded"
UserV1InitializedCheckFailedType = userEventTypePrefix + "initialization.check.failed"
UserV1SignedOutType = userEventTypePrefix + "signed.out"
userV1PasswordEventTypePrefix = userEventTypePrefix + "password."
UserV1PasswordChangedType = userV1PasswordEventTypePrefix + "changed"
UserV1PasswordCodeAddedType = userV1PasswordEventTypePrefix + "code.added"
UserV1PasswordCodeSentType = userV1PasswordEventTypePrefix + "code.sent"
UserV1PasswordCheckSucceededType = userV1PasswordEventTypePrefix + "check.succeeded"
UserV1PasswordCheckFailedType = userV1PasswordEventTypePrefix + "check.failed"
userV1EmailEventTypePrefix = userEventTypePrefix + "email."
UserV1EmailChangedType = userV1EmailEventTypePrefix + "changed"
UserV1EmailVerifiedType = userV1EmailEventTypePrefix + "verified"
UserV1EmailVerificationFailedType = userV1EmailEventTypePrefix + "verification.failed"
UserV1EmailCodeAddedType = userV1EmailEventTypePrefix + "code.added"
UserV1EmailCodeSentType = userV1EmailEventTypePrefix + "code.sent"
userV1PhoneEventTypePrefix = userEventTypePrefix + "phone."
UserV1PhoneChangedType = userV1PhoneEventTypePrefix + "changed"
UserV1PhoneRemovedType = userV1PhoneEventTypePrefix + "removed"
UserV1PhoneVerifiedType = userV1PhoneEventTypePrefix + "verified"
UserV1PhoneVerificationFailedType = userV1PhoneEventTypePrefix + "verification.failed"
UserV1PhoneCodeAddedType = userV1PhoneEventTypePrefix + "code.added"
UserV1PhoneCodeSentType = userV1PhoneEventTypePrefix + "code.sent"
userV1ProfileEventTypePrefix = userEventTypePrefix + "profile."
UserV1ProfileChangedType = userV1ProfileEventTypePrefix + "changed"
userV1AddressEventTypePrefix = userEventTypePrefix + "address."
UserV1AddressChangedType = userV1AddressEventTypePrefix + "changed"
userV1MFAEventTypePrefix = userEventTypePrefix + "mfa."
UserV1MFAInitSkippedType = userV1MFAOTPEventTypePrefix + "init.skipped"
userV1MFAOTPEventTypePrefix = userV1MFAEventTypePrefix + "otp."
UserV1MFAOTPAddedType = userV1MFAOTPEventTypePrefix + "added"
UserV1MFAOTPRemovedType = userV1MFAOTPEventTypePrefix + "removed"
UserV1MFAOTPVerifiedType = userV1MFAOTPEventTypePrefix + "verified"
UserV1MFAOTPCheckSucceededType = userV1MFAOTPEventTypePrefix + "check.succeeded"
UserV1MFAOTPCheckFailedType = userV1MFAOTPEventTypePrefix + "check.failed"
)
func NewUserV1AddedEvent(
ctx context.Context,
userName,
firstName,
lastName,
nickName,
displayName string,
preferredLanguage language.Tag,
gender human.Gender,
emailAddress,
phoneNumber,
country,
locality,
postalCode,
region,
streetAddress string,
) *human.AddedEvent {
return &human.AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1AddedType,
),
UserName: userName,
FirstName: firstName,
LastName: lastName,
NickName: nickName,
DisplayName: displayName,
PreferredLanguage: preferredLanguage,
Gender: gender,
EmailAddress: emailAddress,
PhoneNumber: phoneNumber,
Country: country,
Locality: locality,
PostalCode: postalCode,
Region: region,
StreetAddress: streetAddress,
}
}
func NewUserV1RegisteredEvent(
ctx context.Context,
userName,
firstName,
lastName,
nickName,
displayName string,
preferredLanguage language.Tag,
gender int32,
emailAddress,
phoneNumber,
country,
locality,
postalCode,
region,
streetAddress string,
) *human.RegisteredEvent {
return &human.RegisteredEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1RegisteredType,
),
UserName: userName,
FirstName: firstName,
LastName: lastName,
NickName: nickName,
DisplayName: displayName,
PreferredLanguage: preferredLanguage,
Gender: gender,
EmailAddress: emailAddress,
PhoneNumber: phoneNumber,
Country: country,
Locality: locality,
PostalCode: postalCode,
Region: region,
StreetAddress: streetAddress,
}
}
func NewUserV1InitialCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
) *human.InitialCodeAddedEvent {
return &human.InitialCodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1InitialCodeAddedType,
),
Code: code,
Expiry: expiry,
}
}
func NewUserV1InitialCodeSentEvent(ctx context.Context) *human.InitialCodeSentEvent {
return &human.InitialCodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1InitialCodeSentType,
),
}
}
func NewUserV1InitializedCheckSucceededEvent(ctx context.Context) *human.InitializedCheckSucceededEvent {
return &human.InitializedCheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1InitializedCheckSucceededType,
),
}
}
func NewUserV1InitializedCheckFailedEvent(ctx context.Context) *human.InitializedCheckFailedEvent {
return &human.InitializedCheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1InitializedCheckFailedType,
),
}
}
func NewUserV1SignedOutEvent(ctx context.Context) *human.SignedOutEvent {
return &human.SignedOutEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1SignedOutType,
),
}
}
func NewUserV1PasswordChangedEvent(
ctx context.Context,
secret *crypto.CryptoValue,
changeRequired bool,
) *password.ChangedEvent {
return &password.ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PasswordChangedType,
),
Secret: secret,
ChangeRequired: changeRequired,
}
}
func NewUserV1PasswordCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
notificationType human.NotificationType,
) *password.CodeAddedEvent {
return &password.CodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PasswordCodeAddedType,
),
Code: code,
Expiry: expiry,
NotificationType: notificationType,
}
}
func NewUserV1PasswordCodeSentEvent(ctx context.Context) *password.CodeSentEvent {
return &password.CodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PasswordCodeSentType,
),
}
}
func NewUserV1PasswordCheckSucceededEvent(ctx context.Context) *password.CheckSucceededEvent {
return &password.CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PasswordCheckSucceededType,
),
}
}
func NewUserV1PasswordCheckFailedEvent(ctx context.Context) *password.CheckFailedEvent {
return &password.CheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PasswordCheckFailedType,
),
}
}
func NewUserV1EmailChangedEvent(ctx context.Context, emailAddress string) *email.ChangedEvent {
return &email.ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1EmailChangedType,
),
EmailAddress: emailAddress,
}
}
func NewUserV1EmailVerifiedEvent(ctx context.Context) *email.VerifiedEvent {
return &email.VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1EmailVerifiedType,
),
}
}
func NewUserV1EmailVerificationFailedEvent(ctx context.Context) *email.VerificationFailedEvent {
return &email.VerificationFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1EmailVerificationFailedType,
),
}
}
func NewUserV1EmailCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
) *email.CodeAddedEvent {
return &email.CodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1EmailCodeAddedType,
),
Code: code,
Expiry: expiry,
}
}
func NewUserV1EmailCodeSentEvent(ctx context.Context) *email.CodeSentEvent {
return &email.CodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1EmailCodeSentType,
),
}
}
func NewUserV1PhoneChangedEvent(ctx context.Context, phone string) *phone.ChangedEvent {
return phone.HumanPhoneChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PhoneChangedType,
),
PhoneNumber: phone,
}
}
func NewUserV1PhoneRemovedEvent(ctx context.Context) *phone.RemovedEvent {
return &phone.RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PhoneRemovedType,
),
}
}
func NewUserV1PhoneVerifiedEvent(ctx context.Context) *phone.VerifiedEvent {
return &phone.VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PhoneVerifiedType,
),
}
}
func NewUserV1PhoneVerificationFailedEvent(ctx context.Context) *phone.VerificationFailedEvent {
return &phone.VerificationFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PhoneVerificationFailedType,
),
}
}
func NewUserV1PhoneCodeAddedEvent(
ctx context.Context,
code *crypto.CryptoValue,
expiry time.Duration,
) *phone.CodeAddedEvent {
return &phone.CodeAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PhoneCodeAddedType,
),
Code: code,
Expiry: expiry,
}
}
func NewUserV1PhoneCodeSentEvent(ctx context.Context) *phone.CodeSentEvent {
return &phone.CodeSentEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1PhoneCodeSentType,
),
}
}
func NewUserV1ProfileChangedEvent(
ctx context.Context,
firstName,
lastName,
nickName,
displayName string,
preferredLanguage language.Tag,
gender human.Gender,
) *profile.ChangedEvent {
return &profile.ChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1ProfileChangedType,
),
FirstName: firstName,
LastName: lastName,
NickName: nickName,
DisplayName: displayName,
PreferredLanguage: preferredLanguage,
Gender: gender,
}
}
func NewUserV1AddressChangedEvent(
ctx context.Context,
country,
locality,
postalCode,
region,
streetAddress string,
) *address.HumanAddressChangedEvent {
return &address.HumanAddressChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1AddressChangedType,
),
Country: country,
Locality: locality,
PostalCode: postalCode,
Region: region,
StreetAddress: streetAddress,
}
}
func NewUserV1MFAInitSkippedEvent(ctx context.Context) *mfa.InitSkippedEvent {
return &mfa.InitSkippedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1MFAInitSkippedType,
),
}
}
func NewUserV1MFAOTPAddedEvent(
ctx context.Context,
secret *crypto.CryptoValue,
) *otp.AddedEvent {
return &otp.AddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1MFAOTPAddedType,
),
Secret: secret,
}
}
func NewUserV1MFAOTPVerifiedEvent(ctx context.Context) *otp.VerifiedEvent {
return &otp.VerifiedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1MFAOTPVerifiedType,
),
}
}
func NewUserV1MFAOTPRemovedEvent(ctx context.Context) *otp.RemovedEvent {
return &otp.RemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1MFAOTPRemovedType,
),
}
}
func NewUserV1MFAOTPCheckSucceededEvent(ctx context.Context) *otp.CheckSucceededEvent {
return &otp.CheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1MFAOTPCheckSucceededType,
),
}
}
func NewUserV1MFAOTPCheckFailedEvent(ctx context.Context) *otp.CheckFailedEvent {
return &otp.CheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserV1MFAOTPCheckFailedType,
),
}
}