diff --git a/README.md b/README.md index 0ae1a4b649..d3dcf9395d 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ Details need to be announced, but feel free to contribute already. As long as yo We already have documentation specific [guidelines](./site/CONTRIBUTING.md). +Howto develop ZITADEL: [contribute](./CONTRIBUTING.md) + ## Security See the policy [here](./SECURITY.md) diff --git a/build/README.md b/build/README.md index 4116250a63..66e46bef66 100644 --- a/build/README.md +++ b/build/README.md @@ -40,7 +40,7 @@ COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f build/docker-comp ### Fullstack including database ```Bash -COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f build/docker-compose.yml up --build +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f build/docker-compose-dev.yml up --build ``` ## Debug diff --git a/cmd/zitadel/setup.yaml b/cmd/zitadel/setup.yaml index 45b954926d..3272ca011e 100644 --- a/cmd/zitadel/setup.yaml +++ b/cmd/zitadel/setup.yaml @@ -94,4 +94,6 @@ SetUp: Step6: DefaultLabelPolicy: PrimaryColor: '#222324' - SecondaryColor: '#ffffff' + SecondaryColor: '#ffffff' + Step7: + DefaultSecondFactor: 1 #SecondFactorTypeOTP \ No newline at end of file diff --git a/internal/api/grpc/management/user_grant_converter.go b/internal/api/grpc/management/user_grant_converter.go index fe3bf4c5c1..576e2a27f2 100644 --- a/internal/api/grpc/management/user_grant_converter.go +++ b/internal/api/grpc/management/user_grant_converter.go @@ -79,8 +79,8 @@ func userGrantSearchQueryToModel(query *management.UserGrantSearchQuery) *grant_ func userGrantSearchKeyToModel(key management.UserGrantSearchKey) grant_model.UserGrantSearchKey { switch key { - case management.UserGrantSearchKey_USERGRANTSEARCHKEY_ORG_ID: - return grant_model.UserGrantSearchKeyResourceOwner + case management.UserGrantSearchKey_USERGRANTSEARCHKEY_WITH_GRANTED: + return grant_model.UserGrantSearchKeyWithGranted case management.UserGrantSearchKey_USERGRANTSEARCHKEY_PROJECT_ID: return grant_model.UserGrantSearchKeyProjectID case management.UserGrantSearchKey_USERGRANTSEARCHKEY_USER_ID: diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go index c849c9234a..b753e27bd3 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go @@ -109,8 +109,6 @@ func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *mod return nil, err } request.Audience = appIDs - projectIDAud := request.GetScopeProjectIDsForAud() - request.Audience = append(request.Audience, projectIDAud...) request.AppendAudIfNotExisting(app.ProjectID) if request.LoginHint != "" { err = repo.checkLoginName(ctx, request, request.LoginHint) @@ -624,12 +622,16 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *model.AuthRequest) ( func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView, request *model.AuthRequest, user *user_model.UserView) (model.NextStep, bool, error) { mfaLevel := request.MfaLevel() - promptRequired := (user.MfaMaxSetUp < mfaLevel) || !user.HasRequiredOrgMFALevel(request.LoginPolicy) - if promptRequired || !repo.mfaSkippedOrSetUp(user, request.LoginPolicy) { + allowedProviders, required := user.MfaTypesAllowed(mfaLevel, request.LoginPolicy) + promptRequired := (user.MfaMaxSetUp < mfaLevel) || (len(allowedProviders) == 0 && required) + if promptRequired || !repo.mfaSkippedOrSetUp(user) { types := user.MfaTypesSetupPossible(mfaLevel, request.LoginPolicy) if promptRequired && len(types) == 0 { return nil, false, errors.ThrowPreconditionFailed(nil, "LOGIN-5Hm8s", "Errors.Login.LoginPolicy.MFA.ForceAndNotConfigured") } + if len(types) == 0 { + return nil, true, nil + } return &model.MfaPromptStep{ Required: promptRequired, MfaProviders: types, @@ -639,7 +641,7 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView, default: fallthrough case model.MFALevelNotSetUp: - if user.MfaMaxSetUp == model.MFALevelNotSetUp { + if len(allowedProviders) == 0 { return nil, true, nil } fallthrough @@ -658,11 +660,11 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView, } } return &model.MfaVerificationStep{ - MfaProviders: user.MfaTypesAllowed(mfaLevel, request.LoginPolicy), + MfaProviders: allowedProviders, }, false, nil } -func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView, policy *iam_model.LoginPolicyView) bool { +func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView) bool { if user.MfaMaxSetUp > model.MFALevelNotSetUp { return true } diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go b/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go index 0b14a371cd..020db064f0 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request_test.go @@ -909,6 +909,25 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) { false, errors.IsPreconditionFailed, }, + { + "not set up, no mfas configured, no prompt and true", + fields{ + MfaInitSkippedLifeTime: 30 * 24 * time.Hour, + }, + args{ + request: &model.AuthRequest{ + LoginPolicy: &iam_model.LoginPolicyView{}, + }, + user: &user_model.UserView{ + HumanView: &user_model.HumanView{ + MfaMaxSetUp: model.MFALevelNotSetUp, + }, + }, + }, + nil, + true, + nil, + }, { "not set up, prompt and false", fields{ @@ -988,7 +1007,9 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) { }, args{ request: &model.AuthRequest{ - LoginPolicy: &iam_model.LoginPolicyView{}, + LoginPolicy: &iam_model.LoginPolicyView{ + SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP}, + }, }, user: &user_model.UserView{ HumanView: &user_model.HumanView{ @@ -1054,8 +1075,7 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) { MfaInitSkippedLifeTime time.Duration } type args struct { - user *user_model.UserView - policy *iam_model.LoginPolicyView + user *user_model.UserView } tests := []struct { name string @@ -1072,9 +1092,6 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) { MfaMaxSetUp: model.MFALevelSecondFactor, }, }, - &iam_model.LoginPolicyView{ - SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP}, - }, }, true, }, @@ -1090,9 +1107,6 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) { MfaInitSkipped: time.Now().UTC().Add(-10 * time.Hour), }, }, - &iam_model.LoginPolicyView{ - SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP}, - }, }, true, }, @@ -1108,9 +1122,6 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) { MfaInitSkipped: time.Now().UTC().Add(-40 * 24 * time.Hour), }, }, - &iam_model.LoginPolicyView{ - SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP}, - }, }, false, }, @@ -1120,7 +1131,7 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) { repo := &AuthRequestRepo{ MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime, } - if got := repo.mfaSkippedOrSetUp(tt.args.user, tt.args.policy); got != tt.want { + if got := repo.mfaSkippedOrSetUp(tt.args.user); got != tt.want { t.Errorf("mfaSkippedOrSetUp() = %v, want %v", got, tt.want) } }) diff --git a/internal/auth/repository/eventsourcing/eventstore/token.go b/internal/auth/repository/eventsourcing/eventstore/token.go index c96298507f..358da84a7c 100644 --- a/internal/auth/repository/eventsourcing/eventstore/token.go +++ b/internal/auth/repository/eventsourcing/eventstore/token.go @@ -3,11 +3,13 @@ package eventstore import ( "context" "github.com/caos/logging" + auth_req_model "github.com/caos/zitadel/internal/auth_request/model" "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" + "strings" "time" "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" @@ -18,19 +20,26 @@ type TokenRepo struct { View *view.View } -func (repo *TokenRepo) CreateToken(ctx context.Context, agentID, applicationID, userID string, audience, scopes []string, lifetime time.Duration) (*usr_model.Token, error) { +func (repo *TokenRepo) CreateToken(ctx context.Context, agentID, clientID, userID string, audience, scopes []string, lifetime time.Duration) (*usr_model.Token, error) { preferredLanguage := "" user, _ := repo.View.UserByID(userID) if user != nil { preferredLanguage = user.PreferredLanguage } + + for _, scope := range scopes { + if strings.HasPrefix(scope, auth_req_model.ProjectIDScope) && strings.HasSuffix(scope, auth_req_model.AudSuffix) { + audience = append(audience, strings.TrimSuffix(strings.TrimPrefix(scope, auth_req_model.ProjectIDScope), auth_req_model.AudSuffix)) + } + } + now := time.Now().UTC() token := &usr_model.Token{ ObjectRoot: models.ObjectRoot{ AggregateID: userID, }, UserAgentID: agentID, - ApplicationID: applicationID, + ApplicationID: clientID, Audience: audience, Scopes: scopes, Expiration: now.Add(lifetime), @@ -82,3 +91,12 @@ func (repo *TokenRepo) TokenByID(ctx context.Context, userID, tokenID string) (* } return model.TokenViewToModel(token), nil } + +func AppendAudIfNotExisting(aud string, existingAud []string) []string { + for _, a := range existingAud { + if a == aud { + return existingAud + } + } + return append(existingAud, aud) +} diff --git a/internal/auth/repository/eventsourcing/handler/login_policy.go b/internal/auth/repository/eventsourcing/handler/login_policy.go index d593d4659b..ca01a1ea76 100644 --- a/internal/auth/repository/eventsourcing/handler/login_policy.go +++ b/internal/auth/repository/eventsourcing/handler/login_policy.go @@ -56,6 +56,8 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { return err } err = policy.AppendEvent(event) + case model.LoginPolicyRemoved: + return m.view.DeleteLoginPolicy(event.AggregateID, event.Sequence) default: return m.view.ProcessedLoginPolicySequence(event.Sequence) } diff --git a/internal/auth/repository/eventsourcing/handler/user_grant.go b/internal/auth/repository/eventsourcing/handler/user_grant.go index 34e85537bd..d9ded99e7f 100644 --- a/internal/auth/repository/eventsourcing/handler/user_grant.go +++ b/internal/auth/repository/eventsourcing/handler/user_grant.go @@ -350,6 +350,7 @@ func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *usr_mode func (u *UserGrant) fillProjectData(grant *view_model.UserGrantView, project *proj_model.Project) { grant.ProjectName = project.Name + grant.ProjectOwner = project.ResourceOwner } func (u *UserGrant) fillOrgData(grant *view_model.UserGrantView, org *org_model.Org) { diff --git a/internal/auth/repository/token.go b/internal/auth/repository/token.go index 7c998725ad..c5d5130593 100644 --- a/internal/auth/repository/token.go +++ b/internal/auth/repository/token.go @@ -7,7 +7,7 @@ import ( ) type TokenRepository interface { - CreateToken(ctx context.Context, agentID, applicationID, userID string, audience, scopes []string, lifetime time.Duration) (*usr_model.Token, error) + CreateToken(ctx context.Context, agentID, clientID, userID string, audience, scopes []string, lifetime time.Duration) (*usr_model.Token, error) IsTokenValid(ctx context.Context, userID, tokenID string) (bool, error) TokenByID(ctx context.Context, userID, tokenID string) (*usr_model.TokenView, error) } diff --git a/internal/eventstore/models/object.go b/internal/eventstore/models/object.go index a12a362370..62a6df14de 100644 --- a/internal/eventstore/models/object.go +++ b/internal/eventstore/models/object.go @@ -16,6 +16,9 @@ func (o *ObjectRoot) AppendEvent(event *Event) { if o.AggregateID == "" { o.AggregateID = event.AggregateID } + if o.ResourceOwner == "" { + o.ResourceOwner = event.ResourceOwner + } o.ChangeDate = event.CreationDate if event.PreviousSequence == 0 { @@ -23,7 +26,6 @@ func (o *ObjectRoot) AppendEvent(event *Event) { } o.Sequence = event.Sequence - o.ResourceOwner = event.ResourceOwner } func (o *ObjectRoot) IsZero() bool { return o.AggregateID == "" diff --git a/internal/iam/model/iam.go b/internal/iam/model/iam.go index f10b6295c2..09610a5c89 100644 --- a/internal/iam/model/iam.go +++ b/internal/iam/model/iam.go @@ -13,6 +13,7 @@ const ( Step4 Step5 Step6 + Step7 //StepCount marks the the length of possible steps (StepCount-1 == last possible step) StepCount ) diff --git a/internal/iam/repository/eventsourcing/eventstore.go b/internal/iam/repository/eventsourcing/eventstore.go index 8d9f3590d9..c2fad65924 100644 --- a/internal/iam/repository/eventsourcing/eventstore.go +++ b/internal/iam/repository/eventsourcing/eventstore.go @@ -83,10 +83,12 @@ func (es *IAMEventstore) StartSetup(ctx context.Context, iamID string, step iam_ return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "Setup already started") } - repoIAM := &model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: iamID}, SetUpStarted: model.Step(step)} - if iam != nil { - repoIAM.ObjectRoot = iam.ObjectRoot + if iam == nil { + iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: iamID}} } + iam.SetUpStarted = step + repoIAM := model.IAMFromModel(iam) + createAggregate := IAMSetupStartedAggregate(es.AggregateCreator(), repoIAM) err = es_sdk.Push(ctx, es.PushAggregates, repoIAM.AppendEvents, createAggregate) if err != nil { @@ -603,31 +605,43 @@ func (es *IAMEventstore) RemoveIDPProviderFromLoginPolicy(ctx context.Context, p } func (es *IAMEventstore) AddSecondFactorToLoginPolicy(ctx context.Context, aggregateID string, mfa iam_model.SecondFactorType) (iam_model.SecondFactorType, error) { - if mfa == iam_model.SecondFactorTypeUnspecified { - return 0, caos_errs.ThrowPreconditionFailed(nil, "EVENT-1M8Js", "Errors.IAM.LoginPolicy.MFA.Unspecified") - } - iam, err := es.IAMByID(ctx, aggregateID) + repoIAM, addAggregate, err := es.PrepareAddSecondFactorToLoginPolicy(ctx, aggregateID, mfa) if err != nil { return 0, err } - if _, m := iam.DefaultLoginPolicy.GetSecondFactor(mfa); m != 0 { - return 0, caos_errs.ThrowAlreadyExists(nil, "EVENT-4Rk09", "Errors.IAM.LoginPolicy.MFA.AlreadyExists") - } - repoIam := model.IAMFromModel(iam) - repoMFA := model.SecondFactorFromModel(mfa) - - addAggregate := LoginPolicySecondFactorAddedAggregate(es.Eventstore.AggregateCreator(), repoIam, repoMFA) - err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, addAggregate) + err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoIAM.AppendEvents, addAggregate) if err != nil { return 0, err } - es.iamCache.cacheIAM(repoIam) - if _, m := model.GetMFA(repoIam.DefaultLoginPolicy.SecondFactors, int32(mfa)); m != 0 { + es.iamCache.cacheIAM(repoIAM) + if _, m := model.GetMFA(repoIAM.DefaultLoginPolicy.SecondFactors, int32(mfa)); m != 0 { return iam_model.SecondFactorType(m), nil } return 0, caos_errs.ThrowInternal(nil, "EVENT-5N9so", "Errors.Internal") } +func (es *IAMEventstore) PrepareAddSecondFactorToLoginPolicy(ctx context.Context, aggregateID string, mfa iam_model.SecondFactorType) (*model.IAM, *models.Aggregate, error) { + if mfa == iam_model.SecondFactorTypeUnspecified { + return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-1M8Js", "Errors.IAM.LoginPolicy.MFA.Unspecified") + } + iam, err := es.IAMByID(ctx, aggregateID) + if err != nil { + return nil, nil, err + } + if _, m := iam.DefaultLoginPolicy.GetSecondFactor(mfa); m != 0 { + return nil, nil, caos_errs.ThrowAlreadyExists(nil, "EVENT-4Rk09", "Errors.IAM.LoginPolicy.MFA.AlreadyExists") + } + repoIAM := model.IAMFromModel(iam) + repoMFA := model.SecondFactorFromModel(mfa) + + addAggregate := LoginPolicySecondFactorAddedAggregate(es.Eventstore.AggregateCreator(), repoIAM, repoMFA) + aggregate, err := addAggregate(ctx) + if err != nil { + return nil, nil, err + } + return repoIAM, aggregate, nil +} + func (es *IAMEventstore) RemoveSecondFactorFromLoginPolicy(ctx context.Context, aggregateID string, mfa iam_model.SecondFactorType) error { if mfa == iam_model.SecondFactorTypeUnspecified { return caos_errs.ThrowPreconditionFailed(nil, "EVENT-4gJ9s", "Errors.IAM.LoginPolicy.MFA.Unspecified") diff --git a/internal/management/repository/eventsourcing/eventstore/user_grant.go b/internal/management/repository/eventsourcing/eventstore/user_grant.go index 944ccf32a6..ddcfedb81d 100644 --- a/internal/management/repository/eventsourcing/eventstore/user_grant.go +++ b/internal/management/repository/eventsourcing/eventstore/user_grant.go @@ -2,6 +2,7 @@ package eventstore import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/api/authz" caos_errors "github.com/caos/zitadel/internal/errors" diff --git a/internal/management/repository/eventsourcing/handler/user_grant.go b/internal/management/repository/eventsourcing/handler/user_grant.go index 9bd28c3dd7..e95b153299 100644 --- a/internal/management/repository/eventsourcing/handler/user_grant.go +++ b/internal/management/repository/eventsourcing/handler/user_grant.go @@ -176,6 +176,7 @@ func (u *UserGrant) fillUserData(grant *view_model.UserGrantView, user *usr_mode func (u *UserGrant) fillProjectData(grant *view_model.UserGrantView, project *proj_model.Project) { grant.ProjectName = project.Name + grant.ProjectOwner = project.ResourceOwner } func (u *UserGrant) fillOrgData(grant *view_model.UserGrantView, org *org_model.Org) { diff --git a/internal/setup/config.go b/internal/setup/config.go index 9c8f56056f..423b999695 100644 --- a/internal/setup/config.go +++ b/internal/setup/config.go @@ -12,6 +12,7 @@ type IAMSetUp struct { Step4 *Step4 Step5 *Step5 Step6 *Step6 + Step7 *Step7 } func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) { @@ -25,6 +26,7 @@ func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) { setup.Step4, setup.Step5, setup.Step6, + setup.Step7, } { if step.step() <= currentDone { continue diff --git a/internal/setup/step7.go b/internal/setup/step7.go new file mode 100644 index 0000000000..210fa8fb56 --- /dev/null +++ b/internal/setup/step7.go @@ -0,0 +1,54 @@ +package setup + +import ( + "context" + + "github.com/caos/logging" + + "github.com/caos/zitadel/internal/eventstore/models" + es_sdk "github.com/caos/zitadel/internal/eventstore/sdk" + iam_model "github.com/caos/zitadel/internal/iam/model" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" +) + +type Step7 struct { + DefaultSecondFactor iam_model.SecondFactorType + + setup *Setup +} + +func (step *Step7) isNil() bool { + return step == nil +} + +func (step *Step7) step() iam_model.Step { + return iam_model.Step7 +} + +func (step *Step7) init(setup *Setup) { + step.setup = setup +} + +func (step *Step7) execute(ctx context.Context) (*iam_model.IAM, error) { + iam, agg, err := step.add2FAToPolicy(ctx, step.DefaultSecondFactor) + if err != nil { + logging.Log("SETUP-ZTuS1").WithField("step", step.step()).WithError(err).Error("unable to finish setup (add default mfa to login policy)") + return nil, err + } + iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step()) + if err != nil { + logging.Log("SETUP-OkF8o").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)") + return nil, err + } + err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg) + if err != nil { + logging.Log("SETUP-YbQ6T").WithField("step", step.step()).WithError(err).Error("unable to finish setup") + return nil, err + } + return iam_es_model.IAMToModel(iam), nil +} + +func (step *Step7) add2FAToPolicy(ctx context.Context, secondFactor iam_model.SecondFactorType) (*iam_es_model.IAM, *models.Aggregate, error) { + logging.Log("SETUP-geMGDuZ").Info("adding 2FA to loginPolicy") + return step.setup.IamEvents.PrepareAddSecondFactorToLoginPolicy(ctx, step.setup.iamID, secondFactor) +} diff --git a/internal/user/model/user_view.go b/internal/user/model/user_view.go index 7d2697c73b..96826f0e4e 100644 --- a/internal/user/model/user_view.go +++ b/internal/user/model/user_view.go @@ -142,10 +142,12 @@ func (u *UserView) MfaTypesSetupPossible(level req_model.MFALevel, policy *iam_m return types } -func (u *UserView) MfaTypesAllowed(level req_model.MFALevel, policy *iam_model.LoginPolicyView) []req_model.MFAType { +func (u *UserView) MfaTypesAllowed(level req_model.MFALevel, policy *iam_model.LoginPolicyView) ([]req_model.MFAType, bool) { types := make([]req_model.MFAType, 0) + required := true switch level { default: + required = policy.ForceMFA fallthrough case req_model.MFALevelSecondFactor: if policy.HasSecondFactors() { @@ -172,7 +174,7 @@ func (u *UserView) MfaTypesAllowed(level req_model.MFALevel, policy *iam_model.L } //PLANNED: add token } - return types + return types, required } func (u *UserView) HasRequiredOrgMFALevel(policy *iam_model.LoginPolicyView) bool { diff --git a/internal/usergrant/model/user_grant_view.go b/internal/usergrant/model/user_grant_view.go index 903a5a63b8..b5dd342433 100644 --- a/internal/usergrant/model/user_grant_view.go +++ b/internal/usergrant/model/user_grant_view.go @@ -56,6 +56,7 @@ const ( UserGrantSearchKeyOrgDomain UserGrantSearchKeyProjectName UserGrantSearchKeyDisplayName + UserGrantSearchKeyWithGranted ) type UserGrantSearchQuery struct { diff --git a/internal/usergrant/repository/view/model/user_grant.go b/internal/usergrant/repository/view/model/user_grant.go index 6e2c3c7dde..626ab0e616 100644 --- a/internal/usergrant/repository/view/model/user_grant.go +++ b/internal/usergrant/repository/view/model/user_grant.go @@ -43,6 +43,7 @@ type UserGrantView struct { DisplayName string `json:"-" gorm:"column:display_name"` Email string `json:"-" gorm:"column:email"` ProjectName string `json:"-" gorm:"column:project_name"` + ProjectOwner string `json:"-" gorm:"column:project_owner"` OrgName string `json:"-" gorm:"column:org_name"` OrgPrimaryDomain string `json:"-" gorm:"column:org_primary_domain"` RoleKeys pq.StringArray `json:"roleKeys" gorm:"column:role_keys"` diff --git a/internal/usergrant/repository/view/model/user_grant_test.go b/internal/usergrant/repository/view/model/user_grant_test.go index 40f5edb1af..ca2cd75b40 100644 --- a/internal/usergrant/repository/view/model/user_grant_test.go +++ b/internal/usergrant/repository/view/model/user_grant_test.go @@ -2,12 +2,13 @@ package model import ( "encoding/json" + "reflect" + "testing" + es_models "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/usergrant/model" es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model" "github.com/lib/pq" - "reflect" - "testing" ) func mockUserGrantData(grant *es_model.UserGrant) []byte { diff --git a/internal/usergrant/repository/view/user_grant_view.go b/internal/usergrant/repository/view/user_grant_view.go index c09bdda08b..aa36907b69 100644 --- a/internal/usergrant/repository/view/user_grant_view.go +++ b/internal/usergrant/repository/view/user_grant_view.go @@ -34,13 +34,39 @@ func UserGrantByIDs(db *gorm.DB, table, resourceOwnerID, projectID, userID strin } func SearchUserGrants(db *gorm.DB, table string, req *grant_model.UserGrantSearchRequest) ([]*model.UserGrantView, uint64, error) { - users := make([]*model.UserGrantView, 0) + grants := make([]*model.UserGrantView, 0) + + var orgID string + var withGranted bool + + for i := len(req.Queries) - 1; i >= 0; i-- { + shouldRemove := false + if req.Queries[i].Key == grant_model.UserGrantSearchKeyResourceOwner { + orgID = req.Queries[i].Value.(string) + shouldRemove = true + } + if req.Queries[i].Key == grant_model.UserGrantSearchKeyWithGranted { + withGranted = true + shouldRemove = true + } + if shouldRemove { + req.Queries[i] = req.Queries[len(req.Queries)-1] + req.Queries[len(req.Queries)-1] = nil + req.Queries = req.Queries[:len(req.Queries)-1] + } + } + + if withGranted { + db = db.Where("resource_owner = ? OR project_owner = ?", orgID, orgID) + } else { + db = db.Where("resource_owner = ?", orgID) + } query := repository.PrepareSearchQuery(table, model.UserGrantSearchRequest{Limit: req.Limit, Offset: req.Offset, Queries: req.Queries}) - count, err := query(db, &users) + count, err := query(db, &grants) if err != nil { return nil, 0, err } - return users, count, nil + return grants, count, nil } func UserGrantsByUserID(db *gorm.DB, table, userID string) ([]*model.UserGrantView, error) { diff --git a/internal/view/repository/query.go b/internal/view/repository/query.go index 6623b5687a..8205cda518 100644 --- a/internal/view/repository/query.go +++ b/internal/view/repository/query.go @@ -2,6 +2,7 @@ package repository import ( "fmt" + caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/model" "github.com/jinzhu/gorm" @@ -37,6 +38,7 @@ func PrepareSearchQuery(table string, request SearchRequest) func(db *gorm.DB, r } query = query.Order(fmt.Sprintf("%s %s", column.ToColumnName(), order)) } + for _, q := range request.GetQueries() { var err error query, err = SetQuery(query, q.GetKey(), q.GetValue(), q.GetMethod()) diff --git a/migrations/cockroach/V1.22__user_grant_owners.sql b/migrations/cockroach/V1.22__user_grant_owners.sql new file mode 100644 index 0000000000..07a11eaa08 --- /dev/null +++ b/migrations/cockroach/V1.22__user_grant_owners.sql @@ -0,0 +1,5 @@ +ALTER TABLE management.user_grants ADD COLUMN project_owner STRING; + +ALTER TABLE auth.user_grants ADD COLUMN project_owner STRING; + +ALTER TABLE authz.user_grants ADD COLUMN project_owner STRING; diff --git a/pkg/grpc/management/proto/management.proto b/pkg/grpc/management/proto/management.proto index 0297b4fa03..19eac49b24 100644 --- a/pkg/grpc/management/proto/management.proto +++ b/pkg/grpc/management/proto/management.proto @@ -2863,7 +2863,7 @@ message UserGrantSearchRequest { message UserGrantSearchQuery { UserGrantSearchKey key = 1 [(validate.rules).enum = {not_in: [0]}]; - SearchMethod method = 2 [(validate.rules).enum = {in: [0]}]; + SearchMethod method = 2 [(validate.rules).enum.defined_only = true]; string value = 3; } @@ -2871,7 +2871,7 @@ enum UserGrantSearchKey { USERGRANTSEARCHKEY_UNSPECIFIED = 0; USERGRANTSEARCHKEY_PROJECT_ID = 1; USERGRANTSEARCHKEY_USER_ID = 2; - USERGRANTSEARCHKEY_ORG_ID = 3; + USERGRANTSEARCHKEY_WITH_GRANTED = 3; USERGRANTSEARCHKEY_ROLE_KEY = 4; USERGRANTSEARCHKEY_GRANT_ID = 5; USERGRANTSEARCHKEY_USER_NAME = 6; diff --git a/site/package-lock.json b/site/package-lock.json index fbfb119f8a..9321e70f24 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1060,19 +1060,14 @@ "to-fast-properties": "^2.0.0" } }, - "@formatjs/intl-unified-numberformat": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/@formatjs/intl-unified-numberformat/-/intl-unified-numberformat-3.3.7.tgz", - "integrity": "sha512-KnWgLRHzCAgT9eyt3OS34RHoyD7dPDYhRcuKn+/6Kv2knDF8Im43J6vlSW6Hm1w63fNq3ZIT1cFk7RuVO3Psag==", + "@formatjs/ecma402-abstract": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.4.0.tgz", + "integrity": "sha512-Mv027hcLFjE45K8UJ8PjRpdDGfR0aManEFj1KzoN8zXNveHGEygpZGfFf/FTTMl+QEVSrPAUlyxaCApvmv47AQ==", "requires": { - "@formatjs/intl-utils": "^2.3.0" + "tslib": "^2.0.1" } }, - "@formatjs/intl-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@formatjs/intl-utils/-/intl-utils-2.3.0.tgz", - "integrity": "sha512-KWk80UPIzPmUg+P0rKh6TqspRw0G6eux1PuJr+zz47ftMaZ9QDwbGzHZbtzWkl5hgayM/qrKRutllRC7D/vVXQ==" - }, "@polka/send": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@polka/send/-/send-0.4.0.tgz", @@ -1374,11 +1369,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" - }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -1464,8 +1454,7 @@ "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, "define-properties": { "version": "1.1.3", @@ -1476,6 +1465,11 @@ "object-keys": "^1.0.12" } }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, "electron-to-chromium": { "version": "1.3.587", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.587.tgz", @@ -1533,9 +1527,9 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "estree-walker": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.9.0.tgz", - "integrity": "sha512-12U47o7XHUX329+x3FzNVjCx3SHEzMF0nkDv7r/HnBzX/xNTKxajBk6gyygaxrAFtLj39219oMfbtxv4KpaOiA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz", + "integrity": "sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg==" }, "esutils": { "version": "2.0.3", @@ -1543,6 +1537,11 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "fast-memoize": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", + "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1703,26 +1702,23 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "intl-format-cache": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/intl-format-cache/-/intl-format-cache-4.3.1.tgz", - "integrity": "sha512-OEUYNA7D06agqPOYhbTkl0T8HA3QKSuwWh1HiClEnpd9vw7N+3XsQt5iZ0GUEchp5CW1fQk/tary+NsbF3yQ1Q==" - }, "intl-messageformat": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-7.8.4.tgz", - "integrity": "sha512-yS0cLESCKCYjseCOGXuV4pxJm/buTfyCJ1nzQjryHmSehlptbZbn9fnlk1I9peLopZGGbjj46yHHiTAEZ1qOTA==", + "version": "9.3.18", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.3.18.tgz", + "integrity": "sha512-OKrLWppdxXtRdRCPjmRZ9Ru7UZkZJDlMl+1Vpb3sCLWK0mFpr129K+gIlIb5zrWoAH3NiYDzekBXPTRWCyHSIA==", "requires": { - "intl-format-cache": "^4.2.21", - "intl-messageformat-parser": "^3.6.4" + "fast-memoize": "^2.5.2", + "intl-messageformat-parser": "6.0.16", + "tslib": "^2.0.1" } }, "intl-messageformat-parser": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-3.6.4.tgz", - "integrity": "sha512-RgPGwue0mJtoX2Ax8EmMzJzttxjnva7gx0Q7mKJ4oALrTZvtmCeAw5Msz2PcjW4dtCh/h7vN/8GJCxZO1uv+OA==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-6.0.16.tgz", + "integrity": "sha512-Qy3Zz0vF4fhMVuW4BDqUr55LsOl9enM03wuwbP4Yg7v29rYNpf7Z76Whstu6uDLDJokrjbpgDvRcjSDTAhxKJw==", "requires": { - "@formatjs/intl-unified-numberformat": "^3.2.0" + "@formatjs/ecma402-abstract": "1.4.0", + "tslib": "^2.0.1" } }, "is-arrayish": { @@ -1908,9 +1904,9 @@ } }, "marked": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.2.tgz", - "integrity": "sha512-5jjKHVl/FPo0Z6ocP3zYhKiJLzkwJAw4CZoLjv57FkvbUuwOX4LIBBGGcXjAY6ATcd1q9B8UTj5T9Umauj0QYQ==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.4.tgz", + "integrity": "sha512-6x5TFGCTKSQBLTZtOburGxCxFEBJEGYVLwCMTBCxzvyuisGcC20UNzDSJhCr/cJ/Kmh6ulfJm10g6WWEAJ3kvg==" }, "matchit": { "version": "1.1.0", @@ -1965,6 +1961,11 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2246,18 +2247,18 @@ } }, "rollup": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.33.1.tgz", - "integrity": "sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w==", + "version": "2.33.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.33.2.tgz", + "integrity": "sha512-QPQ6/fWCrzHtSXkI269rhKaC7qXGghYBwXU04b1JsDZ6ibZa3DJ9D1SFAYRMgx1inDg0DaTbb3N4Z1NK/r3fhw==", "dev": true, "requires": { "fsevents": "~2.1.2" } }, "rollup-plugin-svelte": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-6.1.0.tgz", - "integrity": "sha512-TX1nIZSD6ePiSdYIEfpkvR7lLnP1nsSycCVz+vXbm5d5kIe5WMldo6fwcL/T8KPjc42XDgLaRcS74BorpQvpiA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-6.1.1.tgz", + "integrity": "sha512-ijnm0pH1ScrY4uxwaNXBpNVejVzpL2769hIEbAlnqNUWZrffLspu5/k9/l/Wsj3NrEHLQ6wCKGagVJonyfN7ow==", "dev": true, "requires": { "require-relative": "^0.8.7", @@ -2294,6 +2295,14 @@ } } }, + "sade": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", + "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", + "requires": { + "mri": "^1.1.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2364,12 +2373,20 @@ "dev": true }, "sirv": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.6.tgz", - "integrity": "sha512-rYpOXlNbpHiY4nVXxuDf4mXPvKz1reZGap/LkWp9TvcZ84qD/nPBjjH/6GZsgIjVMbOslnY8YYULAyP8jMn1GQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.7.tgz", + "integrity": "sha512-QMT2OTD3CTr8de9VByPmvSEeyt6k8/Cxg0J2kQJ5HNhIWfhFg9ypcIWWzez9rPWnGj+WtJ7AZD/MdT/vdilV/A==", "requires": { - "@polka/url": "^0.5.0", - "mime": "^2.3.1" + "@polka/url": "^1.0.0-next.9", + "mime": "^2.3.1", + "totalist": "^1.0.0" + }, + "dependencies": { + "@polka/url": { + "version": "1.0.0-next.11", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.11.tgz", + "integrity": "sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==" + } } }, "source-map": { @@ -2530,19 +2547,21 @@ } }, "svelte": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.29.4.tgz", - "integrity": "sha512-oW0fGHlyFFMvzRtIvOs84b0fOc0gmZNQcL5Is3hxuTpvaYX3pfd8oHy4KnOvbq4Ca6SG6AHdRMk7OhApTo0NqA==", + "version": "3.29.7", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.29.7.tgz", + "integrity": "sha512-rx0g311kBODvEWUU01DFBUl3MJuJven04bvTVFUG/w0On/wuj0PajQY/QlXcJndFxG+W1s8iXKaB418tdHWc3A==", "dev": true }, "svelte-i18n": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/svelte-i18n/-/svelte-i18n-3.1.0.tgz", - "integrity": "sha512-R4hH422srFiXekbJJYQp/NPgdiffE12ST0mvrrcbNs5SGpLdl4aK6EE1pWEP3BzTxly0witZy9GDERL8nXSDAw==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/svelte-i18n/-/svelte-i18n-3.2.5.tgz", + "integrity": "sha512-EBPEPcf3Ro7av0b8g/owlfb8fQgnYFan/9gfpRtJ5EmJ7SUUnoCD8JngN9FCKY/cBu1kg2aCUCM6XyauMuAvIA==", "requires": { - "commander": "^4.0.1", - "estree-walker": "^0.9.0", - "intl-messageformat": "^7.5.2", + "deepmerge": "^4.2.2", + "dlv": "^1.1.3", + "estree-walker": "^2.0.1", + "intl-messageformat": "^9.3.15", + "sade": "^1.7.4", "tiny-glob": "^0.2.6" } }, @@ -2586,6 +2605,11 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" + }, "trouter": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/trouter/-/trouter-2.0.1.tgz", @@ -2594,6 +2618,11 @@ "matchit": "^1.0.0" } }, + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + }, "uglify-js": { "version": "3.11.5", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.5.tgz", diff --git a/site/package.json b/site/package.json index c9effc2359..39e4dc0efa 100644 --- a/site/package.json +++ b/site/package.json @@ -9,7 +9,8 @@ "start": "node __sapper__/build", "cy:run": "cypress run", "cy:open": "cypress open", - "test": "run-p --race dev cy:run" + "test": "run-p --race dev cy:run", + "imageoptim": "imageoptim --imagealpha 'static/img/*.png'" }, "dependencies": { "@polka/send": "^0.4.0", @@ -20,7 +21,7 @@ "marked": "^1.2.2", "polka": "^0.5.2", "svelte-i18n": "^3.1.0", - "sirv": "^0.4.2" + "sirv": "^1.0.7" }, "devDependencies": { "@babel/core": "^7.12.3", diff --git a/site/static/img/accounts_org_register.png b/site/static/img/accounts_org_register.png index 0adaf3b2b6..0bf4e4a5aa 100644 Binary files a/site/static/img/accounts_org_register.png and b/site/static/img/accounts_org_register.png differ diff --git a/site/static/img/accounts_otp_select.png b/site/static/img/accounts_otp_select.png index 58f604ef3d..6524c64024 100644 Binary files a/site/static/img/accounts_otp_select.png and b/site/static/img/accounts_otp_select.png differ diff --git a/site/static/img/accounts_otp_setup.png b/site/static/img/accounts_otp_setup.png index 85d6fb1b04..7cd6188e70 100644 Binary files a/site/static/img/accounts_otp_setup.png and b/site/static/img/accounts_otp_setup.png differ diff --git a/site/static/img/accounts_otp_setup_done.png b/site/static/img/accounts_otp_setup_done.png index 09292f9209..e56c7f9e3a 100644 Binary files a/site/static/img/accounts_otp_setup_done.png and b/site/static/img/accounts_otp_setup_done.png differ diff --git a/site/static/img/accounts_otp_verify.png b/site/static/img/accounts_otp_verify.png index 2f037e82b6..6cc3ac5ff6 100644 Binary files a/site/static/img/accounts_otp_verify.png and b/site/static/img/accounts_otp_verify.png differ diff --git a/site/static/img/accounts_page.png b/site/static/img/accounts_page.png index a9258bf33f..52e274b876 100644 Binary files a/site/static/img/accounts_page.png and b/site/static/img/accounts_page.png differ diff --git a/site/static/img/accounts_password.png b/site/static/img/accounts_password.png index a1423ba5ee..a7cfb71930 100644 Binary files a/site/static/img/accounts_password.png and b/site/static/img/accounts_password.png differ diff --git a/site/static/img/accounts_verify_code_password.png b/site/static/img/accounts_verify_code_password.png index 1351f5ba89..2804272651 100644 Binary files a/site/static/img/accounts_verify_code_password.png and b/site/static/img/accounts_verify_code_password.png differ diff --git a/site/static/img/accounts_verify_code_password_done.png b/site/static/img/accounts_verify_code_password_done.png index cf64ede5b1..4598888096 100644 Binary files a/site/static/img/accounts_verify_code_password_done.png and b/site/static/img/accounts_verify_code_password_done.png differ diff --git a/site/static/img/console_admin_entry.png b/site/static/img/console_admin_entry.png index 87bc7bbaa0..3166ebb643 100644 Binary files a/site/static/img/console_admin_entry.png and b/site/static/img/console_admin_entry.png differ diff --git a/site/static/img/console_admin_system.png b/site/static/img/console_admin_system.png index f4262cfcd5..c48107b990 100644 Binary files a/site/static/img/console_admin_system.png and b/site/static/img/console_admin_system.png differ diff --git a/site/static/img/console_authz_add_1.png b/site/static/img/console_authz_add_1.png index 6209458ea5..157fcf1acc 100644 Binary files a/site/static/img/console_authz_add_1.png and b/site/static/img/console_authz_add_1.png differ diff --git a/site/static/img/console_authz_add_2.png b/site/static/img/console_authz_add_2.png index 511c225a3f..cd56c5a323 100644 Binary files a/site/static/img/console_authz_add_2.png and b/site/static/img/console_authz_add_2.png differ diff --git a/site/static/img/console_authz_add_3.png b/site/static/img/console_authz_add_3.png index 95279aeaa3..d95652ed5a 100644 Binary files a/site/static/img/console_authz_add_3.png and b/site/static/img/console_authz_add_3.png differ diff --git a/site/static/img/console_authz_overview.png b/site/static/img/console_authz_overview.png index 97b037d7ca..fca20ab82e 100644 Binary files a/site/static/img/console_authz_overview.png and b/site/static/img/console_authz_overview.png differ diff --git a/site/static/img/console_clients_my_first_spa_config.png b/site/static/img/console_clients_my_first_spa_config.png index 281b84b208..2e22583f66 100644 Binary files a/site/static/img/console_clients_my_first_spa_config.png and b/site/static/img/console_clients_my_first_spa_config.png differ diff --git a/site/static/img/console_clients_my_first_spa_wizard_1.png b/site/static/img/console_clients_my_first_spa_wizard_1.png index 5745a18b26..4b9ca19786 100644 Binary files a/site/static/img/console_clients_my_first_spa_wizard_1.png and b/site/static/img/console_clients_my_first_spa_wizard_1.png differ diff --git a/site/static/img/console_clients_my_first_spa_wizard_2.png b/site/static/img/console_clients_my_first_spa_wizard_2.png index 1df0c0c57a..b7beddf193 100644 Binary files a/site/static/img/console_clients_my_first_spa_wizard_2.png and b/site/static/img/console_clients_my_first_spa_wizard_2.png differ diff --git a/site/static/img/console_clients_my_first_spa_wizard_3.png b/site/static/img/console_clients_my_first_spa_wizard_3.png index e5d6009e70..7e84935b97 100644 Binary files a/site/static/img/console_clients_my_first_spa_wizard_3.png and b/site/static/img/console_clients_my_first_spa_wizard_3.png differ diff --git a/site/static/img/console_clients_my_first_spa_wizard_4.png b/site/static/img/console_clients_my_first_spa_wizard_4.png index 072bb1bba8..7f69d9550e 100644 Binary files a/site/static/img/console_clients_my_first_spa_wizard_4.png and b/site/static/img/console_clients_my_first_spa_wizard_4.png differ diff --git a/site/static/img/console_iam_admin_failed.png b/site/static/img/console_iam_admin_failed.png index 200ef92b94..e7df46db23 100644 Binary files a/site/static/img/console_iam_admin_failed.png and b/site/static/img/console_iam_admin_failed.png differ diff --git a/site/static/img/console_iam_admin_views.png b/site/static/img/console_iam_admin_views.png index 27f8ef52fd..a06deb2b42 100644 Binary files a/site/static/img/console_iam_admin_views.png and b/site/static/img/console_iam_admin_views.png differ diff --git a/site/static/img/console_org_domain.png b/site/static/img/console_org_domain.png index 973ed69cef..3f67f65fa8 100644 Binary files a/site/static/img/console_org_domain.png and b/site/static/img/console_org_domain.png differ diff --git a/site/static/img/console_org_domain_add.png b/site/static/img/console_org_domain_add.png index 96e5f9102c..8a22bc4076 100644 Binary files a/site/static/img/console_org_domain_add.png and b/site/static/img/console_org_domain_add.png differ diff --git a/site/static/img/console_org_domain_added.png b/site/static/img/console_org_domain_added.png index ba5b117bc6..a848f84faf 100644 Binary files a/site/static/img/console_org_domain_added.png and b/site/static/img/console_org_domain_added.png differ diff --git a/site/static/img/console_org_domain_default.png b/site/static/img/console_org_domain_default.png index e745955864..be763903de 100644 Binary files a/site/static/img/console_org_domain_default.png and b/site/static/img/console_org_domain_default.png differ diff --git a/site/static/img/console_org_domain_primary.png b/site/static/img/console_org_domain_primary.png index 4d32356330..5daf75d20c 100644 Binary files a/site/static/img/console_org_domain_primary.png and b/site/static/img/console_org_domain_primary.png differ diff --git a/site/static/img/console_org_domain_verified.png b/site/static/img/console_org_domain_verified.png index a217f6b398..551b6e4369 100644 Binary files a/site/static/img/console_org_domain_verified.png and b/site/static/img/console_org_domain_verified.png differ diff --git a/site/static/img/console_org_domain_verify.png b/site/static/img/console_org_domain_verify.png index 973ed69cef..3f67f65fa8 100644 Binary files a/site/static/img/console_org_domain_verify.png and b/site/static/img/console_org_domain_verify.png differ diff --git a/site/static/img/console_org_domain_verify_dns.png b/site/static/img/console_org_domain_verify_dns.png index 03dee5d4c8..8c1f90cfbf 100644 Binary files a/site/static/img/console_org_domain_verify_dns.png and b/site/static/img/console_org_domain_verify_dns.png differ diff --git a/site/static/img/console_org_manage_roles_1.png b/site/static/img/console_org_manage_roles_1.png index 33acfac613..43b7da2c09 100644 Binary files a/site/static/img/console_org_manage_roles_1.png and b/site/static/img/console_org_manage_roles_1.png differ diff --git a/site/static/img/console_org_manage_roles_2.png b/site/static/img/console_org_manage_roles_2.png index 5fa66c066d..b2565d5b05 100644 Binary files a/site/static/img/console_org_manage_roles_2.png and b/site/static/img/console_org_manage_roles_2.png differ diff --git a/site/static/img/console_personal_information.png b/site/static/img/console_personal_information.png index 92bd397373..2d1b20285a 100644 Binary files a/site/static/img/console_personal_information.png and b/site/static/img/console_personal_information.png differ diff --git a/site/static/img/console_personal_information_org_owner.png b/site/static/img/console_personal_information_org_owner.png index a5a6499e6c..4793134c6f 100644 Binary files a/site/static/img/console_personal_information_org_owner.png and b/site/static/img/console_personal_information_org_owner.png differ diff --git a/site/static/img/console_project_manage_roles_1.png b/site/static/img/console_project_manage_roles_1.png index 79d8d835ab..3b6e8a0db2 100644 Binary files a/site/static/img/console_project_manage_roles_1.png and b/site/static/img/console_project_manage_roles_1.png differ diff --git a/site/static/img/console_project_manage_roles_2.png b/site/static/img/console_project_manage_roles_2.png index 5688d3254b..8b272f6562 100644 Binary files a/site/static/img/console_project_manage_roles_2.png and b/site/static/img/console_project_manage_roles_2.png differ diff --git a/site/static/img/console_projects_empty.png b/site/static/img/console_projects_empty.png index b628e0ec2f..d057740ef6 100644 Binary files a/site/static/img/console_projects_empty.png and b/site/static/img/console_projects_empty.png differ diff --git a/site/static/img/console_projects_my_first_project.png b/site/static/img/console_projects_my_first_project.png index 6c871f95c7..64f2e0ab3c 100644 Binary files a/site/static/img/console_projects_my_first_project.png and b/site/static/img/console_projects_my_first_project.png differ diff --git a/site/static/img/console_user_create_done.png b/site/static/img/console_user_create_done.png index ccaf7bba1e..3d5b3d3eeb 100644 Binary files a/site/static/img/console_user_create_done.png and b/site/static/img/console_user_create_done.png differ diff --git a/site/static/img/console_user_create_form.png b/site/static/img/console_user_create_form.png index 12905a0356..27d1608417 100644 Binary files a/site/static/img/console_user_create_form.png and b/site/static/img/console_user_create_form.png differ diff --git a/site/static/img/console_user_entry.png b/site/static/img/console_user_entry.png index 0cfbaf5c4c..c798bda56b 100644 Binary files a/site/static/img/console_user_entry.png and b/site/static/img/console_user_entry.png differ diff --git a/site/static/img/console_user_list.png b/site/static/img/console_user_list.png index debba16db0..d8bea69939 100644 Binary files a/site/static/img/console_user_list.png and b/site/static/img/console_user_list.png differ diff --git a/site/static/img/console_user_list_search.png b/site/static/img/console_user_list_search.png index 0f92171183..35b49a265b 100644 Binary files a/site/static/img/console_user_list_search.png and b/site/static/img/console_user_list_search.png differ diff --git a/site/static/img/console_user_manage_roles_1.png b/site/static/img/console_user_manage_roles_1.png index aacaaf5e6d..b8ed7be016 100644 Binary files a/site/static/img/console_user_manage_roles_1.png and b/site/static/img/console_user_manage_roles_1.png differ diff --git a/site/static/img/console_user_manage_roles_2.png b/site/static/img/console_user_manage_roles_2.png index 7b254a5cb7..c0ebeace65 100644 Binary files a/site/static/img/console_user_manage_roles_2.png and b/site/static/img/console_user_manage_roles_2.png differ diff --git a/site/static/img/console_user_personal_info.png b/site/static/img/console_user_personal_info.png index 3ac63d34ca..292d524b3c 100644 Binary files a/site/static/img/console_user_personal_info.png and b/site/static/img/console_user_personal_info.png differ diff --git a/site/static/img/console_user_personal_information.png b/site/static/img/console_user_personal_information.png index 35072bef38..024be81e0f 100644 Binary files a/site/static/img/console_user_personal_information.png and b/site/static/img/console_user_personal_information.png differ diff --git a/site/static/img/develop2.png b/site/static/img/develop2.png index a2f11a63fd..72610ed390 100644 Binary files a/site/static/img/develop2.png and b/site/static/img/develop2.png differ diff --git a/site/static/img/grafana_client_settings.png b/site/static/img/grafana_client_settings.png index b9de9a8e29..ebe7cc223a 100644 Binary files a/site/static/img/grafana_client_settings.png and b/site/static/img/grafana_client_settings.png differ diff --git a/site/static/img/grafana_login_button.png b/site/static/img/grafana_login_button.png index 1cec6e2ef1..5926489069 100644 Binary files a/site/static/img/grafana_login_button.png and b/site/static/img/grafana_login_button.png differ diff --git a/site/static/img/grafana_profile_settings.png b/site/static/img/grafana_profile_settings.png index 6abaa028bd..f8c7f328fb 100644 Binary files a/site/static/img/grafana_profile_settings.png and b/site/static/img/grafana_profile_settings.png differ diff --git a/site/static/img/grafana_project_settings.png b/site/static/img/grafana_project_settings.png index f3fd6b1812..199412879e 100644 Binary files a/site/static/img/grafana_project_settings.png and b/site/static/img/grafana_project_settings.png differ diff --git a/site/static/img/grafana_zitadel_authorization.png b/site/static/img/grafana_zitadel_authorization.png index 27bd669cf3..e456ac25b3 100644 Binary files a/site/static/img/grafana_zitadel_authorization.png and b/site/static/img/grafana_zitadel_authorization.png differ diff --git a/site/static/img/personal2.png b/site/static/img/personal2.png index 07b64154f0..373fd332e0 100644 Binary files a/site/static/img/personal2.png and b/site/static/img/personal2.png differ diff --git a/site/static/img/projects2.png b/site/static/img/projects2.png index 29f394ce63..36b779e999 100644 Binary files a/site/static/img/projects2.png and b/site/static/img/projects2.png differ diff --git a/site/static/img/usermanual.png b/site/static/img/usermanual.png index 3b4cf3fa7b..5ae41a37fb 100644 Binary files a/site/static/img/usermanual.png and b/site/static/img/usermanual.png differ diff --git a/site/static/img/zitadel_cluster_architecture.png b/site/static/img/zitadel_cluster_architecture.png index c0669c691c..a968610b70 100644 Binary files a/site/static/img/zitadel_cluster_architecture.png and b/site/static/img/zitadel_cluster_architecture.png differ diff --git a/site/static/img/zitadel_multicluster_architecture.png b/site/static/img/zitadel_multicluster_architecture.png index a4c6d15e71..3efccde609 100644 Binary files a/site/static/img/zitadel_multicluster_architecture.png and b/site/static/img/zitadel_multicluster_architecture.png differ diff --git a/site/static/img/zitadel_software_architecture.png b/site/static/img/zitadel_software_architecture.png index 56cab91ffc..30e5442130 100644 Binary files a/site/static/img/zitadel_software_architecture.png and b/site/static/img/zitadel_software_architecture.png differ