Merge branch 'master' into new-eventstore

This commit is contained in:
adlerhurst
2020-10-27 16:07:24 +01:00
809 changed files with 48599 additions and 24100 deletions

View File

@@ -2,6 +2,8 @@ package eventstore
import (
"context"
"strings"
"github.com/caos/logging"
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/systemdefaults"
@@ -11,7 +13,6 @@ import (
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"strings"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
@@ -163,7 +164,7 @@ func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
result := &iam_model.IDPConfigSearchResponse{
Offset: request.Offset,
Limit: request.Limit,
TotalResult: uint64(count),
TotalResult: count,
Result: iam_es_model.IdpConfigViewsToModel(idps),
}
if err == nil {
@@ -173,6 +174,24 @@ func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
return result, nil
}
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyViewToModel(policy), err
}
func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.AddLabelPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy)
}
func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
policy, err := repo.View.LoginPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
@@ -242,3 +261,75 @@ func (repo *IAMRepository) RemoveIDPProviderFromLoginPolicy(ctx context.Context,
}
return es_sdk.PushAggregates(ctx, repo.Eventstore.PushAggregates, nil, aggregates...)
}
func (repo *IAMRepository) GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) {
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
return iam_es_model.PasswordComplexityViewToModel(policy), nil
}
func (repo *IAMRepository) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.AddPasswordComplexityPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.ChangePasswordComplexityPolicy(ctx, policy)
}
func (repo *IAMRepository) GetDefaultPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) {
policy, err := repo.View.PasswordAgePolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
return iam_es_model.PasswordAgeViewToModel(policy), nil
}
func (repo *IAMRepository) AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.AddPasswordAgePolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.ChangePasswordAgePolicy(ctx, policy)
}
func (repo *IAMRepository) GetDefaultPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) {
policy, err := repo.View.PasswordLockoutPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
return iam_es_model.PasswordLockoutViewToModel(policy), nil
}
func (repo *IAMRepository) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.AddPasswordLockoutPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.ChangePasswordLockoutPolicy(ctx, policy)
}
func (repo *IAMRepository) GetOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
policy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
return iam_es_model.OrgIAMViewToModel(policy), nil
}
func (repo *IAMRepository) AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.AddOrgIAMPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
return repo.IAMEventstore.ChangeOrgIAMPolicy(ctx, policy)
}

View File

@@ -2,6 +2,9 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/logging"
admin_model "github.com/caos/zitadel/internal/admin/model"
@@ -10,11 +13,10 @@ import (
"github.com/caos/zitadel/internal/eventstore"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/sdk"
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"
policy_model "github.com/caos/zitadel/internal/policy/model"
policy_es "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
@@ -23,10 +25,9 @@ const (
)
type OrgRepo struct {
Eventstore eventstore.Eventstore
OrgEventstore *org_es.OrgEventstore
UserEventstore *usr_es.UserEventstore
PolicyEventstore *policy_es.PolicyEventstore
Eventstore eventstore.Eventstore
OrgEventstore *org_es.OrgEventstore
UserEventstore *usr_es.UserEventstore
View *admin_view.View
@@ -35,11 +36,12 @@ type OrgRepo struct {
}
func (repo *OrgRepo) SetUpOrg(ctx context.Context, setUp *admin_model.SetupOrg) (*admin_model.SetupOrg, error) {
pwPolicy, err := repo.PolicyEventstore.GetPasswordComplexityPolicy(ctx, policy_model.DefaultPolicy)
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
orgPolicy, err := repo.OrgEventstore.GetOrgIAMPolicy(ctx, policy_model.DefaultPolicy)
pwPolicyView := iam_view.PasswordComplexityViewToModel(pwPolicy)
orgPolicy, err := repo.GetDefaultOrgIAMPolicy(ctx)
if err != nil {
return nil, err
}
@@ -54,7 +56,7 @@ func (repo *OrgRepo) SetUpOrg(ctx context.Context, setUp *admin_model.SetupOrg)
if err != nil {
return nil, err
}
user, userAggregates, err := repo.UserEventstore.PrepareCreateUser(ctx, setUp.User, pwPolicy, orgPolicy, org.AggregateID)
user, userAggregates, err := repo.UserEventstore.PrepareCreateUser(ctx, setUp.User, pwPolicyView, orgPolicy, org.AggregateID)
if err != nil {
return nil, err
}
@@ -92,7 +94,7 @@ func (repo *OrgRepo) SearchOrgs(ctx context.Context, query *org_model.OrgSearchR
result := &org_model.OrgSearchResult{
Offset: query.Offset,
Limit: query.Limit,
TotalResult: uint64(count),
TotalResult: count,
Result: model.OrgsToModel(orgs),
}
if err == nil {
@@ -106,18 +108,34 @@ func (repo *OrgRepo) IsOrgUnique(ctx context.Context, name, domain string) (isUn
return repo.OrgEventstore.IsOrgUnique(ctx, name, domain)
}
func (repo *OrgRepo) GetOrgIamPolicyByID(ctx context.Context, id string) (*org_model.OrgIAMPolicy, error) {
return repo.OrgEventstore.GetOrgIAMPolicy(ctx, id)
func (repo *OrgRepo) GetOrgIAMPolicyByID(ctx context.Context, id string) (*iam_model.OrgIAMPolicyView, error) {
policy, err := repo.View.OrgIAMPolicyByAggregateID(id)
if errors.IsNotFound(err) {
return repo.GetDefaultOrgIAMPolicy(ctx)
}
if err != nil {
return nil, err
}
return iam_es_model.OrgIAMViewToModel(policy), err
}
func (repo *OrgRepo) CreateOrgIamPolicy(ctx context.Context, policy *org_model.OrgIAMPolicy) (*org_model.OrgIAMPolicy, error) {
func (repo *OrgRepo) GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
policy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
policy.Default = true
return iam_es_model.OrgIAMViewToModel(policy), err
}
func (repo *OrgRepo) CreateOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
return repo.OrgEventstore.AddOrgIAMPolicy(ctx, policy)
}
func (repo *OrgRepo) ChangeOrgIamPolicy(ctx context.Context, policy *org_model.OrgIAMPolicy) (*org_model.OrgIAMPolicy, error) {
func (repo *OrgRepo) ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
return repo.OrgEventstore.ChangeOrgIAMPolicy(ctx, policy)
}
func (repo *OrgRepo) RemoveOrgIamPolicy(ctx context.Context, id string) error {
func (repo *OrgRepo) RemoveOrgIAMPolicy(ctx context.Context, id string) error {
return repo.OrgEventstore.RemoveOrgIAMPolicy(ctx, id)
}

View File

@@ -2,18 +2,22 @@ package eventstore
import (
"context"
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_view "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/api/authz"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
type UserRepo struct {
UserEvents *usr_event.UserEventstore
PolicyEvents *policy_event.PolicyEventstore
OrgEvents *org_event.OrgEventstore
UserEvents *usr_event.UserEventstore
OrgEvents *org_event.OrgEventstore
View *admin_view.View
SystemDefaults systemdefaults.SystemDefaults
}
func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_model.User, err error) {
@@ -21,15 +25,23 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_mod
}
func (repo *UserRepo) CreateUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
pwPolicy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, authz.GetCtxData(ctx).OrgID)
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if caos_errs.IsNotFound(err) {
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return nil, err
}
orgPolicy, err := repo.OrgEvents.GetOrgIAMPolicy(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
pwPolicyView := iam_view.PasswordComplexityViewToModel(pwPolicy)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if err != nil && caos_errs.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
}
return repo.UserEvents.CreateUser(ctx, user, pwPolicy, orgPolicy)
orgPolicyView := iam_view.OrgIAMViewToModel(orgPolicy)
return repo.UserEvents.CreateUser(ctx, user, pwPolicyView, orgPolicyView)
}
func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
@@ -37,13 +49,22 @@ func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, re
if resourceOwner != "" {
policyResourceOwner = resourceOwner
}
pwPolicy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, policyResourceOwner)
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(policyResourceOwner)
if caos_errs.IsNotFound(err) {
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return nil, err
}
orgPolicy, err := repo.OrgEvents.GetOrgIAMPolicy(ctx, policyResourceOwner)
pwPolicyView := iam_view.PasswordComplexityViewToModel(pwPolicy)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(policyResourceOwner)
if caos_errs.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return nil, err
}
return repo.UserEvents.RegisterUser(ctx, user, pwPolicy, orgPolicy, resourceOwner)
orgPolicyView := iam_view.OrgIAMViewToModel(orgPolicy)
return repo.UserEvents.RegisterUser(ctx, user, pwPolicyView, orgPolicyView, resourceOwner)
}

View File

@@ -1,9 +1,10 @@
package handler
import (
"time"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"time"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/types"
@@ -35,11 +36,21 @@ type EventstoreRepos struct {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler {
return []query.Handler{
&Org{handler: handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount}},
&IamMember{handler: handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount}, userEvents: repos.UserEvents},
&IamMember{handler: handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount},
userEvents: repos.UserEvents},
&IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}},
&LabelPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount}},
&LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}},
&IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}, systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents},
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, eventstore: eventstore, orgEvents: repos.OrgEvents},
&IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount},
systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents},
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount},
eventstore: eventstore, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults},
&PasswordComplexityPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount}},
&PasswordAgePolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordAgePolicy"), errorCount}},
&PasswordLockoutPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount}},
&OrgIAMPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount}},
&ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount},
orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults},
}
}

View File

@@ -52,8 +52,11 @@ func (m *IamMember) processIamMember(event *models.Event) (err error) {
member := new(iam_model.IAMMemberView)
switch event.Type {
case model.IAMMemberAdded:
member.AppendEvent(event)
m.fillData(member)
err = member.AppendEvent(event)
if err != nil {
return err
}
err = m.fillData(member)
case model.IAMMemberChanged:
err := member.SetData(event)
if err != nil {
@@ -63,7 +66,7 @@ func (m *IamMember) processIamMember(event *models.Event) (err error) {
if err != nil {
return err
}
member.AppendEvent(event)
err = member.AppendEvent(event)
case model.IAMMemberRemoved:
err := member.SetData(event)
if err != nil {
@@ -101,6 +104,8 @@ func (m *IamMember) processUser(event *models.Event) (err error) {
m.fillUserData(member, user)
}
return m.view.PutIAMMembers(members, event.Sequence)
case usr_es_model.UserRemoved:
return m.view.DeleteIAMMembersByUserID(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedIAMMemberSequence(event.Sequence)
}

View File

@@ -66,13 +66,17 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) {
}
return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence)
case model.IDPConfigChanged, org_es_model.IDPConfigChanged:
config := new(iam_model.IDPConfig)
config.AppendEvent(event)
providers, err := m.view.IDPProvidersByIdpConfigID(config.IDPConfigID)
esConfig := new(iam_view_model.IDPConfigView)
providerType := iam_model.IDPProviderTypeSystem
if event.AggregateID != m.systemDefaults.IamID {
providerType = iam_model.IDPProviderTypeOrg
}
esConfig.AppendEvent(providerType, event)
providers, err := m.view.IDPProvidersByIdpConfigID(esConfig.IDPConfigID)
if err != nil {
return err
}
config, err = m.iamEvents.GetIDPConfig(context.Background(), provider.AggregateID, config.IDPConfigID)
config, err := m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
if err != nil {
return err
}
@@ -105,6 +109,7 @@ func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err er
func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) {
provider.Name = config.Name
provider.StylingType = int32(config.StylingType)
provider.IDPConfigType = int32(config.Type)
provider.IDPState = int32(config.State)
}

View File

@@ -0,0 +1,66 @@
package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"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"
)
type LabelPolicy struct {
handler
}
const (
labelPolicyTable = "adminapi.label_policies"
)
func (m *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LabelPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate:
err = m.processLabelPolicy(event)
}
return err
}
func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) {
policy := new(iam_model.LabelPolicyView)
switch event.Type {
case model.LabelPolicyAdded:
err = policy.AppendEvent(event)
case model.LabelPolicyChanged:
policy, err = m.view.LabelPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
default:
return m.view.ProcessedLabelPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutLabelPolicy(policy, policy.Sequence)
}
func (m *LabelPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Wj8sf", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler")
return spooler.HandleError(event, err, m.view.GetLatestLabelPolicyFailedEvent, m.view.ProcessedLabelPolicyFailedEvent, m.view.ProcessedLabelPolicySequence, m.errorCountUntilSkip)
}

View File

@@ -35,7 +35,10 @@ func (o *Org) Reduce(event *es_models.Event) error {
switch event.Type {
case model.OrgAdded:
org.AppendEvent(event)
err := org.AppendEvent(event)
if err != nil {
return err
}
case model.OrgChanged:
err := org.SetData(event)
if err != nil {

View File

@@ -0,0 +1,69 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type OrgIAMPolicy struct {
handler
}
const (
orgIAMPolicyTable = "adminapi.org_iam_policies"
)
func (m *OrgIAMPolicy) ViewModel() string {
return orgIAMPolicyTable
}
func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestOrgIAMPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *OrgIAMPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processOrgIAMPolicy(event)
}
return err
}
func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) {
policy := new(iam_model.OrgIAMPolicyView)
switch event.Type {
case iam_es_model.OrgIAMPolicyAdded, model.OrgIAMPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.OrgIAMPolicyChanged, model.OrgIAMPolicyChanged:
policy, err = m.view.OrgIAMPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.OrgIAMPolicyRemoved:
return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedOrgIAMPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutOrgIAMPolicy(policy, policy.Sequence)
}
func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Wm8fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler")
return spooler.HandleError(event, err, m.view.GetLatestOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicySequence, m.errorCountUntilSkip)
}

View File

@@ -0,0 +1,69 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type PasswordAgePolicy struct {
handler
}
const (
passwordAgePolicyTable = "adminapi.password_age_policies"
)
func (m *PasswordAgePolicy) ViewModel() string {
return passwordAgePolicyTable
}
func (m *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordAgePolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordAgePolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordAgePolicy(event)
}
return err
}
func (m *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err error) {
policy := new(iam_model.PasswordAgePolicyView)
switch event.Type {
case iam_es_model.PasswordAgePolicyAdded, model.PasswordAgePolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.PasswordAgePolicyChanged, model.PasswordAgePolicyChanged:
policy, err = m.view.PasswordAgePolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordAgePolicyRemoved:
return m.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedPasswordAgePolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutPasswordAgePolicy(policy, policy.Sequence)
}
func (m *PasswordAgePolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-nD8sie", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordAge policy handler")
return spooler.HandleError(event, err, m.view.GetLatestPasswordAgePolicyFailedEvent, m.view.ProcessedPasswordAgePolicyFailedEvent, m.view.ProcessedPasswordAgePolicySequence, m.errorCountUntilSkip)
}

View File

@@ -0,0 +1,69 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type PasswordComplexityPolicy struct {
handler
}
const (
passwordComplexityPolicyTable = "adminapi.password_complexity_policies"
)
func (m *PasswordComplexityPolicy) ViewModel() string {
return passwordComplexityPolicyTable
}
func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordComplexityPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordComplexityPolicy(event)
}
return err
}
func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) {
policy := new(iam_model.PasswordComplexityPolicyView)
switch event.Type {
case iam_es_model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.PasswordComplexityPolicyChanged, model.PasswordComplexityPolicyChanged:
policy, err = m.view.PasswordComplexityPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordComplexityPolicyRemoved:
return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence)
}
func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Wm8fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordComplexity policy handler")
return spooler.HandleError(event, err, m.view.GetLatestPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicySequence, m.errorCountUntilSkip)
}

View File

@@ -0,0 +1,69 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type PasswordLockoutPolicy struct {
handler
}
const (
passwordLockoutPolicyTable = "adminapi.password_lockout_policies"
)
func (m *PasswordLockoutPolicy) ViewModel() string {
return passwordLockoutPolicyTable
}
func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordLockoutPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordLockoutPolicy(event)
}
return err
}
func (m *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event) (err error) {
policy := new(iam_model.PasswordLockoutPolicyView)
switch event.Type {
case iam_es_model.PasswordLockoutPolicyAdded, model.PasswordLockoutPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.PasswordLockoutPolicyChanged, model.PasswordLockoutPolicyChanged:
policy, err = m.view.PasswordLockoutPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordLockoutPolicyRemoved:
return m.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedPasswordLockoutPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutPasswordLockoutPolicy(policy, policy.Sequence)
}
func (m *PasswordLockoutPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-nD8sie", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordLockout policy handler")
return spooler.HandleError(event, err, m.view.GetLatestPasswordLockoutPolicyFailedEvent, m.view.ProcessedPasswordLockoutPolicyFailedEvent, m.view.ProcessedPasswordLockoutPolicySequence, m.errorCountUntilSkip)
}

View File

@@ -2,6 +2,8 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/logging"
@@ -18,8 +20,10 @@ import (
type User struct {
handler
eventstore eventstore.Eventstore
orgEvents *org_events.OrgEventstore
eventstore eventstore.Eventstore
orgEvents *org_events.OrgEventstore
iamEvents *iam_es.IAMEventstore
systemDefaults systemdefaults.SystemDefaults
}
const (
@@ -106,7 +110,7 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
}
err = u.fillLoginNames(user)
case es_model.UserRemoved:
err = u.view.DeleteUser(event.AggregateID, event.Sequence)
return u.view.DeleteUser(event.AggregateID, event.Sequence)
default:
return u.view.ProcessedUserSequence(event.Sequence)
}
@@ -136,9 +140,12 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
if err != nil {
return err
}
policy, err := u.orgEvents.GetOrgIAMPolicy(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)
if err != nil {
return err
}
}
users, err := u.view.UsersByOrgID(event.AggregateID)
if err != nil {
@@ -155,9 +162,12 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
if err != nil {
return err
}
policy, err := u.orgEvents.GetOrgIAMPolicy(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)
if err != nil {
return err
}
}
if !policy.UserLoginMustBeDomain {
return nil
@@ -177,9 +187,12 @@ func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
if err != nil {
return err
}
policy, err := u.orgEvents.GetOrgIAMPolicy(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)
if err != nil {
return err
}
}
user.SetLoginNames(policy, org.Domains)
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)

View File

@@ -6,6 +6,7 @@ import (
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
"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"
@@ -68,6 +69,8 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) {
return err
}
return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence)
case model.UserRemoved:
return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedExternalIDPSequence(event.Sequence)
}
@@ -80,16 +83,21 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) {
func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
switch event.Type {
case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged:
configView := new(iam_view_model.IDPConfigView)
config := new(iam_model.IDPConfig)
config.AppendEvent(event)
exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(config.IDPConfigID)
if event.Type == iam_es_model.IDPConfigChanged {
configView.AppendEvent(iam_model.IDPProviderTypeSystem, event)
} else {
configView.AppendEvent(iam_model.IDPProviderTypeOrg, event)
}
exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID)
if err != nil {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = m.iamEvents.GetIDPConfig(context.Background(), config.AggregateID, config.IDPConfigID)
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), config.AggregateID, config.IDPConfigID)
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err

View File

@@ -13,7 +13,6 @@ import (
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_policy "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
@@ -30,6 +29,7 @@ type EsRepository struct {
eventstore.OrgRepo
eventstore.IAMRepository
eventstore.AdministratorRepo
eventstore.UserRepo
}
func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRepository, error) {
@@ -55,13 +55,6 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
if err != nil {
return nil, err
}
policy, err := es_policy.StartPolicy(es_policy.PolicyConfig{
Eventstore: es,
Cache: conf.Eventstore.Cache,
}, systemDefaults)
if err != nil {
return nil, err
}
sqlClient, err := conf.View.Start()
if err != nil {
return nil, err
@@ -76,13 +69,12 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
return &EsRepository{
spooler: spool,
OrgRepo: eventstore.OrgRepo{
Eventstore: es,
OrgEventstore: org,
UserEventstore: user,
PolicyEventstore: policy,
View: view,
SearchLimit: conf.SearchLimit,
SystemDefaults: systemDefaults,
Eventstore: es,
OrgEventstore: org,
UserEventstore: user,
View: view,
SearchLimit: conf.SearchLimit,
SystemDefaults: systemDefaults,
},
IAMRepository: eventstore.IAMRepository{
IAMEventstore: iam,
@@ -96,6 +88,12 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
AdministratorRepo: eventstore.AdministratorRepo{
View: view,
},
UserRepo: eventstore.UserRepo{
UserEvents: user,
OrgEvents: org,
View: view,
SystemDefaults: systemDefaults,
},
}, nil
}

View File

@@ -56,6 +56,14 @@ func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequen
return v.ProcessedExternalIDPSequence(eventSequence)
}
func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64) error {
err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID)
if err != nil {
return err
}
return v.ProcessedExternalIDPSequence(eventSequence)
}
func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(externalIDPTable)
}

View File

@@ -48,6 +48,14 @@ func (v *View) DeleteIAMMember(iamID, userID string, eventSequence uint64) error
return v.ProcessedIAMMemberSequence(eventSequence)
}
func (v *View) DeleteIAMMembersByUserID(userID string, eventSequence uint64) error {
err := view.DeleteIAMMembersByUserID(v.Db, iamMemberTable, userID)
if err != nil {
return err
}
return v.ProcessedIAMMemberSequence(eventSequence)
}
func (v *View) GetLatestIAMMemberSequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(iamMemberTable)
}

View File

@@ -0,0 +1,39 @@
package view
import (
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
labelPolicyTable = "adminapi.label_policies"
)
func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID)
}
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(sequence)
}
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(labelPolicyTable)
}
func (v *View) ProcessedLabelPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(labelPolicyTable, eventSequence)
}
func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(labelPolicyTable, sequence)
}
func (v *View) ProcessedLabelPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@@ -0,0 +1,48 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
orgIAMPolicyTable = "adminapi.org_iam_policies"
)
func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolicyView, error) {
return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID)
}
func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64) error {
err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedOrgIAMPolicySequence(sequence)
}
func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64) error {
err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedOrgIAMPolicySequence(eventSequence)
}
func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(orgIAMPolicyTable)
}
func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence)
}
func (v *View) GetLatestOrgIAMPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(orgIAMPolicyTable, sequence)
}
func (v *View) ProcessedOrgIAMPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@@ -0,0 +1,48 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
passwordAgePolicyTable = "adminapi.password_age_policies"
)
func (v *View) PasswordAgePolicyByAggregateID(aggregateID string) (*model.PasswordAgePolicyView, error) {
return view.GetPasswordAgePolicyByAggregateID(v.Db, passwordAgePolicyTable, aggregateID)
}
func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64) error {
err := view.PutPasswordAgePolicy(v.Db, passwordAgePolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedPasswordAgePolicySequence(sequence)
}
func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64) error {
err := view.DeletePasswordAgePolicy(v.Db, passwordAgePolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedPasswordAgePolicySequence(eventSequence)
}
func (v *View) GetLatestPasswordAgePolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(passwordAgePolicyTable)
}
func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence)
}
func (v *View) GetLatestPasswordAgePolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(passwordAgePolicyTable, sequence)
}
func (v *View) ProcessedPasswordAgePolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@@ -0,0 +1,48 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
passwordComplexityPolicyTable = "adminapi.password_complexity_policies"
)
func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model.PasswordComplexityPolicyView, error) {
return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID)
}
func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64) error {
err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedPasswordComplexityPolicySequence(sequence)
}
func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64) error {
err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedPasswordComplexityPolicySequence(eventSequence)
}
func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(passwordComplexityPolicyTable)
}
func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence)
}
func (v *View) GetLatestPasswordComplexityPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(passwordComplexityPolicyTable, sequence)
}
func (v *View) ProcessedPasswordComplexityPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@@ -0,0 +1,48 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
passwordLockoutPolicyTable = "adminapi.password_lockout_policies"
)
func (v *View) PasswordLockoutPolicyByAggregateID(aggregateID string) (*model.PasswordLockoutPolicyView, error) {
return view.GetPasswordLockoutPolicyByAggregateID(v.Db, passwordLockoutPolicyTable, aggregateID)
}
func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64) error {
err := view.PutPasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedPasswordLockoutPolicySequence(sequence)
}
func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64) error {
err := view.DeletePasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedPasswordLockoutPolicySequence(eventSequence)
}
func (v *View) GetLatestPasswordLockoutPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(passwordLockoutPolicyTable)
}
func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence)
}
func (v *View) GetLatestPasswordLockoutPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(passwordLockoutPolicyTable, sequence)
}
func (v *View) ProcessedPasswordLockoutPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@@ -2,6 +2,7 @@ package repository
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
@@ -28,4 +29,23 @@ type IAMRepository interface {
SearchDefaultIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error)
AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error)
RemoveIDPProviderFromLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) error
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error)
ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error)
GetDefaultPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error)
AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error)
ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error)
GetDefaultPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error)
AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error)
ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error)
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error)
ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error)
}

View File

@@ -2,6 +2,7 @@ package repository
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
admin_model "github.com/caos/zitadel/internal/admin/model"
org_model "github.com/caos/zitadel/internal/org/model"
@@ -13,8 +14,9 @@ type OrgRepository interface {
OrgByID(ctx context.Context, id string) (*org_model.Org, error)
SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error)
GetOrgIamPolicyByID(ctx context.Context, id string) (*org_model.OrgIAMPolicy, error)
CreateOrgIamPolicy(ctx context.Context, policy *org_model.OrgIAMPolicy) (*org_model.OrgIAMPolicy, error)
ChangeOrgIamPolicy(ctx context.Context, policy *org_model.OrgIAMPolicy) (*org_model.OrgIAMPolicy, error)
RemoveOrgIamPolicy(ctx context.Context, id string) error
GetOrgIAMPolicyByID(ctx context.Context, id string) (*iam_model.OrgIAMPolicyView, error)
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
CreateOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error)
ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error)
RemoveOrgIAMPolicy(ctx context.Context, id string) error
}

View File

@@ -77,10 +77,10 @@ func (a *API) healthHandler() http.Handler {
if err != nil && !errors.IsNotFound(err) {
return errors.ThrowPreconditionFailed(err, "API-dsgT2", "IAM SETUP CHECK FAILED")
}
if iam == nil || !iam.SetUpStarted {
if iam == nil || iam.SetUpStarted < iam_model.StepCount-1 {
return errors.ThrowPreconditionFailed(nil, "API-HBfs3", "IAM NOT SET UP")
}
if !iam.SetUpDone {
if iam.SetUpDone < iam_model.StepCount-1 {
return errors.ThrowPreconditionFailed(nil, "API-DASs2", "IAM SETUP RUNNING")
}
return nil
@@ -103,20 +103,20 @@ func handleReadiness(checks []ValidationFunction) func(w http.ResponseWriter, r
return func(w http.ResponseWriter, r *http.Request) {
err := validate(r.Context(), checks)
if err == nil {
http_util.MarshalJSON(w, "ok")
http_util.MarshalJSON(w, "ok", nil, http.StatusOK)
return
}
http_util.MarshalJSON(w, err)
http_util.MarshalJSON(w, nil, err, http.StatusPreconditionFailed)
}
}
func (a *API) handleClientID(w http.ResponseWriter, r *http.Request) {
id, err := a.health.VerifierClientID(r.Context(), "Zitadel Console")
if err != nil {
http_util.MarshalJSON(w, err)
http_util.MarshalJSON(w, nil, err, http.StatusPreconditionFailed)
return
}
http_util.MarshalJSON(w, id)
http_util.MarshalJSON(w, id, nil, http.StatusOK)
}
type ValidationFunction func(ctx context.Context) error

View File

@@ -7,14 +7,18 @@ import (
"strings"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
const (
authenticated = "authenticated"
)
func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID string, verifier *TokenVerifier, authConfig Config, requiredAuthOption Option, method string) (context.Context, error) {
ctx, err := VerifyTokenAndWriteCtxData(ctx, token, orgID, verifier, method)
func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID string, verifier *TokenVerifier, authConfig Config, requiredAuthOption Option, method string) (_ context.Context, err error) {
ctx, span := tracing.NewServerInterceptorSpan(ctx)
defer func() { span.EndWithError(err) }()
ctx, err = VerifyTokenAndWriteCtxData(ctx, token, orgID, verifier, method)
if err != nil {
return nil, err
}
@@ -29,7 +33,9 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID s
return nil, err
}
ctx, userPermissionSpan := tracing.NewNamedSpan(ctx, "checkUserPermissions")
err = checkUserPermissions(req, perms, requiredAuthOption)
userPermissionSpan.EndWithError(err)
if err != nil {
return nil, err
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/caos/zitadel/internal/api/grpc"
http_util "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
type key int
@@ -36,6 +37,9 @@ type Grant struct {
}
func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t *TokenVerifier, method string) (_ context.Context, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
if orgID != "" {
err = t.ExistsOrg(ctx, orgID)
if err != nil {

View File

@@ -4,9 +4,13 @@ import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPerm string, authConfig Config) (context.Context, []string, error) {
func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPerm string, authConfig Config) (_ context.Context, _ []string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
ctxData := GetCtxData(ctx)
if ctxData.IsZero() {
return nil, nil, errors.ThrowUnauthenticated(nil, "AUTH-rKLWEH", "context missing")

View File

@@ -6,6 +6,7 @@ import (
"sync"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
)
const (
@@ -62,7 +63,10 @@ func prefixFromMethod(method string) (string, bool) {
return parts[1], true
}
func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (string, error) {
func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (_ string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
prefix, ok := prefixFromMethod(method)
if !ok {
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-GRD2Q", "Errors.Internal")
@@ -71,7 +75,6 @@ func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (
if !ok {
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-G2qrh", "Errors.Internal")
}
var err error
c := app.(*client)
if c.id != "" {
return c.id, nil
@@ -84,15 +87,22 @@ func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (
return c.id, nil
}
func (v *TokenVerifier) ResolveGrant(ctx context.Context) (*Grant, error) {
func (v *TokenVerifier) ResolveGrant(ctx context.Context) (_ *Grant, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ResolveGrants(ctx)
}
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (_ string, _ []string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ProjectIDAndOriginsByClientID(ctx, clientID)
}
func (v *TokenVerifier) ExistsOrg(ctx context.Context, orgID string) error {
func (v *TokenVerifier) ExistsOrg(ctx context.Context, orgID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ExistsOrg(ctx, orgID)
}
@@ -102,6 +112,9 @@ func (v *TokenVerifier) CheckAuthMethod(method string) (Option, bool) {
}
func verifyAccessToken(ctx context.Context, token string, t *TokenVerifier, method string) (userID, clientID, agentID, prefLang string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
parts := strings.Split(token, BearerPrefix)
if len(parts) != 2 {
return "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "AUTH-7fs1e", "invalid auth header")

View File

@@ -9,9 +9,9 @@ import (
func createOidcIdpToModel(idp *admin.OidcIdpConfigCreate) *iam_model.IDPConfig {
return &iam_model.IDPConfig{
Name: idp.Name,
LogoSrc: idp.LogoSrc,
Type: iam_model.IDPConfigTypeOIDC,
Name: idp.Name,
StylingType: idpConfigStylingTypeToModel(idp.StylingType),
Type: iam_model.IDPConfigTypeOIDC,
OIDCConfig: &iam_model.OIDCIDPConfig{
ClientID: idp.ClientId,
ClientSecretString: idp.ClientSecret,
@@ -27,7 +27,7 @@ func updateIdpToModel(idp *admin.IdpUpdate) *iam_model.IDPConfig {
return &iam_model.IDPConfig{
IDPConfigID: idp.Id,
Name: idp.Name,
LogoSrc: idp.LogoSrc,
StylingType: idpConfigStylingTypeToModel(idp.StylingType),
}
}
@@ -56,7 +56,7 @@ func idpFromModel(idp *iam_model.IDPConfig) *admin.Idp {
ChangeDate: changeDate,
Sequence: idp.Sequence,
Name: idp.Name,
LogoSrc: idp.LogoSrc,
StylingType: idpConfigStylingTypeFromModel(idp.StylingType),
State: idpConfigStateFromModel(idp.State),
IdpConfig: idpConfigFromModel(idp),
}
@@ -75,7 +75,7 @@ func idpViewFromModel(idp *iam_model.IDPConfigView) *admin.IdpView {
ChangeDate: changeDate,
Sequence: idp.Sequence,
Name: idp.Name,
LogoSrc: idp.LogoSrc,
StylingType: idpConfigStylingTypeFromModel(idp.StylingType),
State: idpConfigStateFromModel(idp.State),
IdpConfigView: idpConfigViewFromModel(idp),
}
@@ -206,3 +206,21 @@ func idpConfigsFromView(viewIdps []*iam_model.IDPConfigView) []*admin.IdpView {
}
return idps
}
func idpConfigStylingTypeFromModel(stylingType iam_model.IDPStylingType) admin.IdpStylingType {
switch stylingType {
case iam_model.IDPStylingTypeGoogle:
return admin.IdpStylingType_IDPSTYLINGTYPE_GOOGLE
default:
return admin.IdpStylingType_IDPSTYLINGTYPE_UNSPECIFIED
}
}
func idpConfigStylingTypeToModel(stylingType admin.IdpStylingType) iam_model.IDPStylingType {
switch stylingType {
case admin.IdpStylingType_IDPSTYLINGTYPE_GOOGLE:
return iam_model.IDPStylingTypeGoogle
default:
return iam_model.IDPStylingTypeUnspecified
}
}

View File

@@ -0,0 +1,24 @@
package admin
import (
"context"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, _ *empty.Empty) (*admin.DefaultLabelPolicyView, error) {
result, err := s.iam.GetDefaultLabelPolicy(ctx)
if err != nil {
return nil, err
}
return labelPolicyViewFromModel(result), nil
}
func (s *Server) UpdateDefaultLabelPolicy(ctx context.Context, policy *admin.DefaultLabelPolicyUpdate) (*admin.DefaultLabelPolicy, error) {
result, err := s.iam.ChangeDefaultLabelPolicy(ctx, labelPolicyToModel(policy))
if err != nil {
return nil, err
}
return labelPolicyFromModel(result), nil
}

View File

@@ -0,0 +1,45 @@
package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
)
func labelPolicyToModel(policy *admin.DefaultLabelPolicyUpdate) *iam_model.LabelPolicy {
return &iam_model.LabelPolicy{
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
}
}
func labelPolicyFromModel(policy *iam_model.LabelPolicy) *admin.DefaultLabelPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("ADMIN-QwQG9").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("ADMIN-mAgcI").OnError(err).Debug("date parse failed")
return &admin.DefaultLabelPolicy{
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func labelPolicyViewFromModel(policy *iam_model.LabelPolicyView) *admin.DefaultLabelPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("ADMIN-zMnlF").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("ADMIN-Vhvfp").OnError(err).Debug("date parse failed")
return &admin.DefaultLabelPolicyView{
PrimaryColor: policy.PrimaryColor,
SecondaryColor: policy.SecondaryColor,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -14,7 +14,7 @@ func (s *Server) GetDefaultLoginPolicy(ctx context.Context, _ *empty.Empty) (*ad
return loginPolicyViewFromModel(result), nil
}
func (s *Server) UpdateDefaultLoginPolicy(ctx context.Context, policy *admin.DefaultLoginPolicy) (*admin.DefaultLoginPolicy, error) {
func (s *Server) UpdateDefaultLoginPolicy(ctx context.Context, policy *admin.DefaultLoginPolicyRequest) (*admin.DefaultLoginPolicy, error) {
result, err := s.iam.ChangeDefaultLoginPolicy(ctx, loginPolicyToModel(policy))
if err != nil {
return nil, err

View File

@@ -1,11 +1,13 @@
package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
)
func loginPolicyToModel(policy *admin.DefaultLoginPolicy) *iam_model.LoginPolicy {
func loginPolicyToModel(policy *admin.DefaultLoginPolicyRequest) *iam_model.LoginPolicy {
return &iam_model.LoginPolicy{
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
@@ -14,18 +16,34 @@ func loginPolicyToModel(policy *admin.DefaultLoginPolicy) *iam_model.LoginPolicy
}
func loginPolicyFromModel(policy *iam_model.LoginPolicy) *admin.DefaultLoginPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-3Fsm9").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-5Gsko").OnError(err).Debug("date parse failed")
return &admin.DefaultLoginPolicy{
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
AllowRegister: policy.AllowRegister,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func loginPolicyViewFromModel(policy *iam_model.LoginPolicyView) *admin.DefaultLoginPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-3Gk9s").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-6Jlos").OnError(err).Debug("date parse failed")
return &admin.DefaultLoginPolicyView{
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIDP,
AllowRegister: policy.AllowRegister,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -38,31 +38,47 @@ func (s *Server) SetUpOrg(ctx context.Context, orgSetUp *admin.OrgSetUpRequest)
return setUpOrgResponseFromModel(setUp), err
}
func (s *Server) GetOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyID) (_ *admin.OrgIamPolicy, err error) {
policy, err := s.org.GetOrgIamPolicyByID(ctx, in.OrgId)
func (s *Server) GetDefaultOrgIamPolicy(ctx context.Context, _ *empty.Empty) (_ *admin.OrgIamPolicyView, err error) {
policy, err := s.iam.GetDefaultOrgIAMPolicy(ctx)
if err != nil {
return nil, err
}
return orgIamPolicyFromModel(policy), err
return orgIAMPolicyViewFromModel(policy), err
}
func (s *Server) UpdateDefaultOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyRequest) (_ *admin.OrgIamPolicy, err error) {
policy, err := s.iam.ChangeDefaultOrgIAMPolicy(ctx, orgIAMPolicyRequestToModel(in))
if err != nil {
return nil, err
}
return orgIAMPolicyFromModel(policy), err
}
func (s *Server) GetOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyID) (_ *admin.OrgIamPolicyView, err error) {
policy, err := s.org.GetOrgIAMPolicyByID(ctx, in.OrgId)
if err != nil {
return nil, err
}
return orgIAMPolicyViewFromModel(policy), err
}
func (s *Server) CreateOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyRequest) (_ *admin.OrgIamPolicy, err error) {
policy, err := s.org.CreateOrgIamPolicy(ctx, orgIamPolicyRequestToModel(in))
policy, err := s.org.CreateOrgIAMPolicy(ctx, orgIAMPolicyRequestToModel(in))
if err != nil {
return nil, err
}
return orgIamPolicyFromModel(policy), err
return orgIAMPolicyFromModel(policy), err
}
func (s *Server) UpdateOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyRequest) (_ *admin.OrgIamPolicy, err error) {
policy, err := s.org.ChangeOrgIamPolicy(ctx, orgIamPolicyRequestToModel(in))
policy, err := s.org.ChangeOrgIAMPolicy(ctx, orgIAMPolicyRequestToModel(in))
if err != nil {
return nil, err
}
return orgIamPolicyFromModel(policy), err
return orgIAMPolicyFromModel(policy), err
}
func (s *Server) DeleteOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyID) (_ *empty.Empty, err error) {
err = s.org.RemoveOrgIamPolicy(ctx, in.OrgId)
func (s *Server) RemoveOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyID) (_ *empty.Empty, err error) {
err = s.org.RemoveOrgIAMPolicy(ctx, in.OrgId)
return &empty.Empty{}, err
}

View File

@@ -2,6 +2,7 @@ package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/golang/protobuf/ptypes"
admin_model "github.com/caos/zitadel/internal/admin/model"
@@ -196,7 +197,7 @@ func orgQueryMethodToModel(method admin.OrgSearchMethod) model.SearchMethod {
}
}
func orgIamPolicyFromModel(policy *org_model.OrgIAMPolicy) *admin.OrgIamPolicy {
func orgIAMPolicyFromModel(policy *iam_model.OrgIAMPolicy) *admin.OrgIamPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-ush36").OnError(err).Debug("unable to get timestamp from time")
@@ -205,20 +206,32 @@ func orgIamPolicyFromModel(policy *org_model.OrgIAMPolicy) *admin.OrgIamPolicy {
return &admin.OrgIamPolicy{
OrgId: policy.AggregateID,
Description: policy.Description,
UserLoginMustBeDomain: policy.UserLoginMustBeDomain,
Default: policy.Default,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func orgIamPolicyRequestToModel(policy *admin.OrgIamPolicyRequest) *org_model.OrgIAMPolicy {
return &org_model.OrgIAMPolicy{
func orgIAMPolicyViewFromModel(policy *iam_model.OrgIAMPolicyView) *admin.OrgIamPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-ush36").OnError(err).Debug("unable to get timestamp from time")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-Ps9fW").OnError(err).Debug("unable to get timestamp from time")
return &admin.OrgIamPolicyView{
OrgId: policy.AggregateID,
UserLoginMustBeDomain: policy.UserLoginMustBeDomain,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func orgIAMPolicyRequestToModel(policy *admin.OrgIamPolicyRequest) *iam_model.OrgIAMPolicy {
return &iam_model.OrgIAMPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.OrgId,
},
Description: policy.Description,
UserLoginMustBeDomain: policy.UserLoginMustBeDomain,
}
}

View File

@@ -0,0 +1,23 @@
package admin
import (
"context"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetDefaultPasswordAgePolicy(ctx context.Context, _ *empty.Empty) (*admin.DefaultPasswordAgePolicyView, error) {
result, err := s.iam.GetDefaultPasswordAgePolicy(ctx)
if err != nil {
return nil, err
}
return passwordAgePolicyViewFromModel(result), nil
}
func (s *Server) UpdateDefaultPasswordAgePolicy(ctx context.Context, policy *admin.DefaultPasswordAgePolicyRequest) (*admin.DefaultPasswordAgePolicy, error) {
result, err := s.iam.ChangeDefaultPasswordAgePolicy(ctx, passwordAgePolicyToModel(policy))
if err != nil {
return nil, err
}
return passwordAgePolicyFromModel(result), nil
}

View File

@@ -0,0 +1,45 @@
package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
)
func passwordAgePolicyToModel(policy *admin.DefaultPasswordAgePolicyRequest) *iam_model.PasswordAgePolicy {
return &iam_model.PasswordAgePolicy{
MaxAgeDays: policy.MaxAgeDays,
ExpireWarnDays: policy.ExpireWarnDays,
}
}
func passwordAgePolicyFromModel(policy *iam_model.PasswordAgePolicy) *admin.DefaultPasswordAgePolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-mH9os").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-3tGs9").OnError(err).Debug("date parse failed")
return &admin.DefaultPasswordAgePolicy{
MaxAgeDays: policy.MaxAgeDays,
ExpireWarnDays: policy.ExpireWarnDays,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func passwordAgePolicyViewFromModel(policy *iam_model.PasswordAgePolicyView) *admin.DefaultPasswordAgePolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-2Gs9o").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-8Hjss").OnError(err).Debug("date parse failed")
return &admin.DefaultPasswordAgePolicyView{
MaxAgeDays: policy.MaxAgeDays,
ExpireWarnDays: policy.ExpireWarnDays,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -0,0 +1,23 @@
package admin
import (
"context"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetDefaultPasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*admin.DefaultPasswordComplexityPolicyView, error) {
result, err := s.iam.GetDefaultPasswordComplexityPolicy(ctx)
if err != nil {
return nil, err
}
return passwordComplexityPolicyViewFromModel(result), nil
}
func (s *Server) UpdateDefaultPasswordComplexityPolicy(ctx context.Context, policy *admin.DefaultPasswordComplexityPolicyRequest) (*admin.DefaultPasswordComplexityPolicy, error) {
result, err := s.iam.ChangeDefaultPasswordComplexityPolicy(ctx, passwordComplexityPolicyToModel(policy))
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(result), nil
}

View File

@@ -0,0 +1,54 @@
package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
)
func passwordComplexityPolicyToModel(policy *admin.DefaultPasswordComplexityPolicyRequest) *iam_model.PasswordComplexityPolicy {
return &iam_model.PasswordComplexityPolicy{
MinLength: policy.MinLength,
HasUppercase: policy.HasUppercase,
HasLowercase: policy.HasLowercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
}
}
func passwordComplexityPolicyFromModel(policy *iam_model.PasswordComplexityPolicy) *admin.DefaultPasswordComplexityPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-6Zhs9").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-bMso0").OnError(err).Debug("date parse failed")
return &admin.DefaultPasswordComplexityPolicy{
MinLength: policy.MinLength,
HasUppercase: policy.HasUppercase,
HasLowercase: policy.HasLowercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func passwordComplexityPolicyViewFromModel(policy *iam_model.PasswordComplexityPolicyView) *admin.DefaultPasswordComplexityPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-rTs9f").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-ks9Zt").OnError(err).Debug("date parse failed")
return &admin.DefaultPasswordComplexityPolicyView{
MinLength: policy.MinLength,
HasUppercase: policy.HasUppercase,
HasLowercase: policy.HasLowercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -0,0 +1,23 @@
package admin
import (
"context"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetDefaultPasswordLockoutPolicy(ctx context.Context, _ *empty.Empty) (*admin.DefaultPasswordLockoutPolicyView, error) {
result, err := s.iam.GetDefaultPasswordLockoutPolicy(ctx)
if err != nil {
return nil, err
}
return passwordLockoutPolicyViewFromModel(result), nil
}
func (s *Server) UpdateDefaultPasswordLockoutPolicy(ctx context.Context, policy *admin.DefaultPasswordLockoutPolicyRequest) (*admin.DefaultPasswordLockoutPolicy, error) {
result, err := s.iam.ChangeDefaultPasswordLockoutPolicy(ctx, passwordLockoutPolicyToModel(policy))
if err != nil {
return nil, err
}
return passwordLockoutPolicyFromModel(result), nil
}

View File

@@ -0,0 +1,45 @@
package admin
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/admin"
"github.com/golang/protobuf/ptypes"
)
func passwordLockoutPolicyToModel(policy *admin.DefaultPasswordLockoutPolicyRequest) *iam_model.PasswordLockoutPolicy {
return &iam_model.PasswordLockoutPolicy{
MaxAttempts: policy.MaxAttempts,
ShowLockOutFailures: policy.ShowLockoutFailure,
}
}
func passwordLockoutPolicyFromModel(policy *iam_model.PasswordLockoutPolicy) *admin.DefaultPasswordLockoutPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-4Gsm9f").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-3Gms9").OnError(err).Debug("date parse failed")
return &admin.DefaultPasswordLockoutPolicy{
MaxAttempts: policy.MaxAttempts,
ShowLockoutFailure: policy.ShowLockOutFailures,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func passwordLockoutPolicyViewFromModel(policy *iam_model.PasswordLockoutPolicyView) *admin.DefaultPasswordLockoutPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-7Hmlo").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-0oLgs").OnError(err).Debug("date parse failed")
return &admin.DefaultPasswordLockoutPolicyView{
MaxAttempts: policy.MaxAttempts,
ShowLockoutFailure: policy.ShowLockOutFailures,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -2,13 +2,13 @@ package auth
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/policy/model"
"github.com/caos/zitadel/pkg/grpc/auth"
)
func passwordComplexityPolicyFromModel(policy *model.PasswordComplexityPolicy) *auth.PasswordComplexityPolicy {
func passwordComplexityPolicyFromModel(policy *iam_model.PasswordComplexityPolicyView) *auth.PasswordComplexityPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-Lsi3d").OnError(err).Debug("unable to parse timestamp")
@@ -19,7 +19,6 @@ func passwordComplexityPolicyFromModel(policy *model.PasswordComplexityPolicy) *
Id: policy.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Description: policy.Description,
Sequence: policy.Sequence,
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,

View File

@@ -9,7 +9,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/stats"
"github.com/caos/zitadel/internal/api/http"
grpc_utils "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/tracing"
)
@@ -29,7 +29,7 @@ func TracingStatsClient(ignoredMethods ...GRPCMethod) grpc.DialOption {
}
func DefaultTracingStatsClient() grpc.DialOption {
return TracingStatsClient(http.Healthz, http.Readiness, http.Validation)
return TracingStatsClient(grpc_utils.Healthz, grpc_utils.Readiness, grpc_utils.Validation)
}
type tracingClientHandler struct {

View File

@@ -30,6 +30,9 @@ func CaosToGRPCError(ctx context.Context, err error) error {
}
func ExtractCaosError(err error) (c codes.Code, msg, id string, ok bool) {
if err == nil {
return codes.OK, "", "", false
}
switch caosErr := err.(type) {
case *caos_errs.AlreadyExistsError:
return codes.AlreadyExists, caosErr.GetMessage(), caosErr.GetID(), true

View File

@@ -44,34 +44,40 @@ func appConfigFromModel(app *proj_model.Application) management.AppConfig {
func oidcConfigFromModel(config *proj_model.OIDCConfig) *management.OIDCConfig {
return &management.OIDCConfig{
RedirectUris: config.RedirectUris,
ResponseTypes: oidcResponseTypesFromModel(config.ResponseTypes),
GrantTypes: oidcGrantTypesFromModel(config.GrantTypes),
ApplicationType: oidcApplicationTypeFromModel(config.ApplicationType),
ClientId: config.ClientID,
ClientSecret: config.ClientSecretString,
AuthMethodType: oidcAuthMethodTypeFromModel(config.AuthMethodType),
PostLogoutRedirectUris: config.PostLogoutRedirectUris,
Version: oidcVersionFromModel(config.OIDCVersion),
NoneCompliant: config.Compliance.NoneCompliant,
ComplianceProblems: complianceProblemsToLocalizedMessages(config.Compliance.Problems),
DevMode: config.DevMode,
RedirectUris: config.RedirectUris,
ResponseTypes: oidcResponseTypesFromModel(config.ResponseTypes),
GrantTypes: oidcGrantTypesFromModel(config.GrantTypes),
ApplicationType: oidcApplicationTypeFromModel(config.ApplicationType),
ClientId: config.ClientID,
ClientSecret: config.ClientSecretString,
AuthMethodType: oidcAuthMethodTypeFromModel(config.AuthMethodType),
PostLogoutRedirectUris: config.PostLogoutRedirectUris,
Version: oidcVersionFromModel(config.OIDCVersion),
NoneCompliant: config.Compliance.NoneCompliant,
ComplianceProblems: complianceProblemsToLocalizedMessages(config.Compliance.Problems),
DevMode: config.DevMode,
AccessTokenType: oidcTokenTypeFromModel(config.AccessTokenType),
AccessTokenRoleAssertion: config.AccessTokenRoleAssertion,
IdTokenRoleAssertion: config.IDTokenRoleAssertion,
}
}
func oidcConfigFromApplicationViewModel(app *proj_model.ApplicationView) *management.OIDCConfig {
return &management.OIDCConfig{
RedirectUris: app.OIDCRedirectUris,
ResponseTypes: oidcResponseTypesFromModel(app.OIDCResponseTypes),
GrantTypes: oidcGrantTypesFromModel(app.OIDCGrantTypes),
ApplicationType: oidcApplicationTypeFromModel(app.OIDCApplicationType),
ClientId: app.OIDCClientID,
AuthMethodType: oidcAuthMethodTypeFromModel(app.OIDCAuthMethodType),
PostLogoutRedirectUris: app.OIDCPostLogoutRedirectUris,
Version: oidcVersionFromModel(app.OIDCVersion),
NoneCompliant: app.NoneCompliant,
ComplianceProblems: complianceProblemsToLocalizedMessages(app.ComplianceProblems),
DevMode: app.DevMode,
RedirectUris: app.OIDCRedirectUris,
ResponseTypes: oidcResponseTypesFromModel(app.OIDCResponseTypes),
GrantTypes: oidcGrantTypesFromModel(app.OIDCGrantTypes),
ApplicationType: oidcApplicationTypeFromModel(app.OIDCApplicationType),
ClientId: app.OIDCClientID,
AuthMethodType: oidcAuthMethodTypeFromModel(app.OIDCAuthMethodType),
PostLogoutRedirectUris: app.OIDCPostLogoutRedirectUris,
Version: oidcVersionFromModel(app.OIDCVersion),
NoneCompliant: app.NoneCompliant,
ComplianceProblems: complianceProblemsToLocalizedMessages(app.ComplianceProblems),
DevMode: app.DevMode,
AccessTokenType: oidcTokenTypeFromModel(app.AccessTokenType),
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
IdTokenRoleAssertion: app.IDTokenRoleAssertion,
}
}
@@ -92,14 +98,17 @@ func oidcAppCreateToModel(app *management.OIDCApplicationCreate) *proj_model.App
Name: app.Name,
Type: proj_model.AppTypeOIDC,
OIDCConfig: &proj_model.OIDCConfig{
OIDCVersion: oidcVersionToModel(app.Version),
RedirectUris: app.RedirectUris,
ResponseTypes: oidcResponseTypesToModel(app.ResponseTypes),
GrantTypes: oidcGrantTypesToModel(app.GrantTypes),
ApplicationType: oidcApplicationTypeToModel(app.ApplicationType),
AuthMethodType: oidcAuthMethodTypeToModel(app.AuthMethodType),
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
DevMode: app.DevMode,
OIDCVersion: oidcVersionToModel(app.Version),
RedirectUris: app.RedirectUris,
ResponseTypes: oidcResponseTypesToModel(app.ResponseTypes),
GrantTypes: oidcGrantTypesToModel(app.GrantTypes),
ApplicationType: oidcApplicationTypeToModel(app.ApplicationType),
AuthMethodType: oidcAuthMethodTypeToModel(app.AuthMethodType),
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
DevMode: app.DevMode,
AccessTokenType: oidcTokenTypeToModel(app.AccessTokenType),
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
IDTokenRoleAssertion: app.IdTokenRoleAssertion,
},
}
}
@@ -119,14 +128,17 @@ func oidcConfigUpdateToModel(app *management.OIDCConfigUpdate) *proj_model.OIDCC
ObjectRoot: models.ObjectRoot{
AggregateID: app.ProjectId,
},
AppID: app.ApplicationId,
RedirectUris: app.RedirectUris,
ResponseTypes: oidcResponseTypesToModel(app.ResponseTypes),
GrantTypes: oidcGrantTypesToModel(app.GrantTypes),
ApplicationType: oidcApplicationTypeToModel(app.ApplicationType),
AuthMethodType: oidcAuthMethodTypeToModel(app.AuthMethodType),
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
DevMode: app.DevMode,
AppID: app.ApplicationId,
RedirectUris: app.RedirectUris,
ResponseTypes: oidcResponseTypesToModel(app.ResponseTypes),
GrantTypes: oidcGrantTypesToModel(app.GrantTypes),
ApplicationType: oidcApplicationTypeToModel(app.ApplicationType),
AuthMethodType: oidcAuthMethodTypeToModel(app.AuthMethodType),
PostLogoutRedirectUris: app.PostLogoutRedirectUris,
DevMode: app.DevMode,
AccessTokenType: oidcTokenTypeToModel(app.AccessTokenType),
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
IDTokenRoleAssertion: app.IdTokenRoleAssertion,
}
}
@@ -351,6 +363,28 @@ func oidcAuthMethodTypeFromModel(authType proj_model.OIDCAuthMethodType) managem
}
}
func oidcTokenTypeToModel(tokenType management.OIDCTokenType) proj_model.OIDCTokenType {
switch tokenType {
case management.OIDCTokenType_OIDCTokenType_Bearer:
return proj_model.OIDCTokenTypeBearer
case management.OIDCTokenType_OIDCTokenType_JWT:
return proj_model.OIDCTokenTypeJWT
default:
return proj_model.OIDCTokenTypeBearer
}
}
func oidcTokenTypeFromModel(tokenType proj_model.OIDCTokenType) management.OIDCTokenType {
switch tokenType {
case proj_model.OIDCTokenTypeBearer:
return management.OIDCTokenType_OIDCTokenType_Bearer
case proj_model.OIDCTokenTypeJWT:
return management.OIDCTokenType_OIDCTokenType_JWT
default:
return management.OIDCTokenType_OIDCTokenType_Bearer
}
}
func oidcVersionFromModel(version proj_model.OIDCVersion) management.OIDCVersion {
switch version {
case proj_model.OIDCVersionV1:

View File

@@ -9,7 +9,19 @@ func iamFromModel(iam *iam_model.IAM) *management.Iam {
return &management.Iam{
IamProjectId: iam.IAMProjectID,
GlobalOrgId: iam.GlobalOrgID,
SetUpDone: iam.SetUpDone,
SetUpStarted: iam.SetUpStarted,
SetUpDone: iamSetupStepFromModel(iam.SetUpDone),
SetUpStarted: iamSetupStepFromModel(iam.SetUpStarted),
}
}
func iamSetupStepFromModel(step iam_model.Step) management.IamSetupStep {
switch step {
case iam_model.Step1:
return management.IamSetupStep_iam_setup_step_1
//TODO: label policy
// case iam_model.Step2:
// return management.IamSetupStep_iam_setup_step_2
default:
return management.IamSetupStep_iam_setup_step_UNDEFINED
}
}

View File

@@ -61,7 +61,11 @@ func (s *Server) UpdateOidcIdpConfig(ctx context.Context, request *management.Oi
}
func (s *Server) SearchIdps(ctx context.Context, request *management.IdpSearchRequest) (*management.IdpSearchResponse, error) {
response, err := s.org.SearchIDPConfigs(ctx, idpConfigSearchRequestToModel(request))
searchRequest, err := idpConfigSearchRequestToModel(request)
if err != nil {
return nil, err
}
response, err := s.org.SearchIDPConfigs(ctx, searchRequest)
if err != nil {
return nil, err
}

View File

@@ -2,16 +2,18 @@ package management
import (
"github.com/caos/logging"
caos_errors "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes"
"strconv"
)
func createOidcIdpToModel(idp *management.OidcIdpConfigCreate) *iam_model.IDPConfig {
return &iam_model.IDPConfig{
Name: idp.Name,
LogoSrc: idp.LogoSrc,
Type: iam_model.IDPConfigTypeOIDC,
Name: idp.Name,
StylingType: idpConfigStylingTypeToModel(idp.StylingType),
Type: iam_model.IDPConfigTypeOIDC,
OIDCConfig: &iam_model.OIDCIDPConfig{
ClientID: idp.ClientId,
ClientSecretString: idp.ClientSecret,
@@ -27,7 +29,7 @@ func updateIdpToModel(idp *management.IdpUpdate) *iam_model.IDPConfig {
return &iam_model.IDPConfig{
IDPConfigID: idp.Id,
Name: idp.Name,
LogoSrc: idp.LogoSrc,
StylingType: idpConfigStylingTypeToModel(idp.StylingType),
}
}
@@ -56,7 +58,7 @@ func idpFromModel(idp *iam_model.IDPConfig) *management.Idp {
ChangeDate: changeDate,
Sequence: idp.Sequence,
Name: idp.Name,
LogoSrc: idp.LogoSrc,
StylingType: idpConfigStylingTypeFromModel(idp.StylingType),
State: idpConfigStateFromModel(idp.State),
IdpConfig: idpConfigFromModel(idp),
}
@@ -76,7 +78,7 @@ func idpViewFromModel(idp *iam_model.IDPConfigView) *management.IdpView {
Sequence: idp.Sequence,
ProviderType: idpProviderTypeFromModel(idp.IDPProviderType),
Name: idp.Name,
LogoSrc: idp.LogoSrc,
StylingType: idpConfigStylingTypeFromModel(idp.StylingType),
State: idpConfigStateFromModel(idp.State),
IdpConfigView: idpConfigViewFromModel(idp),
}
@@ -131,29 +133,47 @@ func idpConfigStateFromModel(state iam_model.IDPConfigState) management.IdpState
}
}
func idpConfigSearchRequestToModel(request *management.IdpSearchRequest) *iam_model.IDPConfigSearchRequest {
return &iam_model.IDPConfigSearchRequest{
Limit: request.Limit,
Offset: request.Offset,
Queries: idpConfigSearchQueriesToModel(request.Queries),
func idpConfigSearchRequestToModel(request *management.IdpSearchRequest) (*iam_model.IDPConfigSearchRequest, error) {
convertedSearchRequest := &iam_model.IDPConfigSearchRequest{
Limit: request.Limit,
Offset: request.Offset,
}
convertedQueries, err := idpConfigSearchQueriesToModel(request.Queries)
if err != nil {
return nil, err
}
convertedSearchRequest.Queries = convertedQueries
return convertedSearchRequest, nil
}
func idpConfigSearchQueriesToModel(queries []*management.IdpSearchQuery) []*iam_model.IDPConfigSearchQuery {
func idpConfigSearchQueriesToModel(queries []*management.IdpSearchQuery) ([]*iam_model.IDPConfigSearchQuery, error) {
modelQueries := make([]*iam_model.IDPConfigSearchQuery, len(queries))
for i, query := range queries {
modelQueries[i] = idpConfigSearchQueryToModel(query)
converted, err := idpConfigSearchQueryToModel(query)
if err != nil {
return nil, err
}
modelQueries[i] = converted
}
return modelQueries
return modelQueries, nil
}
func idpConfigSearchQueryToModel(query *management.IdpSearchQuery) *iam_model.IDPConfigSearchQuery {
return &iam_model.IDPConfigSearchQuery{
func idpConfigSearchQueryToModel(query *management.IdpSearchQuery) (*iam_model.IDPConfigSearchQuery, error) {
converted := &iam_model.IDPConfigSearchQuery{
Key: idpConfigSearchKeyToModel(query.Key),
Method: searchMethodToModel(query.Method),
Value: query.Value,
}
if query.Key != management.IdpSearchKey_IDPSEARCHKEY_PROVIDER_TYPE {
return converted, nil
}
value, err := idpProviderTypeStringToModel(query.Value)
if err != nil {
return nil, err
}
converted.Value = value
return converted, nil
}
func idpConfigSearchKeyToModel(key management.IdpSearchKey) iam_model.IDPConfigSearchKey {
@@ -211,3 +231,33 @@ func oidcMappingFieldToModel(field management.OIDCMappingField) iam_model.OIDCMa
return iam_model.OIDCMappingFieldUnspecified
}
}
func idpConfigStylingTypeFromModel(stylingType iam_model.IDPStylingType) management.IdpStylingType {
switch stylingType {
case iam_model.IDPStylingTypeGoogle:
return management.IdpStylingType_IDPSTYLINGTYPE_GOOGLE
default:
return management.IdpStylingType_IDPSTYLINGTYPE_UNSPECIFIED
}
}
func idpConfigStylingTypeToModel(stylingType management.IdpStylingType) iam_model.IDPStylingType {
switch stylingType {
case management.IdpStylingType_IDPSTYLINGTYPE_GOOGLE:
return iam_model.IDPStylingTypeGoogle
default:
return iam_model.IDPStylingTypeUnspecified
}
}
func idpProviderTypeStringToModel(providerType string) (iam_model.IDPProviderType, error) {
i, _ := strconv.ParseInt(providerType, 10, 32)
switch management.IdpProviderType(i) {
case management.IdpProviderType_IDPPROVIDERTYPE_SYSTEM:
return iam_model.IDPProviderTypeSystem, nil
case management.IdpProviderType_IDPPROVIDERTYPE_ORG:
return iam_model.IDPProviderTypeOrg, nil
default:
return 0, caos_errors.ThrowPreconditionFailed(nil, "MGMT-6is9f", "Errors.Org.IDP.InvalidSearchQuery")
}
}

View File

@@ -14,16 +14,24 @@ func (s *Server) GetLoginPolicy(ctx context.Context, _ *empty.Empty) (*managemen
return loginPolicyViewFromModel(result), nil
}
func (s *Server) CreateLoginPolicy(ctx context.Context, policy *management.LoginPolicyAdd) (*management.LoginPolicy, error) {
result, err := s.org.AddLoginPolicy(ctx, loginPolicyAddToModel(policy))
func (s *Server) GetDefaultLoginPolicy(ctx context.Context, _ *empty.Empty) (*management.LoginPolicyView, error) {
result, err := s.org.GetDefaultLoginPolicy(ctx)
if err != nil {
return nil, err
}
return loginPolicyViewFromModel(result), nil
}
func (s *Server) CreateLoginPolicy(ctx context.Context, policy *management.LoginPolicyRequest) (*management.LoginPolicy, error) {
result, err := s.org.AddLoginPolicy(ctx, loginPolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return loginPolicyFromModel(result), nil
}
func (s *Server) UpdateLoginPolicy(ctx context.Context, policy *management.LoginPolicy) (*management.LoginPolicy, error) {
result, err := s.org.ChangeLoginPolicy(ctx, loginPolicyToModel(policy))
func (s *Server) UpdateLoginPolicy(ctx context.Context, policy *management.LoginPolicyRequest) (*management.LoginPolicy, error) {
result, err := s.org.ChangeLoginPolicy(ctx, loginPolicyRequestToModel(policy))
if err != nil {
return nil, err
}

View File

@@ -1,18 +1,13 @@
package management
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes"
)
func loginPolicyAddToModel(policy *management.LoginPolicyAdd) *iam_model.LoginPolicy {
return &iam_model.LoginPolicy{
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
AllowRegister: policy.AllowRegister,
}
}
func loginPolicyToModel(policy *management.LoginPolicy) *iam_model.LoginPolicy {
func loginPolicyRequestToModel(policy *management.LoginPolicyRequest) *iam_model.LoginPolicy {
return &iam_model.LoginPolicy{
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
@@ -21,19 +16,35 @@ func loginPolicyToModel(policy *management.LoginPolicy) *iam_model.LoginPolicy {
}
func loginPolicyFromModel(policy *iam_model.LoginPolicy) *management.LoginPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-2Fsm8").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-3Flo0").OnError(err).Debug("date parse failed")
return &management.LoginPolicy{
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
AllowRegister: policy.AllowRegister,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}
func loginPolicyViewFromModel(policy *iam_model.LoginPolicyView) *management.LoginPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-5Tsm8").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-8dJgs").OnError(err).Debug("date parse failed")
return &management.LoginPolicyView{
Default: policy.Default,
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIDP,
AllowRegister: policy.AllowRegister,
CreationDate: creationDate,
ChangeDate: changeDate,
}
}

View File

@@ -98,10 +98,10 @@ func (s *Server) OrgChanges(ctx context.Context, changesRequest *management.Chan
return orgChangesToResponse(response, changesRequest.GetSequenceOffset(), changesRequest.GetLimit()), nil
}
func (s *Server) GetMyOrgIamPolicy(ctx context.Context, _ *empty.Empty) (_ *management.OrgIamPolicy, err error) {
func (s *Server) GetMyOrgIamPolicy(ctx context.Context, _ *empty.Empty) (_ *management.OrgIamPolicyView, err error) {
policy, err := s.org.GetMyOrgIamPolicy(ctx)
if err != nil {
return nil, err
}
return orgIamPolicyFromModel(policy), err
return orgIamPolicyViewFromModel(policy), err
}

View File

@@ -2,6 +2,7 @@ package management
import (
"encoding/json"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
@@ -227,10 +228,8 @@ func orgChangesToMgtAPI(changes *org_model.OrgChanges) (_ []*management.Change)
return result
}
func orgIamPolicyFromModel(policy *org_model.OrgIAMPolicy) *management.OrgIamPolicy {
return &management.OrgIamPolicy{
OrgId: policy.AggregateID,
Description: policy.Description,
func orgIamPolicyViewFromModel(policy *iam_model.OrgIAMPolicyView) *management.OrgIamPolicyView {
return &management.OrgIamPolicyView{
UserLoginMustBeDomain: policy.UserLoginMustBeDomain,
Default: policy.Default,
}

View File

@@ -0,0 +1,44 @@
package management
import (
"context"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetPasswordAgePolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordAgePolicyView, error) {
result, err := s.org.GetPasswordAgePolicy(ctx)
if err != nil {
return nil, err
}
return passwordAgePolicyViewFromModel(result), nil
}
func (s *Server) GetDefaultPasswordAgePolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordAgePolicyView, error) {
result, err := s.org.GetDefaultPasswordAgePolicy(ctx)
if err != nil {
return nil, err
}
return passwordAgePolicyViewFromModel(result), nil
}
func (s *Server) CreatePasswordAgePolicy(ctx context.Context, policy *management.PasswordAgePolicyRequest) (*management.PasswordAgePolicy, error) {
result, err := s.org.AddPasswordAgePolicy(ctx, passwordAgePolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return passwordAgePolicyFromModel(result), nil
}
func (s *Server) UpdatePasswordAgePolicy(ctx context.Context, policy *management.PasswordAgePolicyRequest) (*management.PasswordAgePolicy, error) {
result, err := s.org.ChangePasswordAgePolicy(ctx, passwordAgePolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return passwordAgePolicyFromModel(result), nil
}
func (s *Server) RemovePasswordAgePolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) {
err := s.org.RemovePasswordAgePolicy(ctx)
return &empty.Empty{}, err
}

View File

@@ -0,0 +1,46 @@
package management
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes"
)
func passwordAgePolicyRequestToModel(policy *management.PasswordAgePolicyRequest) *iam_model.PasswordAgePolicy {
return &iam_model.PasswordAgePolicy{
MaxAgeDays: policy.MaxAgeDays,
ExpireWarnDays: policy.ExpireWarnDays,
}
}
func passwordAgePolicyFromModel(policy *iam_model.PasswordAgePolicy) *management.PasswordAgePolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-bMd9o").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-jFs89").OnError(err).Debug("date parse failed")
return &management.PasswordAgePolicy{
MaxAgeDays: policy.MaxAgeDays,
ExpireWarnDays: policy.ExpireWarnDays,
CreationDate: changeDate,
ChangeDate: creationDate,
}
}
func passwordAgePolicyViewFromModel(policy *iam_model.PasswordAgePolicyView) *management.PasswordAgePolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-4Bms9").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-6Hmlo").OnError(err).Debug("date parse failed")
return &management.PasswordAgePolicyView{
Default: policy.Default,
MaxAgeDays: policy.MaxAgeDays,
ExpireWarnDays: policy.ExpireWarnDays,
ChangeDate: changeDate,
CreationDate: creationDate,
}
}

View File

@@ -0,0 +1,44 @@
package management
import (
"context"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetPasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordComplexityPolicyView, error) {
result, err := s.org.GetPasswordComplexityPolicy(ctx)
if err != nil {
return nil, err
}
return passwordComplexityPolicyViewFromModel(result), nil
}
func (s *Server) GetDefaultPasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordComplexityPolicyView, error) {
result, err := s.org.GetDefaultPasswordComplexityPolicy(ctx)
if err != nil {
return nil, err
}
return passwordComplexityPolicyViewFromModel(result), nil
}
func (s *Server) CreatePasswordComplexityPolicy(ctx context.Context, policy *management.PasswordComplexityPolicyRequest) (*management.PasswordComplexityPolicy, error) {
result, err := s.org.AddPasswordComplexityPolicy(ctx, passwordComplexityPolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(result), nil
}
func (s *Server) UpdatePasswordComplexityPolicy(ctx context.Context, policy *management.PasswordComplexityPolicyRequest) (*management.PasswordComplexityPolicy, error) {
result, err := s.org.ChangePasswordComplexityPolicy(ctx, passwordComplexityPolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(result), nil
}
func (s *Server) RemovePasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) {
err := s.org.RemovePasswordComplexityPolicy(ctx)
return &empty.Empty{}, err
}

View File

@@ -0,0 +1,55 @@
package management
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes"
)
func passwordComplexityPolicyRequestToModel(policy *management.PasswordComplexityPolicyRequest) *iam_model.PasswordComplexityPolicy {
return &iam_model.PasswordComplexityPolicy{
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasSymbol: policy.HasSymbol,
HasNumber: policy.HasNumber,
}
}
func passwordComplexityPolicyFromModel(policy *iam_model.PasswordComplexityPolicy) *management.PasswordComplexityPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-5Gslo").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-Bmd9e").OnError(err).Debug("date parse failed")
return &management.PasswordComplexityPolicy{
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasSymbol: policy.HasSymbol,
HasNumber: policy.HasNumber,
CreationDate: changeDate,
ChangeDate: creationDate,
}
}
func passwordComplexityPolicyViewFromModel(policy *iam_model.PasswordComplexityPolicyView) *management.PasswordComplexityPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-wmi8f").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-dmOp0").OnError(err).Debug("date parse failed")
return &management.PasswordComplexityPolicyView{
Default: policy.Default,
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasSymbol: policy.HasSymbol,
HasNumber: policy.HasNumber,
CreationDate: changeDate,
ChangeDate: creationDate,
}
}

View File

@@ -0,0 +1,44 @@
package management
import (
"context"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetPasswordLockoutPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordLockoutPolicyView, error) {
result, err := s.org.GetPasswordLockoutPolicy(ctx)
if err != nil {
return nil, err
}
return passwordLockoutPolicyViewFromModel(result), nil
}
func (s *Server) GetDefaultPasswordLockoutPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordLockoutPolicyView, error) {
result, err := s.org.GetDefaultPasswordLockoutPolicy(ctx)
if err != nil {
return nil, err
}
return passwordLockoutPolicyViewFromModel(result), nil
}
func (s *Server) CreatePasswordLockoutPolicy(ctx context.Context, policy *management.PasswordLockoutPolicyRequest) (*management.PasswordLockoutPolicy, error) {
result, err := s.org.AddPasswordLockoutPolicy(ctx, passwordLockoutPolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return passwordLockoutPolicyFromModel(result), nil
}
func (s *Server) UpdatePasswordLockoutPolicy(ctx context.Context, policy *management.PasswordLockoutPolicyRequest) (*management.PasswordLockoutPolicy, error) {
result, err := s.org.ChangePasswordLockoutPolicy(ctx, passwordLockoutPolicyRequestToModel(policy))
if err != nil {
return nil, err
}
return passwordLockoutPolicyFromModel(result), nil
}
func (s *Server) RemovePasswordLockoutPolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) {
err := s.org.RemovePasswordLockoutPolicy(ctx)
return &empty.Empty{}, err
}

View File

@@ -0,0 +1,46 @@
package management
import (
"github.com/caos/logging"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes"
)
func passwordLockoutPolicyRequestToModel(policy *management.PasswordLockoutPolicyRequest) *iam_model.PasswordLockoutPolicy {
return &iam_model.PasswordLockoutPolicy{
MaxAttempts: policy.MaxAttempts,
ShowLockOutFailures: policy.ShowLockoutFailure,
}
}
func passwordLockoutPolicyFromModel(policy *iam_model.PasswordLockoutPolicy) *management.PasswordLockoutPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-bMd9o").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-jFs89").OnError(err).Debug("date parse failed")
return &management.PasswordLockoutPolicy{
MaxAttempts: policy.MaxAttempts,
ShowLockoutFailure: policy.ShowLockOutFailures,
CreationDate: changeDate,
ChangeDate: creationDate,
}
}
func passwordLockoutPolicyViewFromModel(policy *iam_model.PasswordLockoutPolicyView) *management.PasswordLockoutPolicyView {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-4Bms9").OnError(err).Debug("date parse failed")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-6Hmlo").OnError(err).Debug("date parse failed")
return &management.PasswordLockoutPolicyView{
Default: policy.Default,
MaxAttempts: policy.MaxAttempts,
ShowLockoutFailure: policy.ShowLockOutFailures,
ChangeDate: changeDate,
CreationDate: creationDate,
}
}

View File

@@ -1,112 +0,0 @@
package management
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/pkg/grpc/management"
)
func (s *Server) CreatePasswordComplexityPolicy(ctx context.Context, policy *management.PasswordComplexityPolicyCreate) (*management.PasswordComplexityPolicy, error) {
policyresp, err := s.policy.CreatePasswordComplexityPolicy(ctx, passwordComplexityPolicyCreateToModel(policy))
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(policyresp), nil
}
func (s *Server) GetPasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordComplexityPolicy, error) {
policy, err := s.policy.GetPasswordComplexityPolicy(ctx)
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(policy), nil
}
func (s *Server) GetDefaultPasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordComplexityPolicy, error) {
policy, err := s.policy.GetDefaultPasswordComplexityPolicy(ctx)
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(policy), nil
}
func (s *Server) UpdatePasswordComplexityPolicy(ctx context.Context, policy *management.PasswordComplexityPolicyUpdate) (*management.PasswordComplexityPolicy, error) {
policyresp, err := s.policy.UpdatePasswordComplexityPolicy(ctx, passwordComplexityPolicyUpdateToModel(policy))
if err != nil {
return nil, err
}
return passwordComplexityPolicyFromModel(policyresp), nil
}
func (s *Server) DeletePasswordComplexityPolicy(ctx context.Context, ID *management.PasswordComplexityPolicyID) (*empty.Empty, error) {
return nil, errors.ThrowUnimplemented(nil, "GRPC-skw3f", "Not implemented")
}
func (s *Server) CreatePasswordAgePolicy(ctx context.Context, policy *management.PasswordAgePolicyCreate) (*management.PasswordAgePolicy, error) {
policyresp, err := s.policy.CreatePasswordAgePolicy(ctx, passwordAgePolicyCreateToModel(policy))
if err != nil {
return nil, err
}
return passwordAgePolicyFromModel(policyresp), nil
}
func (s *Server) GetPasswordAgePolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordAgePolicy, error) {
policy, err := s.policy.GetPasswordAgePolicy(ctx)
if err != nil {
return nil, err
}
return passwordAgePolicyFromModel(policy), nil
}
func (s *Server) UpdatePasswordAgePolicy(ctx context.Context, policy *management.PasswordAgePolicyUpdate) (*management.PasswordAgePolicy, error) {
policyresp, err := s.policy.UpdatePasswordAgePolicy(ctx, passwordAgePolicyUpdateToModel(policy))
if err != nil {
return nil, err
}
return passwordAgePolicyFromModel(policyresp), nil
}
func (s *Server) DeletePasswordAgePolicy(ctx context.Context, ID *management.PasswordAgePolicyID) (*empty.Empty, error) {
return nil, errors.ThrowUnimplemented(nil, "GRPC-plo67", "Not implemented")
}
func (s *Server) CreatePasswordLockoutPolicy(ctx context.Context, policy *management.PasswordLockoutPolicyCreate) (*management.PasswordLockoutPolicy, error) {
policyresp, err := s.policy.CreatePasswordLockoutPolicy(ctx, passwordLockoutPolicyCreateToModel(policy))
if err != nil {
return nil, err
}
return passwordLockoutPolicyFromModel(policyresp), nil
}
func (s *Server) GetPasswordLockoutPolicy(ctx context.Context, _ *empty.Empty) (*management.PasswordLockoutPolicy, error) {
policy, err := s.policy.GetPasswordLockoutPolicy(ctx)
if err != nil {
return nil, err
}
return passwordLockoutPolicyFromModel(policy), nil
}
func (s *Server) UpdatePasswordLockoutPolicy(ctx context.Context, policy *management.PasswordLockoutPolicyUpdate) (*management.PasswordLockoutPolicy, error) {
policyresp, err := s.policy.UpdatePasswordLockoutPolicy(ctx, passwordLockoutPolicyUpdateToModel(policy))
if err != nil {
return nil, err
}
return passwordLockoutPolicyFromModel(policyresp), nil
}
func (s *Server) DeletePasswordLockoutPolicy(ctx context.Context, ID *management.PasswordLockoutPolicyID) (*empty.Empty, error) {
return nil, errors.ThrowUnimplemented(nil, "GRPC-GHkd9", "Not implemented")
}

View File

@@ -1,68 +0,0 @@
package management
import (
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/policy/model"
"github.com/caos/zitadel/pkg/grpc/management"
)
func passwordAgePolicyFromModel(policy *model.PasswordAgePolicy) *management.PasswordAgePolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-6ILdB").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-ngUzJ").OnError(err).Debug("unable to parse timestamp")
return &management.PasswordAgePolicy{
Id: policy.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: policy.Sequence,
Description: policy.Description,
ExpireWarnDays: policy.ExpireWarnDays,
MaxAgeDays: policy.MaxAgeDays,
IsDefault: policy.AggregateID == "",
}
}
func passwordAgePolicyToModel(policy *management.PasswordAgePolicy) *model.PasswordAgePolicy {
creationDate, err := ptypes.Timestamp(policy.CreationDate)
logging.Log("GRPC-2QSfU").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.Timestamp(policy.ChangeDate)
logging.Log("GRPC-LdU91").OnError(err).Debug("unable to parse timestamp")
return &model.PasswordAgePolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.Id,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: policy.Sequence,
},
Description: policy.Description,
ExpireWarnDays: policy.ExpireWarnDays,
MaxAgeDays: policy.MaxAgeDays,
}
}
func passwordAgePolicyCreateToModel(policy *management.PasswordAgePolicyCreate) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
Description: policy.Description,
ExpireWarnDays: policy.ExpireWarnDays,
MaxAgeDays: policy.MaxAgeDays,
}
}
func passwordAgePolicyUpdateToModel(policy *management.PasswordAgePolicyUpdate) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.Id,
},
Description: policy.Description,
ExpireWarnDays: policy.ExpireWarnDays,
MaxAgeDays: policy.MaxAgeDays,
}
}

View File

@@ -1,81 +0,0 @@
package management
import (
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/policy/model"
"github.com/caos/zitadel/pkg/grpc/management"
)
func passwordComplexityPolicyFromModel(policy *model.PasswordComplexityPolicy) *management.PasswordComplexityPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-cQRHE").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-PVA1c").OnError(err).Debug("unable to parse timestamp")
return &management.PasswordComplexityPolicy{
Id: policy.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Description: policy.Description,
Sequence: policy.Sequence,
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
IsDefault: policy.AggregateID == "",
}
}
func passwordComplexityPolicyToModel(policy *management.PasswordComplexityPolicy) *model.PasswordComplexityPolicy {
creationDate, err := ptypes.Timestamp(policy.CreationDate)
logging.Log("GRPC-asmEZ").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.Timestamp(policy.ChangeDate)
logging.Log("GRPC-MCE4o").OnError(err).Debug("unable to parse timestamp")
return &model.PasswordComplexityPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.Id,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: policy.Sequence,
},
Description: policy.Description,
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
}
}
func passwordComplexityPolicyCreateToModel(policy *management.PasswordComplexityPolicyCreate) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
Description: policy.Description,
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
}
}
func passwordComplexityPolicyUpdateToModel(policy *management.PasswordComplexityPolicyUpdate) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.Id,
},
Description: policy.Description,
MinLength: policy.MinLength,
HasLowercase: policy.HasLowercase,
HasUppercase: policy.HasUppercase,
HasNumber: policy.HasNumber,
HasSymbol: policy.HasSymbol,
}
}

View File

@@ -1,70 +0,0 @@
package management
import (
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/policy/model"
"github.com/caos/zitadel/pkg/grpc/management"
)
func passwordLockoutPolicyFromModel(policy *model.PasswordLockoutPolicy) *management.PasswordLockoutPolicy {
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
logging.Log("GRPC-JRSbT").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
logging.Log("GRPC-1sizr").OnError(err).Debug("unable to parse timestamp")
return &management.PasswordLockoutPolicy{
Id: policy.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: policy.Sequence,
Description: policy.Description,
MaxAttempts: policy.MaxAttempts,
ShowLockOutFailures: policy.ShowLockOutFailures,
IsDefault: policy.AggregateID == "",
}
}
func passwordLockoutPolicyToModel(policy *management.PasswordLockoutPolicy) *model.PasswordLockoutPolicy {
creationDate, err := ptypes.Timestamp(policy.CreationDate)
logging.Log("GRPC-8a511").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.Timestamp(policy.ChangeDate)
logging.Log("GRPC-2rdGv").OnError(err).Debug("unable to parse timestamp")
return &model.PasswordLockoutPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.Id,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: policy.Sequence,
},
Description: policy.Description,
MaxAttempts: policy.MaxAttempts,
ShowLockOutFailures: policy.ShowLockOutFailures,
}
}
func passwordLockoutPolicyCreateToModel(policy *management.PasswordLockoutPolicyCreate) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
Description: policy.Description,
MaxAttempts: policy.MaxAttempts,
ShowLockOutFailures: policy.ShowLockOutFailures,
}
}
func passwordLockoutPolicyUpdateToModel(policy *management.PasswordLockoutPolicyUpdate) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: policy.Id,
},
Description: policy.Description,
MaxAttempts: policy.MaxAttempts,
ShowLockOutFailures: policy.ShowLockOutFailures,
}
}

View File

@@ -12,7 +12,7 @@ import (
)
func (s *Server) CreateProject(ctx context.Context, in *management.ProjectCreateRequest) (*management.Project, error) {
project, err := s.project.CreateProject(ctx, in.Name)
project, err := s.project.CreateProject(ctx, projectCreateToModel(in))
if err != nil {
return nil, err
}

View File

@@ -22,12 +22,14 @@ func projectFromModel(project *proj_model.Project) *management.Project {
logging.Log("GRPC-di7rw").OnError(err).Debug("unable to parse timestamp")
return &management.Project{
Id: project.AggregateID,
State: projectStateFromModel(project.State),
CreationDate: creationDate,
ChangeDate: changeDate,
Name: project.Name,
Sequence: project.Sequence,
Id: project.AggregateID,
State: projectStateFromModel(project.State),
CreationDate: creationDate,
ChangeDate: changeDate,
Name: project.Name,
Sequence: project.Sequence,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
}
}
@@ -60,13 +62,15 @@ func projectViewFromModel(project *proj_model.ProjectView) *management.ProjectVi
logging.Log("GRPC-sope3").OnError(err).Debug("unable to parse timestamp")
return &management.ProjectView{
ProjectId: project.ProjectID,
State: projectStateFromModel(project.State),
CreationDate: creationDate,
ChangeDate: changeDate,
Name: project.Name,
Sequence: project.Sequence,
ResourceOwner: project.ResourceOwner,
ProjectId: project.ProjectID,
State: projectStateFromModel(project.State),
CreationDate: creationDate,
ChangeDate: changeDate,
Name: project.Name,
Sequence: project.Sequence,
ResourceOwner: project.ResourceOwner,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
}
}
@@ -117,12 +121,22 @@ func projectStateFromModel(state proj_model.ProjectState) management.ProjectStat
}
}
func projectCreateToModel(project *management.ProjectCreateRequest) *proj_model.Project {
return &proj_model.Project{
Name: project.Name,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
}
}
func projectUpdateToModel(project *management.ProjectUpdateRequest) *proj_model.Project {
return &proj_model.Project{
ObjectRoot: models.ObjectRoot{
AggregateID: project.Id,
},
Name: project.Name,
Name: project.Name,
ProjectRoleAssertion: project.ProjectRoleAssertion,
ProjectRoleCheck: project.ProjectRoleCheck,
}
}

View File

@@ -19,7 +19,6 @@ var _ management.ManagementServiceServer = (*Server)(nil)
type Server struct {
project repository.ProjectRepository
policy repository.PolicyRepository
org repository.OrgRepository
user repository.UserRepository
usergrant repository.UserGrantRepository
@@ -35,7 +34,6 @@ type Config struct {
func CreateServer(repo repository.Repository, sd systemdefaults.SystemDefaults) *Server {
return &Server{
project: repo,
policy: repo,
org: repo,
user: repo,
usergrant: repo,

View File

@@ -3,7 +3,6 @@ package management
import (
"context"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/golang/protobuf/ptypes/empty"
)
@@ -91,7 +90,8 @@ func (s *Server) UnlockUser(ctx context.Context, in *management.UserID) (*manage
}
func (s *Server) DeleteUser(ctx context.Context, in *management.UserID) (*empty.Empty, error) {
return nil, errors.ThrowUnimplemented(nil, "GRPC-as4fg", "Not implemented")
err := s.user.RemoveUser(ctx, in.Id)
return &empty.Empty{}, err
}
func (s *Server) UpdateUserMachine(ctx context.Context, in *management.UpdateMachineRequest) (*management.MachineResponse, error) {

View File

@@ -135,7 +135,7 @@ func userGrantViewFromModel(grant *grant_model.UserGrantView) *management.UserGr
Email: grant.Email,
ProjectName: grant.ProjectName,
OrgName: grant.OrgName,
OrgDomain: grant.OrgDomain,
OrgDomain: grant.OrgPrimaryDomain,
RoleKeys: grant.RoleKeys,
UserId: grant.UserID,
ProjectId: grant.ProjectID,

View File

@@ -0,0 +1,11 @@
package grpc
const (
Healthz = "/Healthz"
Readiness = "/Ready"
Validation = "/Validate"
)
var (
Probes = []string{Healthz, Readiness, Validation}
)

View File

@@ -10,6 +10,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
grpc_util "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/tracing"
)
func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor {
@@ -18,9 +19,13 @@ func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Co
}
}
func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier *authz.TokenVerifier, authConfig authz.Config) (interface{}, error) {
func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier *authz.TokenVerifier, authConfig authz.Config) (_ interface{}, err error) {
ctx, span := tracing.NewServerInterceptorSpan(ctx)
defer func() { span.EndWithError(err) }()
authOpt, needsToken := verifier.CheckAuthMethod(info.FullMethod)
if !needsToken {
span.End()
return handler(ctx, req)
}
@@ -31,10 +36,10 @@ func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
orgID := grpc_util.GetHeader(ctx, http.ZitadelOrgID)
ctx, err := authz.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt, info.FullMethod)
ctx, err = authz.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt, info.FullMethod)
if err != nil {
return nil, err
}
span.End()
return handler(ctx, req)
}

View File

@@ -9,7 +9,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/stats"
"github.com/caos/zitadel/internal/api/http"
grpc_utils "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/tracing"
)
@@ -30,7 +30,7 @@ func TracingStatsServer(ignoredMethods ...GRPCMethod) grpc.ServerOption {
}
func DefaultTracingStatsServer() grpc.ServerOption {
return TracingStatsServer(http.Healthz, http.Readiness, http.Validation)
return TracingStatsServer(grpc_utils.Healthz, grpc_utils.Readiness, grpc_utils.Validation)
}
type tracingServerHandler struct {

View File

@@ -27,7 +27,7 @@ type Server interface {
func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang language.Tag) *grpc.Server {
return grpc.NewServer(
middleware.TracingStatsServer(http.Healthz, http.Readiness, http.Validation),
middleware.DefaultTracingStatsServer(),
grpc.UnaryInterceptor(
grpc_middleware.ChainUnaryServer(
middleware.ErrorHandler(),

View File

@@ -7,7 +7,11 @@ import (
"github.com/caos/logging"
)
func MarshalJSON(w http.ResponseWriter, i interface{}) {
func MarshalJSON(w http.ResponseWriter, i interface{}, err error, statusCode int) {
if err != nil {
http.Error(w, err.Error(), statusCode)
return
}
b, err := json.Marshal(i)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)

View File

@@ -10,3 +10,9 @@ import (
func DefaultTraceHandler(handler http.Handler) http.Handler {
return tracing.TraceHandler(handler, http_utils.Probes...)
}
func TraceHandler(ignoredMethods ...string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return tracing.TraceHandler(handler, ignoredMethods...)
}
}

View File

@@ -1,9 +1,9 @@
package http
const (
Healthz = "/Healthz"
Readiness = "/Ready"
Validation = "/Validate"
Healthz = "/healthz"
Readiness = "/ready"
Validation = "/validate"
)
var (

View File

@@ -3,6 +3,7 @@ package oidc
import (
"context"
"fmt"
"strings"
"time"
"github.com/caos/oidc/pkg/oidc"
@@ -11,14 +12,26 @@ import (
"github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/errors"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/tracing"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
)
func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest, userID string) (op.AuthRequest, error) {
func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest, userID string) (_ op.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sd436", "no user agent id")
}
app, err := o.repo.ApplicationByClientID(ctx, req.ClientID)
if err != nil {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-AEG4d", "Errors.Internal")
}
req.Scopes, err = o.assertProjectRoleScopes(app, req.Scopes)
if err != nil {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-Gqrfg", "Errors.Internal")
}
authRequest := CreateAuthRequestToBusiness(ctx, req, userAgentID, userID)
resp, err := o.repo.CreateAuthRequest(ctx, authRequest)
if err != nil {
@@ -27,7 +40,9 @@ func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest
return AuthRequestFromBusiness(resp)
}
func (o *OPStorage) AuthRequestByID(ctx context.Context, id string) (op.AuthRequest, error) {
func (o *OPStorage) AuthRequestByID(ctx context.Context, id string) (_ op.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-D3g21", "no user agent id")
@@ -39,7 +54,9 @@ func (o *OPStorage) AuthRequestByID(ctx context.Context, id string) (op.AuthRequ
return AuthRequestFromBusiness(resp)
}
func (o *OPStorage) AuthRequestByCode(ctx context.Context, code string) (op.AuthRequest, error) {
func (o *OPStorage) AuthRequestByCode(ctx context.Context, code string) (_ op.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
resp, err := o.repo.AuthRequestByCode(ctx, code)
if err != nil {
return nil, err
@@ -47,7 +64,9 @@ func (o *OPStorage) AuthRequestByCode(ctx context.Context, code string) (op.Auth
return AuthRequestFromBusiness(resp)
}
func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) error {
func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return errors.ThrowPreconditionFailed(nil, "OIDC-Dgus2", "no user agent id")
@@ -55,11 +74,15 @@ func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) error {
return o.repo.SaveAuthCode(ctx, id, code, userAgentID)
}
func (o *OPStorage) DeleteAuthRequest(ctx context.Context, id string) error {
func (o *OPStorage) DeleteAuthRequest(ctx context.Context, id string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return o.repo.DeleteAuthRequest(ctx, id)
}
func (o *OPStorage) CreateToken(ctx context.Context, req op.TokenRequest) (string, time.Time, error) {
func (o *OPStorage) CreateToken(ctx context.Context, req op.TokenRequest) (_ string, _ time.Time, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
var userAgentID, applicationID string
authReq, ok := req.(*AuthRequest)
if ok {
@@ -70,7 +93,7 @@ func (o *OPStorage) CreateToken(ctx context.Context, req op.TokenRequest) (strin
if err != nil {
return "", time.Time{}, err
}
return resp.ID, resp.Expiration, nil
return resp.TokenID, resp.Expiration, nil
}
func grantsToScopes(grants []*grant_model.UserGrantView) []string {
@@ -83,7 +106,9 @@ func grantsToScopes(grants []*grant_model.UserGrantView) []string {
return scopes
}
func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID string) error {
func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
userAgentID, ok := middleware.UserAgentIDFromCtx(ctx)
if !ok {
return errors.ThrowPreconditionFailed(nil, "OIDC-fso7F", "no user agent id")
@@ -95,10 +120,31 @@ func (o *OPStorage) GetSigningKey(ctx context.Context, keyCh chan<- jose.Signing
o.repo.GetSigningKey(ctx, keyCh, errCh, timer)
}
func (o *OPStorage) GetKeySet(ctx context.Context) (*jose.JSONWebKeySet, error) {
func (o *OPStorage) GetKeySet(ctx context.Context) (_ *jose.JSONWebKeySet, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return o.repo.GetKeySet(ctx)
}
func (o *OPStorage) SaveNewKeyPair(ctx context.Context) error {
return o.repo.GenerateSigningKeyPair(ctx, o.signingKeyAlgorithm)
}
func (o *OPStorage) assertProjectRoleScopes(app *proj_model.ApplicationView, scopes []string) ([]string, error) {
if !app.ProjectRoleAssertion {
return scopes, nil
}
for _, scope := range scopes {
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
return scopes, nil
}
}
roles, err := o.repo.ProjectRolesByProjectID(app.ProjectID)
if err != nil {
return nil, err
}
for _, role := range roles {
scopes = append(scopes, ScopeProjectRolePrefix+role.Key)
}
return scopes, nil
}

View File

@@ -2,6 +2,7 @@ package oidc
import (
"context"
"strings"
"golang.org/x/text/language"
"gopkg.in/square/go-jose.v2"
@@ -14,7 +15,9 @@ import (
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
)
const (
@@ -24,10 +27,15 @@ const (
scopePhone = "phone"
scopeAddress = "address"
ScopeProjectRolePrefix = "urn:zitadel:iam:org:project:role:"
ClaimProjectRoles = "urn:zitadel:iam:org:project:roles"
oidcCtx = "oidc"
)
func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (op.Client, error) {
func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (_ op.Client, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
client, err := o.repo.ApplicationByClientID(ctx, id)
if err != nil {
return nil, err
@@ -35,10 +43,20 @@ func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (op.Clie
if client.State != proj_model.AppStateActive {
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sdaGg", "client is not active")
}
return ClientFromBusiness(client, o.defaultLoginURL, o.defaultAccessTokenLifetime, o.defaultIdTokenLifetime)
projectRoles, err := o.repo.ProjectRolesByProjectID(client.ProjectID)
if err != nil {
return nil, err
}
allowedScopes := make([]string, len(projectRoles))
for i, role := range projectRoles {
allowedScopes[i] = ScopeProjectRolePrefix + role.Key
}
return ClientFromBusiness(client, o.defaultLoginURL, o.defaultAccessTokenLifetime, o.defaultIdTokenLifetime, allowedScopes)
}
func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (*jose.JSONWebKey, error) {
func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (_ *jose.JSONWebKey, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
key, err := o.repo.MachineKeyByID(ctx, keyID)
if err != nil {
return nil, err
@@ -57,7 +75,9 @@ func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID strin
}, nil
}
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) error {
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
ctx = authz.SetCtxData(ctx, authz.CtxData{
UserID: oidcCtx,
OrgID: oidcCtx,
@@ -65,10 +85,12 @@ func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secr
return o.repo.AuthorizeOIDCApplication(ctx, id, secret)
}
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, origin string) (*oidc.Userinfo, error) {
token, err := o.repo.TokenByID(ctx, tokenID)
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, subject, origin string) (_ oidc.UserInfo, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
token, err := o.repo.TokenByID(ctx, subject, tokenID)
if err != nil {
return nil, err
return nil, errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
}
if token.ApplicationID != "" {
app, err := o.repo.ApplicationByClientID(ctx, token.ApplicationID)
@@ -79,65 +101,128 @@ func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, origin st
return nil, errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
}
}
return o.GetUserinfoFromScopes(ctx, token.UserID, token.Scopes)
return o.GetUserinfoFromScopes(ctx, token.UserID, token.ApplicationID, token.Scopes)
}
func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, scopes []string) (*oidc.Userinfo, error) {
func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID, applicationID string, scopes []string) (_ oidc.UserInfo, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
user, err := o.repo.UserByID(ctx, userID)
if err != nil {
return nil, err
}
userInfo := new(oidc.Userinfo)
userInfo := oidc.NewUserInfo()
roles := make([]string, 0)
for _, scope := range scopes {
switch scope {
case scopeOpenID:
userInfo.Subject = user.ID
case scopeEmail:
case oidc.ScopeOpenID:
userInfo.SetSubject(user.ID)
case oidc.ScopeEmail:
if user.HumanView == nil {
continue
}
userInfo.Email = user.Email
userInfo.EmailVerified = user.IsEmailVerified
case scopeProfile:
userInfo.PreferredUsername = user.PreferredLoginName
userInfo.UpdatedAt = user.ChangeDate
userInfo.SetEmail(user.Email, user.IsEmailVerified)
case oidc.ScopeProfile:
userInfo.SetPreferredUsername(user.PreferredLoginName)
userInfo.SetUpdatedAt(user.ChangeDate)
if user.HumanView != nil {
userInfo.Name = user.DisplayName
userInfo.FamilyName = user.LastName
userInfo.GivenName = user.FirstName
userInfo.Nickname = user.NickName
userInfo.Gender = oidc.Gender(getGender(user.Gender))
userInfo.Locale, err = language.Parse(user.PreferredLanguage)
userInfo.SetName(user.DisplayName)
userInfo.SetFamilyName(user.LastName)
userInfo.SetGivenName(user.FirstName)
userInfo.SetNickname(user.NickName)
userInfo.SetGender(oidc.Gender(getGender(user.Gender)))
locale, _ := language.Parse(user.PreferredLanguage)
userInfo.SetLocale(locale)
} else {
userInfo.Name = user.MachineView.Name
userInfo.SetName(user.MachineView.Name)
}
case scopePhone:
case oidc.ScopePhone:
if user.HumanView == nil {
continue
}
userInfo.PhoneNumber = user.Phone
userInfo.PhoneNumberVerified = user.IsPhoneVerified
case scopeAddress:
userInfo.SetPhone(user.Phone, user.IsPhoneVerified)
case oidc.ScopeAddress:
if user.HumanView == nil {
continue
}
if user.StreetAddress == "" && user.Locality == "" && user.Region == "" && user.PostalCode == "" && user.Country == "" {
continue
}
userInfo.Address = &oidc.UserinfoAddress{
StreetAddress: user.StreetAddress,
Locality: user.Locality,
Region: user.Region,
PostalCode: user.PostalCode,
Country: user.Country,
}
userInfo.SetAddress(oidc.NewUserInfoAddress(user.StreetAddress, user.Locality, user.Region, user.PostalCode, user.Country, ""))
default:
userInfo.Authorizations = append(userInfo.Authorizations, scope)
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
roles = append(roles, strings.TrimPrefix(scope, ScopeProjectRolePrefix))
}
}
}
if len(roles) == 0 || applicationID == "" {
return userInfo, nil
}
projectRoles, err := o.assertRoles(ctx, userID, applicationID, roles)
if err != nil {
return nil, err
}
if len(projectRoles) > 0 {
userInfo.AppendClaims(ClaimProjectRoles, projectRoles)
}
return userInfo, nil
}
func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, applicationID string, scopes []string) (claims map[string]interface{}, err error) {
roles := make([]string, 0)
for _, scope := range scopes {
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
roles = append(roles, strings.TrimPrefix(scope, ScopeProjectRolePrefix))
}
}
if len(roles) == 0 || applicationID == "" {
return nil, nil
}
projectRoles, err := o.assertRoles(ctx, userID, applicationID, roles)
if err != nil {
return nil, err
}
if len(projectRoles) > 0 {
claims = map[string]interface{}{ClaimProjectRoles: projectRoles}
}
return claims, err
}
func (o *OPStorage) assertRoles(ctx context.Context, userID, applicationID string, requestedRoles []string) (map[string]map[string]string, error) {
app, err := o.repo.ApplicationByClientID(ctx, applicationID)
if err != nil {
return nil, err
}
grants, err := o.repo.UserGrantsByProjectAndUserID(app.ProjectID, userID)
if err != nil {
return nil, err
}
projectRoles := make(map[string]map[string]string)
for _, requestedRole := range requestedRoles {
for _, grant := range grants {
checkGrantedRoles(projectRoles, grant, requestedRole)
}
}
return projectRoles, nil
}
func checkGrantedRoles(roles map[string]map[string]string, grant *grant_model.UserGrantView, requestedRole string) {
for _, grantedRole := range grant.RoleKeys {
if requestedRole == grantedRole {
appendRole(roles, grantedRole, grant.ResourceOwner, grant.OrgPrimaryDomain)
}
}
}
func appendRole(roles map[string]map[string]string, role, orgID, orgPrimaryDomain string) {
if roles[role] == nil {
roles[role] = make(map[string]string, 0)
}
roles[role][orgID] = orgPrimaryDomain
}
func getGender(gender user_model.Gender) string {
switch gender {
case user_model.GenderFemale:

View File

@@ -1,9 +1,9 @@
package oidc
import (
"github.com/caos/oidc/pkg/oidc"
"time"
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/pkg/op"
"github.com/caos/zitadel/internal/errors"
@@ -15,13 +15,20 @@ type Client struct {
defaultLoginURL string
defaultAccessTokenLifetime time.Duration
defaultIdTokenLifetime time.Duration
allowedScopes []string
}
func ClientFromBusiness(app *model.ApplicationView, defaultLoginURL string, defaultAccessTokenLifetime, defaultIdTokenLifetime time.Duration) (op.Client, error) {
func ClientFromBusiness(app *model.ApplicationView, defaultLoginURL string, defaultAccessTokenLifetime, defaultIdTokenLifetime time.Duration, allowedScopes []string) (op.Client, error) {
if !app.IsOIDC {
return nil, errors.ThrowInvalidArgument(nil, "OIDC-d5bhD", "client is not a proper oidc application")
}
return &Client{ApplicationView: app, defaultLoginURL: defaultLoginURL, defaultAccessTokenLifetime: defaultAccessTokenLifetime, defaultIdTokenLifetime: defaultIdTokenLifetime}, nil
return &Client{
ApplicationView: app,
defaultLoginURL: defaultLoginURL,
defaultAccessTokenLifetime: defaultAccessTokenLifetime,
defaultIdTokenLifetime: defaultIdTokenLifetime,
allowedScopes: allowedScopes},
nil
}
func (c *Client) ApplicationType() op.ApplicationType {
@@ -56,6 +63,18 @@ func (c *Client) DevMode() bool {
return c.ApplicationView.DevMode
}
func (c *Client) AllowedScopes() []string {
return c.allowedScopes
}
func (c *Client) AssertAdditionalIdTokenScopes() bool {
return c.IDTokenRoleAssertion
}
func (c *Client) AssertAdditionalAccessTokenScopes() bool {
return c.AccessTokenRoleAssertion
}
func (c *Client) AccessTokenLifetime() time.Duration {
return c.defaultAccessTokenLifetime //PLANNED: impl from real client
}
@@ -65,7 +84,18 @@ func (c *Client) IDTokenLifetime() time.Duration {
}
func (c *Client) AccessTokenType() op.AccessTokenType {
return op.AccessTokenTypeBearer //PLANNED: impl from real client
return accessTokenTypeToOIDC(c.ApplicationView.AccessTokenType)
}
func accessTokenTypeToOIDC(tokenType model.OIDCTokenType) op.AccessTokenType {
switch tokenType {
case model.OIDCTokenTypeBearer:
return op.AccessTokenTypeBearer
case model.OIDCTokenTypeJWT:
return op.AccessTokenTypeJWT
default:
return op.AccessTokenTypeBearer
}
}
func authMethodToOIDC(authType model.OIDCAuthMethodType) op.AuthMethod {

View File

@@ -59,6 +59,7 @@ func NewProvider(ctx context.Context, config OPHandlerConfig, repo repository.Re
config.OPConfig,
newStorage(config.StorageConfig, repo),
op.WithHttpInterceptors(
middleware.TraceHandler(),
middleware.NoCacheInterceptor,
cookieHandler,
http_utils.CopyHeadersToContext,

View File

@@ -16,11 +16,13 @@ type AuthRequestRepository interface {
SaveAuthCode(ctx context.Context, id, code, userAgentID string) error
DeleteAuthRequest(ctx context.Context, id string) error
CheckLoginName(ctx context.Context, id, loginName, userAgentID string) error
CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *model.ExternalUser) error
CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *model.ExternalUser, info *model.BrowserInfo) error
SelectUser(ctx context.Context, id, userID, userAgentID string) error
SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) error
VerifyPassword(ctx context.Context, id, userID, password, userAgentID string, info *model.BrowserInfo) error
VerifyMfaOTP(ctx context.Context, agentID, authRequestID, code, userAgentID string, info *model.BrowserInfo) error
LinkExternalUsers(ctx context.Context, authReqID, userAgentID string) error
AutoRegisterExternalUser(ctx context.Context, user *user_model.User, externalIDP *user_model.ExternalIDP, member *org_model.OrgMember, authReqID, userAgentID, resourceOwner string) error
LinkExternalUsers(ctx context.Context, authReqID, userAgentID string, info *model.BrowserInfo) error
AutoRegisterExternalUser(ctx context.Context, user *user_model.User, externalIDP *user_model.ExternalIDP, member *org_model.OrgMember, authReqID, userAgentID, resourceOwner string, info *model.BrowserInfo) error
ResetLinkingUsers(ctx context.Context, authReqID, userAgentID string) error
GetOrgByPrimaryDomain(primaryDomain string) (*org_model.OrgView, error)
}

View File

@@ -2,35 +2,36 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/api/authz"
"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/view/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
"time"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/auth_request/model"
cache "github.com/caos/zitadel/internal/auth_request/repository"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"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/view/model"
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/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"
)
type AuthRequestRepo struct {
UserEvents *user_event.UserEventstore
OrgEvents *org_event.OrgEventstore
PolicyEvents *policy_event.PolicyEventstore
AuthRequests cache.AuthRequestCache
View *view.View
@@ -40,13 +41,15 @@ type AuthRequestRepo struct {
OrgViewProvider orgViewProvider
LoginPolicyViewProvider loginPolicyViewProvider
IDPProviderViewProvider idpProviderViewProvider
UserGrantProvider userGrantProvider
IdGenerator id.Generator
PasswordCheckLifeTime time.Duration
MfaInitSkippedLifeTime time.Duration
MfaSoftwareCheckLifeTime time.Duration
MfaHardwareCheckLifeTime time.Duration
PasswordCheckLifeTime time.Duration
ExternalLoginCheckLifeTime time.Duration
MfaInitSkippedLifeTime time.Duration
MfaSoftwareCheckLifeTime time.Duration
MfaHardwareCheckLifeTime time.Duration
IAMID string
}
@@ -74,6 +77,12 @@ type userEventProvider interface {
type orgViewProvider interface {
OrgByID(string) (*org_view_model.OrgView, error)
OrgByPrimaryDomain(string) (*org_view_model.OrgView, error)
}
type userGrantProvider interface {
ApplicationByClientID(context.Context, string) (*project_view_model.ApplicationView, error)
UserGrantsByProjectAndUserID(string, string) ([]*grant_view_model.UserGrantView, error)
}
func (repo *AuthRequestRepo) Health(ctx context.Context) error {
@@ -83,20 +92,26 @@ func (repo *AuthRequestRepo) Health(ctx context.Context) error {
return repo.AuthRequests.Health(ctx)
}
func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *model.AuthRequest) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *model.AuthRequest) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
reqID, err := repo.IdGenerator.Next()
if err != nil {
return nil, err
}
request.ID = reqID
ids, err := repo.View.AppIDsFromProjectByClientID(ctx, request.ApplicationID)
app, err := repo.View.ApplicationByClientID(ctx, request.ApplicationID)
if err != nil {
return nil, err
}
request.Audience = ids
appIDs, err := repo.View.AppIDsFromProjectID(ctx, app.ProjectID)
if err != nil {
return nil, err
}
request.Audience = appIDs
if request.LoginHint != "" {
err = repo.checkLoginName(ctx, request, request.LoginHint)
logging.LogWithFields("EVENT-aG311", "login name", request.LoginHint, "id", request.ID, "applicationID", request.ApplicationID).Debug("login hint invalid")
logging.LogWithFields("EVENT-aG311", "login name", request.LoginHint, "id", request.ID, "applicationID", request.ApplicationID).OnError(err).Debug("login hint invalid")
}
err = repo.AuthRequests.SaveAuthRequest(ctx, request)
if err != nil {
@@ -105,15 +120,21 @@ func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *mod
return request, nil
}
func (repo *AuthRequestRepo) AuthRequestByID(ctx context.Context, id, userAgentID string) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) AuthRequestByID(ctx context.Context, id, userAgentID string) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return repo.getAuthRequestNextSteps(ctx, id, userAgentID, false)
}
func (repo *AuthRequestRepo) AuthRequestByIDCheckLoggedIn(ctx context.Context, id, userAgentID string) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) AuthRequestByIDCheckLoggedIn(ctx context.Context, id, userAgentID string) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return repo.getAuthRequestNextSteps(ctx, id, userAgentID, true)
}
func (repo *AuthRequestRepo) SaveAuthCode(ctx context.Context, id, code, userAgentID string) error {
func (repo *AuthRequestRepo) SaveAuthCode(ctx context.Context, id, code, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@@ -122,7 +143,9 @@ func (repo *AuthRequestRepo) SaveAuthCode(ctx context.Context, id, code, userAge
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) AuthRequestByCode(ctx context.Context, code string) (*model.AuthRequest, error) {
func (repo *AuthRequestRepo) AuthRequestByCode(ctx context.Context, code string) (_ *model.AuthRequest, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.AuthRequests.GetAuthRequestByCode(ctx, code)
if err != nil {
return nil, err
@@ -135,11 +158,15 @@ func (repo *AuthRequestRepo) AuthRequestByCode(ctx context.Context, code string)
return request, nil
}
func (repo *AuthRequestRepo) DeleteAuthRequest(ctx context.Context, id string) error {
func (repo *AuthRequestRepo) DeleteAuthRequest(ctx context.Context, id string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return repo.AuthRequests.DeleteAuthRequest(ctx, id)
}
func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName, userAgentID string) error {
func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@@ -151,7 +178,9 @@ func (repo *AuthRequestRepo) CheckLoginName(ctx context.Context, id, loginName,
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) error {
func (repo *AuthRequestRepo) SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
@@ -163,18 +192,28 @@ func (repo *AuthRequestRepo) SelectExternalIDP(ctx context.Context, authReqID, i
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, externalUser *model.ExternalUser) error {
func (repo *AuthRequestRepo) CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, externalUser *model.ExternalUser, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
}
err = repo.checkExternalUserLogin(request, externalUser.IDPConfigID, externalUser.ExternalUserID)
if errors.IsNotFound(err) {
return repo.setLinkingUser(ctx, request, externalUser)
if err := repo.setLinkingUser(ctx, request, externalUser); err != nil {
return err
}
return err
}
if err != nil {
return err
}
err = repo.UserEvents.ExternalLoginChecked(ctx, request.UserID, request.WithCurrentInfo(info))
if err != nil {
return err
}
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
@@ -183,7 +222,9 @@ func (repo *AuthRequestRepo) setLinkingUser(ctx context.Context, request *model.
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAgentID string) error {
func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAgentID string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@@ -196,7 +237,9 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAge
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) VerifyPassword(ctx context.Context, id, userID, password, userAgentID string, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) VerifyPassword(ctx context.Context, id, userID, password, userAgentID string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, id, userAgentID)
if err != nil {
return err
@@ -207,7 +250,9 @@ func (repo *AuthRequestRepo) VerifyPassword(ctx context.Context, id, userID, pas
return repo.UserEvents.CheckPassword(ctx, userID, password, request.WithCurrentInfo(info))
}
func (repo *AuthRequestRepo) VerifyMfaOTP(ctx context.Context, authRequestID, userID, code, userAgentID string, info *model.BrowserInfo) error {
func (repo *AuthRequestRepo) VerifyMfaOTP(ctx context.Context, authRequestID, userID, code, userAgentID string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authRequestID, userAgentID)
if err != nil {
return err
@@ -218,7 +263,9 @@ func (repo *AuthRequestRepo) VerifyMfaOTP(ctx context.Context, authRequestID, us
return repo.UserEvents.CheckMfaOTP(ctx, userID, code, request.WithCurrentInfo(info))
}
func (repo *AuthRequestRepo) LinkExternalUsers(ctx context.Context, authReqID, userAgentID string) error {
func (repo *AuthRequestRepo) LinkExternalUsers(ctx context.Context, authReqID, userAgentID string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
@@ -227,11 +274,27 @@ func (repo *AuthRequestRepo) LinkExternalUsers(ctx context.Context, authReqID, u
if err != nil {
return err
}
err = repo.UserEvents.ExternalLoginChecked(ctx, request.UserID, request.WithCurrentInfo(info))
if err != nil {
return err
}
request.LinkingUsers = nil
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, registerUser *user_model.User, externalIDP *user_model.ExternalIDP, orgMember *org_model.OrgMember, authReqID, userAgentID, resourceOwner string) error {
func (repo *AuthRequestRepo) ResetLinkingUsers(ctx context.Context, authReqID, userAgentID string) error {
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
}
request.LinkingUsers = nil
request.SelectedIDPConfigID = ""
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, registerUser *user_model.User, externalIDP *user_model.ExternalIDP, orgMember *org_model.OrgMember, authReqID, userAgentID, resourceOwner string, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequest(ctx, authReqID, userAgentID)
if err != nil {
return err
@@ -240,15 +303,23 @@ func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, regis
if resourceOwner != "" {
policyResourceOwner = resourceOwner
}
pwPolicy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, policyResourceOwner)
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(policyResourceOwner)
if errors.IsNotFound(err) {
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.IAMID)
}
if err != nil {
return err
}
orgPolicy, err := repo.OrgEvents.GetOrgIAMPolicy(ctx, policyResourceOwner)
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(pwPolicy)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(policyResourceOwner)
if errors.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.IAMID)
}
if err != nil {
return err
}
user, aggregates, err := repo.UserEvents.PrepareRegisterUser(ctx, registerUser, externalIDP, pwPolicy, orgPolicy, resourceOwner)
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
user, aggregates, err := repo.UserEvents.PrepareRegisterUser(ctx, registerUser, externalIDP, pwPolicyView, orgPolicyView, resourceOwner)
if err != nil {
return err
}
@@ -266,8 +337,13 @@ func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, regis
return err
}
request.UserID = user.AggregateID
request.UserOrgID = user.ResourceOwner
request.SelectedIDPConfigID = externalIDP.IDPConfigID
request.LinkingUsers = nil
err = repo.UserEvents.ExternalLoginChecked(ctx, request.UserID, request.WithCurrentInfo(info))
if err != nil {
return err
}
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
@@ -317,7 +393,14 @@ func (repo *AuthRequestRepo) getLoginPolicyAndIDPProviders(ctx context.Context,
func (repo *AuthRequestRepo) fillLoginPolicy(ctx context.Context, request *model.AuthRequest) error {
orgID := request.UserOrgID
if orgID == "" {
orgID = request.GetScopeOrgID()
primaryDomain := request.GetScopeOrgPrimaryDomain()
if primaryDomain != "" {
org, err := repo.GetOrgByPrimaryDomain(primaryDomain)
if err != nil {
return err
}
orgID = org.ID
}
}
if orgID == "" {
orgID = repo.IAMID
@@ -335,7 +418,16 @@ func (repo *AuthRequestRepo) fillLoginPolicy(ctx context.Context, request *model
}
func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *model.AuthRequest, loginName string) (err error) {
orgID := request.GetScopeOrgID()
primaryDomain := request.GetScopeOrgPrimaryDomain()
orgID := ""
if primaryDomain != "" {
org, err := repo.GetOrgByPrimaryDomain(primaryDomain)
if err != nil {
return err
}
orgID = org.ID
}
user := new(user_view_model.UserView)
if orgID != "" {
user, err = repo.View.UserByLoginNameAndResourceOwner(loginName, orgID)
@@ -356,6 +448,14 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *model.
return nil
}
func (repo AuthRequestRepo) GetOrgByPrimaryDomain(primaryDomain string) (*org_model.OrgView, error) {
org, err := repo.OrgViewProvider.OrgByPrimaryDomain(primaryDomain)
if err != nil {
return nil, err
}
return org_view_model.OrgToModel(org), nil
}
func (repo AuthRequestRepo) checkLoginPolicyWithResourceOwner(ctx context.Context, request *model.AuthRequest, user *user_view_model.UserView) error {
loginPolicy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, user.ResourceOwner)
if err != nil {
@@ -386,10 +486,15 @@ func (repo *AuthRequestRepo) checkSelectedExternalIDP(request *model.AuthRequest
}
func (repo *AuthRequestRepo) checkExternalUserLogin(request *model.AuthRequest, idpConfigID, externalUserID string) (err error) {
orgID := request.GetScopeOrgID()
primaryDomain := request.GetScopeOrgPrimaryDomain()
externalIDP := new(user_view_model.ExternalIDPView)
if orgID != "" {
externalIDP, err = repo.View.ExternalIDPByExternalUserIDAndIDPConfigIDAndResourceOwner(externalUserID, idpConfigID, orgID)
org := new(org_model.OrgView)
if primaryDomain != "" {
org, err = repo.GetOrgByPrimaryDomain(primaryDomain)
if err != nil {
return err
}
externalIDP, err = repo.View.ExternalIDPByExternalUserIDAndIDPConfigIDAndResourceOwner(externalUserID, idpConfigID, org.ID)
} else {
externalIDP, err = repo.View.ExternalIDPByExternalUserIDAndIDPConfigID(externalUserID, idpConfigID)
}
@@ -435,7 +540,11 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *model.AuthR
return nil, err
}
if request.SelectedIDPConfigID == "" {
if (request.SelectedIDPConfigID != "" || userSession.SelectedIDPConfigID != "") && (request.LinkingUsers == nil || len(request.LinkingUsers) == 0) {
if !checkVerificationTime(userSession.ExternalLoginVerification, repo.ExternalLoginCheckLifeTime) {
return append(steps, &model.ExternalLoginStep{}), nil
}
} else if (request.SelectedIDPConfigID == "" && userSession.SelectedIDPConfigID == "") || (request.SelectedIDPConfigID != "" && request.LinkingUsers != nil && len(request.LinkingUsers) > 0) {
if user.InitRequired {
return append(steps, &model.InitUserStep{PasswordSet: user.PasswordSet}), nil
}
@@ -473,6 +582,15 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *model.AuthR
}
//PLANNED: consent step
missing, err := userGrantRequired(ctx, request, user, repo.UserGrantProvider)
if err != nil {
return nil, err
}
if missing {
return append(steps, &model.GrantRequiredStep{}), nil
}
return append(steps, &model.RedirectToCallbackStep{}), nil
}
@@ -603,6 +721,7 @@ func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eve
es_model.UserDeactivated,
es_model.HumanPasswordCheckSucceeded,
es_model.HumanPasswordCheckFailed,
es_model.HumanExternalLoginCheckSucceeded,
es_model.HumanMFAOTPCheckSucceeded,
es_model.HumanMFAOTPCheckFailed,
es_model.HumanSignedOut:
@@ -649,21 +768,32 @@ func activeUserByID(ctx context.Context, userViewProvider userViewProvider, user
}
func userByID(ctx context.Context, viewProvider userViewProvider, eventProvider userEventProvider, userID string) (*user_model.UserView, error) {
user, err := viewProvider.UserByID(userID)
if err != nil {
return nil, err
user, viewErr := viewProvider.UserByID(userID)
if viewErr != nil && !errors.IsNotFound(viewErr) {
return nil, viewErr
} else if user == nil {
user = new(user_view_model.UserView)
}
events, err := eventProvider.UserEventsByID(ctx, userID, user.Sequence)
if err != nil {
logging.Log("EVENT-dfg42").WithError(err).Debug("error retrieving new events")
return user_view_model.UserToModel(user), nil
}
if len(events) == 0 {
if viewErr != nil {
return nil, viewErr
}
return user_view_model.UserToModel(user), viewErr
}
userCopy := *user
for _, event := range events {
if err := userCopy.AppendEvent(event); err != nil {
return user_view_model.UserToModel(user), nil
}
}
if userCopy.State == int32(user_model.UserStateDeleted) {
return nil, errors.ThrowNotFound(nil, "EVENT-3F9so", "Errors.User.NotFound")
}
return user_view_model.UserToModel(&userCopy), nil
}
@@ -700,3 +830,23 @@ func linkingIDPConfigExistingInAllowedIDPs(linkingUsers []*model.ExternalUser, i
}
return true
}
func userGrantRequired(ctx context.Context, request *model.AuthRequest, user *user_model.UserView, userGrantProvider userGrantProvider) (_ bool, err error) {
var app *project_view_model.ApplicationView
switch request.Request.Type() {
case model.AuthRequestTypeOIDC:
app, err = userGrantProvider.ApplicationByClientID(ctx, request.ApplicationID)
if err != nil {
return false, err
}
default:
return false, errors.ThrowPreconditionFailed(nil, "EVENT-dfrw2", "Errors.AuthRequest.RequestTypeNotSupported")
}
if !app.ProjectRoleCheck {
return false, nil
}
grants, err := userGrantProvider.UserGrantsByProjectAndUserID(app.ProjectID, user.ID)
if err != nil {
return false, err
}
return len(grants) == 0, nil
}

View File

@@ -15,10 +15,12 @@ import (
es_models "github.com/caos/zitadel/internal/eventstore/models"
org_model "github.com/caos/zitadel/internal/org/model"
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"
)
type mockViewNoUserSession struct{}
@@ -42,9 +44,10 @@ func (m *mockViewErrUserSession) UserSessionsByAgentID(string) ([]*user_view_mod
}
type mockViewUserSession struct {
PasswordVerification time.Time
MfaSoftwareVerification time.Time
Users []mockUser
ExternalLoginVerification time.Time
PasswordVerification time.Time
MfaSoftwareVerification time.Time
Users []mockUser
}
type mockUser struct {
@@ -54,8 +57,9 @@ type mockUser struct {
func (m *mockViewUserSession) UserSessionByIDs(string, string) (*user_view_model.UserSessionView, error) {
return &user_view_model.UserSessionView{
PasswordVerification: m.PasswordVerification,
MfaSoftwareVerification: m.MfaSoftwareVerification,
ExternalLoginVerification: m.ExternalLoginVerification,
PasswordVerification: m.PasswordVerification,
MfaSoftwareVerification: m.MfaSoftwareVerification,
}, nil
}
@@ -139,25 +143,54 @@ func (m *mockViewOrg) OrgByID(string) (*org_view_model.OrgView, error) {
}, nil
}
func (m *mockViewOrg) OrgByPrimaryDomain(string) (*org_view_model.OrgView, error) {
return &org_view_model.OrgView{
State: int32(m.State),
}, nil
}
type mockViewErrOrg struct{}
func (m *mockViewErrOrg) OrgByID(string) (*org_view_model.OrgView, error) {
return nil, errors.ThrowInternal(nil, "id", "internal error")
}
func (m *mockViewErrOrg) OrgByPrimaryDomain(string) (*org_view_model.OrgView, error) {
return nil, errors.ThrowInternal(nil, "id", "internal error")
}
type mockUserGrants struct {
roleCheck bool
userGrants int
}
func (m *mockUserGrants) ApplicationByClientID(ctx context.Context, s string) (*proj_view_model.ApplicationView, error) {
return &proj_view_model.ApplicationView{ProjectRoleCheck: m.roleCheck}, nil
}
func (m *mockUserGrants) UserGrantsByProjectAndUserID(s string, s2 string) ([]*grant_view_model.UserGrantView, error) {
var grants []*grant_view_model.UserGrantView
if m.userGrants > 0 {
grants = make([]*grant_view_model.UserGrantView, m.userGrants)
}
return grants, nil
}
func TestAuthRequestRepo_nextSteps(t *testing.T) {
type fields struct {
UserEvents *user_event.UserEventstore
AuthRequests *cache.AuthRequestCache
View *view.View
userSessionViewProvider userSessionViewProvider
userViewProvider userViewProvider
userEventProvider userEventProvider
orgViewProvider orgViewProvider
PasswordCheckLifeTime time.Duration
MfaInitSkippedLifeTime time.Duration
MfaSoftwareCheckLifeTime time.Duration
MfaHardwareCheckLifeTime time.Duration
UserEvents *user_event.UserEventstore
AuthRequests *cache.AuthRequestCache
View *view.View
userSessionViewProvider userSessionViewProvider
userViewProvider userViewProvider
userEventProvider userEventProvider
orgViewProvider orgViewProvider
userGrantProvider userGrantProvider
PasswordCheckLifeTime time.Duration
ExternalLoginCheckLifeTime time.Duration
MfaInitSkippedLifeTime time.Duration
MfaSoftwareCheckLifeTime time.Duration
MfaHardwareCheckLifeTime time.Duration
}
type args struct {
request *model.AuthRequest
@@ -381,7 +414,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
nil,
},
{
"external user (no password set), callback",
"external user (no external verification), external login step",
fields{
userSessionViewProvider: &mockViewUserSession{
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
@@ -395,6 +428,27 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
[]model.NextStep{&model.ExternalLoginStep{}},
nil,
},
{
"external user (external verification set), callback",
fields{
userSessionViewProvider: &mockViewUserSession{
ExternalLoginVerification: time.Now().UTC().Add(-5 * time.Minute),
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MfaLevelSoftware),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
userGrantProvider: &mockUserGrants{},
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID", Request: &model.AuthRequestOIDC{}}, false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
nil,
},
@@ -417,18 +471,21 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
"external user (no password check needed), callback",
fields{
userSessionViewProvider: &mockViewUserSession{
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
ExternalLoginVerification: time.Now().UTC().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MfaLevelSoftware),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MfaSoftwareCheckLifeTime: 18 * time.Hour,
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
userGrantProvider: &mockUserGrants{},
MfaSoftwareCheckLifeTime: 18 * time.Hour,
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID", Request: &model.AuthRequestOIDC{}}, false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
nil,
},
@@ -458,17 +515,19 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
"external user, mfa not verified, mfa check step",
fields{
userSessionViewProvider: &mockViewUserSession{
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
ExternalLoginVerification: time.Now().UTC().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
PasswordSet: true,
OTPState: int32(user_model.MfaStateReady),
MfaMaxSetUp: int32(model.MfaLevelSoftware),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
[]model.NextStep{&model.MfaVerificationStep{
@@ -553,10 +612,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
userGrantProvider: &mockUserGrants{},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&model.AuthRequest{UserID: "UserID", Request: &model.AuthRequestOIDC{}}, false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
nil,
},
@@ -574,15 +634,66 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
userGrantProvider: &mockUserGrants{},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone}, true},
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone, Request: &model.AuthRequestOIDC{}}, true},
[]model.NextStep{&model.RedirectToCallbackStep{}},
nil,
},
{
"linking users, link users step",
"prompt none, checkLoggedIn true, authenticated and required user grants missing, grant required step",
fields{
userSessionViewProvider: &mockViewUserSession{
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MfaLevelSoftware),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
userGrantProvider: &mockUserGrants{
roleCheck: true,
userGrants: 0,
},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone, Request: &model.AuthRequestOIDC{}}, true},
[]model.NextStep{&model.GrantRequiredStep{}},
nil,
},
{
"prompt none, checkLoggedIn true, authenticated and required user grants exist, redirect to callback step",
fields{
userSessionViewProvider: &mockViewUserSession{
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MfaLevelSoftware),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
userGrantProvider: &mockUserGrants{
roleCheck: true,
userGrants: 2,
},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone, Request: &model.AuthRequestOIDC{}}, true},
[]model.NextStep{&model.RedirectToCallbackStep{}},
nil,
},
{
"linking users, password step",
fields{
userSessionViewProvider: &mockViewUserSession{
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
@@ -596,6 +707,32 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MfaSoftwareCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
UserID: "UserID",
SelectedIDPConfigID: "IDPConfigID",
LinkingUsers: []*model.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
}, false},
[]model.NextStep{&model.PasswordStep{}},
nil,
},
{
"linking users, linking step",
fields{
userSessionViewProvider: &mockViewUserSession{
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MfaLevelSoftware),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MfaSoftwareCheckLifeTime: 18 * time.Hour,
PasswordCheckLifeTime: 10 * 24 * time.Hour,
},
args{
&model.AuthRequest{
UserID: "UserID",
@@ -609,17 +746,19 @@ 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,
UserViewProvider: tt.fields.userViewProvider,
UserEventProvider: tt.fields.userEventProvider,
OrgViewProvider: tt.fields.orgViewProvider,
PasswordCheckLifeTime: tt.fields.PasswordCheckLifeTime,
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
MfaSoftwareCheckLifeTime: tt.fields.MfaSoftwareCheckLifeTime,
MfaHardwareCheckLifeTime: tt.fields.MfaHardwareCheckLifeTime,
UserEvents: tt.fields.UserEvents,
AuthRequests: tt.fields.AuthRequests,
View: tt.fields.View,
UserSessionViewProvider: tt.fields.userSessionViewProvider,
UserViewProvider: tt.fields.userViewProvider,
UserEventProvider: tt.fields.userEventProvider,
OrgViewProvider: tt.fields.orgViewProvider,
UserGrantProvider: tt.fields.userGrantProvider,
PasswordCheckLifeTime: tt.fields.PasswordCheckLifeTime,
ExternalLoginCheckLifeTime: tt.fields.ExternalLoginCheckLifeTime,
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
MfaSoftwareCheckLifeTime: tt.fields.MfaSoftwareCheckLifeTime,
MfaHardwareCheckLifeTime: tt.fields.MfaHardwareCheckLifeTime,
}
got, err := repo.nextSteps(context.Background(), tt.args.request, tt.args.checkLoggedIn)
if (err != nil && tt.wantErr == nil) || (tt.wantErr != nil && !tt.wantErr(err)) {
@@ -988,7 +1127,9 @@ func Test_userByID(t *testing.T) {
{
"not found, not found error",
args{
viewProvider: &mockViewNoUser{},
userID: "userID",
viewProvider: &mockViewNoUser{},
eventProvider: &mockEventUser{},
},
nil,
errors.IsNotFound,

View File

@@ -3,6 +3,9 @@ package eventstore
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
@@ -13,8 +16,6 @@ import (
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"
policy_model "github.com/caos/zitadel/internal/policy/model"
policy_es "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
)
@@ -23,12 +24,12 @@ const (
)
type OrgRepository struct {
SearchLimit uint64
OrgEventstore *org_es.OrgEventstore
UserEventstore *usr_es.UserEventstore
PolicyEventstore *policy_es.PolicyEventstore
SearchLimit uint64
OrgEventstore *org_es.OrgEventstore
UserEventstore *usr_es.UserEventstore
View *auth_view.View
View *auth_view.View
SystemDefaults systemdefaults.SystemDefaults
}
func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error) {
@@ -53,14 +54,16 @@ func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.Or
}
func (repo *OrgRepository) RegisterOrg(ctx context.Context, register *auth_model.RegisterOrg) (*auth_model.RegisterOrg, error) {
pwPolicy, err := repo.PolicyEventstore.GetPasswordComplexityPolicy(ctx, policy_model.DefaultPolicy)
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
orgPolicy, err := repo.OrgEventstore.GetOrgIAMPolicy(ctx, policy_model.DefaultPolicy)
pwPolicyView := iam_view_model.PasswordComplexityViewToModel(pwPolicy)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
orgPolicyView := iam_view_model.OrgIAMViewToModel(orgPolicy)
users := func(ctx context.Context, domain string) ([]*es_models.Aggregate, error) {
userIDs, err := repo.View.UserIDsByDomain(domain)
if err != nil {
@@ -72,7 +75,7 @@ func (repo *OrgRepository) RegisterOrg(ctx context.Context, register *auth_model
if err != nil {
return nil, err
}
user, userAggregates, err := repo.UserEventstore.PrepareRegisterUser(ctx, register.User, nil, pwPolicy, orgPolicy, org.AggregateID)
user, userAggregates, err := repo.UserEventstore.PrepareRegisterUser(ctx, register.User, nil, pwPolicyView, orgPolicyView, org.AggregateID)
if err != nil {
return nil, err
}
@@ -95,12 +98,25 @@ func (repo *OrgRepository) RegisterOrg(ctx context.Context, register *auth_model
return RegisterToModel(registerModel), nil
}
func (repo *OrgRepository) GetDefaultOrgIamPolicy(ctx context.Context) *org_model.OrgIAMPolicy {
return repo.OrgEventstore.GetDefaultOrgIAMPolicy(ctx)
func (repo *OrgRepository) GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
policy := iam_view_model.OrgIAMViewToModel(orgPolicy)
policy.IAMDomain = repo.SystemDefaults.Domain
return policy, err
}
func (repo *OrgRepository) GetOrgIamPolicy(ctx context.Context, orgID string) (*org_model.OrgIAMPolicy, error) {
return repo.OrgEventstore.GetOrgIAMPolicy(ctx, orgID)
func (repo *OrgRepository) GetOrgIAMPolicy(ctx context.Context, orgID string) (*iam_model.OrgIAMPolicyView, error) {
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(orgID)
if errors.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return nil, err
}
return iam_view_model.OrgIAMViewToModel(orgPolicy), nil
}
func (repo *OrgRepository) GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error) {
@@ -110,3 +126,18 @@ func (repo *OrgRepository) GetIDPConfigByID(ctx context.Context, idpConfigID str
}
return iam_view_model.IDPConfigViewToModel(idpConfig), nil
}
func (repo *OrgRepository) GetMyPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) {
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {
return nil, err
}
policy.Default = true
}
if err != nil {
return nil, err
}
return iam_view_model.PasswordComplexityViewToModel(policy), err
}

View File

@@ -1,18 +0,0 @@
package eventstore
import (
"context"
"github.com/caos/zitadel/internal/api/authz"
pol_model "github.com/caos/zitadel/internal/policy/model"
pol_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
)
type PolicyRepo struct {
PolicyEvents *pol_event.PolicyEventstore
}
func (repo *PolicyRepo) GetMyPasswordComplexityPolicy(ctx context.Context) (*pol_model.PasswordComplexityPolicy, error) {
ctxData := authz.GetCtxData(ctx)
return repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, ctxData.OrgID)
}

View File

@@ -0,0 +1,21 @@
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
}
func (a *ApplicationRepo) ProjectRolesByProjectID(projectID string) ([]*model.ProjectRoleView, error) {
roles, err := a.View.ProjectRolesByProjectID(projectID)
if err != nil {
return nil, err
}
return proj_view_model.ProjectRolesToModel(roles), nil
}

View File

@@ -2,38 +2,83 @@ package eventstore
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
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"
"time"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
token_model "github.com/caos/zitadel/internal/token/model"
token_view_model "github.com/caos/zitadel/internal/token/repository/view/model"
)
type TokenRepo struct {
View *view.View
UserEvents *user_event.UserEventstore
View *view.View
}
func (repo *TokenRepo) CreateToken(ctx context.Context, agentID, applicationID, userID string, audience, scopes []string, lifetime time.Duration) (*token_model.Token, error) {
func (repo *TokenRepo) CreateToken(ctx context.Context, agentID, applicationID, userID string, audience, scopes []string, lifetime time.Duration) (*usr_model.Token, error) {
preferredLanguage := ""
user, _ := repo.View.UserByID(userID)
if user != nil {
preferredLanguage = user.PreferredLanguage
}
token, err := repo.View.CreateToken(agentID, applicationID, userID, preferredLanguage, audience, scopes, lifetime)
if err != nil {
return nil, err
now := time.Now().UTC()
token := &usr_model.Token{
ObjectRoot: models.ObjectRoot{
AggregateID: userID,
},
UserAgentID: agentID,
ApplicationID: applicationID,
Audience: audience,
Scopes: scopes,
Expiration: now.Add(lifetime),
PreferredLanguage: preferredLanguage,
}
return token_view_model.TokenToModel(token), nil
return repo.UserEvents.TokenAdded(ctx, token)
}
func (repo *TokenRepo) IsTokenValid(ctx context.Context, tokenID string) (bool, error) {
return repo.View.IsTokenValid(tokenID)
func (repo *TokenRepo) IsTokenValid(ctx context.Context, userID, tokenID string) (bool, error) {
token, err := repo.TokenByID(ctx, userID, tokenID)
if err == nil {
return token.Expiration.After(time.Now().UTC()), nil
}
if errors.IsNotFound(err) {
return false, nil
}
return false, err
}
func (repo *TokenRepo) TokenByID(ctx context.Context, tokenID string) (*token_model.Token, error) {
token, err := repo.View.TokenByID(tokenID)
if err != nil {
return nil, err
func (repo *TokenRepo) TokenByID(ctx context.Context, userID, tokenID string) (*usr_model.TokenView, error) {
token, viewErr := repo.View.TokenByID(tokenID)
if viewErr != nil && !errors.IsNotFound(viewErr) {
return nil, viewErr
}
return token_view_model.TokenToModel(token), nil
if errors.IsNotFound(viewErr) {
token = new(model.TokenView)
token.ID = tokenID
token.UserID = userID
}
events, esErr := repo.UserEvents.UserEventsByID(ctx, userID, token.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-4T90g", "Errors.Token.NotFound")
}
if esErr != nil {
logging.Log("EVENT-5Nm9s").WithError(viewErr).Debug("error retrieving new events")
return model.TokenViewToModel(token), nil
}
viewToken := *token
for _, event := range events {
err := token.AppendEventIfMyToken(event)
if err != nil {
return model.TokenViewToModel(&viewToken), nil
}
}
if !token.Expiration.After(time.Now().UTC()) || token.Deactivated {
return nil, errors.ThrowNotFound(nil, "EVENT-5Bm9s", "Errors.Token.NotFound")
}
return model.TokenViewToModel(token), nil
}

View File

@@ -3,6 +3,9 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/config/systemdefaults"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
@@ -13,7 +16,7 @@ import (
"github.com/caos/zitadel/internal/eventstore/sdk"
org_model "github.com/caos/zitadel/internal/org/model"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
@@ -21,12 +24,12 @@ import (
)
type UserRepo struct {
SearchLimit uint64
Eventstore eventstore.Eventstore
UserEvents *user_event.UserEventstore
OrgEvents *org_event.OrgEventstore
PolicyEvents *policy_event.PolicyEventstore
View *view.View
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 {
@@ -46,15 +49,23 @@ func (repo *UserRepo) registerUser(ctx context.Context, registerUser *model.User
if resourceOwner != "" {
policyResourceOwner = resourceOwner
}
pwPolicy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, policyResourceOwner)
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(policyResourceOwner)
if errors.IsNotFound(err) {
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return nil, err
}
orgPolicy, err := repo.OrgEvents.GetOrgIAMPolicy(ctx, policyResourceOwner)
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(pwPolicy)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(policyResourceOwner)
if errors.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return nil, err
}
user, aggregates, err := repo.UserEvents.PrepareRegisterUser(ctx, registerUser, externalIDP, pwPolicy, orgPolicy, resourceOwner)
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
user, aggregates, err := repo.UserEvents.PrepareRegisterUser(ctx, registerUser, externalIDP, pwPolicyView, orgPolicyView, resourceOwner)
if err != nil {
return nil, err
}
@@ -215,20 +226,30 @@ func (repo *UserRepo) ChangeMyAddress(ctx context.Context, address *model.Addres
}
func (repo *UserRepo) ChangeMyPassword(ctx context.Context, old, new string) error {
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, authz.GetCtxData(ctx).OrgID)
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return err
}
_, err = repo.UserEvents.ChangePassword(ctx, policy, authz.GetCtxData(ctx).UserID, old, new)
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
_, err = repo.UserEvents.ChangePassword(ctx, pwPolicyView, authz.GetCtxData(ctx).UserID, old, new)
return err
}
func (repo *UserRepo) ChangePassword(ctx context.Context, userID, old, new string) error {
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, authz.GetCtxData(ctx).OrgID)
func (repo *UserRepo) ChangePassword(ctx context.Context, userID, old, new string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return err
}
_, err = repo.UserEvents.ChangePassword(ctx, policy, userID, old, new)
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
_, err = repo.UserEvents.ChangePassword(ctx, pwPolicyView, userID, old, new)
return err
}
@@ -279,11 +300,15 @@ func (repo *UserRepo) RemoveMyMfaOTP(ctx context.Context) error {
func (repo *UserRepo) ChangeMyUsername(ctx context.Context, username string) error {
ctxData := authz.GetCtxData(ctx)
orgPolicy, err := repo.OrgEvents.GetOrgIAMPolicy(ctx, ctxData.OrgID)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(ctxData.OrgID)
if errors.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return err
}
return repo.UserEvents.ChangeUsername(ctx, ctxData.UserID, username, orgPolicy)
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
return repo.UserEvents.ChangeUsername(ctx, ctxData.UserID, username, orgPolicyView)
}
func (repo *UserRepo) ResendInitVerificationMail(ctx context.Context, userID string) error {
_, err := repo.UserEvents.CreateInitializeUserCodeByID(ctx, userID)
@@ -291,11 +316,15 @@ func (repo *UserRepo) ResendInitVerificationMail(ctx context.Context, userID str
}
func (repo *UserRepo) VerifyInitCode(ctx context.Context, userID, code, password string) error {
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, authz.GetCtxData(ctx).OrgID)
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return err
}
return repo.UserEvents.VerifyInitCode(ctx, policy, userID, code, password)
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
return repo.UserEvents.VerifyInitCode(ctx, pwPolicyView, userID, code, password)
}
func (repo *UserRepo) SkipMfaInit(ctx context.Context, userID string) error {
@@ -311,11 +340,15 @@ func (repo *UserRepo) RequestPasswordReset(ctx context.Context, loginname string
}
func (repo *UserRepo) SetPassword(ctx context.Context, userID, code, password string) error {
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, authz.GetCtxData(ctx).OrgID)
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if errors.IsNotFound(err) {
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return err
}
return repo.UserEvents.SetPassword(ctx, policy, userID, code, password)
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
return repo.UserEvents.SetPassword(ctx, pwPolicyView, userID, code, password)
}
func (repo *UserRepo) SignOut(ctx context.Context, agentID string) error {
@@ -346,6 +379,9 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView,
return usr_view_model.UserToModel(user), nil
}
}
if userCopy.State == int32(model.UserStateDeleted) {
return nil, errors.ThrowNotFound(nil, "EVENT-vZ8us", "Errors.User.NotFound")
}
return usr_view_model.UserToModel(&userCopy), nil
}
@@ -366,11 +402,15 @@ func (repo *UserRepo) MyUserChanges(ctx context.Context, lastSequence uint64, li
func (repo *UserRepo) ChangeUsername(ctx context.Context, userID, username string) error {
policyResourceOwner := authz.GetCtxData(ctx).OrgID
orgPolicy, err := repo.OrgEvents.GetOrgIAMPolicy(ctx, policyResourceOwner)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(policyResourceOwner)
if errors.IsNotFound(err) {
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
}
if err != nil {
return err
}
return repo.UserEvents.ChangeUsername(ctx, userID, username, orgPolicy)
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
return repo.UserEvents.ChangeUsername(ctx, userID, username, orgPolicyView)
}
func checkIDs(ctx context.Context, obj es_models.ObjectRoot) error {

View File

@@ -1,6 +1,8 @@
package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
@@ -32,10 +34,17 @@ func (p *Application) EventQuery() (*models.SearchQuery, error) {
return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil
}
func (p *Application) Reduce(event *models.Event) (err error) {
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)
if err != nil {
return err
}
app.ProjectRoleCheck = project.ProjectRoleCheck
app.ProjectRoleAssertion = project.ProjectRoleAssertion
err = app.AppendEvent(event)
case es_model.ApplicationChanged,
es_model.OIDCConfigAdded,
@@ -46,24 +55,40 @@ func (p *Application) Reduce(event *models.Event) (err error) {
if err != nil {
return err
}
app, err = p.view.ApplicationByID(event.AggregateID, app.ID)
app, err = a.view.ApplicationByID(event.AggregateID, app.ID)
if err != nil {
return err
}
err = app.AppendEvent(event)
case es_model.ApplicationRemoved:
err := app.SetData(event)
err = app.SetData(event)
if err != nil {
return err
}
return p.view.DeleteApplication(app.ID, event.Sequence)
return a.view.DeleteApplication(app.ID, event.Sequence)
case es_model.ProjectChanged:
apps, err := a.view.ApplicationsByProjectID(event.AggregateID)
if err != nil {
return err
}
if len(apps) == 0 {
return a.view.ProcessedApplicationSequence(event.Sequence)
}
for _, app := range apps {
if err := app.AppendEvent(event); err != nil {
return err
}
}
return a.view.PutApplications(apps, event.Sequence)
case es_model.ProjectRemoved:
return a.view.DeleteApplicationsByProjectID(event.AggregateID)
default:
return p.view.ProcessedApplicationSequence(event.Sequence)
return a.view.ProcessedApplicationSequence(event.Sequence)
}
if err != nil {
return err
}
return p.view.PutApplication(app)
return a.view.PutApplication(app)
}
func (p *Application) OnError(event *models.Event, spoolerError error) error {

View File

@@ -37,7 +37,8 @@ type EventstoreRepos struct {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler {
return []query.Handler{
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, orgEvents: repos.OrgEvents},
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount},
orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, iamID: systemDefaults.IamID},
&UserSession{handler: handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount}, userEvents: repos.UserEvents},
&UserMembership{handler: handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount}, orgEvents: repos.OrgEvents, projectEvents: repos.ProjectEvents},
&Token{handler: handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount}, ProjectEvents: repos.ProjectEvents},
@@ -57,6 +58,9 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
&IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}},
&IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount}, systemDefaults: systemDefaults, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents},
&ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount}, systemDefaults: systemDefaults, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents},
&PasswordComplexityPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount}},
&OrgIAMPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount}},
&ProjectRole{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount}, projectEvents: repos.ProjectEvents},
}
}

View File

@@ -66,16 +66,21 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) {
}
return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence)
case model.IDPConfigChanged, org_es_model.IDPConfigChanged:
config := new(iam_model.IDPConfig)
config.AppendEvent(event)
providers, err := m.view.IDPProvidersByIDPConfigID(config.IDPConfigID)
esConfig := new(iam_view_model.IDPConfigView)
providerType := iam_model.IDPProviderTypeSystem
if event.AggregateID != m.systemDefaults.IamID {
providerType = iam_model.IDPProviderTypeOrg
}
esConfig.AppendEvent(providerType, event)
providers, err := m.view.IDPProvidersByIDPConfigID(esConfig.IDPConfigID)
if err != nil {
return err
}
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = m.iamEvents.GetIDPConfig(context.Background(), provider.AggregateID, config.IDPConfigID)
config := new(iam_model.IDPConfig)
if event.AggregateID == m.systemDefaults.IamID {
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
}
if err != nil {
return err
@@ -111,6 +116,7 @@ func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err er
func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) {
provider.Name = config.Name
provider.StylingType = int32(config.StylingType)
provider.IDPConfigType = int32(config.Type)
provider.IDPState = int32(config.State)
}

View File

@@ -46,6 +46,17 @@ func (o *Org) Reduce(event *es_models.Event) (err error) {
return err
}
err = org.AppendEvent(event)
case model.OrgDomainPrimarySet:
domain := new(org_model.OrgDomainView)
err = domain.SetData(event)
if err != nil {
return err
}
org, err = o.view.OrgByID(event.AggregateID)
if err != nil {
return err
}
org.Domain = domain.Domain
default:
return o.view.ProcessedOrgSequence(event.Sequence)
}

View File

@@ -0,0 +1,69 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type OrgIAMPolicy struct {
handler
}
const (
orgIAMPolicyTable = "auth.org_iam_policies"
)
func (m *OrgIAMPolicy) ViewModel() string {
return orgIAMPolicyTable
}
func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestOrgIAMPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *OrgIAMPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processOrgIAMPolicy(event)
}
return err
}
func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) {
policy := new(iam_model.OrgIAMPolicyView)
switch event.Type {
case iam_es_model.OrgIAMPolicyAdded, model.OrgIAMPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.OrgIAMPolicyChanged, model.OrgIAMPolicyChanged:
policy, err = m.view.OrgIAMPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.OrgIAMPolicyRemoved:
return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedOrgIAMPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutOrgIAMPolicy(policy, policy.Sequence)
}
func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-3Gj8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler")
return spooler.HandleError(event, err, m.view.GetLatestOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicyFailedEvent, m.view.ProcessedOrgIAMPolicySequence, m.errorCountUntilSkip)
}

View File

@@ -0,0 +1,69 @@
package handler
import (
"github.com/caos/logging"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
type PasswordComplexityPolicy struct {
handler
}
const (
passwordComplexityPolicyTable = "auth.password_complexity_policies"
)
func (m *PasswordComplexityPolicy) ViewModel() string {
return passwordComplexityPolicyTable
}
func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordComplexityPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordComplexityPolicy(event)
}
return err
}
func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) {
policy := new(iam_model.PasswordComplexityPolicyView)
switch event.Type {
case iam_es_model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.PasswordComplexityPolicyChanged, model.PasswordComplexityPolicyChanged:
policy, err = m.view.PasswordComplexityPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordComplexityPolicyRemoved:
return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence)
}
if err != nil {
return err
}
return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence)
}
func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordComplexity policy handler")
return spooler.HandleError(event, err, m.view.GetLatestPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicyFailedEvent, m.view.ProcessedPasswordComplexityPolicySequence, m.errorCountUntilSkip)
}

View File

@@ -0,0 +1,70 @@
package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
"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"
view_model "github.com/caos/zitadel/internal/project/repository/view/model"
)
type ProjectRole struct {
handler
projectEvents *proj_event.ProjectEventstore
}
const (
projectRoleTable = "auth.project_roles"
)
func (p *ProjectRole) ViewModel() string {
return projectRoleTable
}
func (p *ProjectRole) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestProjectRoleSequence()
if err != nil {
return nil, err
}
return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil
}
func (p *ProjectRole) Reduce(event *models.Event) (err error) {
role := new(view_model.ProjectRoleView)
switch event.Type {
case es_model.ProjectRoleAdded:
err = role.AppendEvent(event)
case es_model.ProjectRoleChanged:
err = role.SetData(event)
if err != nil {
return err
}
role, err = p.view.ProjectRoleByIDs(event.AggregateID, event.ResourceOwner, role.Key)
if err != nil {
return err
}
err = role.AppendEvent(event)
case es_model.ProjectRoleRemoved:
err = role.SetData(event)
if err != nil {
return err
}
return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence)
case es_model.ProjectRemoved:
return p.view.DeleteProjectRolesByProjectID(event.AggregateID)
default:
return p.view.ProcessedProjectRoleSequence(event.Sequence)
}
if err != nil {
return err
}
return p.view.PutProjectRole(role)
}
func (p *ProjectRole) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-lso9w", "id", event.AggregateID).WithError(err).Warn("something went wrong in project role handler")
return spooler.HandleError(event, err, p.view.GetLatestProjectRoleFailedEvent, p.view.ProcessedProjectRoleFailedEvent, p.view.ProcessedProjectRoleSequence, p.errorCountUntilSkip)
}

View File

@@ -24,12 +24,12 @@ const (
tokenTable = "auth.tokens"
)
func (u *Token) ViewModel() string {
func (t *Token) ViewModel() string {
return tokenTable
}
func (u *Token) EventQuery() (*models.SearchQuery, error) {
sequence, err := u.view.GetLatestTokenSequence()
func (t *Token) EventQuery() (*models.SearchQuery, error) {
sequence, err := t.view.GetLatestTokenSequence()
if err != nil {
return nil, err
}
@@ -41,41 +41,48 @@ func (u *Token) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (u *Token) Reduce(event *models.Event) (err error) {
func (t *Token) Reduce(event *models.Event) (err error) {
switch event.Type {
case user_es_model.UserTokenAdded:
token := new(view_model.TokenView)
err := token.AppendEvent(event)
if err != nil {
return err
}
return t.view.PutToken(token)
case user_es_model.UserProfileChanged,
user_es_model.HumanProfileChanged:
user := new(view_model.UserView)
user.AppendEvent(event)
tokens, err := u.view.TokensByUserID(event.AggregateID)
tokens, err := t.view.TokensByUserID(event.AggregateID)
if err != nil {
return err
}
for _, token := range tokens {
token.PreferredLanguage = user.PreferredLanguage
}
return u.view.PutTokens(tokens, event.Sequence)
return t.view.PutTokens(tokens, event.Sequence)
case user_es_model.SignedOut,
user_es_model.HumanSignedOut:
id, err := agentIDFromSession(event)
if err != nil {
return err
}
return u.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence)
return t.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence)
case user_es_model.UserLocked,
user_es_model.UserDeactivated,
user_es_model.UserRemoved:
return u.view.DeleteUserTokens(event.AggregateID, event.Sequence)
return t.view.DeleteUserTokens(event.AggregateID, event.Sequence)
case project_es_model.ApplicationDeactivated,
project_es_model.ApplicationRemoved:
application, err := applicationFromSession(event)
if err != nil {
return err
}
return u.view.DeleteApplicationTokens(event.Sequence, application.AppID)
return t.view.DeleteApplicationTokens(event.Sequence, application.AppID)
case project_es_model.ProjectDeactivated,
project_es_model.ProjectRemoved:
project, err := u.ProjectEvents.ProjectByID(context.Background(), event.AggregateID)
project, err := t.ProjectEvents.ProjectByID(context.Background(), event.AggregateID)
if err != nil {
return err
}
@@ -83,15 +90,15 @@ func (u *Token) Reduce(event *models.Event) (err error) {
for _, app := range project.Applications {
applicationsIDs = append(applicationsIDs, app.AppID)
}
return u.view.DeleteApplicationTokens(event.Sequence, applicationsIDs...)
return t.view.DeleteApplicationTokens(event.Sequence, applicationsIDs...)
default:
return u.view.ProcessedTokenSequence(event.Sequence)
return t.view.ProcessedTokenSequence(event.Sequence)
}
}
func (u *Token) OnError(event *models.Event, err error) error {
func (t *Token) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-3jkl4", "id", event.AggregateID).WithError(err).Warn("something went wrong in token handler")
return spooler.HandleError(event, err, u.view.GetLatestTokenFailedEvent, u.view.ProcessedTokenFailedEvent, u.view.ProcessedTokenSequence, u.errorCountUntilSkip)
return spooler.HandleError(event, err, t.view.GetLatestTokenFailedEvent, t.view.ProcessedTokenFailedEvent, t.view.ProcessedTokenSequence, t.errorCountUntilSkip)
}
func agentIDFromSession(event *models.Event) (string, error) {

View File

@@ -2,6 +2,7 @@ package handler
import (
"context"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
es_models "github.com/caos/zitadel/internal/eventstore/models"
org_model "github.com/caos/zitadel/internal/org/model"
@@ -21,6 +22,8 @@ type User struct {
handler
eventstore eventstore.Eventstore
orgEvents *org_events.OrgEventstore
iamEvents *iam_es.IAMEventstore
iamID string
}
const (
@@ -111,7 +114,7 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
}
err = u.fillLoginNames(user)
case es_model.UserRemoved:
err = u.view.DeleteUser(event.AggregateID, event.Sequence)
return u.view.DeleteUser(event.AggregateID, event.Sequence)
default:
return u.view.ProcessedUserSequence(event.Sequence)
}
@@ -126,9 +129,12 @@ func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
if err != nil {
return err
}
policy, err := u.orgEvents.GetOrgIAMPolicy(context.Background(), user.ResourceOwner)
if err != nil {
return err
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
if err != nil {
return err
}
}
user.SetLoginNames(policy, org.Domains)
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
@@ -155,9 +161,12 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
if err != nil {
return err
}
policy, err := u.orgEvents.GetOrgIAMPolicy(context.Background(), event.ResourceOwner)
if err != nil {
return err
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
if err != nil {
return err
}
}
users, err := u.view.UsersByOrgID(event.AggregateID)
if err != nil {
@@ -174,9 +183,12 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
if err != nil {
return err
}
policy, err := u.orgEvents.GetOrgIAMPolicy(context.Background(), event.ResourceOwner)
if err != nil {
return err
policy := org.OrgIamPolicy
if policy == nil {
policy, err = u.iamEvents.GetOrgIAMPolicy(context.Background(), u.iamID)
if err != nil {
return err
}
}
if !policy.UserLoginMustBeDomain {
return nil

View File

@@ -5,17 +5,17 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
"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/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/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"
)
type ExternalIDP struct {
@@ -68,6 +68,8 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) {
return err
}
return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence)
case model.UserRemoved:
return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedExternalIDPSequence(event.Sequence)
}
@@ -80,16 +82,21 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) {
func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
switch event.Type {
case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged:
configView := new(iam_view_model.IDPConfigView)
config := new(iam_model.IDPConfig)
config.AppendEvent(event)
exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(config.IDPConfigID)
if event.Type == iam_es_model.IDPConfigChanged {
configView.AppendEvent(iam_model.IDPProviderTypeSystem, event)
} else {
configView.AppendEvent(iam_model.IDPProviderTypeOrg, event)
}
exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID)
if err != nil {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = m.iamEvents.GetIDPConfig(context.Background(), config.AggregateID, config.IDPConfigID)
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), config.AggregateID, config.IDPConfigID)
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err

View File

@@ -5,13 +5,13 @@ import (
"strings"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/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/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
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"
@@ -71,7 +71,7 @@ func (u *UserGrant) Reduce(event *models.Event) (err error) {
case proj_es_model.ProjectAggregate:
err = u.processProject(event)
case iam_es_model.IAMAggregate:
err = u.processIamMember(event, "IAM", false)
err = u.processIAMMember(event, "IAM", false)
case org_es_model.OrgAggregate:
return u.processOrg(event)
}
@@ -132,7 +132,6 @@ func (u *UserGrant) processUser(event *models.Event) (err error) {
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
}
return nil
}
func (u *UserGrant) processProject(event *models.Event) (err error) {
@@ -161,7 +160,6 @@ func (u *UserGrant) processProject(event *models.Event) (err error) {
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
}
return nil
}
func (u *UserGrant) processOrg(event *models.Event) (err error) {
@@ -175,7 +173,7 @@ func (u *UserGrant) processOrg(event *models.Event) (err error) {
}
}
func (u *UserGrant) processIamMember(event *models.Event, rolePrefix string, suffix bool) error {
func (u *UserGrant) processIAMMember(event *models.Event, rolePrefix string, suffix bool) error {
member := new(iam_es_model.IAMMember)
switch event.Type {
@@ -309,7 +307,8 @@ func (u *UserGrant) setIamProjectID() error {
if err != nil {
return err
}
if !iam.SetUpDone {
if iam.SetUpDone < iam_model.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done")
}
u.iamProjectID = iam.IAMProjectID
@@ -355,6 +354,12 @@ func (u *UserGrant) fillProjectData(grant *view_model.UserGrantView, project *pr
func (u *UserGrant) fillOrgData(grant *view_model.UserGrantView, org *org_model.Org) {
grant.OrgName = org.Name
for _, domain := range org.Domains {
if domain.Primary {
grant.OrgPrimaryDomain = domain.Domain
break
}
}
}
func (u *UserGrant) OnError(event *models.Event, err error) error {

View File

@@ -2,6 +2,7 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model"
@@ -39,7 +40,7 @@ func (m *UserMembership) EventQuery() (*models.SearchQuery, error) {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate).
AggregateTypeFilter(iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate, model.UserAggregate).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
@@ -51,6 +52,8 @@ func (m *UserMembership) Reduce(event *models.Event) (err error) {
err = m.processOrg(event)
case proj_es_model.ProjectAggregate:
err = m.processProject(event)
case model.UserAggregate:
err = m.processUser(event)
}
return err
}
@@ -104,7 +107,7 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) {
case org_es_model.OrgMemberRemoved:
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence)
case org_es_model.OrgChanged:
err = m.updateOrgName(event)
return m.updateOrgName(event)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
}
@@ -175,7 +178,11 @@ func (m *UserMembership) processProject(event *models.Event) (err error) {
case proj_es_model.ProjectGrantMemberRemoved:
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence)
case proj_es_model.ProjectChanged:
err = m.updateProjectDisplayName(event)
return m.updateProjectDisplayName(event)
case proj_es_model.ProjectRemoved:
return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence)
case proj_es_model.ProjectGrantRemoved:
return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
}
@@ -210,7 +217,16 @@ func (m *UserMembership) updateProjectDisplayName(event *models.Event) error {
return m.view.BulkPutUserMemberships(memberships, event.Sequence)
}
func (m *UserMembership) processUser(event *models.Event) (err error) {
switch event.Type {
case model.UserRemoved:
return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
}
}
func (m *UserMembership) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Ms3fj", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgmember handler")
logging.LogWithFields("SPOOL-Ms3fj", "id", event.AggregateID).WithError(err).Warn("something went wrong in user membership handler")
return spooler.HandleError(event, err, m.view.GetLatestUserMembershipFailedEvent, m.view.ProcessedUserMembershipFailedEvent, m.view.ProcessedUserMembershipSequence, m.errorCountUntilSkip)
}

View File

@@ -45,6 +45,7 @@ func (u *UserSession) Reduce(event *models.Event) (err error) {
es_model.SignedOut,
es_model.HumanPasswordCheckSucceeded,
es_model.HumanPasswordCheckFailed,
es_model.HumanExternalLoginCheckSucceeded,
es_model.HumanMFAOTPCheckSucceeded,
es_model.HumanMFAOTPCheckFailed,
es_model.HumanSignedOut:

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