fix: commandside queries (#1313)

* fix: move user by id to query side

* fix: move get passwordless to query side

# Conflicts:
#	internal/user/repository/eventsourcing/eventstore.go

* fix: move get passwordless to query side

* remove user eventstore

* remove unused models

* org changes

* org changes

* fix: move org queries to query side

* fix: remove org eventstore

* fix: remove org eventstore

* fix: remove org eventstore

* remove project from es v1

* project cleanup

* project cleanup

* fix: remove org eventstore

* fix: remove iam eventstore

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Fabi 2021-02-22 14:08:47 +01:00 committed by GitHub
parent 2ba56595b1
commit 428ef4acdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
106 changed files with 2301 additions and 2799 deletions

View File

@ -1,11 +0,0 @@
package model
import (
org_model "github.com/caos/zitadel/internal/org/model"
usr_model "github.com/caos/zitadel/internal/user/model"
)
type SetupOrg struct {
*org_model.Org
*usr_model.User
}

View File

@ -2,7 +2,11 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
"strings"
caos_errs "github.com/caos/zitadel/internal/errors"
@ -11,19 +15,14 @@ import (
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type IAMRepository struct {
SearchLimit uint64
*iam_es.IAMEventstore
OrgEvents *org_es.OrgEventstore
UserEvents *usr_es.UserEventstore
Eventstore eventstore.Eventstore
SearchLimit uint64
View *admin_view.View
SystemDefaults systemdefaults.SystemDefaults
Roles []string
@ -130,7 +129,7 @@ func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_mode
if caos_errs.IsNotFound(viewErr) {
policy = new(iam_es_model.LoginPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.LoginPolicy.NotFound")
}
@ -199,7 +198,7 @@ func (repo *IAMRepository) GetDefaultPasswordComplexityPolicy(ctx context.Contex
if caos_errs.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordComplexityPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-1Mc0s", "Errors.IAM.PasswordComplexityPolicy.NotFound")
}
@ -224,7 +223,7 @@ func (repo *IAMRepository) GetDefaultPasswordAgePolicy(ctx context.Context) (*ia
if caos_errs.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordAgePolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-vMyS3", "Errors.IAM.PasswordAgePolicy.NotFound")
}
@ -249,7 +248,7 @@ func (repo *IAMRepository) GetDefaultPasswordLockoutPolicy(ctx context.Context)
if caos_errs.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordLockoutPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2M9oP", "Errors.IAM.PasswordLockoutPolicy.NotFound")
}
@ -274,7 +273,7 @@ func (repo *IAMRepository) GetOrgIAMPolicy(ctx context.Context) (*iam_model.OrgI
if caos_errs.IsNotFound(viewErr) {
policy = new(iam_es_model.OrgIAMPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-MkoL0", "Errors.IAM.OrgIAMPolicy.NotFound")
}
@ -344,3 +343,11 @@ func (repo *IAMRepository) GetDefaultMailText(ctx context.Context, textType stri
text.Default = true
return iam_es_model.MailTextViewToModel(text), err
}
func (repo *IAMRepository) getIAMEvents(ctx context.Context, sequence uint64) ([]*models.Event, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, sequence)
if err != nil {
return nil, err
}
return repo.Eventstore.FilterEvents(ctx, query)
}

View File

@ -2,9 +2,12 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/logging"
@ -13,15 +16,11 @@ import (
"github.com/caos/zitadel/internal/eventstore"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/org/repository/view/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type OrgRepo struct {
Eventstore eventstore.Eventstore
OrgEventstore *org_es.OrgEventstore
UserEventstore *usr_es.UserEventstore
Eventstore eventstore.Eventstore
View *admin_view.View
@ -29,8 +28,29 @@ type OrgRepo struct {
SystemDefaults systemdefaults.SystemDefaults
}
func (repo *OrgRepo) OrgByID(ctx context.Context, id string) (*org_model.Org, error) {
return repo.OrgEventstore.OrgByID(ctx, org_model.NewOrg(id))
func (repo *OrgRepo) OrgByID(ctx context.Context, id string) (*org_model.OrgView, error) {
org, viewErr := repo.View.OrgByID(id)
if viewErr != nil && !errors.IsNotFound(viewErr) {
return nil, viewErr
}
if errors.IsNotFound(viewErr) {
org = new(model.OrgView)
}
events, esErr := repo.getOrgEvents(ctx, id, org.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-Lsoj7", "Errors.Org.NotFound")
}
if esErr != nil {
logging.Log("EVENT-PSoc3").WithError(esErr).Debug("error retrieving new events")
return model.OrgToModel(org), nil
}
orgCopy := *org
for _, event := range events {
if err := orgCopy.AppendEvent(event); err != nil {
return model.OrgToModel(&orgCopy), nil
}
}
return model.OrgToModel(&orgCopy), nil
}
func (repo *OrgRepo) SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error) {
@ -55,7 +75,18 @@ func (repo *OrgRepo) SearchOrgs(ctx context.Context, query *org_model.OrgSearchR
}
func (repo *OrgRepo) IsOrgUnique(ctx context.Context, name, domain string) (isUnique bool, err error) {
return repo.OrgEventstore.IsOrgUnique(ctx, name, domain)
var found bool
err = es_sdk.Filter(ctx, repo.Eventstore.FilterEvents, isUniqueValidation(&found), view.OrgNameUniqueQuery(name))
if (err != nil && !errors.IsNotFound(err)) || found {
return false, err
}
err = es_sdk.Filter(ctx, repo.Eventstore.FilterEvents, isUniqueValidation(&found), view.OrgDomainUniqueQuery(domain))
if err != nil && !errors.IsNotFound(err) {
return false, err
}
return !found, nil
}
func (repo *OrgRepo) GetOrgIAMPolicyByID(ctx context.Context, id string) (*iam_model.OrgIAMPolicyView, error) {
@ -77,3 +108,22 @@ func (repo *OrgRepo) GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.Org
policy.Default = true
return iam_es_model.OrgIAMViewToModel(policy), err
}
func (repo *OrgRepo) getOrgEvents(ctx context.Context, orgID string, sequence uint64) ([]*models.Event, error) {
query, err := view.OrgByIDQuery(orgID, sequence)
if err != nil {
return nil, err
}
return repo.Eventstore.FilterEvents(ctx, query)
}
func isUniqueValidation(unique *bool) func(events ...*models.Event) error {
return func(events ...*models.Event) error {
if len(events) == 0 {
return nil
}
*unique = *unique || events[0].Type == org_es_model.OrgDomainReserved || events[0].Type == org_es_model.OrgNameReserved
return nil
}
}

View File

@ -1,36 +0,0 @@
package eventstore
import (
admin_model "github.com/caos/zitadel/internal/admin/model"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
type Setup struct {
*model.Org
*usr_es.User
}
func (s *Setup) AppendEvents(events ...*es_models.Event) error {
for _, event := range events {
var err error
switch event.AggregateType {
case model.OrgAggregate:
err = s.Org.AppendEvent(event)
case usr_es.UserAggregate:
err = s.User.AppendEvent(event)
}
if err != nil {
return err
}
}
return nil
}
func SetupToModel(setup *Setup) *admin_model.SetupOrg {
return &admin_model.SetupOrg{
Org: model.OrgToModel(setup.Org),
User: usr_es.UserToModel(setup.User),
}
}

View File

@ -8,9 +8,6 @@ import (
"github.com/caos/zitadel/internal/config/types"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/query"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type Configs map[string]*Config
@ -32,19 +29,12 @@ func (h *handler) Eventstore() eventstore.Eventstore {
return h.es
}
type EventstoreRepos struct {
UserEvents *usr_event.UserEventstore
IamEvents *iam_event.IAMEventstore
OrgEvents *org_event.OrgEventstore
}
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, defaults systemdefaults.SystemDefaults) []query.Handler {
return []query.Handler{
newOrg(
handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}),
newIAMMember(
handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount, es},
repos.UserEvents),
handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount, es}),
newIDPConfig(
handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}),
newLabelPolicy(
@ -53,13 +43,9 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount, es}),
newIDPProvider(
handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es},
defaults,
repos.IamEvents,
repos.OrgEvents),
defaults),
newUser(
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
repos.OrgEvents,
repos.IamEvents,
defaults),
newPasswordComplexityPolicy(
handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount, es}),
@ -71,9 +57,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
newExternalIDP(
handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es},
defaults,
repos.IamEvents,
repos.OrgEvents),
defaults),
newMailTemplate(
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
newMailText(

View File

@ -2,16 +2,19 @@ package handler
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/user/repository/view"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
@ -21,14 +24,12 @@ const (
type IAMMember struct {
handler
userEvents *usr_event.UserEventstore
subscription *eventstore.Subscription
}
func newIAMMember(handler handler, userEvents *usr_event.UserEventstore) *IAMMember {
func newIAMMember(handler handler) *IAMMember {
iamMember := &IAMMember{
handler: handler,
userEvents: userEvents,
handler: handler,
}
iamMember.subscribe()
@ -129,7 +130,7 @@ func (m *IAMMember) processUser(event *es_models.Event) (err error) {
if len(members) == 0 {
return m.view.ProcessedIAMMemberSequence(event)
}
user, err := m.userEvents.UserByID(context.Background(), event.AggregateID)
user, err := m.getUserByID(event.AggregateID)
if err != nil {
return err
}
@ -145,7 +146,7 @@ func (m *IAMMember) processUser(event *es_models.Event) (err error) {
}
func (m *IAMMember) fillData(member *iam_model.IAMMemberView) (err error) {
user, err := m.userEvents.UserByID(context.Background(), member.UserID)
user, err := m.getUserByID(member.UserID)
if err != nil {
return err
}
@ -153,16 +154,16 @@ func (m *IAMMember) fillData(member *iam_model.IAMMemberView) (err error) {
return nil
}
func (m *IAMMember) fillUserData(member *iam_model.IAMMemberView, user *usr_model.User) {
func (m *IAMMember) fillUserData(member *iam_model.IAMMemberView, user *view_model.UserView) {
member.UserName = user.UserName
if user.Human != nil {
if user.HumanView != nil {
member.FirstName = user.FirstName
member.LastName = user.LastName
member.DisplayName = user.FirstName + " " + user.LastName
member.Email = user.EmailAddress
member.Email = user.Email
}
if user.Machine != nil {
member.DisplayName = user.Machine.Name
if user.MachineView != nil {
member.DisplayName = user.MachineView.Name
}
}
func (m *IAMMember) OnError(event *es_models.Event, err error) error {
@ -173,3 +174,36 @@ func (m *IAMMember) OnError(event *es_models.Event, err error) error {
func (m *IAMMember) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateIAMMemberSpoolerRunTimestamp)
}
func (m *IAMMember) getUserByID(userID string) (*view_model.UserView, error) {
user, usrErr := m.view.UserByID(userID)
if usrErr != nil && !caos_errs.IsNotFound(usrErr) {
return nil, usrErr
}
if user == nil {
user = &view_model.UserView{}
}
events, err := m.getUserEvents(userID, user.Sequence)
if err != nil {
return user, usrErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user, nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "HANDLER-4n9fs", "Errors.User.NotFound")
}
return &userCopy, nil
}
func (m *IAMMember) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return m.es.FilterEvents(context.Background(), query)
}

View File

@ -2,6 +2,12 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/errors"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
@ -10,10 +16,8 @@ import (
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
@ -24,22 +28,16 @@ const (
type IDPProvider struct {
handler
systemDefaults systemdefaults.SystemDefaults
iamEvents *eventsourcing.IAMEventstore
orgEvents *org_events.OrgEventstore
subscription *eventstore.Subscription
}
func newIDPProvider(
handler handler,
systemDefaults systemdefaults.SystemDefaults,
iamEvents *eventsourcing.IAMEventstore,
orgEvents *org_events.OrgEventstore,
) *IDPProvider {
h := &IDPProvider{
handler: handler,
systemDefaults: systemDefaults,
iamEvents: iamEvents,
orgEvents: orgEvents,
}
h.subscribe()
@ -117,7 +115,7 @@ func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
if err != nil {
return err
}
config, err := i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err := i.getDefaultIDPConfig(context.Background(), esConfig.IDPConfigID)
if err != nil {
return err
}
@ -137,9 +135,9 @@ func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
var config *iam_model.IDPConfig
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, provider.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), provider.IDPConfigID)
} else {
config, err = i.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
config, err = i.getOrgIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
}
if err != nil {
return err
@ -163,3 +161,64 @@ func (i *IDPProvider) OnError(event *es_models.Event, err error) error {
func (i *IDPProvider) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp)
}
func (i *IDPProvider) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-4m0fs", "Errors.Org.IdpNotExisting")
}
func (i *IDPProvider) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: es_models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-4m9gs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *IDPProvider) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *IDPProvider) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-4M=Fs", "Errors.IAM.IdpNotExisting")
}

View File

@ -2,12 +2,12 @@ package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/repository/view/model"
)
@ -53,7 +53,7 @@ func (o *Org) EventQuery() (*es_models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.OrgQuery(sequence.CurrentSequence), nil
return view.OrgQuery(sequence.CurrentSequence), nil
}
func (o *Org) CurrentSequence() (uint64, error) {

View File

@ -2,9 +2,15 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
caos_errs "github.com/caos/zitadel/internal/errors"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"k8s.io/apimachinery/pkg/api/errors"
"github.com/caos/logging"
@ -14,7 +20,6 @@ import (
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
org_model "github.com/caos/zitadel/internal/org/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -27,22 +32,16 @@ const (
type User struct {
handler
eventstore eventstore.Eventstore
orgEvents *org_events.OrgEventstore
iamEvents *iam_es.IAMEventstore
systemDefaults systemdefaults.SystemDefaults
subscription *eventstore.Subscription
}
func newUser(
handler handler,
orgEvents *org_events.OrgEventstore,
iamEvents *iam_es.IAMEventstore,
systemDefaults systemdefaults.SystemDefaults,
) *User {
h := &User{
handler: handler,
orgEvents: orgEvents,
iamEvents: iamEvents,
systemDefaults: systemDefaults,
}
@ -184,13 +183,13 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
}
func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.systemDefaults.IamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -206,13 +205,13 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
}
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.systemDefaults.IamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -231,17 +230,18 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
}
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(user.ResourceOwner))
org, err := u.getOrgByID(context.Background(), user.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.systemDefaults.IamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
}
user.SetLoginNames(policy, org.Domains)
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
return nil
@ -255,3 +255,53 @@ func (u *User) OnError(event *models.Event, err error) error {
func (u *User) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp)
}
func (u *User) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.eventstore.FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *User) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.eventstore.FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *User) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2Fj8s", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
}

View File

@ -2,24 +2,25 @@ package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -29,22 +30,16 @@ const (
type ExternalIDP struct {
handler
systemDefaults systemdefaults.SystemDefaults
iamEvents *eventsourcing.IAMEventstore
orgEvents *org_es.OrgEventstore
subscription *eventstore.Subscription
}
func newExternalIDP(
handler handler,
systemDefaults systemdefaults.SystemDefaults,
iamEvents *eventsourcing.IAMEventstore,
orgEvents *org_es.OrgEventstore,
) *ExternalIDP {
h := &ExternalIDP{
handler: handler,
systemDefaults: systemDefaults,
iamEvents: iamEvents,
orgEvents: orgEvents,
}
h.subscribe()
@ -138,9 +133,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), configView.IDPConfigID)
} else {
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.getOrgIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err
@ -155,9 +150,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
}
func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
config, err := i.getOrgIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
if caos_errs.IsNotFound(err) {
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), externalIDP.IDPConfigID)
}
if err != nil {
return err
@ -178,3 +173,64 @@ func (i *ExternalIDP) OnError(event *models.Event, err error) error {
func (i *ExternalIDP) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp)
}
func (i *ExternalIDP) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2n8Fh", "Errors.Org.IdpNotExisting")
}
func (i *ExternalIDP) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-MOFMs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *ExternalIDP) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}
func (u *ExternalIDP) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-49O0f", "Errors.IAM.IdpNotExisting")
}

View File

@ -3,16 +3,12 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/eventstore"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/handler"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/spooler"
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/config/types"
es_int "github.com/caos/zitadel/internal/eventstore"
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type Config struct {
@ -35,23 +31,6 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
if err != nil {
return nil, err
}
iam, err := es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
org := es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: conf.Domain}, systemDefaults)
user, err := es_usr.StartUser(es_usr.UserConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
sqlClient, err := conf.View.Start()
if err != nil {
return nil, err
@ -61,22 +40,18 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
return nil, err
}
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, handler.EventstoreRepos{UserEvents: user, OrgEvents: org, IamEvents: iam}, systemDefaults)
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
return &EsRepository{
spooler: spool,
OrgRepo: eventstore.OrgRepo{
Eventstore: es,
OrgEventstore: org,
UserEventstore: user,
View: view,
SearchLimit: conf.SearchLimit,
SystemDefaults: systemDefaults,
},
IAMRepository: eventstore.IAMRepository{
IAMEventstore: iam,
OrgEvents: org,
UserEvents: user,
Eventstore: es,
View: view,
SystemDefaults: systemDefaults,
SearchLimit: conf.SearchLimit,
@ -89,13 +64,5 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
}
func (repo *EsRepository) Health(ctx context.Context) error {
err := repo.Eventstore.Health(ctx)
if err != nil {
return err
}
err = repo.UserEventstore.Health(ctx)
if err != nil {
return err
}
return repo.OrgEventstore.Health(ctx)
return nil
}

View File

@ -17,12 +17,12 @@ type SpoolerConfig struct {
Handlers handler.Configs
}
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, repos handler.EventstoreRepos, defaults systemdefaults.SystemDefaults) *spooler.Spooler {
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, defaults systemdefaults.SystemDefaults) *spooler.Spooler {
spoolerConfig := spooler.Config{
Eventstore: es,
Locker: &locker{dbClient: sql},
ConcurrentWorkers: c.ConcurrentWorkers,
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, repos, defaults),
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, defaults),
}
spool := spoolerConfig.New()
spool.Start()

View File

@ -10,7 +10,7 @@ import (
type OrgRepository interface {
IsOrgUnique(ctx context.Context, name, domain string) (bool, error)
OrgByID(ctx context.Context, id string) (*org_model.Org, error)
OrgByID(ctx context.Context, id string) (*org_model.OrgView, error)
SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error)
GetOrgIAMPolicyByID(ctx context.Context, id string) (*iam_model.OrgIAMPolicyView, error)

View File

@ -14,7 +14,7 @@ func (s *Server) GetOrgByID(ctx context.Context, orgID *admin.OrgID) (_ *admin.O
if err != nil {
return nil, err
}
return orgFromModel(org), nil
return orgViewFromModel(org), nil
}
func (s *Server) SearchOrgs(ctx context.Context, request *admin.OrgSearchRequest) (_ *admin.OrgSearchResponse, err error) {

View File

@ -8,7 +8,6 @@ import (
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
admin_model "github.com/caos/zitadel/internal/admin/model"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/model"
org_model "github.com/caos/zitadel/internal/org/model"
@ -28,13 +27,6 @@ func orgCreateRequestToDomain(org *admin.CreateOrgRequest) *domain.Org {
return o
}
func setUpOrgResponseFromModel(setUp *admin_model.SetupOrg) *admin.OrgSetUpResponse {
return &admin.OrgSetUpResponse{
Org: orgFromModel(setUp.Org),
User: userFromModel(setUp.User),
}
}
func orgSearchResponseFromModel(request *org_model.OrgSearchResult) *admin.OrgSearchResponse {
timestamp, err := ptypes.TimestampProto(request.Timestamp)
logging.Log("GRPC-shu7s").OnError(err).Debug("unable to get timestamp from time")

View File

@ -6,7 +6,6 @@ import (
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
"golang.org/x/text/language"
)
@ -77,125 +76,6 @@ func machineCreateToDomain(machine *admin.CreateMachineRequest) *domain.Machine
}
}
func userCreateRequestToModel(user *admin.CreateUserRequest) *usr_model.User {
var human *usr_model.Human
var machine *usr_model.Machine
if h := user.GetHuman(); h != nil {
human = humanCreateToModel(h)
}
if m := user.GetMachine(); m != nil {
machine = machineCreateToModel(m)
}
return &usr_model.User{
UserName: user.UserName,
Human: human,
Machine: machine,
}
}
func humanCreateToModel(u *admin.CreateHumanRequest) *usr_model.Human {
preferredLanguage, err := language.Parse(u.PreferredLanguage)
logging.Log("GRPC-1ouQc").OnError(err).Debug("language malformed")
human := &usr_model.Human{
Profile: &usr_model.Profile{
FirstName: u.FirstName,
LastName: u.LastName,
NickName: u.NickName,
PreferredLanguage: preferredLanguage,
Gender: genderToModel(u.Gender),
},
Email: &usr_model.Email{
EmailAddress: u.Email,
IsEmailVerified: u.IsEmailVerified,
},
Address: &usr_model.Address{
Country: u.Country,
Locality: u.Locality,
PostalCode: u.PostalCode,
Region: u.Region,
StreetAddress: u.StreetAddress,
},
}
if u.Password != "" {
human.Password = &usr_model.Password{SecretString: u.Password}
}
if u.Phone != "" {
human.Phone = &usr_model.Phone{PhoneNumber: u.Phone, IsPhoneVerified: u.IsPhoneVerified}
}
return human
}
func machineCreateToModel(machine *admin.CreateMachineRequest) *usr_model.Machine {
return &usr_model.Machine{
Name: machine.Name,
Description: machine.Description,
}
}
func userFromModel(user *usr_model.User) *admin.UserResponse {
creationDate, err := ptypes.TimestampProto(user.CreationDate)
logging.Log("GRPC-yo0FW").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(user.ChangeDate)
logging.Log("GRPC-jxoQr").OnError(err).Debug("unable to parse timestamp")
userResp := &admin.UserResponse{
Id: user.AggregateID,
State: userStateFromModel(user.State),
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: user.Sequence,
UserName: user.UserName,
}
if user.Machine != nil {
userResp.User = &admin.UserResponse_Machine{Machine: machineFromModel(user.Machine)}
}
if user.Human != nil {
userResp.User = &admin.UserResponse_Human{Human: humanFromModel(user.Human)}
}
return userResp
}
func machineFromModel(account *usr_model.Machine) *admin.MachineResponse {
return &admin.MachineResponse{
Name: account.Name,
Description: account.Description,
}
}
func humanFromModel(user *usr_model.Human) *admin.HumanResponse {
human := &admin.HumanResponse{
FirstName: user.FirstName,
LastName: user.LastName,
DisplayName: user.DisplayName,
NickName: user.NickName,
PreferredLanguage: user.PreferredLanguage.String(),
Gender: genderFromModel(user.Gender),
}
if user.Email != nil {
human.Email = user.EmailAddress
human.IsEmailVerified = user.IsEmailVerified
}
if user.Phone != nil {
human.Phone = user.PhoneNumber
human.IsPhoneVerified = user.IsPhoneVerified
}
if user.Address != nil {
human.Country = user.Country
human.Locality = user.Locality
human.PostalCode = user.PostalCode
human.Region = user.Region
human.StreetAddress = user.StreetAddress
}
return human
}
func externalIDPViewsToDomain(idps []*usr_model.ExternalIDPView) []*domain.ExternalIDP {
externalIDPs := make([]*domain.ExternalIDP, len(idps))
for i, idp := range idps {

View File

@ -438,7 +438,7 @@ func verifyWebAuthNFromDomain(u2f *domain.WebAuthNToken) *auth.WebAuthNResponse
}
}
func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNToken) *auth.WebAuthNTokens {
func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNView) *auth.WebAuthNTokens {
result := make([]*auth.WebAuthNToken, len(tokens))
for i, token := range tokens {
result[i] = webAuthNTokenFromModel(token)
@ -446,10 +446,10 @@ func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNToken) *auth.WebAuthNTo
return &auth.WebAuthNTokens{Tokens: result}
}
func webAuthNTokenFromModel(token *usr_model.WebAuthNToken) *auth.WebAuthNToken {
func webAuthNTokenFromModel(token *usr_model.WebAuthNView) *auth.WebAuthNToken {
return &auth.WebAuthNToken{
Id: token.WebAuthNTokenID,
Name: token.WebAuthNTokenName,
Id: token.TokenID,
Name: token.Name,
State: auth.MFAState(token.State),
}
}

View File

@ -9,7 +9,7 @@ import (
)
func (s *Server) GetIam(ctx context.Context, _ *empty.Empty) (*management.Iam, error) {
iam, err := s.iam.IAMByID(ctx, s.systemDefaults.IamID)
iam, err := s.project.GetIAMByID(ctx)
if err != nil {
return nil, err
}

View File

@ -624,7 +624,7 @@ func userChangesToMgtAPI(changes *usr_model.UserChanges) (_ []*management.Change
return result
}
func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNToken) *management.WebAuthNTokens {
func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNView) *management.WebAuthNTokens {
result := make([]*management.WebAuthNToken, len(tokens))
for i, token := range tokens {
result[i] = webAuthNTokenFromModel(token)
@ -632,10 +632,10 @@ func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNToken) *management.WebA
return &management.WebAuthNTokens{Tokens: result}
}
func webAuthNTokenFromModel(token *usr_model.WebAuthNToken) *management.WebAuthNToken {
func webAuthNTokenFromModel(token *usr_model.WebAuthNView) *management.WebAuthNToken {
return &management.WebAuthNToken{
Id: token.WebAuthNTokenID,
Name: token.WebAuthNTokenName,
Id: token.TokenID,
Name: token.Name,
State: mfaStateFromModel(token.State),
}
}

View File

@ -37,35 +37,6 @@ func humanFromDomain(user *domain.Human) *management.HumanResponse {
return human
}
func humanFromModel(user *usr_model.Human) *management.HumanResponse {
human := &management.HumanResponse{
FirstName: user.FirstName,
LastName: user.LastName,
DisplayName: user.DisplayName,
NickName: user.NickName,
PreferredLanguage: user.PreferredLanguage.String(),
//TODO: User Converter
Gender: management.Gender(user.Gender),
}
if user.Email != nil {
human.Email = user.EmailAddress
human.IsEmailVerified = user.IsEmailVerified
}
if user.Phone != nil {
human.Phone = user.PhoneNumber
human.IsPhoneVerified = user.IsPhoneVerified
}
if user.Address != nil {
human.Country = user.Country
human.Locality = user.Locality
human.PostalCode = user.PostalCode
human.Region = user.Region
human.StreetAddress = user.StreetAddress
}
return human
}
func humanViewFromModel(user *usr_model.HumanView) *management.HumanView {
passwordChanged, err := ptypes.TimestampProto(user.PasswordChanged)
logging.Log("MANAG-h4ByY").OnError(err).Debug("unable to parse date")

View File

@ -1,11 +0,0 @@
package model
import (
org_model "github.com/caos/zitadel/internal/org/model"
usr_model "github.com/caos/zitadel/internal/user/model"
)
type RegisterOrg struct {
*org_model.Org
*usr_model.User
}

View File

@ -5,16 +5,14 @@ import (
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/command"
)
type ApplicationRepo struct {
Commands *command.CommandSide
View *view.View
ProjectEvents *proj_event.ProjectEventstore
Commands *command.CommandSide
View *view.View
}
func (a *ApplicationRepo) ApplicationByClientID(ctx context.Context, clientID string) (*model.ApplicationView, error) {

View File

@ -20,12 +20,10 @@ import (
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/id"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_view_model "github.com/caos/zitadel/internal/org/repository/view/model"
project_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
user_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
grant_view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
@ -33,8 +31,6 @@ import (
type AuthRequestRepo struct {
Command *command.CommandSide
UserEvents *user_event.UserEventstore
OrgEvents *org_event.OrgEventstore
AuthRequests cache.AuthRequestCache
View *view.View
@ -93,9 +89,6 @@ type userGrantProvider interface {
}
func (repo *AuthRequestRepo) Health(ctx context.Context) error {
if err := repo.UserEvents.Health(ctx); err != nil {
return err
}
return repo.AuthRequests.Health(ctx)
}

View File

@ -21,7 +21,6 @@ import (
org_view_model "github.com/caos/zitadel/internal/org/repository/view/model"
proj_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
user_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
user_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
user_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
grant_view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
@ -198,7 +197,6 @@ func (m *mockUserGrants) UserGrantsByProjectAndUserID(s string, s2 string) ([]*g
func TestAuthRequestRepo_nextSteps(t *testing.T) {
type fields struct {
UserEvents *user_event.UserEventstore
AuthRequests *cache.AuthRequestCache
View *view.View
userSessionViewProvider userSessionViewProvider
@ -958,7 +956,6 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := &AuthRequestRepo{
UserEvents: tt.fields.UserEvents,
AuthRequests: tt.fields.AuthRequests,
View: tt.fields.View,
UserSessionViewProvider: tt.fields.userSessionViewProvider,

View File

@ -14,9 +14,7 @@ import (
auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
org_model "github.com/caos/zitadel/internal/org/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/org/repository/view/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
const (
@ -24,9 +22,7 @@ const (
)
type OrgRepository struct {
SearchLimit uint64
OrgEventstore *org_es.OrgEventstore
UserEventstore *usr_es.UserEventstore
SearchLimit uint64
View *auth_view.View
SystemDefaults systemdefaults.SystemDefaults

View File

@ -3,13 +3,11 @@ package eventstore
import (
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
type ProjectRepo struct {
View *view.View
ProjectEvents *proj_event.ProjectEventstore
View *view.View
}
func (a *ApplicationRepo) ProjectRolesByProjectID(projectID string) ([]*model.ProjectRoleView, error) {

View File

@ -1,36 +0,0 @@
package eventstore
import (
auth_model "github.com/caos/zitadel/internal/auth/model"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
type Register struct {
*model.Org
*usr_es.User
}
func (r *Register) AppendEvents(events ...*es_models.Event) error {
for _, event := range events {
var err error
switch event.AggregateType {
case model.OrgAggregate:
err = r.Org.AppendEvent(event)
case usr_es.UserAggregate:
err = r.User.AppendEvent(event)
}
if err != nil {
return err
}
}
return nil
}
func RegisterToModel(register *Register) *auth_model.RegisterOrg {
return &auth_model.RegisterOrg{
Org: model.OrgToModel(register.Org),
User: usr_es.UserToModel(register.User),
}
}

View File

@ -4,21 +4,22 @@ import (
"context"
"time"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
usr_view "github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/errors"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/user/repository/view/model"
)
type TokenRepo struct {
UserEvents *user_event.UserEventstore
ProjectEvents *proj_event.ProjectEventstore
View *view.View
Eventstore eventstore.Eventstore
View *view.View
}
func (repo *TokenRepo) IsTokenValid(ctx context.Context, userID, tokenID string) (bool, error) {
@ -43,7 +44,7 @@ func (repo *TokenRepo) TokenByID(ctx context.Context, userID, tokenID string) (*
token.UserID = userID
}
events, esErr := repo.UserEvents.UserEventsByID(ctx, userID, token.Sequence)
events, esErr := repo.getUserEvents(ctx, userID, token.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-4T90g", "Errors.Token.NotFound")
}
@ -65,11 +66,10 @@ func (repo *TokenRepo) TokenByID(ctx context.Context, userID, tokenID string) (*
return model.TokenViewToModel(token), nil
}
func AppendAudIfNotExisting(aud string, existingAud []string) []string {
for _, a := range existingAud {
if a == aud {
return existingAud
}
func (r *TokenRepo) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) {
query, err := usr_view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return append(existingAud, aud)
return r.Eventstore.FilterEvents(ctx, query)
}

View File

@ -2,6 +2,8 @@ package eventstore
import (
"context"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/config/systemdefaults"
key_model "github.com/caos/zitadel/internal/key/model"
@ -12,25 +14,23 @@ import (
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
key_view_model "github.com/caos/zitadel/internal/key/repository/view/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_view "github.com/caos/zitadel/internal/user/repository/view"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
type UserRepo struct {
SearchLimit uint64
Eventstore eventstore.Eventstore
UserEvents *user_event.UserEventstore
OrgEvents *org_event.OrgEventstore
View *view.View
SystemDefaults systemdefaults.SystemDefaults
}
func (repo *UserRepo) Health(ctx context.Context) error {
return repo.UserEvents.Health(ctx)
return repo.Eventstore.Health(ctx)
}
func (repo *UserRepo) MyUser(ctx context.Context) (*model.UserView, error) {
@ -118,12 +118,15 @@ func (repo *UserRepo) MyUserMFAs(ctx context.Context) ([]*model.MultiFactor, err
return mfas, nil
}
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error) {
return repo.UserEvents.GetPasswordless(ctx, userID)
}
func (repo *UserRepo) GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNToken, error) {
return repo.UserEvents.GetPasswordless(ctx, authz.GetCtxData(ctx).UserID)
func (repo *UserRepo) GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNView, error) {
user, err := repo.UserByID(ctx, authz.GetCtxData(ctx).UserID)
if err != nil {
return nil, err
}
if user.HumanView == nil {
return nil, errors.ThrowPreconditionFailed(nil, "USER-9kF98", "Errors.User.NotHuman")
}
return user.HumanView.PasswordlessTokens, nil
}
func (repo *UserRepo) UserSessionUserIDsByAgentID(ctx context.Context, agentID string) ([]string, error) {
@ -143,7 +146,7 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView,
if err != nil {
return nil, err
}
events, err := repo.UserEvents.UserEventsByID(ctx, id, user.Sequence)
events, err := repo.getUserEvents(ctx, id, user.Sequence)
if err != nil {
logging.Log("EVENT-PSoc3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
return usr_view_model.UserToModel(user), nil
@ -160,12 +163,16 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView,
return usr_view_model.UserToModel(&userCopy), nil
}
func (repo *UserRepo) UserEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error) {
return repo.getUserEvents(ctx, id, sequence)
}
func (repo *UserRepo) UserByLoginName(ctx context.Context, loginname string) (*model.UserView, error) {
user, err := repo.View.UserByLoginName(loginname)
if err != nil {
return nil, err
}
events, err := repo.UserEvents.UserEventsByID(ctx, user.ID, user.Sequence)
events, err := repo.getUserEvents(ctx, user.ID, user.Sequence)
if err != nil {
logging.Log("EVENT-PSoc3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
return usr_view_model.UserToModel(user), nil
@ -182,19 +189,19 @@ func (repo *UserRepo) UserByLoginName(ctx context.Context, loginname string) (*m
return usr_view_model.UserToModel(&userCopy), nil
}
func (repo *UserRepo) MyUserChanges(ctx context.Context, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error) {
changes, err := repo.UserEvents.UserChanges(ctx, authz.GetCtxData(ctx).UserID, lastSequence, limit, sortAscending)
changes, err := repo.getUserChanges(ctx, authz.GetCtxData(ctx).UserID, lastSequence, limit, sortAscending)
if err != nil {
return nil, err
}
for _, change := range changes.Changes {
change.ModifierName = change.ModifierID
user, _ := repo.UserEvents.UserByID(ctx, change.ModifierID)
user, _ := repo.UserByID(ctx, change.ModifierID)
if user != nil {
if user.Human != nil {
if user.HumanView != nil {
change.ModifierName = user.DisplayName
}
if user.Machine != nil {
change.ModifierName = user.Machine.Name
if user.MachineView != nil {
change.ModifierName = user.MachineView.Name
}
}
}
@ -208,3 +215,55 @@ func (repo *UserRepo) MachineKeyByID(ctx context.Context, keyID string) (*key_mo
}
return key_view_model.AuthNKeyToModel(key), nil
}
func (r *UserRepo) getUserChanges(ctx context.Context, userID string, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error) {
query := usr_view.ChangesQuery(userID, lastSequence, limit, sortAscending)
events, err := r.Eventstore.FilterEvents(ctx, query)
if err != nil {
logging.Log("EVENT-g9HCv").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-htuG9", "Errors.Internal")
}
if len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-6cAxe", "Errors.User.NoChanges")
}
result := make([]*model.UserChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-8GTGS").OnError(err).Debug("unable to parse timestamp")
change := &model.UserChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierID: event.EditorUser,
Sequence: event.Sequence,
}
//TODO: now all types should be unmarshalled, e.g. password
// if len(event.Data) != 0 {
// user := new(model.User)
// err := json.Unmarshal(event.Data, user)
// logging.Log("EVENT-Rkg7X").OnError(err).Debug("unable to unmarshal data")
// change.Data = user
// }
result[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &model.UserChanges{
Changes: result,
LastSequence: lastSequence,
}, nil
}
func (r *UserRepo) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) {
query, err := usr_view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return r.Eventstore.FilterEvents(ctx, query)
}

View File

@ -5,13 +5,15 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_model "github.com/caos/zitadel/internal/project/model"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -21,14 +23,12 @@ const (
type Application struct {
handler
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newApplication(handler handler, projectEvents *proj_event.ProjectEventstore) *Application {
func newApplication(handler handler) *Application {
h := &Application{
handler: handler,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -66,14 +66,14 @@ func (a *Application) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil
return proj_view.ProjectQuery(sequence.CurrentSequence), nil
}
func (a *Application) Reduce(event *models.Event) (err error) {
app := new(view_model.ApplicationView)
switch event.Type {
case es_model.ApplicationAdded:
project, err := a.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := a.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -139,3 +139,24 @@ func (a *Application) OnError(event *models.Event, spoolerError error) error {
func (a *Application) OnSuccess() error {
return spooler.HandleSuccess(a.view.UpdateApplicationSpoolerRunTimestamp)
}
func (a *Application) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, a.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-DBf32", "Errors.Project.NotFound")
}
return es_model.ProjectToModel(esProject), nil
}

View File

@ -3,16 +3,11 @@ package handler
import (
"time"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/config/types"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/query"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/types"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type Configs map[string]*Config
@ -34,42 +29,24 @@ func (h *handler) Eventstore() eventstore.Eventstore {
return h.es
}
type EventstoreRepos struct {
UserEvents *usr_event.UserEventstore
ProjectEvents *proj_event.ProjectEventstore
OrgEvents *org_events.OrgEventstore
IamEvents *iam_events.IAMEventstore
}
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, systemDefaults sd.SystemDefaults) []query.Handler {
return []query.Handler{
newUser(
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
repos.OrgEvents,
repos.IamEvents,
systemDefaults.IamID),
newUserSession(
handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount, es},
repos.UserEvents),
handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount, es}),
newUserMembership(
handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount, es},
repos.OrgEvents,
repos.ProjectEvents),
handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount, es}),
newToken(
handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount, es},
repos.ProjectEvents),
handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount, es}),
newKey(
handler{view, bulkLimit, configs.cycleDuration("Key"), errorCount, es}),
newApplication(handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es},
repos.ProjectEvents),
newApplication(handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es}),
newOrg(
handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}),
newUserGrant(
handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es},
repos.ProjectEvents,
repos.UserEvents,
repos.OrgEvents,
repos.IamEvents,
systemDefaults.IamID),
newAuthNKeys(
handler{view, bulkLimit, configs.cycleDuration("MachineKey"), errorCount, es}),
@ -79,20 +56,15 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}),
newIDPProvider(
handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es},
systemDefaults,
repos.IamEvents,
repos.OrgEvents),
systemDefaults),
newExternalIDP(
handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es},
systemDefaults,
repos.IamEvents,
repos.OrgEvents),
systemDefaults),
newPasswordComplexityPolicy(
handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount, es}),
newOrgIAMPolicy(
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es},
repos.ProjectEvents),
newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es}),
}
}

View File

@ -2,12 +2,16 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/errors"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
@ -26,22 +30,16 @@ const (
type IDPProvider struct {
handler
systemDefaults systemdefaults.SystemDefaults
iamEvents *eventsourcing.IAMEventstore
orgEvents *org_es.OrgEventstore
subscription *eventstore.Subscription
}
func newIDPProvider(
h handler,
defaults systemdefaults.SystemDefaults,
iamEvents *eventsourcing.IAMEventstore,
orgEvents *org_es.OrgEventstore,
) *IDPProvider {
idpProvider := &IDPProvider{
handler: h,
systemDefaults: defaults,
iamEvents: iamEvents,
orgEvents: orgEvents,
}
idpProvider.subscribe()
@ -121,9 +119,9 @@ func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) {
}
config := new(iam_model.IDPConfig)
if event.AggregateID == i.systemDefaults.IamID {
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.TODO(), esConfig.IDPConfigID)
} else {
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err = i.getOrgIDPConfig(context.TODO(), event.AggregateID, esConfig.IDPConfigID)
}
if err != nil {
return err
@ -146,9 +144,9 @@ func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) {
func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
var config *iam_model.IDPConfig
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, provider.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), provider.IDPConfigID)
} else {
config, err = i.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
config, err = i.getOrgIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
}
if err != nil {
return err
@ -172,3 +170,64 @@ func (i *IDPProvider) OnError(event *models.Event, err error) error {
func (i *IDPProvider) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp)
}
func (i *IDPProvider) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-2m9fS", "Errors.Org.IdpNotExisting")
}
func (i *IDPProvider) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-6m0fS", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *IDPProvider) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *IDPProvider) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-49O0f", "Errors.IAM.IdpNotExisting")
}

View File

@ -2,12 +2,12 @@ package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/repository/view/model"
)
@ -61,7 +61,7 @@ func (o *Org) EventQuery() (*es_models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.OrgQuery(sequence.CurrentSequence), nil
return view.OrgQuery(sequence.CurrentSequence), nil
}
func (o *Org) Reduce(event *es_models.Event) (err error) {

View File

@ -7,9 +7,8 @@ import (
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_events "github.com/caos/zitadel/internal/project/repository/eventsourcing"
"github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -19,17 +18,14 @@ const (
type ProjectRole struct {
handler
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newProjectRole(
handler handler,
projectEvents *proj_events.ProjectEventstore,
) *ProjectRole {
h := &ProjectRole{
handler: handler,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -67,7 +63,7 @@ func (p *ProjectRole) EventQuery() (*es_models.SearchQuery, error) {
if err != nil {
return nil, err
}
return proj_events.ProjectQuery(sequence.CurrentSequence), nil
return proj_view.ProjectQuery(sequence.CurrentSequence), nil
}
func (p *ProjectRole) Reduce(event *es_models.Event) (err error) {

View File

@ -5,15 +5,18 @@ import (
"encoding/json"
"github.com/caos/logging"
"k8s.io/apimachinery/pkg/api/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_model "github.com/caos/zitadel/internal/project/model"
project_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
user_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
@ -24,17 +27,14 @@ const (
type Token struct {
handler
ProjectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newToken(
handler handler,
projectEvents *proj_event.ProjectEventstore,
) *Token {
h := &Token{
handler: handler,
ProjectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -118,7 +118,7 @@ func (t *Token) Reduce(event *models.Event) (err error) {
return t.view.DeleteApplicationTokens(event, application.AppID)
case project_es_model.ProjectDeactivated,
project_es_model.ProjectRemoved:
project, err := t.ProjectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := t.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -158,3 +158,24 @@ func applicationFromSession(event *models.Event) (*project_es_model.Application,
func (t *Token) OnSuccess() error {
return spooler.HandleSuccess(t.view.UpdateTokenSpoolerRunTimestamp)
}
func (t *Token) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &project_es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, t.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Dsdw2", "Errors.Project.NotFound")
}
return project_es_model.ProjectToModel(esProject), nil
}

View File

@ -2,19 +2,23 @@ package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -23,23 +27,17 @@ const (
type User struct {
handler
orgEvents *org_events.OrgEventstore
iamEvents *iam_es.IAMEventstore
iamID string
subscription *eventstore.Subscription
}
func newUser(
handler handler,
orgEvents *org_events.OrgEventstore,
iamEvents *iam_es.IAMEventstore,
iamID string,
) *User {
h := &User{
handler: handler,
orgEvents: orgEvents,
iamEvents: iamEvents,
iamID: iamID,
handler: handler,
iamID: iamID,
}
h.subscribe()
@ -169,13 +167,13 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
}
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(user.ResourceOwner))
org, err := u.getOrgByID(context.Background(), user.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -201,13 +199,13 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
}
func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -223,13 +221,13 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
}
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -255,3 +253,53 @@ func (u *User) OnError(event *models.Event, err error) error {
func (u *User) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp)
}
func (u *User) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *User) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *User) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9fs", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
}

View File

@ -2,7 +2,6 @@ package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
@ -10,15 +9,18 @@ import (
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_model "github.com/caos/zitadel/internal/org/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -28,22 +30,16 @@ const (
type ExternalIDP struct {
handler
systemDefaults systemdefaults.SystemDefaults
iamEvents *eventsourcing.IAMEventstore
orgEvents *org_es.OrgEventstore
subscription *eventstore.Subscription
}
func newExternalIDP(
handler handler,
defaults systemdefaults.SystemDefaults,
iamEvents *eventsourcing.IAMEventstore,
orgEvents *org_es.OrgEventstore,
) *ExternalIDP {
h := &ExternalIDP{
handler: handler,
systemDefaults: defaults,
iamEvents: iamEvents,
orgEvents: orgEvents,
}
h.subscribe()
@ -137,9 +133,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), configView.IDPConfigID)
} else {
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.getOrgIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err
@ -155,9 +151,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
}
func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
config, err := i.getOrgIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
if caos_errs.IsNotFound(err) {
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), externalIDP.IDPConfigID)
}
if err != nil {
return err
@ -178,3 +174,64 @@ func (i *ExternalIDP) OnError(event *models.Event, err error) error {
func (i *ExternalIDP) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp)
}
func (i *ExternalIDP) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2m9fS", "Errors.Org.IdpNotExisting")
}
func (i *ExternalIDP) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-6m0fS", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *ExternalIDP) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}
func (u *ExternalIDP) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-mmk5d", "Errors.IAM.IdpNotExisting")
}

View File

@ -2,8 +2,16 @@ package handler
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"strings"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
org_view "github.com/caos/zitadel/internal/org/repository/view"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
@ -13,16 +21,12 @@ import (
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_events "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
@ -35,30 +39,18 @@ const (
type UserGrant struct {
handler
projectEvents *proj_event.ProjectEventstore
userEvents *usr_events.UserEventstore
orgEvents *org_events.OrgEventstore
iamEvents *iam_events.IAMEventstore
iamID string
iamProjectID string
subscription *eventstore.Subscription
iamID string
iamProjectID string
subscription *eventstore.Subscription
}
func newUserGrant(
handler handler,
projectEvents *proj_event.ProjectEventstore,
userEvents *usr_events.UserEventstore,
orgEvents *org_events.OrgEventstore,
iamEvents *iam_events.IAMEventstore,
iamID string,
) *UserGrant {
h := &UserGrant{
handler: handler,
projectEvents: projectEvents,
userEvents: userEvents,
orgEvents: orgEvents,
iamEvents: iamEvents,
iamID: iamID,
handler: handler,
iamID: iamID,
}
h.subscribe()
@ -166,7 +158,7 @@ func (u *UserGrant) processUser(event *models.Event) (err error) {
if len(grants) == 0 {
return u.view.ProcessedUserGrantSequence(event)
}
user, err := u.userEvents.UserByID(context.Background(), event.AggregateID)
user, err := u.getUserByID(event.AggregateID)
if err != nil {
return err
}
@ -186,7 +178,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) {
if err != nil {
return err
}
project, err := u.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := u.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -348,7 +340,7 @@ func (u *UserGrant) setIamProjectID() error {
if u.iamProjectID != "" {
return nil
}
iam, err := u.iamEvents.IAMByID(context.Background(), u.iamID)
iam, err := u.getIAMByID(context.Background())
if err != nil {
return err
}
@ -361,18 +353,18 @@ func (u *UserGrant) setIamProjectID() error {
}
func (u *UserGrant) fillData(grant *view_model.UserGrantView, resourceOwner string) (err error) {
user, err := u.userEvents.UserByID(context.Background(), grant.UserID)
user, err := u.getUserByID(grant.UserID)
if err != nil {
return err
}
u.fillUserData(grant, user)
project, err := u.projectEvents.ProjectByID(context.Background(), grant.ProjectID)
project, err := u.getProjectByID(context.Background(), grant.ProjectID)
if err != nil {
return err
}
u.fillProjectData(grant, project)
org, err := u.orgEvents.OrgByID(context.TODO(), org_model.NewOrg(resourceOwner))
org, err := u.getOrgByID(context.TODO(), resourceOwner)
if err != nil {
return err
}
@ -380,16 +372,16 @@ func (u *UserGrant) fillData(grant *view_model.UserGrantView, resourceOwner stri
return nil
}
func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *usr_model.User) {
func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *model.UserView) {
grant.UserName = user.UserName
if user.Human != nil {
if user.HumanView != nil {
grant.FirstName = user.FirstName
grant.LastName = user.LastName
grant.DisplayName = user.FirstName + " " + user.LastName
grant.Email = user.EmailAddress
grant.Email = user.Email
}
if user.Machine != nil {
grant.DisplayName = user.Machine.Name
if user.MachineView != nil {
grant.DisplayName = user.MachineView.Name
}
}
@ -416,3 +408,96 @@ func (u *UserGrant) OnError(event *models.Event, err error) error {
func (u *UserGrant) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp)
}
func (u *UserGrant) getUserByID(userID string) (*model.UserView, error) {
user, usrErr := u.view.UserByID(userID)
if usrErr != nil && !caos_errs.IsNotFound(usrErr) {
return nil, usrErr
}
if user == nil {
user = &model.UserView{}
}
events, err := u.getUserEvents(userID, user.Sequence)
if err != nil {
return user, usrErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user, nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "HANDLER-m9dos", "Errors.User.NotFound")
}
return &userCopy, nil
}
func (u *UserGrant) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return u.es.FilterEvents(context.Background(), query)
}
func (u *UserGrant) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := org_view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *UserGrant) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &proj_es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-DAfng", "Errors.Project.NotFound")
}
return proj_es_model.ProjectToModel(esProject), nil
}
func (u *UserGrant) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}

View File

@ -4,17 +4,21 @@ import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
org_view "github.com/caos/zitadel/internal/org/repository/view"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -26,20 +30,14 @@ const (
type UserMembership struct {
handler
orgEvents *org_event.OrgEventstore
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newUserMembership(
handler handler,
orgEvents *org_event.OrgEventstore,
projectEvents *proj_event.ProjectEventstore,
) *UserMembership {
h := &UserMembership{
handler: handler,
orgEvents: orgEvents,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -156,7 +154,7 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) {
}
func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (err error) {
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(member.ResourceOwner))
org, err := m.getOrgByID(context.Background(), member.ResourceOwner)
if err != nil {
return err
}
@ -168,7 +166,7 @@ func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (e
}
func (m *UserMembership) updateOrgName(event *models.Event) error {
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.AggregateID))
org, err := m.getOrgByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -231,7 +229,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) {
}
func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) {
project, err := m.projectEvents.ProjectByID(context.Background(), member.AggregateID)
project, err := m.getProjectByID(context.Background(), member.AggregateID)
if err != nil {
return err
}
@ -240,7 +238,7 @@ func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembers
}
func (m *UserMembership) updateProjectDisplayName(event *models.Event) error {
project, err := m.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := m.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -272,3 +270,45 @@ func (m *UserMembership) OnError(event *models.Event, err error) error {
func (m *UserMembership) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateUserMembershipSpoolerRunTimestamp)
}
func (u *UserMembership) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := org_view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *UserMembership) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &proj_es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-Dbfw2", "Errors.Project.NotFound")
}
return proj_es_model.ProjectToModel(esProject), nil
}

View File

@ -8,9 +8,8 @@ import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/user/repository/eventsourcing"
user_events "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/user/repository/view"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
@ -20,17 +19,14 @@ const (
type UserSession struct {
handler
userEvents *user_events.UserEventstore
subscription *eventstore.Subscription
}
func newUserSession(
handler handler,
userEvents *user_events.UserEventstore,
) *UserSession {
h := &UserSession{
handler: handler,
userEvents: userEvents,
handler: handler,
}
h.subscribe()
@ -68,7 +64,7 @@ func (u *UserSession) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.UserQuery(sequence.CurrentSequence), nil
return view.UserQuery(sequence.CurrentSequence), nil
}
func (u *UserSession) Reduce(event *models.Event) (err error) {

View File

@ -5,7 +5,6 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/eventstore"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/handler"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/spooler"
auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/auth_request/repository/cache"
@ -15,11 +14,7 @@ import (
"github.com/caos/zitadel/internal/crypto"
es_int "github.com/caos/zitadel/internal/eventstore"
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/id"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/query"
)
@ -34,7 +29,8 @@ type Config struct {
}
type EsRepository struct {
spooler *es_spol.Spooler
spooler *es_spol.Spooler
Eventstore es_int.Eventstore
eventstore.UserRepo
eventstore.AuthRequestRepo
eventstore.TokenRepo
@ -69,73 +65,36 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
return nil, err
}
user, err := es_user.StartUser(
es_user.UserConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
},
systemDefaults,
)
if err != nil {
return nil, err
}
authReq, err := cache.Start(conf.AuthRequest)
if err != nil {
return nil, err
}
iam, err := es_iam.StartIAM(
es_iam.IAMConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
},
systemDefaults,
)
if err != nil {
return nil, err
}
project, err := es_proj.StartProject(
es_proj.ProjectConfig{
Cache: conf.Eventstore.Cache,
Eventstore: es,
},
systemDefaults,
)
if err != nil {
return nil, err
}
iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
org := es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: conf.Domain}, systemDefaults)
repos := handler.EventstoreRepos{UserEvents: user, ProjectEvents: project, OrgEvents: org, IamEvents: iam}
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, repos, systemDefaults)
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
userRepo := eventstore.UserRepo{
SearchLimit: conf.SearchLimit,
Eventstore: es,
View: view,
SystemDefaults: systemDefaults,
}
return &EsRepository{
spool,
eventstore.UserRepo{
SearchLimit: conf.SearchLimit,
Eventstore: es,
UserEvents: user,
OrgEvents: org,
View: view,
SystemDefaults: systemDefaults,
},
es,
userRepo,
eventstore.AuthRequestRepo{
Command: command,
UserEvents: user,
OrgEvents: org,
AuthRequests: authReq,
View: view,
UserSessionViewProvider: view,
UserViewProvider: view,
UserCommandProvider: command,
UserEventProvider: user,
UserEventProvider: &userRepo,
OrgViewProvider: view,
IDPProviderViewProvider: view,
LoginPolicyViewProvider: view,
@ -149,18 +108,16 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
IAMID: systemDefaults.IamID,
},
eventstore.TokenRepo{
UserEvents: user,
ProjectEvents: project,
View: view,
Eventstore: es,
View: view,
},
eventstore.KeyRepository{
View: view,
SigningKeyRotation: systemDefaults.KeyConfig.SigningKeyRotation.Duration,
},
eventstore.ApplicationRepo{
Commands: command,
View: view,
ProjectEvents: project,
Commands: command,
View: view,
},
eventstore.UserSessionRepo{
@ -176,8 +133,6 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
eventstore.OrgRepository{
SearchLimit: conf.SearchLimit,
View: view,
OrgEventstore: org,
UserEventstore: user,
SystemDefaults: systemDefaults,
},
eventstore.IAMRepository{

View File

@ -19,12 +19,12 @@ type SpoolerConfig struct {
Handlers handler.Configs
}
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, client *sql.DB, repos handler.EventstoreRepos, systemDefaults sd.SystemDefaults) *spooler.Spooler {
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, client *sql.DB, systemDefaults sd.SystemDefaults) *spooler.Spooler {
spoolerConfig := spooler.Config{
Eventstore: es,
Locker: &locker{dbClient: client},
ConcurrentWorkers: c.ConcurrentWorkers,
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, repos, systemDefaults),
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults),
}
spool := spoolerConfig.New()
spool.Start()

View File

@ -11,8 +11,6 @@ import (
type UserRepository interface {
myUserRepo
GetPasswordless(ctx context.Context, id string) ([]*model.WebAuthNToken, error)
UserSessionUserIDsByAgentID(ctx context.Context, agentID string) ([]string, error)
UserByID(ctx context.Context, userID string) (*model.UserView, error)
@ -36,7 +34,7 @@ type myUserRepo interface {
MyUserMFAs(ctx context.Context) ([]*model.MultiFactor, error)
GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNToken, error)
GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNView, error)
MyUserChanges(ctx context.Context, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error)

View File

@ -5,18 +5,16 @@ import (
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/iam/model"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
)
type IamRepo struct {
IAMID string
IAMEvents *iam_event.IAMEventstore
IAMID string
IAMV2Query *query.QuerySide
}
func (repo *IamRepo) Health(ctx context.Context) error {
return repo.IAMEvents.Health(ctx)
return nil
}
func (repo *IamRepo) IamByID(ctx context.Context) (*model.IAM, error) {

View File

@ -2,28 +2,33 @@ package eventstore
import (
"context"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"k8s.io/apimachinery/pkg/api/errors"
"strings"
"time"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
usr_view "github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/crypto"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/user/repository/view/model"
)
type TokenVerifierRepo struct {
TokenVerificationKey [32]byte
IAMID string
IAMEvents *iam_event.IAMEventstore
ProjectEvents *proj_event.ProjectEventstore
UserEvents *usr_event.UserEventstore
Eventstore eventstore.Eventstore
View *view.View
}
@ -38,7 +43,7 @@ func (repo *TokenVerifierRepo) TokenByID(ctx context.Context, tokenID, userID st
token.UserID = userID
}
events, esErr := repo.UserEvents.UserEventsByID(ctx, userID, token.Sequence)
events, esErr := repo.getUserEvents(ctx, userID, token.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-4T90g", "Errors.Token.NotFound")
}
@ -110,7 +115,7 @@ func (repo *TokenVerifierRepo) VerifierClientID(ctx context.Context, appName str
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
iam, err := repo.IAMEvents.IAMByID(ctx, repo.IAMID)
iam, err := repo.getIAMByID(ctx)
if err != nil {
return "", err
}
@ -120,3 +125,28 @@ func (repo *TokenVerifierRepo) VerifierClientID(ctx context.Context, appName str
}
return app.OIDCClientID, nil
}
func (r *TokenVerifierRepo) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) {
query, err := usr_view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return r.Eventstore.FilterEvents(ctx, query)
}
func (u *TokenVerifierRepo) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore.FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}

View File

@ -2,11 +2,17 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"k8s.io/apimachinery/pkg/api/errors"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
global_model "github.com/caos/zitadel/internal/model"
user_model "github.com/caos/zitadel/internal/user/model"
user_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -19,7 +25,7 @@ type UserGrantRepo struct {
IamID string
IamProjectID string
Auth authz.Config
IamEvents *iam_event.IAMEventstore
Eventstore eventstore.Eventstore
}
func (repo *UserGrantRepo) Health() error {
@ -94,7 +100,7 @@ func (repo *UserGrantRepo) FillIamProjectID(ctx context.Context) error {
if repo.IamProjectID != "" {
return nil
}
iam, err := repo.IamEvents.IAMByID(ctx, repo.IamID)
iam, err := repo.getIAMByID(ctx)
if err != nil {
return err
}
@ -118,6 +124,23 @@ func (repo *UserGrantRepo) mapRoleToPermission(permissions *grant_model.Permissi
return permissions
}
func (u *UserGrantRepo) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore.FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}
func userMembershipToMembership(membership *user_view_model.UserMembershipView) *authz.Membership {
return &authz.Membership{
MemberType: authz.MemberType(membership.MemberType),

View File

@ -7,8 +7,8 @@ import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -61,7 +61,7 @@ func (a *Application) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil
return view.ProjectQuery(sequence.CurrentSequence), nil
}
func (a *Application) Reduce(event *models.Event) (err error) {

View File

@ -1,7 +1,6 @@
package handler
import (
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"time"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
@ -9,8 +8,6 @@ import (
"github.com/caos/zitadel/internal/config/types"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/query"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
project_events "github.com/caos/zitadel/internal/project/repository/eventsourcing"
)
type Configs map[string]*Config
@ -32,22 +29,13 @@ func (h *handler) Eventstore() eventstore.Eventstore {
return h.es
}
type EventstoreRepos struct {
IAMEvents *eventsourcing.IAMEventstore
OrgEvents *org_events.OrgEventstore
ProjectEvents *project_events.ProjectEventstore
}
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, systemDefaults sd.SystemDefaults) []query.Handler {
return []query.Handler{
newUserGrant(
handler{view, bulkLimit, configs.cycleDuration("UserGrants"), errorCount, es},
repos.IAMEvents,
systemDefaults.IamID),
newUserMembership(
handler{view, bulkLimit, configs.cycleDuration("UserMemberships"), errorCount, es},
repos.OrgEvents,
repos.ProjectEvents),
handler{view, bulkLimit, configs.cycleDuration("UserMemberships"), errorCount, es}),
newApplication(
handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es}),
newOrg(

View File

@ -2,12 +2,12 @@ package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/repository/view/model"
)
@ -61,7 +61,7 @@ func (o *Org) EventQuery() (*es_models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.OrgQuery(sequence.CurrentSequence), nil
return view.OrgQuery(sequence.CurrentSequence), nil
}
func (o *Org) Reduce(event *es_models.Event) error {

View File

@ -2,6 +2,9 @@ package handler
import (
"context"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"strings"
"github.com/caos/logging"
@ -13,7 +16,6 @@ import (
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
@ -27,7 +29,6 @@ const (
type UserGrant struct {
handler
iamEvents *iam_events.IAMEventstore
iamID string
iamProjectID string
subscription *eventstore.Subscription
@ -35,13 +36,11 @@ type UserGrant struct {
func newUserGrant(
handler handler,
iamEvents *iam_events.IAMEventstore,
iamID string,
) *UserGrant {
h := &UserGrant{
handler: handler,
iamEvents: iamEvents,
iamID: iamID,
handler: handler,
iamID: iamID,
}
h.subscribe()
@ -258,7 +257,7 @@ func (u *UserGrant) setIamProjectID() error {
if u.iamProjectID != "" {
return nil
}
iam, err := u.iamEvents.IAMByID(context.Background(), u.iamID)
iam, err := u.getIAMByID(context.Background())
if err != nil {
return err
}
@ -277,3 +276,20 @@ func (u *UserGrant) OnError(event *models.Event, err error) error {
func (u *UserGrant) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp)
}
func (u *UserGrant) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}

View File

@ -4,17 +4,21 @@ import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
org_view "github.com/caos/zitadel/internal/org/repository/view"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -26,20 +30,14 @@ const (
type UserMembership struct {
handler
orgEvents *org_event.OrgEventstore
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newUserMembership(
handler handler,
orgEvents *org_event.OrgEventstore,
projectEvents *proj_event.ProjectEventstore,
) *UserMembership {
h := &UserMembership{
handler: handler,
orgEvents: orgEvents,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -156,7 +154,7 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) {
}
func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (err error) {
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(member.ResourceOwner))
org, err := m.getOrgByID(context.Background(), member.ResourceOwner)
if err != nil {
return err
}
@ -168,7 +166,7 @@ func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (e
}
func (m *UserMembership) updateOrgName(event *models.Event) error {
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.AggregateID))
org, err := m.getOrgByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -231,7 +229,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) {
}
func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) {
project, err := m.projectEvents.ProjectByID(context.Background(), member.AggregateID)
project, err := m.getProjectByID(context.Background(), member.AggregateID)
if err != nil {
return err
}
@ -240,7 +238,7 @@ func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembers
}
func (m *UserMembership) updateProjectDisplayName(event *models.Event) error {
project, err := m.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := m.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -272,3 +270,42 @@ func (m *UserMembership) OnError(event *models.Event, err error) error {
func (m *UserMembership) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateUserMembershipSpoolerRunTimestamp)
}
func (u *UserMembership) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := org_view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
var esOrg *org_es_model.Org
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *UserMembership) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &proj_es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-Dfrt2", "Errors.Project.NotFound")
}
return proj_es_model.ProjectToModel(esProject), nil
}

View File

@ -2,24 +2,19 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/auth_request/repository/cache"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/eventstore"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/handler"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/spooler"
authz_view "github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/config/types"
es_int "github.com/caos/zitadel/internal/eventstore"
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/id"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
)
type Config struct {
@ -55,60 +50,30 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults) (*
return nil, err
}
iam, err := es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
org := es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: conf.Domain}, systemDefaults)
project, err := es_proj.StartProject(es_proj.ProjectConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
user, err := es_user.StartUser(
es_user.UserConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
},
systemDefaults,
)
if err != nil {
return nil, err
}
iamV2, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
repos := handler.EventstoreRepos{IAMEvents: iam, OrgEvents: org, ProjectEvents: project}
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, repos, systemDefaults)
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
return &EsRepository{
spool,
eventstore.UserGrantRepo{
View: view,
IamID: systemDefaults.IamID,
Auth: authZ,
IamEvents: iam,
View: view,
IamID: systemDefaults.IamID,
Auth: authZ,
Eventstore: es,
},
eventstore.IamRepo{
IAMID: systemDefaults.IamID,
IAMEvents: iam,
IAMV2Query: iamV2,
},
eventstore.TokenVerifierRepo{
//TODO: Add Token Verification Key
IAMID: systemDefaults.IamID,
IAMEvents: iam,
ProjectEvents: project,
UserEvents: user,
View: view,
Eventstore: es,
IAMID: systemDefaults.IamID,
View: view,
},
}, nil
}

View File

@ -19,12 +19,12 @@ type SpoolerConfig struct {
Handlers handler.Configs
}
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, repos handler.EventstoreRepos, systemDefaults sd.SystemDefaults) *spooler.Spooler {
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, systemDefaults sd.SystemDefaults) *spooler.Spooler {
spoolerConfig := spooler.Config{
Eventstore: es,
Locker: &locker{dbClient: sql},
ConcurrentWorkers: c.ConcurrentWorkers,
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, repos, systemDefaults),
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults),
}
spool := spoolerConfig.New()
spool.Start()

View File

@ -1,85 +1,11 @@
package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/cache/config"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
type IAMEventstore struct {
es_int.Eventstore
iamCache *IAMCache
}
type IAMConfig struct {
es_int.Eventstore
Cache *config.CacheConfig
}
func StartIAM(conf IAMConfig, systemDefaults sd.SystemDefaults) (*IAMEventstore, error) {
iamCache, err := StartCache(conf.Cache)
if err != nil {
return nil, err
}
return &IAMEventstore{
Eventstore: conf.Eventstore,
iamCache: iamCache,
}, nil
}
func (es *IAMEventstore) IAMByID(ctx context.Context, id string) (_ *iam_model.IAM, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
iam := es.iamCache.getIAM(id)
query, err := IAMByIDQuery(iam.AggregateID, iam.Sequence)
if err != nil {
return nil, err
}
err = es_sdk.Filter(ctx, es.FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
es.iamCache.cacheIAM(iam)
return model.IAMToModel(iam), nil
}
func (es *IAMEventstore) IAMEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error) {
query, err := IAMByIDQuery(id, sequence)
if err != nil {
return nil, err
}
return es.FilterEvents(ctx, query)
}
func (es *IAMEventstore) GetIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := es.IAMByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Scj8s", "Errors.IAM.IdpNotExisting")
}
func (es *IAMEventstore) GetOrgIAMPolicy(ctx context.Context, iamID string) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := es.IAMByID(ctx, iamID)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2Fj8s", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
}

View File

@ -0,0 +1,21 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
)
func IAMByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, error) {
if id == "" {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-4ng8sd", "id should be filled")
}
return IAMQuery(latestSequence).
AggregateIDFilter(id), nil
}
func IAMQuery(latestSequence uint64) *es_models.SearchQuery {
return es_models.NewSearchQuery().
AggregateTypeFilter(iam_es_model.IAMAggregate).
LatestSequenceFilter(latestSequence)
}

View File

@ -2,11 +2,17 @@ package eventstore
import (
"context"
"encoding/json"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_view "github.com/caos/zitadel/internal/org/repository/view"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/golang/protobuf/ptypes"
"strings"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/config/systemdefaults"
@ -17,10 +23,10 @@ import (
mgmt_view "github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
global_model "github.com/caos/zitadel/internal/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
const (
@ -28,10 +34,8 @@ const (
)
type OrgRepository struct {
SearchLimit uint64
*org_es.OrgEventstore
UserEvents *usr_es.UserEventstore
IAMEventstore *iam_es.IAMEventstore
SearchLimit uint64
Eventstore eventstore.Eventstore
View *mgmt_view.View
Roles []string
SystemDefaults systemdefaults.SystemDefaults
@ -91,19 +95,19 @@ func (repo *OrgRepository) SearchMyOrgDomains(ctx context.Context, request *org_
}
func (repo *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error) {
changes, err := repo.OrgEventstore.OrgChanges(ctx, id, lastSequence, limit, sortAscending)
changes, err := repo.getOrgChanges(ctx, id, lastSequence, limit, sortAscending)
if err != nil {
return nil, err
}
for _, change := range changes.Changes {
change.ModifierName = change.ModifierId
user, _ := repo.UserEvents.UserByID(ctx, change.ModifierId)
user, _ := repo.userByID(ctx, change.ModifierId)
if user != nil {
if user.Human != nil {
if user.HumanView != nil {
change.ModifierName = user.DisplayName
}
if user.Machine != nil {
change.ModifierName = user.Machine.Name
if user.MachineView != nil {
change.ModifierName = user.MachineView.Name
}
}
}
@ -204,7 +208,7 @@ func (repo *OrgRepository) GetLoginPolicy(ctx context.Context) (*iam_model.Login
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.LoginPolicyView)
}
events, esErr := repo.OrgEventstore.OrgEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getOrgEvents(ctx, repo.SystemDefaults.IamID, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return repo.GetDefaultLoginPolicy(ctx)
}
@ -237,7 +241,7 @@ func (repo *OrgRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_mode
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.LoginPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, domain.IAMID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.LoginPolicy.NotFound")
}
@ -315,7 +319,7 @@ func (repo *OrgRepository) GetPasswordComplexityPolicy(ctx context.Context) (*ia
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordComplexityPolicyView)
}
events, esErr := repo.OrgEventstore.OrgEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getOrgEvents(ctx, repo.SystemDefaults.IamID, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return repo.GetDefaultPasswordComplexityPolicy(ctx)
}
@ -340,7 +344,7 @@ func (repo *OrgRepository) GetDefaultPasswordComplexityPolicy(ctx context.Contex
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordComplexityPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.PasswordComplexityPolicy.NotFound")
}
@ -366,7 +370,7 @@ func (repo *OrgRepository) GetPasswordAgePolicy(ctx context.Context) (*iam_model
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordAgePolicyView)
}
events, esErr := repo.OrgEventstore.OrgEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getOrgEvents(ctx, repo.SystemDefaults.IamID, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return repo.GetDefaultPasswordAgePolicy(ctx)
}
@ -391,7 +395,7 @@ func (repo *OrgRepository) GetDefaultPasswordAgePolicy(ctx context.Context) (*ia
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordAgePolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.PasswordAgePolicy.NotFound")
}
@ -417,7 +421,7 @@ func (repo *OrgRepository) GetPasswordLockoutPolicy(ctx context.Context) (*iam_m
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordLockoutPolicyView)
}
events, esErr := repo.OrgEventstore.OrgEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getOrgEvents(ctx, repo.SystemDefaults.IamID, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return repo.GetDefaultPasswordLockoutPolicy(ctx)
}
@ -442,7 +446,7 @@ func (repo *OrgRepository) GetDefaultPasswordLockoutPolicy(ctx context.Context)
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.PasswordLockoutPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.PasswordLockoutPolicy.NotFound")
}
@ -507,3 +511,99 @@ func (repo *OrgRepository) GetMailTexts(ctx context.Context) (*iam_model.MailTex
}
return iam_es_model.MailTextsViewToModel(texts, defaultIn), err
}
func (repo *OrgRepository) getOrgChanges(ctx context.Context, orgID string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error) {
query := org_view.ChangesQuery(orgID, lastSequence, limit, sortAscending)
events, err := repo.Eventstore.FilterEvents(context.Background(), query)
if err != nil {
logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-328b1", "Errors.Org.NotFound")
}
if len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-FpQqK", "Errors.Changes.NotFound")
}
changes := make([]*org_model.OrgChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-qxIR7").OnError(err).Debug("unable to parse timestamp")
change := &org_model.OrgChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierId: event.EditorUser,
Sequence: event.Sequence,
}
if event.Data != nil {
org := new(org_es_model.Org)
err := json.Unmarshal(event.Data, org)
logging.Log("EVENT-XCLEm").OnError(err).Debug("unable to unmarshal data")
change.Data = org
}
changes[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &org_model.OrgChanges{
Changes: changes,
LastSequence: lastSequence,
}, nil
}
func (repo *OrgRepository) userByID(ctx context.Context, id string) (*usr_model.UserView, error) {
user, viewErr := repo.View.UserByID(id)
if viewErr != nil && !errors.IsNotFound(viewErr) {
return nil, viewErr
}
if errors.IsNotFound(viewErr) {
user = new(usr_es_model.UserView)
}
events, esErr := repo.getUserEvents(ctx, id, user.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3nF8s", "Errors.User.NotFound")
}
if esErr != nil {
logging.Log("EVENT-PSoc3").WithError(esErr).Debug("error retrieving new events")
return usr_es_model.UserToModel(user), nil
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return usr_es_model.UserToModel(user), nil
}
}
if userCopy.State == int32(usr_es_model.UserStateDeleted) {
return nil, errors.ThrowNotFound(nil, "EVENT-3n8Fs", "Errors.User.NotFound")
}
return usr_es_model.UserToModel(&userCopy), nil
}
func (r *OrgRepository) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return r.Eventstore.FilterEvents(ctx, query)
}
func (es *OrgRepository) getOrgEvents(ctx context.Context, id string, sequence uint64) ([]*models.Event, error) {
query, err := org_view.OrgByIDQuery(id, sequence)
if err != nil {
return nil, err
}
return es.Eventstore.FilterEvents(ctx, query)
}
func (repo *OrgRepository) getIAMEvents(ctx context.Context, sequence uint64) ([]*models.Event, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, sequence)
if err != nil {
return nil, err
}
return repo.Eventstore.FilterEvents(ctx, query)
}

View File

@ -2,33 +2,40 @@ package eventstore
import (
"context"
"encoding/json"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"strings"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"k8s.io/apimachinery/pkg/api/errors"
"github.com/caos/zitadel/internal/api/authz"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/eventstore/models"
key_model "github.com/caos/zitadel/internal/key/model"
key_view_model "github.com/caos/zitadel/internal/key/repository/view/model"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
global_model "github.com/caos/zitadel/internal/model"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
"github.com/caos/zitadel/internal/project/repository/view/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_view "github.com/caos/zitadel/internal/user/repository/view"
usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
type ProjectRepo struct {
es_int.Eventstore
SearchLimit uint64
ProjectEvents *proj_event.ProjectEventstore
UserEvents *usr_event.UserEventstore
IAMEvents *iam_event.IAMEventstore
View *view.View
Roles []string
IAMID string
SearchLimit uint64
View *view.View
Roles []string
IAMID string
}
func (repo *ProjectRepo) ProjectByID(ctx context.Context, id string) (*proj_model.ProjectView, error) {
@ -40,7 +47,7 @@ func (repo *ProjectRepo) ProjectByID(ctx context.Context, id string) (*proj_mode
project = new(model.ProjectView)
}
events, esErr := repo.ProjectEvents.ProjectEventsByID(ctx, id, project.Sequence)
events, esErr := repo.getProjectEvents(ctx, id, project.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-8yfKu", "Errors.Project.NotFound")
}
@ -175,19 +182,19 @@ func (repo *ProjectRepo) SearchProjectRoles(ctx context.Context, projectID strin
}
func (repo *ProjectRepo) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ProjectChanges, error) {
changes, err := repo.ProjectEvents.ProjectChanges(ctx, id, lastSequence, limit, sortAscending)
changes, err := repo.getProjectChanges(ctx, id, lastSequence, limit, sortAscending)
if err != nil {
return nil, err
}
for _, change := range changes.Changes {
change.ModifierName = change.ModifierId
user, _ := repo.UserEvents.UserByID(ctx, change.ModifierId)
user, _ := repo.userByID(ctx, change.ModifierId)
if user != nil {
if user.Human != nil {
if user.HumanView != nil {
change.ModifierName = user.DisplayName
}
if user.Machine != nil {
change.ModifierName = user.Machine.Name
if user.MachineView != nil {
change.ModifierName = user.MachineView.Name
}
}
}
@ -204,7 +211,7 @@ func (repo *ProjectRepo) ApplicationByID(ctx context.Context, projectID, appID s
app.ID = appID
}
events, esErr := repo.ProjectEvents.ProjectEventsByID(ctx, projectID, app.Sequence)
events, esErr := repo.getProjectEvents(ctx, projectID, app.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Fshu8", "Errors.Application.NotFound")
}
@ -249,19 +256,19 @@ func (repo *ProjectRepo) SearchApplications(ctx context.Context, request *proj_m
}
func (repo *ProjectRepo) ApplicationChanges(ctx context.Context, id string, appId string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ApplicationChanges, error) {
changes, err := repo.ProjectEvents.ApplicationChanges(ctx, id, appId, lastSequence, limit, sortAscending)
changes, err := repo.getApplicationChanges(ctx, id, appId, lastSequence, limit, sortAscending)
if err != nil {
return nil, err
}
for _, change := range changes.Changes {
change.ModifierName = change.ModifierId
user, _ := repo.UserEvents.UserByID(ctx, change.ModifierId)
user, _ := repo.userByID(ctx, change.ModifierId)
if user != nil {
if user.Human != nil {
if user.HumanView != nil {
change.ModifierName = user.DisplayName
}
if user.Machine != nil {
change.ModifierName = user.Machine.Name
if user.MachineView != nil {
change.ModifierName = user.MachineView.Name
}
}
}
@ -295,7 +302,7 @@ func (repo *ProjectRepo) GetClientKey(ctx context.Context, projectID, applicatio
return nil, viewErr
}
events, esErr := repo.ProjectEvents.ProjectEventsByID(ctx, projectID, key.Sequence)
events, esErr := repo.getProjectEvents(ctx, projectID, key.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-SFf2g", "Errors.User.KeyNotFound")
}
@ -436,7 +443,7 @@ func (repo *ProjectRepo) SearchProjectGrantMembers(ctx context.Context, request
}
func (repo *ProjectRepo) GetProjectMemberRoles(ctx context.Context) ([]string, error) {
iam, err := repo.IAMEvents.IAMByID(ctx, repo.IAMID)
iam, err := repo.GetIAMByID(ctx)
if err != nil {
return nil, err
}
@ -462,3 +469,158 @@ func (repo *ProjectRepo) GetProjectGrantMemberRoles() []string {
}
return roles
}
func (repo *ProjectRepo) userByID(ctx context.Context, id string) (*usr_model.UserView, error) {
user, viewErr := repo.View.UserByID(id)
if viewErr != nil && !caos_errs.IsNotFound(viewErr) {
return nil, viewErr
}
if caos_errs.IsNotFound(viewErr) {
user = new(usr_es_model.UserView)
}
events, esErr := repo.getUserEvents(ctx, id, user.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-4n8Fs", "Errors.User.NotFound")
}
if esErr != nil {
logging.Log("EVENT-PSoc3").WithError(esErr).Debug("error retrieving new events")
return usr_es_model.UserToModel(user), nil
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return usr_es_model.UserToModel(user), nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2m0Fs", "Errors.User.NotFound")
}
return usr_es_model.UserToModel(&userCopy), nil
}
func (r *ProjectRepo) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) {
query, err := usr_view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return r.Eventstore.FilterEvents(ctx, query)
}
func (repo *ProjectRepo) getProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ProjectChanges, error) {
query := proj_view.ChangesQuery(id, lastSequence, limit, sortAscending)
events, err := repo.Eventstore.FilterEvents(context.Background(), query)
if err != nil {
logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable")
return nil, caos_errs.ThrowInternal(err, "EVENT-328b1", "Errors.Internal")
}
if len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-FpQqK", "Errors.Changes.NotFound")
}
changes := make([]*proj_model.ProjectChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-qxIR7").OnError(err).Debug("unable to parse timestamp")
change := &proj_model.ProjectChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierId: event.EditorUser,
Sequence: event.Sequence,
}
if event.Data != nil {
var data interface{}
if strings.Contains(change.EventType, "application") {
data = new(proj_model.Application)
} else {
data = new(proj_model.Project)
}
err = json.Unmarshal(event.Data, data)
logging.Log("EVENT-NCkpN").OnError(err).Debug("unable to unmarshal data")
change.Data = data
}
changes[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &proj_model.ProjectChanges{
Changes: changes,
LastSequence: lastSequence,
}, nil
}
func (repo *ProjectRepo) getProjectEvents(ctx context.Context, id string, sequence uint64) ([]*models.Event, error) {
query, err := proj_view.ProjectByIDQuery(id, sequence)
if err != nil {
return nil, err
}
return repo.Eventstore.FilterEvents(ctx, query)
}
func (repo *ProjectRepo) getApplicationChanges(ctx context.Context, projectID string, appID string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ApplicationChanges, error) {
query := proj_view.ChangesQuery(projectID, lastSequence, limit, sortAscending)
events, err := repo.Eventstore.FilterEvents(ctx, query)
if err != nil {
logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable")
return nil, caos_errs.ThrowInternal(err, "EVENT-sw6Ku", "Errors.Internal")
}
if len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-9IHLP", "Errors.Changes.NotFound")
}
result := make([]*proj_model.ApplicationChange, 0)
for _, event := range events {
if !strings.Contains(event.Type.String(), "application") || event.Data == nil {
continue
}
app := new(proj_model.Application)
err := json.Unmarshal(event.Data, app)
logging.Log("EVENT-GIiKD").OnError(err).Debug("unable to unmarshal data")
if app.AppID != appID {
continue
}
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-MJzeN").OnError(err).Debug("unable to parse timestamp")
result = append(result, &proj_model.ApplicationChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierId: event.EditorUser,
Sequence: event.Sequence,
Data: app,
})
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &proj_model.ApplicationChanges{
Changes: result,
LastSequence: lastSequence,
}, nil
}
func (u *ProjectRepo) GetIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore.FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}

View File

@ -2,6 +2,9 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/eventstore/models"
usr_view "github.com/caos/zitadel/internal/user/repository/view"
"github.com/golang/protobuf/ptypes"
"github.com/caos/logging"
@ -14,9 +17,7 @@ import (
key_view_model "github.com/caos/zitadel/internal/key/repository/view/model"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
global_model "github.com/caos/zitadel/internal/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/view/repository"
)
@ -24,8 +25,6 @@ import (
type UserRepo struct {
es_int.Eventstore
SearchLimit uint64
UserEvents *usr_event.UserEventstore
OrgEvents *org_event.OrgEventstore
View *view.View
SystemDefaults systemdefaults.SystemDefaults
}
@ -38,7 +37,7 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*usr_model.UserV
if caos_errs.IsNotFound(viewErr) {
user = new(model.UserView)
}
events, esErr := repo.UserEvents.UserEventsByID(ctx, id, user.Sequence)
events, esErr := repo.getUserEvents(ctx, id, user.Sequence)
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Lsoj7", "Errors.User.NotFound")
}
@ -84,19 +83,19 @@ func (repo *UserRepo) UserIDsByDomain(ctx context.Context, domain string) ([]str
}
func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*usr_model.UserChanges, error) {
changes, err := repo.UserEvents.UserChanges(ctx, id, lastSequence, limit, sortAscending)
changes, err := repo.getUserChanges(ctx, id, lastSequence, limit, sortAscending)
if err != nil {
return nil, err
}
for _, change := range changes.Changes {
change.ModifierName = change.ModifierID
user, _ := repo.UserEvents.UserByID(ctx, change.ModifierID)
user, _ := repo.UserByID(ctx, change.ModifierID)
if user != nil {
if user.Human != nil {
change.ModifierName = user.Human.DisplayName
if user.HumanView != nil {
change.ModifierName = user.HumanView.DisplayName
}
if user.Machine != nil {
change.ModifierName = user.Machine.Name
if user.MachineView != nil {
change.ModifierName = user.MachineView.Name
}
}
}
@ -133,8 +132,15 @@ func (repo *UserRepo) UserMFAs(ctx context.Context, userID string) ([]*usr_model
return mfas, nil
}
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNToken, error) {
return repo.UserEvents.GetPasswordless(ctx, userID)
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNView, error) {
user, err := repo.UserByID(ctx, userID)
if err != nil {
return nil, err
}
if user.HumanView == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-9anf8", "Errors.User.NotHuman")
}
return user.HumanView.PasswordlessTokens, nil
}
func (repo *UserRepo) ProfileByID(ctx context.Context, userID string) (*usr_model.Profile, error) {
@ -274,6 +280,58 @@ func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_mo
return result, nil
}
func (r *UserRepo) getUserChanges(ctx context.Context, userID string, lastSequence uint64, limit uint64, sortAscending bool) (*usr_model.UserChanges, error) {
query := usr_view.ChangesQuery(userID, lastSequence, limit, sortAscending)
events, err := r.Eventstore.FilterEvents(ctx, query)
if err != nil {
logging.Log("EVENT-g9HCv").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-htuG9", "Errors.Internal")
}
if len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-6cAxe", "Errors.User.NoChanges")
}
result := make([]*usr_model.UserChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-8GTGS").OnError(err).Debug("unable to parse timestamp")
change := &usr_model.UserChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierID: event.EditorUser,
Sequence: event.Sequence,
}
//TODO: now all types should be unmarshalled, e.g. password
// if len(event.Data) != 0 {
// user := new(model.User)
// err := json.Unmarshal(event.Data, user)
// logging.Log("EVENT-Rkg7X").OnError(err).Debug("unable to unmarshal data")
// change.Data = user
// }
result[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &usr_model.UserChanges{
Changes: result,
LastSequence: lastSequence,
}, nil
}
func (r *UserRepo) getUserEvents(ctx context.Context, userID string, sequence uint64) ([]*models.Event, error) {
query, err := usr_view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return r.Eventstore.FilterEvents(ctx, query)
}
func handleSearchUserMembershipsPermissions(ctx context.Context, request *usr_model.UserMembershipSearchRequest, sequence *repository.CurrentSequence) *usr_model.UserMembershipSearchResponse {
permissions := authz.GetAllPermissionsFromCtx(ctx)
iamPerm := authz.HasGlobalExplicitPermission(permissions, iamMemberReadPerm)

View File

@ -5,13 +5,15 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_model "github.com/caos/zitadel/internal/project/model"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -21,17 +23,14 @@ const (
type Application struct {
handler
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newApplication(
handler handler,
projectEvents *proj_event.ProjectEventstore,
) *Application {
h := &Application{
handler: handler,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -69,14 +68,14 @@ func (a *Application) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil
return proj_view.ProjectQuery(sequence.CurrentSequence), nil
}
func (a *Application) Reduce(event *models.Event) (err error) {
app := new(view_model.ApplicationView)
switch event.Type {
case es_model.ApplicationAdded:
project, err := a.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := a.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -139,3 +138,24 @@ func (a *Application) OnError(event *models.Event, spoolerError error) error {
func (a *Application) OnSuccess() error {
return spooler.HandleSuccess(a.view.UpdateApplicationSpoolerRunTimestamp)
}
func (a *Application) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, a.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-ADvfs", "Errors.Project.NotFound")
}
return es_model.ProjectToModel(esProject), nil
}

View File

@ -7,11 +7,7 @@ import (
"github.com/caos/zitadel/internal/config/types"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/query"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type Configs map[string]*Config
@ -33,48 +29,27 @@ func (h *handler) Eventstore() eventstore.Eventstore {
return h.es
}
type EventstoreRepos struct {
ProjectEvents *proj_event.ProjectEventstore
UserEvents *usr_event.UserEventstore
OrgEvents *org_event.OrgEventstore
IamEvents *iam_event.IAMEventstore
}
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, defaults systemdefaults.SystemDefaults) []query.Handler {
return []query.Handler{
newProject(
handler{view, bulkLimit, configs.cycleDuration("Project"), errorCount, es}),
newProjectGrant(
handler{view, bulkLimit, configs.cycleDuration("ProjectGrant"), errorCount, es},
repos.ProjectEvents,
repos.OrgEvents),
newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es},
repos.ProjectEvents),
newProjectMember(handler{view, bulkLimit, configs.cycleDuration("ProjectMember"), errorCount, es},
repos.UserEvents),
newProjectGrantMember(handler{view, bulkLimit, configs.cycleDuration("ProjectGrantMember"), errorCount, es},
repos.UserEvents),
newApplication(handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es},
repos.ProjectEvents),
handler{view, bulkLimit, configs.cycleDuration("ProjectGrant"), errorCount, es}),
newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es}),
newProjectMember(handler{view, bulkLimit, configs.cycleDuration("ProjectMember"), errorCount, es}),
newProjectGrantMember(handler{view, bulkLimit, configs.cycleDuration("ProjectGrantMember"), errorCount, es}),
newApplication(handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es}),
newUser(handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
repos.OrgEvents,
repos.IamEvents,
defaults.IamID),
newUserGrant(handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es},
repos.ProjectEvents,
repos.UserEvents,
repos.OrgEvents),
newUserGrant(handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es}),
newOrg(
handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}),
newOrgMember(
handler{view, bulkLimit, configs.cycleDuration("OrgMember"), errorCount, es},
repos.UserEvents),
handler{view, bulkLimit, configs.cycleDuration("OrgMember"), errorCount, es}),
newOrgDomain(
handler{view, bulkLimit, configs.cycleDuration("OrgDomain"), errorCount, es}),
newUserMembership(
handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount, es},
repos.OrgEvents,
repos.ProjectEvents),
handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount, es}),
newAuthNKeys(
handler{view, bulkLimit, configs.cycleDuration("MachineKeys"), errorCount, es}),
newIDPConfig(
@ -85,16 +60,10 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es}),
newIDPProvider(
handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es},
defaults,
repos.IamEvents,
repos.OrgEvents),
defaults),
newExternalIDP(
handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es},
defaults,
repos.IamEvents,
repos.OrgEvents),
defaults),
newPasswordComplexityPolicy(
handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount, es}),
newPasswordAgePolicy(

View File

@ -2,19 +2,22 @@ package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_model "github.com/caos/zitadel/internal/org/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -24,22 +27,16 @@ const (
type IDPProvider struct {
handler
systemDefaults systemdefaults.SystemDefaults
iamEvents *eventsourcing.IAMEventstore
orgEvents *org_es.OrgEventstore
subscription *eventstore.Subscription
}
func newIDPProvider(
handler handler,
systemDefaults systemdefaults.SystemDefaults,
iamEvents *eventsourcing.IAMEventstore,
orgEvents *org_es.OrgEventstore,
) *IDPProvider {
h := &IDPProvider{
handler: handler,
systemDefaults: systemDefaults,
iamEvents: iamEvents,
orgEvents: orgEvents,
}
h.subscribe()
@ -119,9 +116,9 @@ func (m *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
}
config := new(iam_model.IDPConfig)
if event.AggregateID == m.systemDefaults.IamID {
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err = m.getDefaultIDPConfig(context.Background(), esConfig.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err = m.getOrgIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
}
if err != nil {
return err
@ -144,9 +141,9 @@ func (m *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
var config *iam_model.IDPConfig
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, provider.IDPConfigID)
config, err = m.getDefaultIDPConfig(context.Background(), provider.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
config, err = m.getOrgIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
}
if err != nil {
return err
@ -170,3 +167,64 @@ func (m *IDPProvider) OnError(event *es_models.Event, err error) error {
func (m *IDPProvider) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateIDPProviderSpoolerRunTimestamp)
}
func (i *IDPProvider) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2m9dS", "Errors.Org.IdpNotExisting")
}
func (i *IDPProvider) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: es_models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-4n9fs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *IDPProvider) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *IDPProvider) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-4M0fs", "Errors.IAM.IdpNotExisting")
}

View File

@ -2,12 +2,12 @@ package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/repository/view/model"
)
@ -61,7 +61,7 @@ func (o *Org) EventQuery() (*es_models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.OrgQuery(sequence.CurrentSequence), nil
return view.OrgQuery(sequence.CurrentSequence), nil
}
func (o *Org) Reduce(event *es_models.Event) (err error) {

View File

@ -2,6 +2,8 @@ package handler
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
@ -12,8 +14,8 @@ import (
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
const (
@ -22,17 +24,14 @@ const (
type OrgMember struct {
handler
userEvents *usr_event.UserEventstore
subscription *eventstore.Subscription
}
func newOrgMember(
handler handler,
userEvents *usr_event.UserEventstore,
) *OrgMember {
h := &OrgMember{
handler: handler,
userEvents: userEvents,
handler: handler,
}
h.subscribe()
@ -133,7 +132,7 @@ func (m *OrgMember) processUser(event *models.Event) (err error) {
if len(members) == 0 {
return m.view.ProcessedOrgMemberSequence(event)
}
user, err := m.userEvents.UserByID(context.Background(), event.AggregateID)
user, err := m.getUserByID(event.AggregateID)
if err != nil {
return err
}
@ -149,7 +148,7 @@ func (m *OrgMember) processUser(event *models.Event) (err error) {
}
func (m *OrgMember) fillData(member *org_model.OrgMemberView) (err error) {
user, err := m.userEvents.UserByID(context.Background(), member.UserID)
user, err := m.getUserByID(member.UserID)
if err != nil {
return err
}
@ -157,16 +156,16 @@ func (m *OrgMember) fillData(member *org_model.OrgMemberView) (err error) {
return nil
}
func (m *OrgMember) fillUserData(member *org_model.OrgMemberView, user *usr_model.User) {
func (m *OrgMember) fillUserData(member *org_model.OrgMemberView, user *usr_view_model.UserView) {
member.UserName = user.UserName
if user.Human != nil {
if user.HumanView != nil {
member.FirstName = user.FirstName
member.LastName = user.LastName
member.DisplayName = user.FirstName + " " + user.LastName
member.Email = user.EmailAddress
member.Email = user.Email
}
if user.Machine != nil {
member.DisplayName = user.Machine.Name
if user.MachineView != nil {
member.DisplayName = user.MachineView.Name
}
}
func (m *OrgMember) OnError(event *models.Event, err error) error {
@ -177,3 +176,36 @@ func (m *OrgMember) OnError(event *models.Event, err error) error {
func (o *OrgMember) OnSuccess() error {
return spooler.HandleSuccess(o.view.UpdateOrgMemberSpoolerRunTimestamp)
}
func (u *OrgMember) getUserByID(userID string) (*usr_view_model.UserView, error) {
user, usrErr := u.view.UserByID(userID)
if usrErr != nil && !caos_errs.IsNotFound(usrErr) {
return nil, usrErr
}
if user == nil {
user = &usr_view_model.UserView{}
}
events, err := u.getUserEvents(userID, user.Sequence)
if err != nil {
return user, usrErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user, nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "HANDLER-m9dos", "Errors.User.NotFound")
}
return &userCopy, nil
}
func (u *OrgMember) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return u.es.FilterEvents(context.Background(), query)
}

View File

@ -7,8 +7,8 @@ import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -61,7 +61,7 @@ func (p *Project) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return proj_event.ProjectQuery(sequence.CurrentSequence), nil
return proj_view.ProjectQuery(sequence.CurrentSequence), nil
}
func (p *Project) Reduce(event *models.Event) (err error) {

View File

@ -5,15 +5,18 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -23,20 +26,14 @@ const (
type ProjectGrant struct {
handler
projectEvents *proj_event.ProjectEventstore
orgEvents *org_event.OrgEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newProjectGrant(
handler handler,
projectEvents *proj_event.ProjectEventstore,
orgEvents *org_event.OrgEventstore,
) *ProjectGrant {
h := &ProjectGrant{
handler: handler,
projectEvents: projectEvents,
orgEvents: orgEvents,
handler: handler,
}
h.subscribe()
@ -74,7 +71,7 @@ func (p *ProjectGrant) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return proj_event.ProjectQuery(sequence.CurrentSequence), nil
return proj_view.ProjectQuery(sequence.CurrentSequence), nil
}
func (p *ProjectGrant) Reduce(event *models.Event) (err error) {
@ -97,11 +94,11 @@ func (p *ProjectGrant) Reduce(event *models.Event) (err error) {
}
grantedProject.Name = project.Name
org, err := p.orgEvents.OrgByID(context.TODO(), org_model.NewOrg(grantedProject.OrgID))
org, err := p.getOrgByID(context.TODO(), grantedProject.OrgID)
if err != nil {
return err
}
resourceOwner, err := p.orgEvents.OrgByID(context.TODO(), org_model.NewOrg(grantedProject.ResourceOwner))
resourceOwner, err := p.getOrgByID(context.TODO(), grantedProject.ResourceOwner)
if err != nil {
return err
}
@ -145,7 +142,7 @@ func (p *ProjectGrant) fillOrgData(grantedProject *view_model.ProjectGrantView,
}
func (p *ProjectGrant) getProject(projectID string) (*proj_model.Project, error) {
return p.projectEvents.ProjectByID(context.Background(), projectID)
return p.getProjectByID(context.Background(), projectID)
}
func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, event *models.Event) error {
@ -167,3 +164,46 @@ func (p *ProjectGrant) OnError(event *models.Event, err error) error {
func (p *ProjectGrant) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateProjectGrantSpoolerRunTimestamp)
}
func (u *ProjectGrant) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *ProjectGrant) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-NBrw2", "Errors.Project.NotFound")
}
return es_model.ProjectToModel(esProject), nil
}

View File

@ -2,6 +2,9 @@ package handler
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/user/repository/view"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/logging"
@ -13,7 +16,6 @@ import (
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
@ -23,17 +25,14 @@ const (
type ProjectGrantMember struct {
handler
userEvents *usr_event.UserEventstore
subscription *eventstore.Subscription
}
func newProjectGrantMember(
handler handler,
userEvents *usr_event.UserEventstore,
) *ProjectGrantMember {
h := &ProjectGrantMember{
handler: handler,
userEvents: userEvents,
handler: handler,
}
h.subscribe()
@ -140,7 +139,7 @@ func (p *ProjectGrantMember) processUser(event *models.Event) (err error) {
if len(members) == 0 {
return p.view.ProcessedProjectGrantMemberSequence(event)
}
user, err := p.userEvents.UserByID(context.Background(), event.AggregateID)
user, err := p.getUserByID(event.AggregateID)
if err != nil {
return err
}
@ -154,7 +153,7 @@ func (p *ProjectGrantMember) processUser(event *models.Event) (err error) {
}
func (p *ProjectGrantMember) fillData(member *view_model.ProjectGrantMemberView) (err error) {
user, err := p.userEvents.UserByID(context.Background(), member.UserID)
user, err := p.getUserByID(member.UserID)
if err != nil {
return err
}
@ -162,16 +161,16 @@ func (p *ProjectGrantMember) fillData(member *view_model.ProjectGrantMemberView)
return nil
}
func (p *ProjectGrantMember) fillUserData(member *view_model.ProjectGrantMemberView, user *usr_model.User) {
func (p *ProjectGrantMember) fillUserData(member *view_model.ProjectGrantMemberView, user *usr_view_model.UserView) {
member.UserName = user.UserName
if user.Human != nil {
if user.HumanView != nil {
member.FirstName = user.FirstName
member.LastName = user.LastName
member.DisplayName = user.FirstName + " " + user.LastName
member.Email = user.EmailAddress
member.Email = user.Email
}
if user.Machine != nil {
member.DisplayName = user.Machine.Name
if user.MachineView != nil {
member.DisplayName = user.MachineView.Name
}
}
@ -183,3 +182,36 @@ func (p *ProjectGrantMember) OnError(event *models.Event, err error) error {
func (p *ProjectGrantMember) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateProjectGrantMemberSpoolerRunTimestamp)
}
func (u *ProjectGrantMember) getUserByID(userID string) (*usr_view_model.UserView, error) {
user, usrErr := u.view.UserByID(userID)
if usrErr != nil && !caos_errs.IsNotFound(usrErr) {
return nil, usrErr
}
if user == nil {
user = &usr_view_model.UserView{}
}
events, err := u.getUserEvents(userID, user.Sequence)
if err != nil {
return user, usrErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user, nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "HANDLER-m9dos", "Errors.User.NotFound")
}
return &userCopy, nil
}
func (u *ProjectGrantMember) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return u.es.FilterEvents(context.Background(), query)
}

View File

@ -2,6 +2,8 @@ package handler
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/logging"
@ -13,8 +15,8 @@ import (
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
const (
@ -23,17 +25,14 @@ const (
type ProjectMember struct {
handler
userEvents *usr_event.UserEventstore
subscription *eventstore.Subscription
}
func newProjectMember(
handler handler,
userEvents *usr_event.UserEventstore,
) *ProjectMember {
h := &ProjectMember{
handler: handler,
userEvents: userEvents,
handler: handler,
}
h.subscribe()
@ -136,7 +135,7 @@ func (p *ProjectMember) processUser(event *models.Event) (err error) {
if len(members) == 0 {
return p.view.ProcessedProjectMemberSequence(event)
}
user, err := p.userEvents.UserByID(context.Background(), event.AggregateID)
user, err := p.getUserByID(event.AggregateID)
if err != nil {
return err
}
@ -151,7 +150,7 @@ func (p *ProjectMember) processUser(event *models.Event) (err error) {
}
func (p *ProjectMember) fillData(member *view_model.ProjectMemberView) (err error) {
user, err := p.userEvents.UserByID(context.Background(), member.UserID)
user, err := p.getUserByID(member.UserID)
if err != nil {
return err
}
@ -159,16 +158,16 @@ func (p *ProjectMember) fillData(member *view_model.ProjectMemberView) (err erro
return nil
}
func (p *ProjectMember) fillUserData(member *view_model.ProjectMemberView, user *usr_model.User) {
func (p *ProjectMember) fillUserData(member *view_model.ProjectMemberView, user *usr_view_model.UserView) {
member.UserName = user.UserName
if user.Human != nil {
if user.HumanView != nil {
member.FirstName = user.FirstName
member.LastName = user.LastName
member.Email = user.EmailAddress
member.Email = user.Email
member.DisplayName = user.FirstName + " " + user.LastName
}
if user.Machine != nil {
member.DisplayName = user.Machine.Name
if user.MachineView != nil {
member.DisplayName = user.MachineView.Name
}
}
func (p *ProjectMember) OnError(event *models.Event, err error) error {
@ -179,3 +178,36 @@ func (p *ProjectMember) OnError(event *models.Event, err error) error {
func (p *ProjectMember) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateProjectMemberSpoolerRunTimestamp)
}
func (u *ProjectMember) getUserByID(userID string) (*usr_view_model.UserView, error) {
user, usrErr := u.view.UserByID(userID)
if usrErr != nil && !caos_errs.IsNotFound(usrErr) {
return nil, usrErr
}
if user == nil {
user = &usr_view_model.UserView{}
}
events, err := u.getUserEvents(userID, user.Sequence)
if err != nil {
return user, usrErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user, nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "HANDLER-m9dos", "Errors.User.NotFound")
}
return &userCopy, nil
}
func (u *ProjectMember) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return u.es.FilterEvents(context.Background(), query)
}

View File

@ -7,9 +7,8 @@ import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
@ -19,17 +18,14 @@ const (
type ProjectRole struct {
handler
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newProjectRole(
handler handler,
projectEvents *proj_event.ProjectEventstore,
) *ProjectRole {
h := &ProjectRole{
handler: handler,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -67,7 +63,7 @@ func (p *ProjectRole) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil
return proj_view.ProjectQuery(sequence.CurrentSequence), nil
}
func (p *ProjectRole) Reduce(event *models.Event) (err error) {

View File

@ -2,19 +2,23 @@ package handler
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -23,23 +27,17 @@ const (
type User struct {
handler
orgEvents *org_events.OrgEventstore
iamEvents *iam_es.IAMEventstore
iamID string
subscription *eventstore.Subscription
}
func newUser(
handler handler,
orgEvents *org_events.OrgEventstore,
iamEvents *iam_es.IAMEventstore,
iamID string,
) *User {
h := &User{
handler: handler,
orgEvents: orgEvents,
iamEvents: iamEvents,
iamID: iamID,
handler: handler,
iamID: iamID,
}
h.subscribe()
@ -180,13 +178,13 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
}
func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -202,13 +200,13 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
}
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -227,13 +225,13 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
}
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(user.ResourceOwner))
org, err := u.getOrgByID(context.Background(), user.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.TODO())
if err != nil {
return err
}
@ -251,3 +249,53 @@ func (u *User) OnError(event *models.Event, err error) error {
func (u *User) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp)
}
func (u *User) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *User) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *User) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2Fj8s", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
}

View File

@ -2,6 +2,11 @@ package handler
import (
"context"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/logging"
@ -12,10 +17,8 @@ import (
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -28,22 +31,16 @@ const (
type ExternalIDP struct {
handler
systemDefaults systemdefaults.SystemDefaults
iamEvents *eventsourcing.IAMEventstore
orgEvents *org_es.OrgEventstore
subscription *eventstore.Subscription
}
func newExternalIDP(
handler handler,
systemDefaults systemdefaults.SystemDefaults,
iamEvents *eventsourcing.IAMEventstore,
orgEvents *org_es.OrgEventstore,
) *ExternalIDP {
h := &ExternalIDP{
handler: handler,
systemDefaults: systemDefaults,
iamEvents: iamEvents,
orgEvents: orgEvents,
}
h.subscribe()
@ -137,9 +134,9 @@ func (i *ExternalIDP) processIdpConfig(event *es_models.Event) (err error) {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), configView.IDPConfigID)
} else {
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.getOrgIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err
@ -155,9 +152,9 @@ func (i *ExternalIDP) processIdpConfig(event *es_models.Event) (err error) {
}
func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
config, err := i.getOrgIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
if caos_errs.IsNotFound(err) {
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID)
config, err = i.getDefaultIDPConfig(context.Background(), externalIDP.IDPConfigID)
}
if err != nil {
return err
@ -178,3 +175,64 @@ func (i *ExternalIDP) OnError(event *es_models.Event, err error) error {
func (i *ExternalIDP) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp)
}
func (i *ExternalIDP) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-22n7G", "Errors.Org.IdpNotExisting")
}
func (i *ExternalIDP) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: es_models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-4m0fs", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *ExternalIDP) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}
func (u *ExternalIDP) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-22Nv8", "Errors.IAM.IdpNotExisting")
}

View File

@ -4,18 +4,25 @@ import (
"context"
"github.com/caos/logging"
"k8s.io/apimachinery/pkg/api/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
org_view "github.com/caos/zitadel/internal/org/repository/view"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
"github.com/caos/zitadel/internal/user/repository/view"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
org_model "github.com/caos/zitadel/internal/org/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_events "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
@ -27,23 +34,14 @@ const (
type UserGrant struct {
handler
projectEvents *proj_event.ProjectEventstore
userEvents *usr_events.UserEventstore
orgEvents *org_events.OrgEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newUserGrant(
handler handler,
projectEvents *proj_event.ProjectEventstore,
userEvents *usr_events.UserEventstore,
orgEvents *org_events.OrgEventstore,
) *UserGrant {
h := &UserGrant{
handler: handler,
projectEvents: projectEvents,
userEvents: userEvents,
orgEvents: orgEvents,
handler: handler,
}
h.subscribe()
@ -141,7 +139,7 @@ func (u *UserGrant) processUser(event *es_models.Event) (err error) {
if len(grants) == 0 {
return u.view.ProcessedUserGrantSequence(event)
}
user, err := u.userEvents.UserByID(context.Background(), event.AggregateID)
user, err := u.getUserByID(event.AggregateID)
if err != nil {
return err
}
@ -164,7 +162,7 @@ func (u *UserGrant) processProject(event *es_models.Event) (err error) {
if len(grants) == 0 {
return u.view.ProcessedUserGrantSequence(event)
}
project, err := u.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := u.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -178,18 +176,18 @@ func (u *UserGrant) processProject(event *es_models.Event) (err error) {
}
func (u *UserGrant) fillData(grant *view_model.UserGrantView, resourceOwner string) (err error) {
user, err := u.userEvents.UserByID(context.Background(), grant.UserID)
user, err := u.getUserByID(grant.UserID)
if err != nil {
return err
}
u.fillUserData(grant, user)
project, err := u.projectEvents.ProjectByID(context.Background(), grant.ProjectID)
project, err := u.getProjectByID(context.Background(), grant.ProjectID)
if err != nil {
return err
}
u.fillProjectData(grant, project)
org, err := u.orgEvents.OrgByID(context.TODO(), org_model.NewOrg(resourceOwner))
org, err := u.getOrgByID(context.TODO(), resourceOwner)
if err != nil {
return err
}
@ -197,16 +195,16 @@ func (u *UserGrant) fillData(grant *view_model.UserGrantView, resourceOwner stri
return nil
}
func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *usr_model.User) {
func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *usr_view_model.UserView) {
grant.UserName = user.UserName
if user.Human != nil {
if user.HumanView != nil {
grant.FirstName = user.FirstName
grant.LastName = user.LastName
grant.DisplayName = user.FirstName + " " + user.LastName
grant.Email = user.EmailAddress
grant.Email = user.Email
}
if user.Machine != nil {
grant.DisplayName = user.Machine.Name
if user.MachineView != nil {
grant.DisplayName = user.MachineView.Name
}
}
@ -233,3 +231,79 @@ func (u *UserGrant) OnError(event *es_models.Event, err error) error {
func (u *UserGrant) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp)
}
func (u *UserGrant) getUserByID(userID string) (*usr_view_model.UserView, error) {
user, usrErr := u.view.UserByID(userID)
if usrErr != nil && !caos_errs.IsNotFound(usrErr) {
return nil, usrErr
}
if user == nil {
user = &usr_view_model.UserView{}
}
events, err := u.getUserEvents(userID, user.Sequence)
if err != nil {
return user, usrErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user, nil
}
}
if userCopy.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "HANDLER-m9dos", "Errors.User.NotFound")
}
return &userCopy, nil
}
func (u *UserGrant) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}
return u.es.FilterEvents(context.Background(), query)
}
func (u *UserGrant) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := org_view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *UserGrant) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &proj_es_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Dfb42", "Errors.Project.NotFound")
}
return proj_es_model.ProjectToModel(esProject), nil
}

View File

@ -3,6 +3,14 @@ package handler
import (
"context"
"k8s.io/apimachinery/pkg/api/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
org_view "github.com/caos/zitadel/internal/org/repository/view"
proj_model "github.com/caos/zitadel/internal/project/model"
proj_view "github.com/caos/zitadel/internal/project/repository/view"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
@ -11,9 +19,7 @@ import (
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
@ -26,20 +32,14 @@ const (
type UserMembership struct {
handler
orgEvents *org_event.OrgEventstore
projectEvents *proj_event.ProjectEventstore
subscription *eventstore.Subscription
subscription *eventstore.Subscription
}
func newUserMembership(
handler handler,
orgEvents *org_event.OrgEventstore,
projectEvents *proj_event.ProjectEventstore,
) *UserMembership {
h := &UserMembership{
handler: handler,
orgEvents: orgEvents,
projectEvents: projectEvents,
handler: handler,
}
h.subscribe()
@ -155,7 +155,7 @@ func (m *UserMembership) processOrg(event *es_models.Event) (err error) {
}
func (m *UserMembership) fillOrgDisplayName(member *usr_es_model.UserMembershipView) (err error) {
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(member.AggregateID))
org, err := m.getOrgByID(context.Background(), member.AggregateID)
if err != nil {
return err
}
@ -164,7 +164,7 @@ func (m *UserMembership) fillOrgDisplayName(member *usr_es_model.UserMembershipV
}
func (m *UserMembership) updateOrgDisplayName(event *es_models.Event) error {
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.AggregateID))
org, err := m.getOrgByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -220,7 +220,7 @@ func (m *UserMembership) processProject(event *es_models.Event) (err error) {
}
func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) {
project, err := m.projectEvents.ProjectByID(context.Background(), member.AggregateID)
project, err := m.getProjectByID(context.Background(), member.AggregateID)
if err != nil {
return err
}
@ -229,7 +229,7 @@ func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembers
}
func (m *UserMembership) updateProjectDisplayName(event *es_models.Event) error {
project, err := m.projectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := m.getProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@ -261,3 +261,46 @@ func (m *UserMembership) OnError(event *es_models.Event, err error) error {
func (m *UserMembership) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateUserMembershipSpoolerRunTimestamp)
}
func (u *UserMembership) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := org_view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: es_models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *UserMembership) getProjectByID(ctx context.Context, projID string) (*proj_model.Project, error) {
query, err := proj_view.ProjectByIDQuery(projID, 0)
if err != nil {
return nil, err
}
esProject := &proj_es_model.Project{
ObjectRoot: es_models.ObjectRoot{
AggregateID: projID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esProject.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esProject.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-Bg32b", "Errors.Project.NotFound")
}
return proj_es_model.ProjectToModel(esProject), nil
}

View File

@ -1,22 +1,15 @@
package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/config/types"
es_int "github.com/caos/zitadel/internal/eventstore"
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/eventstore"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/handler"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/spooler"
mgmt_view "github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type Config struct {
@ -34,6 +27,7 @@ type EsRepository struct {
eventstore.UserRepo
eventstore.UserGrantRepo
eventstore.IAMRepository
view *mgmt_view.View
}
func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRepository, error) {
@ -53,55 +47,25 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
return nil, err
}
project, err := es_proj.StartProject(es_proj.ProjectConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
user, err := es_usr.StartUser(es_usr.UserConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
org := es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: conf.Domain}, systemDefaults)
iam, err := es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
eventstoreRepos := handler.EventstoreRepos{ProjectEvents: project, UserEvents: user, OrgEvents: org, IamEvents: iam}
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, eventstoreRepos, systemDefaults)
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
return &EsRepository{
spooler: spool,
OrgRepository: eventstore.OrgRepository{conf.SearchLimit, org, user, iam, view, roles, systemDefaults},
ProjectRepo: eventstore.ProjectRepo{es, conf.SearchLimit, project, user, iam, view, roles, systemDefaults.IamID},
UserRepo: eventstore.UserRepo{es, conf.SearchLimit, user, org, view, systemDefaults},
OrgRepository: eventstore.OrgRepository{conf.SearchLimit, es, view, roles, systemDefaults},
ProjectRepo: eventstore.ProjectRepo{es, conf.SearchLimit, view, roles, systemDefaults.IamID},
UserRepo: eventstore.UserRepo{es, conf.SearchLimit, view, systemDefaults},
UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, view},
IAMRepository: eventstore.IAMRepository{
IAMV2Query: iamV2Query,
},
view: view,
}, nil
}
func (repo *EsRepository) Health() error {
return repo.ProjectEvents.Health(context.Background())
}
func (repo *EsRepository) IAMByID(ctx context.Context, id string) (*iam_model.IAM, error) {
return repo.IAMRepository.IAMByID(ctx, id)
return repo.view.Health()
}

View File

@ -17,12 +17,12 @@ type SpoolerConfig struct {
Handlers handler.Configs
}
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, eventstoreRepos handler.EventstoreRepos, defaults systemdefaults.SystemDefaults) *spooler.Spooler {
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, defaults systemdefaults.SystemDefaults) *spooler.Spooler {
spoolerConfig := spooler.Config{
Eventstore: es,
Locker: &locker{dbClient: sql},
ConcurrentWorkers: c.ConcurrentWorkers,
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, eventstoreRepos, defaults),
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, defaults),
}
spool := spoolerConfig.New()
spool.Start()

View File

@ -2,6 +2,7 @@ package repository
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
key_model "github.com/caos/zitadel/internal/key/model"
"github.com/caos/zitadel/internal/project/model"
@ -28,12 +29,12 @@ type ProjectRepository interface {
ApplicationChanges(ctx context.Context, id string, secId string, lastSequence uint64, limit uint64, sortAscending bool) (*model.ApplicationChanges, error)
SearchClientKeys(ctx context.Context, request *key_model.AuthNKeySearchRequest) (*key_model.AuthNKeySearchResponse, error)
GetClientKey(ctx context.Context, projectID, applicationID, keyID string) (*key_model.AuthNKeyView, error)
AddClientKey(ctx context.Context, key *model.ClientKey) (*model.ClientKey, error)
RemoveClientKey(ctx context.Context, projectID, applicationID, keyID string) error
ProjectGrantByID(ctx context.Context, grantID string) (*model.ProjectGrantView, error)
SearchProjectGrantMembers(ctx context.Context, request *model.ProjectGrantMemberSearchRequest) (*model.ProjectGrantMemberSearchResponse, error)
ProjectGrantMemberByID(ctx context.Context, projectID, userID string) (*model.ProjectGrantMemberView, error)
GetProjectGrantMemberRoles() []string
GetIAMByID(ctx context.Context) (*iam_model.IAM, error)
}

View File

@ -21,7 +21,7 @@ type UserRepository interface {
UserMFAs(ctx context.Context, userID string) ([]*model.MultiFactor, error)
GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error)
GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNView, error)
SearchExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error)
ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*model.ExternalIDPView, error)

View File

@ -12,10 +12,7 @@ import (
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/i18n"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/notification/repository/eventsourcing/view"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type Configs map[string]*Config
@ -37,13 +34,7 @@ func (h *handler) Eventstore() eventstore.Eventstore {
return h.es
}
type EventstoreRepos struct {
UserEvents *usr_event.UserEventstore
OrgEvents *org_event.OrgEventstore
IAMEvents *iam_es.IAMEventstore
}
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, command *command.CommandSide, repos EventstoreRepos, systemDefaults sd.SystemDefaults, i18n *i18n.Translator, dir http.FileSystem) []query.Handler {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, command *command.CommandSide, systemDefaults sd.SystemDefaults, i18n *i18n.Translator, dir http.FileSystem) []query.Handler {
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.UserVerificationKey)
if err != nil {
logging.Log("HANDL-s90ew").WithError(err).Debug("error create new aes crypto")
@ -51,14 +42,11 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
return []query.Handler{
newNotifyUser(
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
repos.OrgEvents,
repos.IAMEvents,
systemDefaults.IamID,
),
newNotification(
handler{view, bulkLimit, configs.cycleDuration("Notification"), errorCount, es},
command,
repos.UserEvents,
systemDefaults,
aesCrypto,
i18n,

View File

@ -3,6 +3,7 @@ package handler
import (
"context"
"encoding/json"
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/zitadel/internal/user/repository/view/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/v2/command"
@ -24,7 +25,6 @@ import (
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/notification/types"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
@ -47,7 +47,6 @@ const (
type Notification struct {
handler
command *command.CommandSide
userEvents *usr_event.UserEventstore
systemDefaults sd.SystemDefaults
AesCrypto crypto.EncryptionAlgorithm
i18n *i18n.Translator
@ -58,7 +57,6 @@ type Notification struct {
func newNotification(
handler handler,
command *command.CommandSide,
userEvents *usr_event.UserEventstore,
defaults sd.SystemDefaults,
aesCrypto crypto.EncryptionAlgorithm,
translator *i18n.Translator,
@ -67,7 +65,6 @@ func newNotification(
h := &Notification{
handler: handler,
command: command,
userEvents: userEvents,
systemDefaults: defaults,
i18n: translator,
statikDir: statikDir,
@ -109,7 +106,7 @@ func (n *Notification) EventQuery() (*models.SearchQuery, error) {
if err != nil {
return nil, err
}
return usr_event.UserQuery(sequence.CurrentSequence), nil
return view.UserQuery(sequence.CurrentSequence), nil
}
func (n *Notification) Reduce(event *models.Event) (err error) {
@ -331,7 +328,7 @@ func (n *Notification) checkIfAlreadyHandled(userID string, sequence uint64, eve
}
func (n *Notification) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) {
query, err := usr_event.UserByIDQuery(userID, sequence)
query, err := view.UserByIDQuery(userID, sequence)
if err != nil {
return nil, err
}

View File

@ -2,15 +2,20 @@ package handler
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_view "github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
org_model "github.com/caos/zitadel/internal/org/model"
org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -22,23 +27,17 @@ const (
type NotifyUser struct {
handler
orgEvents *org_events.OrgEventstore
iamEvents *iam_es.IAMEventstore
iamID string
subscription *eventstore.Subscription
}
func newNotifyUser(
handler handler,
orgEvents *org_events.OrgEventstore,
iamEvents *iam_es.IAMEventstore,
iamID string,
) *NotifyUser {
h := &NotifyUser{
handler: handler,
orgEvents: orgEvents,
iamEvents: iamEvents,
iamID: iamID,
handler: handler,
iamID: iamID,
}
h.subscribe()
@ -157,13 +156,13 @@ func (u *NotifyUser) ProcessOrg(event *es_models.Event) (err error) {
}
func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -183,13 +182,13 @@ func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
}
func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) error {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner))
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -212,13 +211,13 @@ func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) e
}
func (u *NotifyUser) fillLoginNames(user *view_model.NotifyUser) (err error) {
org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(user.ResourceOwner))
org, err := u.getOrgByID(context.Background(), user.ResourceOwner)
if err != nil {
return err
}
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
@ -236,3 +235,49 @@ func (p *NotifyUser) OnError(event *es_models.Event, err error) error {
func (u *NotifyUser) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateNotifyUserSpoolerRunTimestamp)
}
func (u *NotifyUser) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := org_view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
var esOrg *org_es_model.Org
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *NotifyUser) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *NotifyUser) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2Fj8s", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
}

View File

@ -1,7 +1,6 @@
package eventsourcing
import (
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/command"
"net/http"
@ -10,11 +9,8 @@ import (
es_int "github.com/caos/zitadel/internal/eventstore"
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/i18n"
"github.com/caos/zitadel/internal/notification/repository/eventsourcing/handler"
"github.com/caos/zitadel/internal/notification/repository/eventsourcing/spooler"
noti_view "github.com/caos/zitadel/internal/notification/repository/eventsourcing/view"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"golang.org/x/text/language"
)
@ -45,28 +41,11 @@ func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, c
return nil, err
}
user, err := es_usr.StartUser(es_usr.UserConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
org := es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: conf.Domain}, systemDefaults)
translator, err := i18n.NewTranslator(dir, i18n.TranslatorConfig{DefaultLanguage: conf.DefaultLanguage})
if err != nil {
return nil, err
}
iam, err := es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
eventstoreRepos := handler.EventstoreRepos{UserEvents: user, OrgEvents: org, IAMEvents: iam}
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, command, eventstoreRepos, systemDefaults, translator, dir)
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, command, systemDefaults, translator, dir)
return &EsRepository{
spool,

View File

@ -20,12 +20,12 @@ type SpoolerConfig struct {
Handlers handler.Configs
}
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, command *command.CommandSide, eventstoreRepos handler.EventstoreRepos, systemDefaults sd.SystemDefaults, i18n *i18n.Translator, dir http.FileSystem) *spooler.Spooler {
func StartSpooler(c SpoolerConfig, es eventstore.Eventstore, view *view.View, sql *sql.DB, command *command.CommandSide, systemDefaults sd.SystemDefaults, i18n *i18n.Translator, dir http.FileSystem) *spooler.Spooler {
spoolerConfig := spooler.Config{
Eventstore: es,
Locker: &locker{dbClient: sql},
ConcurrentWorkers: c.ConcurrentWorkers,
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, eventstoreRepos, systemDefaults, i18n, dir),
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, systemDefaults, i18n, dir),
}
spool := spoolerConfig.New()
spool.Start()

View File

@ -1,191 +0,0 @@
package eventsourcing
import (
"context"
"encoding/json"
"github.com/caos/logging"
http_utils "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/id"
org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/golang/protobuf/ptypes"
)
type OrgEventstore struct {
eventstore.Eventstore
IAMDomain string
IamID string
idGenerator id.Generator
verificationAlgorithm crypto.EncryptionAlgorithm
verificationGenerator crypto.Generator
verificationValidator func(domain string, token string, verifier string, checkType http_utils.CheckType) error
secretCrypto crypto.Crypto
}
type OrgConfig struct {
eventstore.Eventstore
IAMDomain string
VerificationConfig *crypto.KeyConfig
}
func StartOrg(conf OrgConfig, defaults systemdefaults.SystemDefaults) *OrgEventstore {
verificationAlg, err := crypto.NewAESCrypto(defaults.DomainVerification.VerificationKey)
logging.Log("EVENT-aZ22d").OnError(err).Panic("cannot create verificationAlgorithm for domain verification")
verificationGen := crypto.NewEncryptionGenerator(defaults.DomainVerification.VerificationGenerator, verificationAlg)
aesCrypto, err := crypto.NewAESCrypto(defaults.IDPConfigVerificationKey)
logging.Log("EVENT-Sn8du").OnError(err).Panic("cannot create verificationAlgorithm for idp config verification")
return &OrgEventstore{
Eventstore: conf.Eventstore,
idGenerator: id.SonyFlakeGenerator,
verificationAlgorithm: verificationAlg,
verificationGenerator: verificationGen,
verificationValidator: http_utils.ValidateDomain,
IAMDomain: conf.IAMDomain,
IamID: defaults.IamID,
secretCrypto: aesCrypto,
}
}
func (es *OrgEventstore) OrgByID(ctx context.Context, org *org_model.Org) (*org_model.Org, error) {
if org == nil {
return nil, errors.ThrowInvalidArgument(nil, "EVENT-gQTYP", "Errors.Org.Empty")
}
query, err := OrgByIDQuery(org.AggregateID, org.Sequence)
if err != nil {
return nil, err
}
esOrg := model.OrgFromModel(org)
err = es_sdk.Filter(ctx, es.FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound")
}
return model.OrgToModel(esOrg), nil
}
func (es *OrgEventstore) OrgEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error) {
query, err := OrgByIDQuery(id, sequence)
if err != nil {
return nil, err
}
return es.FilterEvents(ctx, query)
}
func (es *OrgEventstore) IsOrgUnique(ctx context.Context, name, domain string) (isUnique bool, err error) {
var found bool
err = es_sdk.Filter(ctx, es.FilterEvents, isUniqueValidation(&found), OrgNameUniqueQuery(name))
if (err != nil && !errors.IsNotFound(err)) || found {
return false, err
}
err = es_sdk.Filter(ctx, es.FilterEvents, isUniqueValidation(&found), OrgDomainUniqueQuery(domain))
if err != nil && !errors.IsNotFound(err) {
return false, err
}
return !found, nil
}
func isUniqueValidation(unique *bool) func(events ...*es_models.Event) error {
return func(events ...*es_models.Event) error {
if len(events) == 0 {
return nil
}
*unique = *unique || events[0].Type == model.OrgDomainReserved || events[0].Type == model.OrgNameReserved
return nil
}
}
func (es *OrgEventstore) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error) {
query := ChangesQuery(id, lastSequence, limit, sortAscending)
events, err := es.Eventstore.FilterEvents(context.Background(), query)
if err != nil {
logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-328b1", "Errors.Org.NotFound")
}
if len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-FpQqK", "Errors.Changes.NotFound")
}
changes := make([]*org_model.OrgChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-qxIR7").OnError(err).Debug("unable to parse timestamp")
change := &org_model.OrgChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierId: event.EditorUser,
Sequence: event.Sequence,
}
if event.Data != nil {
org := new(model.Org)
err := json.Unmarshal(event.Data, org)
logging.Log("EVENT-XCLEm").OnError(err).Debug("unable to unmarshal data")
change.Data = org
}
changes[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &org_model.OrgChanges{
Changes: changes,
LastSequence: lastSequence,
}, nil
}
func ChangesQuery(orgID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
query := es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate)
if !sortAscending {
query.OrderDesc()
}
query.LatestSequenceFilter(latestSequence).
AggregateIDFilter(orgID).
SetLimit(limit)
return query
}
func (es *OrgEventstore) GetOrgIAMPolicy(ctx context.Context, orgID string) (*iam_model.OrgIAMPolicy, error) {
existingOrg, err := es.OrgByID(ctx, org_model.NewOrg(orgID))
if err != nil {
return nil, err
}
if existingOrg.OrgIamPolicy == nil {
return nil, errors.ThrowNotFound(nil, "EVENT-3F9sf", "Errors.Org.OrgIAM.NotExisting")
}
return existingOrg.OrgIamPolicy, nil
}
func (es *OrgEventstore) GetIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := es.OrgByID(ctx, org_model.NewOrg(aggregateID))
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-Qlo0d", "Errors.Org.IdpNotExisting")
}

View File

@ -1,10 +0,0 @@
package repository
import es_models "github.com/caos/zitadel/internal/eventstore/models"
type Org struct {
es_models.ObjectRoot
Name string
Domain string
}

View File

@ -1,8 +1,6 @@
package eventsourcing
package view
import (
"context"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
@ -16,6 +14,12 @@ func OrgByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, err
AggregateIDFilter(id), nil
}
func OrgQuery(latestSequence uint64) *es_models.SearchQuery {
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate).
LatestSequenceFilter(latestSequence)
}
func OrgDomainUniqueQuery(domain string) *es_models.SearchQuery {
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgDomainAggregate).
@ -32,12 +36,16 @@ func OrgNameUniqueQuery(name string) *es_models.SearchQuery {
SetLimit(1)
}
func OrgQuery(latestSequence uint64) *es_models.SearchQuery {
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate).
LatestSequenceFilter(latestSequence)
}
func ChangesQuery(orgID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
query := es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate)
func OrgAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, id string, sequence uint64) (*es_models.Aggregate, error) {
return aggCreator.NewAggregate(ctx, id, model.OrgAggregate, model.OrgVersion, sequence, es_models.OverwriteResourceOwner(id))
if !sortAscending {
query.OrderDesc()
}
query.LatestSequenceFilter(latestSequence).
AggregateIDFilter(orgID).
SetLimit(limit)
return query
}

View File

@ -1,206 +1,46 @@
package eventsourcing
import (
"context"
"encoding/json"
"strings"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/cache/config"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
"github.com/caos/zitadel/internal/id"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
)
const (
projectOwnerRole = "PROJECT_OWNER"
projectOwnerGlobalRole = "PROJECT_OWNER_GLOBAL"
)
type ProjectEventstore struct {
es_int.Eventstore
projectCache *ProjectCache
passwordAlg crypto.HashAlgorithm
pwGenerator crypto.Generator
idGenerator id.Generator
ClientKeySize int
}
type ProjectConfig struct {
es_int.Eventstore
Cache *config.CacheConfig
}
func StartProject(conf ProjectConfig, systemDefaults sd.SystemDefaults) (*ProjectEventstore, error) {
projectCache, err := StartCache(conf.Cache)
if err != nil {
return nil, err
}
passwordAlg := crypto.NewBCrypt(systemDefaults.SecretGenerators.PasswordSaltCost)
pwGenerator := crypto.NewHashGenerator(systemDefaults.SecretGenerators.ClientSecretGenerator, passwordAlg)
return &ProjectEventstore{
Eventstore: conf.Eventstore,
projectCache: projectCache,
passwordAlg: passwordAlg,
pwGenerator: pwGenerator,
idGenerator: id.SonyFlakeGenerator,
ClientKeySize: int(systemDefaults.SecretGenerators.ApplicationKeySize),
}, nil
}
func (es *ProjectEventstore) ProjectByID(ctx context.Context, id string) (*proj_model.Project, error) {
project := es.projectCache.getProject(id)
query, err := ProjectByIDQuery(project.AggregateID, project.Sequence)
if err != nil {
return nil, err
}
err = es_sdk.Filter(ctx, es.FilterEvents, project.AppendEvents, query)
if err != nil && !(caos_errs.IsNotFound(err) && project.Sequence != 0) {
return nil, err
}
if project.State == int32(proj_model.ProjectStateRemoved) {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dG8ie", "Errors.Project.NotFound")
}
es.projectCache.cacheProject(project)
return model.ProjectToModel(project), nil
}
func (es *ProjectEventstore) ProjectEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error) {
query, err := ProjectByIDQuery(id, sequence)
if err != nil {
return nil, err
}
return es.FilterEvents(ctx, query)
}
func (es *ProjectEventstore) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ProjectChanges, error) {
query := ChangesQuery(id, lastSequence, limit, sortAscending)
events, err := es.Eventstore.FilterEvents(context.Background(), query)
if err != nil {
logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-328b1", "Errors.Internal")
}
if len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-FpQqK", "Errors.Changes.NotFound")
}
changes := make([]*proj_model.ProjectChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-qxIR7").OnError(err).Debug("unable to parse timestamp")
change := &proj_model.ProjectChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierId: event.EditorUser,
Sequence: event.Sequence,
}
if event.Data != nil {
var data interface{}
if strings.Contains(change.EventType, "application") {
data = new(model.Application)
} else {
data = new(model.Project)
}
err = json.Unmarshal(event.Data, data)
logging.Log("EVENT-NCkpN").OnError(err).Debug("unable to unmarshal data")
change.Data = data
}
changes[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &proj_model.ProjectChanges{
Changes: changes,
LastSequence: lastSequence,
}, nil
}
func ChangesQuery(projectID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
query := es_models.NewSearchQuery().
AggregateTypeFilter(model.ProjectAggregate)
if !sortAscending {
query.OrderDesc()
}
query.LatestSequenceFilter(latestSequence).
AggregateIDFilter(projectID).
SetLimit(limit)
return query
}
func (es *ProjectEventstore) ApplicationByIDs(ctx context.Context, projectID, appID string) (*proj_model.Application, error) {
if projectID == "" || appID == "" {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-ld93d", "Errors.Project.IDMissing")
}
project, err := es.ProjectByID(ctx, projectID)
if err != nil {
return nil, err
}
if _, a := project.GetApp(appID); a != nil {
return a, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-8ei2s", "Errors.Project.App.NotFound")
}
func (es *ProjectEventstore) ApplicationChanges(ctx context.Context, projectID string, appID string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ApplicationChanges, error) {
query := ChangesQuery(projectID, lastSequence, limit, sortAscending)
events, err := es.Eventstore.FilterEvents(ctx, query)
if err != nil {
logging.Log("EVENT-ZRffs").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-sw6Ku", "Errors.Internal")
}
if len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-9IHLP", "Errors.Changes.NotFound")
}
result := make([]*proj_model.ApplicationChange, 0)
for _, event := range events {
if !strings.Contains(event.Type.String(), "application") || event.Data == nil {
continue
}
app := new(model.Application)
err := json.Unmarshal(event.Data, app)
logging.Log("EVENT-GIiKD").OnError(err).Debug("unable to unmarshal data")
if app.AppID != appID {
continue
}
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-MJzeN").OnError(err).Debug("unable to parse timestamp")
result = append(result, &proj_model.ApplicationChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierId: event.EditorUser,
Sequence: event.Sequence,
Data: app,
})
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &proj_model.ApplicationChanges{
Changes: result,
LastSequence: lastSequence,
}, nil
}
//
//import (
// "github.com/caos/zitadel/internal/cache/config"
// sd "github.com/caos/zitadel/internal/config/systemdefaults"
// "github.com/caos/zitadel/internal/crypto"
// es_int "github.com/caos/zitadel/internal/eventstore"
// "github.com/caos/zitadel/internal/id"
//)
//
//const (
// projectOwnerRole = "PROJECT_OWNER"
// projectOwnerGlobalRole = "PROJECT_OWNER_GLOBAL"
//)
//
//type ProjectEventstore struct {
// es_int.Eventstore
// projectCache *ProjectCache
// passwordAlg crypto.HashAlgorithm
// pwGenerator crypto.Generator
// idGenerator id.Generator
// ClientKeySize int
//}
//
//type ProjectConfig struct {
// es_int.Eventstore
// Cache *config.CacheConfig
//}
//
//func StartProject(conf ProjectConfig, systemDefaults sd.SystemDefaults) (*ProjectEventstore, error) {
// projectCache, err := StartCache(conf.Cache)
// if err != nil {
// return nil, err
// }
// passwordAlg := crypto.NewBCrypt(systemDefaults.SecretGenerators.PasswordSaltCost)
// pwGenerator := crypto.NewHashGenerator(systemDefaults.SecretGenerators.ClientSecretGenerator, passwordAlg)
// return &ProjectEventstore{
// Eventstore: conf.Eventstore,
// projectCache: projectCache,
// passwordAlg: passwordAlg,
// pwGenerator: pwGenerator,
// idGenerator: id.SonyFlakeGenerator,
// ClientKeySize: int(systemDefaults.SecretGenerators.ApplicationKeySize),
// }, nil
//}

View File

@ -10,20 +10,6 @@ import (
"github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
)
func ProjectByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, error) {
if id == "" {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dke74", "Errors.Project.ProjectIDMissing")
}
return ProjectQuery(latestSequence).
AggregateIDFilter(id), nil
}
func ProjectQuery(latestSequence uint64) *es_models.SearchQuery {
return es_models.NewSearchQuery().
AggregateTypeFilter(model.ProjectAggregate).
LatestSequenceFilter(latestSequence)
}
func ProjectAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, project *model.Project) (*es_models.Aggregate, error) {
if project == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-doe93", "Errors.Internal")

View File

@ -0,0 +1,34 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
)
func ProjectByIDQuery(id string, latestSequence uint64) (*es_models.SearchQuery, error) {
if id == "" {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dke74", "Errors.Project.ProjectIDMissing")
}
return ProjectQuery(latestSequence).
AggregateIDFilter(id), nil
}
func ProjectQuery(latestSequence uint64) *es_models.SearchQuery {
return es_models.NewSearchQuery().
AggregateTypeFilter(model.ProjectAggregate).
LatestSequenceFilter(latestSequence)
}
func ChangesQuery(projectID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
query := es_models.NewSearchQuery().
AggregateTypeFilter(model.ProjectAggregate)
if !sortAscending {
query.OrderDesc()
}
query.LatestSequenceFilter(latestSequence).
AggregateIDFilter(projectID).
SetLimit(limit)
return query
}

View File

@ -1,19 +1,5 @@
package model
import (
"github.com/caos/zitadel/internal/crypto"
es_models "github.com/caos/zitadel/internal/eventstore/models"
)
type OTP struct {
es_models.ObjectRoot
Secret *crypto.CryptoValue
SecretString string
Url string
State MFAState
}
type MFAState int32
const (

View File

@ -1,103 +0,0 @@
package model
import (
iam_model "github.com/caos/zitadel/internal/iam/model"
"strings"
caos_errors "github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/golang/protobuf/ptypes/timestamp"
)
type User struct {
es_models.ObjectRoot
State UserState
UserName string
*Human
*Machine
}
type UserState int32
const (
UserStateUnspecified UserState = iota
UserStateActive
UserStateInactive
UserStateDeleted
UserStateLocked
UserStateSuspend
UserStateInitial
)
func (u *User) CheckOrgIAMPolicy(policy *iam_model.OrgIAMPolicyView) error {
if policy == nil {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
}
if policy.UserLoginMustBeDomain && strings.Contains(u.UserName, "@") {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-se4sJ", "Errors.User.EmailAsUsernameNotAllowed")
}
if !policy.UserLoginMustBeDomain && u.Profile != nil && u.UserName == "" && u.Email != nil {
u.UserName = u.EmailAddress
}
return nil
}
func (u *User) SetNamesAsDisplayname() {
if u.Profile != nil && u.DisplayName == "" && u.FirstName != "" && u.LastName != "" {
u.DisplayName = u.FirstName + " " + u.LastName
}
}
type UserChanges struct {
Changes []*UserChange
LastSequence uint64
}
type UserChange struct {
ChangeDate *timestamp.Timestamp `json:"changeDate,omitempty"`
EventType string `json:"eventType,omitempty"`
Sequence uint64 `json:"sequence,omitempty"`
ModifierID string `json:"modifierUser,omitempty"`
ModifierName string `json:"-"`
Data interface{} `json:"data,omitempty"`
}
func (u *User) IsActive() bool {
return u.State == UserStateActive
}
func (u *User) IsInitial() bool {
return u.State == UserStateInitial
}
func (u *User) IsInactive() bool {
return u.State == UserStateInactive
}
func (u *User) IsLocked() bool {
return u.State == UserStateLocked
}
func (u *User) IsValid() bool {
if u.Human == nil && u.Machine == nil || u.UserName == "" {
return false
}
if u.Human != nil {
return u.Human.IsValid()
}
return u.Machine.IsValid()
}
func (u *User) CheckOrgIamPolicy(policy *iam_model.OrgIAMPolicy) error {
if policy == nil {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
}
if policy.UserLoginMustBeDomain && strings.Contains(u.UserName, "@") {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-se4sJ", "Errors.User.EmailAsUsernameNotAllowed")
}
if !policy.UserLoginMustBeDomain && u.Profile != nil && u.UserName == "" && u.Email != nil {
u.UserName = u.EmailAddress
}
return nil
}

View File

@ -0,0 +1,19 @@
package model
import (
"github.com/golang/protobuf/ptypes/timestamp"
)
type UserChanges struct {
Changes []*UserChange
LastSequence uint64
}
type UserChange struct {
ChangeDate *timestamp.Timestamp `json:"changeDate,omitempty"`
EventType string `json:"eventType,omitempty"`
Sequence uint64 `json:"sequence,omitempty"`
ModifierID string `json:"modifierUser,omitempty"`
ModifierName string `json:"-"`
Data interface{} `json:"data,omitempty"`
}

View File

@ -1,203 +0,0 @@
package model
import (
"bytes"
caos_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/v2/domain"
"strings"
"time"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/crypto"
es_models "github.com/caos/zitadel/internal/eventstore/models"
)
type Human struct {
es_models.ObjectRoot
*Password
*Profile
*Email
*Phone
*Address
ExternalIDPs []*ExternalIDP
InitCode *InitUserCode
EmailCode *EmailCode
PhoneCode *PhoneCode
PasswordCode *PasswordCode
OTP *OTP
U2FTokens []*WebAuthNToken
PasswordlessTokens []*WebAuthNToken
U2FLogins []*WebAuthNLogin
PasswordlessLogins []*WebAuthNLogin
}
type InitUserCode struct {
es_models.ObjectRoot
Code *crypto.CryptoValue
Expiry time.Duration
}
type Gender int32
const (
GenderUnspecified Gender = iota
GenderFemale
GenderMale
GenderDiverse
)
func (u *Human) CheckOrgIAMPolicy(userName string, policy *domain.OrgIAMPolicy) error {
if policy == nil {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
}
if policy.UserLoginMustBeDomain && strings.Contains(userName, "@") {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-se4sJ", "Errors.User.EmailAsUsernameNotAllowed")
}
if !policy.UserLoginMustBeDomain && u.Profile != nil && userName == "" && u.Email != nil {
userName = u.EmailAddress
}
return nil
}
func (u *Human) SetNamesAsDisplayname() {
if u.Profile != nil && u.DisplayName == "" && u.FirstName != "" && u.LastName != "" {
u.DisplayName = u.FirstName + " " + u.LastName
}
}
func (u *Human) IsValid() bool {
return u.Profile != nil && u.FirstName != "" && u.LastName != "" && u.Email != nil && u.Email.IsValid() && u.Phone == nil || (u.Phone != nil && u.Phone.PhoneNumber != "" && u.Phone.IsValid())
}
func (u *Human) IsInitialState() bool {
return u.Email == nil || !u.IsEmailVerified || (u.ExternalIDPs == nil || len(u.ExternalIDPs) == 0) && (u.Password == nil || u.SecretString == "")
}
func (u *Human) IsOTPReady() bool {
return u.OTP != nil && u.OTP.State == MFAStateReady
}
func (u *Human) HashPasswordIfExisting(policy *iam_model.PasswordComplexityPolicyView, passwordAlg crypto.HashAlgorithm, onetime bool) error {
if u.Password != nil {
return u.Password.HashPasswordIfExisting(policy, passwordAlg, onetime)
}
return nil
}
func (u *Human) GenerateInitCodeIfNeeded(initGenerator crypto.Generator) error {
if !u.IsInitialState() {
return nil
}
u.InitCode = new(InitUserCode)
return u.InitCode.GenerateInitUserCode(initGenerator)
}
func (u *Human) GeneratePhoneCodeIfNeeded(phoneGenerator crypto.Generator) error {
if u.Phone == nil || u.IsPhoneVerified {
return nil
}
u.PhoneCode = new(PhoneCode)
return u.PhoneCode.GeneratePhoneCode(phoneGenerator)
}
func (u *Human) GenerateEmailCodeIfNeeded(emailGenerator crypto.Generator) error {
if u.Email == nil || u.IsEmailVerified {
return nil
}
u.EmailCode = new(EmailCode)
return u.EmailCode.GenerateEmailCode(emailGenerator)
}
func (init *InitUserCode) GenerateInitUserCode(generator crypto.Generator) error {
initCodeCrypto, _, err := crypto.NewCode(generator)
if err != nil {
return err
}
init.Code = initCodeCrypto
init.Expiry = generator.Expiry()
return nil
}
func (u *Human) GetExternalIDP(externalIDP *ExternalIDP) (int, *ExternalIDP) {
for i, idp := range u.ExternalIDPs {
if idp.UserID == externalIDP.UserID {
return i, idp
}
}
return -1, nil
}
func (u *Human) GetU2F(webAuthNTokenID string) (int, *WebAuthNToken) {
for i, u2f := range u.U2FTokens {
if u2f.WebAuthNTokenID == webAuthNTokenID {
return i, u2f
}
}
return -1, nil
}
func (u *Human) GetU2FByKeyID(keyID []byte) (int, *WebAuthNToken) {
for i, u2f := range u.U2FTokens {
if bytes.Compare(u2f.KeyID, keyID) == 0 {
return i, u2f
}
}
return -1, nil
}
func (u *Human) GetU2FToVerify() (int, *WebAuthNToken) {
for i, u2f := range u.U2FTokens {
if u2f.State == MFAStateNotReady {
return i, u2f
}
}
return -1, nil
}
func (u *Human) GetPasswordless(webAuthNTokenID string) (int, *WebAuthNToken) {
for i, u2f := range u.PasswordlessTokens {
if u2f.WebAuthNTokenID == webAuthNTokenID {
return i, u2f
}
}
return -1, nil
}
func (u *Human) GetPasswordlessByKeyID(keyID []byte) (int, *WebAuthNToken) {
for i, pwl := range u.PasswordlessTokens {
if bytes.Compare(pwl.KeyID, keyID) == 0 {
return i, pwl
}
}
return -1, nil
}
func (u *Human) GetPasswordlessToVerify() (int, *WebAuthNToken) {
for i, u2f := range u.PasswordlessTokens {
if u2f.State == MFAStateNotReady {
return i, u2f
}
}
return -1, nil
}
func (u *Human) GetU2FLogin(authReqID string) (int, *WebAuthNLogin) {
for i, u2f := range u.U2FLogins {
if u2f.AuthRequest.ID == authReqID {
return i, u2f
}
}
return -1, nil
}
func (u *Human) GetPasswordlessLogin(authReqID string) (int, *WebAuthNLogin) {
for i, pw := range u.PasswordlessLogins {
if pw.AuthRequest.ID == authReqID {
return i, pw
}
}
return -1, nil
}

View File

@ -1,105 +0,0 @@
package model
import (
"testing"
)
func TestIsUserValid(t *testing.T) {
type args struct {
user *Human
}
tests := []struct {
name string
args args
result bool
errFunc func(err error) bool
}{
{
name: "user with minimal data",
args: args{
user: &Human{
Profile: &Profile{
FirstName: "FirstName",
LastName: "LastName",
},
Email: &Email{
EmailAddress: "Email",
},
},
},
result: true,
},
{
name: "user with phone data",
args: args{
user: &Human{
Profile: &Profile{
FirstName: "FirstName",
LastName: "LastName",
},
Email: &Email{
EmailAddress: "Email",
},
Phone: &Phone{
PhoneNumber: "+41711234569",
},
},
},
result: true,
},
{
name: "user with address data",
args: args{
user: &Human{
Profile: &Profile{
FirstName: "FirstName",
LastName: "LastName",
},
Email: &Email{
EmailAddress: "Email",
},
Address: &Address{
StreetAddress: "Teufenerstrasse 19",
PostalCode: "9000",
Locality: "St. Gallen",
Country: "Switzerland",
},
},
},
result: true,
},
{
name: "user with all data",
args: args{
user: &Human{
Profile: &Profile{
FirstName: "FirstName",
LastName: "LastName",
},
Email: &Email{
EmailAddress: "Email",
},
Phone: &Phone{
PhoneNumber: "+41711234569",
},
Address: &Address{
StreetAddress: "Teufenerstrasse 19",
PostalCode: "9000",
Locality: "St. Gallen",
Country: "Switzerland",
},
},
},
result: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isValid := tt.args.user.IsValid()
if tt.result != isValid {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result, isValid)
}
})
}
}

View File

@ -1,28 +0,0 @@
package model
import (
"time"
"github.com/caos/zitadel/internal/eventstore/models"
key_model "github.com/caos/zitadel/internal/key/model"
)
type Machine struct {
models.ObjectRoot
Name string
Description string
}
func (sa *Machine) IsValid() bool {
return sa.Name != ""
}
type MachineKey struct {
models.ObjectRoot
KeyID string
Type key_model.AuthNKeyType
ExpirationDate time.Time
PrivateKey []byte
}

View File

@ -108,6 +108,27 @@ type UserSearchResponse struct {
Timestamp time.Time
}
type UserState int32
const (
UserStateUnspecified UserState = iota
UserStateActive
UserStateInactive
UserStateDeleted
UserStateLocked
UserStateSuspend
UserStateInitial
)
type Gender int32
const (
GenderUnspecified Gender = iota
GenderFemale
GenderMale
GenderDiverse
)
func (r *UserSearchRequest) EnsureLimit(limit uint64) {
if r.Limit == 0 || r.Limit > limit {
r.Limit = limit

View File

@ -1,58 +0,0 @@
package model
import (
"github.com/caos/zitadel/internal/auth_request/model"
es_models "github.com/caos/zitadel/internal/eventstore/models"
)
type WebAuthNToken struct {
es_models.ObjectRoot
WebAuthNTokenID string
CredentialCreationData []byte
State MFAState
Challenge string
AllowedCredentialIDs [][]byte
UserVerification UserVerificationRequirement
KeyID []byte
PublicKey []byte
AttestationType string
AAGUID []byte
SignCount uint32
WebAuthNTokenName string
}
type WebAuthNLogin struct {
es_models.ObjectRoot
CredentialAssertionData []byte
Challenge string
AllowedCredentialIDs [][]byte
UserVerification UserVerificationRequirement
*model.AuthRequest
}
type WebAuthNMethod int32
const (
WebAuthNMethodUnspecified WebAuthNMethod = iota
WebAuthNMethodU2F
WebAuthNMethodPasswordless
)
type UserVerificationRequirement int32
const (
UserVerificationRequirementUnspecified UserVerificationRequirement = iota
UserVerificationRequirementRequired
UserVerificationRequirementPreferred
UserVerificationRequirementDiscouraged
)
type AuthenticatorAttachment int32
const (
AuthenticatorAttachmentUnspecified AuthenticatorAttachment = iota
AuthenticatorAttachmentPlattform
AuthenticatorAttachmentCrossPlattform
)

View File

@ -1,35 +0,0 @@
package eventsourcing
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/cache"
"github.com/caos/zitadel/internal/cache/config"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
type UserCache struct {
userCache cache.Cache
}
func StartCache(conf *config.CacheConfig) (*UserCache, error) {
userCache, err := conf.Config.NewCache()
logging.Log("EVENT-vJG2j").OnError(err).Panic("unable to create user cache")
return &UserCache{userCache: userCache}, nil
}
func (c *UserCache) getUser(id string) *model.User {
user := &model.User{ObjectRoot: models.ObjectRoot{AggregateID: id}}
if err := c.userCache.Get(id, user); err != nil {
logging.Log("EVENT-AtS0S").WithError(err).Debug("error in getting cache")
}
return user
}
func (c *UserCache) cacheUser(user *model.User) {
err := c.userCache.Set(user.AggregateID, user)
if err != nil {
logging.Log("EVENT-0V2gX").WithError(err).Debug("error in setting project cache")
}
}

View File

@ -1,143 +0,0 @@
package eventsourcing
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/cache/config"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
"github.com/golang/protobuf/ptypes"
)
type UserEventstore struct {
es_int.Eventstore
userCache *UserCache
}
type UserConfig struct {
es_int.Eventstore
Cache *config.CacheConfig
PasswordSaltCost int
}
func StartUser(conf UserConfig, systemDefaults sd.SystemDefaults) (*UserEventstore, error) {
userCache, err := StartCache(conf.Cache)
if err != nil {
return nil, err
}
return &UserEventstore{
Eventstore: conf.Eventstore,
userCache: userCache,
}, nil
}
func (es *UserEventstore) UserByID(ctx context.Context, id string) (*usr_model.User, error) {
user := es.userCache.getUser(id)
query, err := UserByIDQuery(user.AggregateID, user.Sequence)
if err != nil {
return nil, err
}
err = es_sdk.Filter(ctx, es.FilterEvents, user.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && user.Sequence == 0 {
return nil, err
}
if user.State == int32(usr_model.UserStateDeleted) {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-6hsK9", "Errors.User.NotFound")
}
es.userCache.cacheUser(user)
return model.UserToModel(user), nil
}
func (es *UserEventstore) HumanByID(ctx context.Context, userID string) (*usr_model.User, error) {
if userID == "" {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-3M9sf", "Errors.User.UserIDMissing")
}
user, err := es.UserByID(ctx, userID)
if err != nil {
return nil, err
}
if user.Human == nil {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-jLHYG", "Errors.User.NotHuman")
}
return user, nil
}
func (es *UserEventstore) UserEventsByID(ctx context.Context, id string, sequence uint64) ([]*es_models.Event, error) {
query, err := UserByIDQuery(id, sequence)
if err != nil {
return nil, err
}
return es.FilterEvents(ctx, query)
}
func (es *UserEventstore) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*usr_model.UserChanges, error) {
query := ChangesQuery(id, lastSequence, limit, sortAscending)
events, err := es.Eventstore.FilterEvents(ctx, query)
if err != nil {
logging.Log("EVENT-g9HCv").WithError(err).Warn("eventstore unavailable")
return nil, errors.ThrowInternal(err, "EVENT-htuG9", "Errors.Internal")
}
if len(events) == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-6cAxe", "Errors.User.NoChanges")
}
result := make([]*usr_model.UserChange, len(events))
for i, event := range events {
creationDate, err := ptypes.TimestampProto(event.CreationDate)
logging.Log("EVENT-8GTGS").OnError(err).Debug("unable to parse timestamp")
change := &usr_model.UserChange{
ChangeDate: creationDate,
EventType: event.Type.String(),
ModifierID: event.EditorUser,
Sequence: event.Sequence,
}
//TODO: now all types should be unmarshalled, e.g. password
// if len(event.Data) != 0 {
// user := new(model.User)
// err := json.Unmarshal(event.Data, user)
// logging.Log("EVENT-Rkg7X").OnError(err).Debug("unable to unmarshal data")
// change.Data = user
// }
result[i] = change
if lastSequence < event.Sequence {
lastSequence = event.Sequence
}
}
return &usr_model.UserChanges{
Changes: result,
LastSequence: lastSequence,
}, nil
}
func ChangesQuery(userID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
query := es_models.NewSearchQuery().
AggregateTypeFilter(model.UserAggregate)
if !sortAscending {
query.OrderDesc()
}
query.LatestSequenceFilter(latestSequence).
AggregateIDFilter(userID).
SetLimit(limit)
return query
}
func (es *UserEventstore) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNToken, error) {
user, err := es.HumanByID(ctx, userID)
if err != nil {
return nil, err
}
return user.PasswordlessTokens, nil
}

View File

@ -21,22 +21,6 @@ type OTPVerified struct {
UserAgentID string `json:"userAgentID,omitempty"`
}
func OTPFromModel(otp *model.OTP) *OTP {
return &OTP{
ObjectRoot: otp.ObjectRoot,
Secret: otp.Secret,
State: int32(otp.State),
}
}
func OTPToModel(otp *OTP) *model.OTP {
return &model.OTP{
ObjectRoot: otp.ObjectRoot,
Secret: otp.Secret,
State: model.MFAState(otp.State),
}
}
func (u *Human) appendOTPAddedEvent(event *es_models.Event) error {
u.OTP = &OTP{
State: int32(model.MFAStateNotReady),

View File

@ -24,42 +24,6 @@ type User struct {
*Machine
}
func UserFromModel(user *model.User) *User {
var human *Human
if user.Human != nil {
human = HumanFromModel(user.Human)
}
var machine *Machine
if user.Machine != nil {
machine = MachineFromModel(user.Machine)
}
return &User{
ObjectRoot: user.ObjectRoot,
State: int32(user.State),
UserName: user.UserName,
Human: human,
Machine: machine,
}
}
func UserToModel(user *User) *model.User {
var human *model.Human
if user.Human != nil {
human = HumanToModel(user.Human)
}
var machine *model.Machine
if user.Machine != nil {
machine = MachineToModel(user.Machine)
}
return &model.User{
ObjectRoot: user.ObjectRoot,
State: model.UserState(user.State),
UserName: user.UserName,
Human: human,
Machine: machine,
}
}
func (u *User) AppendEvents(events ...*es_models.Event) error {
for _, event := range events {
if err := u.AppendEvent(event); err != nil {

View File

@ -37,113 +37,6 @@ type InitUserCode struct {
Expiry time.Duration `json:"expiry,omitempty"`
}
func HumanFromModel(user *model.Human) *Human {
human := new(Human)
if user.Password != nil {
human.Password = PasswordFromModel(user.Password)
}
if user.Profile != nil {
human.Profile = ProfileFromModel(user.Profile)
}
if user.Email != nil {
human.Email = EmailFromModel(user.Email)
}
if user.Phone != nil {
human.Phone = PhoneFromModel(user.Phone)
}
if user.Address != nil {
human.Address = AddressFromModel(user.Address)
}
if user.OTP != nil {
human.OTP = OTPFromModel(user.OTP)
}
if user.ExternalIDPs != nil {
human.ExternalIDPs = ExternalIDPsFromModel(user.ExternalIDPs)
}
if user.U2FTokens != nil {
human.U2FTokens = WebAuthNsFromModel(user.U2FTokens)
}
if user.PasswordlessTokens != nil {
human.PasswordlessTokens = WebAuthNsFromModel(user.PasswordlessTokens)
}
if user.U2FLogins != nil {
human.U2FLogins = WebAuthNLoginsFromModel(user.U2FLogins)
}
if user.PasswordlessLogins != nil {
human.PasswordlessLogins = WebAuthNLoginsFromModel(user.PasswordlessLogins)
}
return human
}
func HumanToModel(user *Human) *model.Human {
human := new(model.Human)
if user.Password != nil {
human.Password = PasswordToModel(user.Password)
}
if user.Profile != nil {
human.Profile = ProfileToModel(user.Profile)
}
if user.Email != nil {
human.Email = EmailToModel(user.Email)
}
if user.Phone != nil {
human.Phone = PhoneToModel(user.Phone)
}
if user.Address != nil {
human.Address = AddressToModel(user.Address)
}
if user.ExternalIDPs != nil {
human.ExternalIDPs = ExternalIDPsToModel(user.ExternalIDPs)
}
if user.InitCode != nil {
human.InitCode = InitCodeToModel(user.InitCode)
}
if user.EmailCode != nil {
human.EmailCode = EmailCodeToModel(user.EmailCode)
}
if user.PhoneCode != nil {
human.PhoneCode = PhoneCodeToModel(user.PhoneCode)
}
if user.PasswordCode != nil {
human.PasswordCode = PasswordCodeToModel(user.PasswordCode)
}
if user.OTP != nil {
human.OTP = OTPToModel(user.OTP)
}
if user.U2FTokens != nil {
human.U2FTokens = WebAuthNsToModel(user.U2FTokens)
}
if user.PasswordlessTokens != nil {
human.PasswordlessTokens = WebAuthNsToModel(user.PasswordlessTokens)
}
if user.U2FLogins != nil {
human.U2FLogins = WebAuthNLoginsToModel(user.U2FLogins)
}
if user.PasswordlessLogins != nil {
human.PasswordlessLogins = WebAuthNLoginsToModel(user.PasswordlessLogins)
}
return human
}
func InitCodeFromModel(code *model.InitUserCode) *InitUserCode {
if code == nil {
return nil
}
return &InitUserCode{
ObjectRoot: code.ObjectRoot,
Expiry: code.Expiry,
Code: code.Code,
}
}
func InitCodeToModel(code *InitUserCode) *model.InitUserCode {
return &model.InitUserCode{
ObjectRoot: code.ObjectRoot,
Expiry: code.Expiry,
Code: code.Code,
}
}
func (p *Human) AppendEvents(events ...*es_models.Event) error {
for _, event := range events {
if err := p.AppendEvent(event); err != nil {

Some files were not shown because too many files have changed in this diff Show More