Merge branch 'master' into new-eventstore

# Conflicts:
#	go.sum
This commit is contained in:
Fabiennne 2020-12-03 10:11:18 +01:00
commit 2a25c0b617
331 changed files with 6536 additions and 2046 deletions

View File

@ -32,3 +32,11 @@ updates:
commit-message:
prefix: chore
include: scope
- package-ecosystem: "docker"
directory: "/site/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
commit-message:
prefix: chore
include: scope

View File

@ -17,15 +17,19 @@ jobs:
steps:
- name: Checkout Repo
uses: actions/checkout@v2
- name: Install and Build
run: |
npm install
npx sapper export --legacy
- uses: docker/build-push-action@v2
with:
context: .
file: ./site/dockerfile
platforms: linux/amd64
tags: zitadel:docs
push: false
outputs: type=local,dest=output
- name: Archive Production Artifact
uses: actions/upload-artifact@master
with:
name: export
path: site/__sapper__/export
path: output
deploydocs:
name: Deploy
needs: builddocs

View File

@ -1,19 +0,0 @@
name: Spellcheck
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
spellcheck:
name: Typo CI (GitHub Action)
runs-on: ubuntu-latest
timeout-minutes: 4
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- name: TypoCheck
uses: typoci/spellcheck-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,42 +0,0 @@
# What language dictionaries should it use? Currently Typo CI supports:
# de
# en
# en_GB
# es
# fr
# it
# pt
# pt_BR
dictionaries:
- en
- en_GB
- de
# Any files/folders we should ignore?
excluded_files:
- ".codecov/*"
- ".github/*"
- "build/*"
- "k8s/*"
- "*.min.css"
- "*.css.map"
- "*.min.js"
- "*.js.map"
- "package-lock.json"
- "package.json"
- ".releaserc.js"
- ".typo-ci.yml"
- ".gitignore"
- "go.mod"
- "go.sum"
# Any typos we should ignore?
excluded_words:
- typoci
- idps
- ZITADEL's
- otel
- otlp
# Would you like filenames to also be spellchecked?
spellcheck_filenames: false

View File

@ -37,7 +37,7 @@ Go check it out under [zitadel.ch](https://zitadel.ch)
### Run your own IAM
Stay tuned, we will soon publish a guide how you can deploy a **hyperconverged** system with our automation tooling called [**ORBOS**](https://github.com/caos/orbos/).
With [**ORBOS**](https://github.com/caos/orbos/) you will be able to run [**Kubernetes**](https://kubernetes.io/) on **GCE** or **StaticProvider** within 20 minutes. To achieve this, [[**ORBOS**](https://github.com/caos/orbos/) will bootstrap and maintain a [**Kubernetes**](https://kubernetes.io/) cluster, essential platform components (logging, metrics, ingress, ...), a secure [**CockroachDB**](https://www.cockroachlabs.com/) cluster and **ZITADEL** itself.
With [**ORBOS**](https://github.com/caos/orbos/) you will be able to run [**Kubernetes**](https://kubernetes.io/) with Google on **[GCEProvider](https://cloud.google.com/compute)**, on **[StaticProvider](https://github.com/caos/orbos/blob/master/docs/orbiter/static.md)** for in-house scenarios or on the Swiss based **[CloudscaleProvider](https://www.cloudscale.ch/)** within 20 minutes. To achieve this, [**ORBOS**](https://github.com/caos/orbos/) will bootstrap and maintain a [**Kubernetes**](https://kubernetes.io/) cluster, essential platform components (logging, metrics, ingress, ...), a secure [**CockroachDB**](https://www.cockroachlabs.com/) cluster and **ZITADEL** itself.
The combination of the tools [**ORBOS**](https://github.com/caos/orbos/) and **ZITADEL** is what makes the operation easy and scalable.

View File

@ -34,7 +34,7 @@ COPY internal/protoc/protoc-gen-authoption/authoption/options.proto authoption/o
## With this step we prepare all node_modules, this helps caching the build
## Speed up this step by mounting your local node_modules directory
#######################
FROM node:12 as npm-base
FROM node:15 as npm-base
WORKDIR console
COPY console/package.json console/package-lock.json ./
RUN npm install \

View File

@ -11,6 +11,8 @@ export ZITADEL_TRACING_FRACTION=0.1
export ZITADEL_TRACING_ENDPOINT=localhost:9096
export ZITADEL_TRACING_TYPE=google
export ZITADEL_METRICS_TYPE=otel
# Log
export ZITADEL_LOG_LEVEL=debug

View File

@ -3,6 +3,7 @@ package main
import (
"context"
"flag"
metrics "github.com/caos/zitadel/internal/telemetry/metrics/config"
"github.com/caos/logging"
admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing"
@ -21,7 +22,7 @@ import (
mgmt_es "github.com/caos/zitadel/internal/management/repository/eventsourcing"
"github.com/caos/zitadel/internal/notification"
"github.com/caos/zitadel/internal/setup"
tracing "github.com/caos/zitadel/internal/tracing/config"
tracing "github.com/caos/zitadel/internal/telemetry/tracing/config"
"github.com/caos/zitadel/internal/ui"
"github.com/caos/zitadel/internal/ui/console"
"github.com/caos/zitadel/internal/ui/login"
@ -30,6 +31,7 @@ import (
type Config struct {
Log logging.Config
Tracing tracing.TracingConfig
Metrics metrics.MetricsConfig
InternalAuthZ internal_authz.Config
SystemDefaults sd.SystemDefaults
@ -125,14 +127,16 @@ func startUI(ctx context.Context, conf *Config, authRepo *auth_es.EsRepository)
}
func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsRepository, authRepo *auth_es.EsRepository) {
apis := api.Create(conf.API, conf.InternalAuthZ, authZRepo, conf.SystemDefaults)
roles := make([]string, len(conf.InternalAuthZ.RolePermissionMappings))
for i, role := range conf.InternalAuthZ.RolePermissionMappings {
roles[i] = role.Role
}
adminRepo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, roles)
logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo")
apis := api.Create(conf.API, conf.InternalAuthZ, authZRepo, authRepo, adminRepo, conf.SystemDefaults)
if *adminEnabled {
adminRepo, err := admin_es.Start(ctx, conf.Admin, conf.SystemDefaults, roles)
logging.Log("API-D42tq").OnError(err).Fatal("error starting auth repo")
apis.RegisterServer(ctx, admin.CreateServer(adminRepo))
}
if *managementEnabled {

View File

@ -96,4 +96,6 @@ SetUp:
PrimaryColor: '#222324'
SecondaryColor: '#ffffff'
Step7:
DefaultSecondFactor: 1 #SecondFactorTypeOTP
DefaultSecondFactor: 1 #SecondFactorTypeOTP
Step8:
DefaultSecondFactor: 2 #SecondFactorTypeU2F

View File

@ -11,6 +11,11 @@ Tracing:
Fraction: $ZITADEL_TRACING_FRACTION
Endpoint: $ZITADEL_TRACING_ENDPOINT
Metrics:
Type: 'otel'
Config:
MeterName: 'github.com/caos/zitadel'
AuthZ:
Repository:
Eventstore:
@ -224,7 +229,7 @@ UI:
Login:
Handler:
BaseURL: '$ZITADEL_ACCOUNTS'
OidcAuthCallbackURL: '$ZITADEL_AUTHORIZE/authorize/'
OidcAuthCallbackURL: '$ZITADEL_AUTHORIZE/authorize/callback?id='
ZitadelURL: '$ZITADEL_CONSOLE'
LanguageCookieName: 'caos.zitadel.login.lang'
DefaultLanguage: 'de'

View File

@ -53,7 +53,7 @@ SystemDefaults:
VerificationLifetimes:
PasswordCheck: 240h #10d
ExternalLoginCheck: 240h #10d
MfaInitSkip: 720h #30d
MFAInitSkip: 720h #30d
SecondFactorCheck: 18h
MultiFactorCheck: 12h
IamID: 'IAM'
@ -124,4 +124,8 @@ SystemDefaults:
Subject: 'DomainClaimed.Subject'
Greeting: 'DomainClaimed.Greeting'
Text: 'DomainClaimed.Text'
ButtonText: 'DomainClaimed.ButtonText'
ButtonText: 'DomainClaimed.ButtonText'
WebAuthN:
ID: $ZITADEL_COOKIE_DOMAIN
Origin: $ZITADEL_ACCOUNTS
DisplayName: ZITADEL

View File

@ -18,13 +18,20 @@
<td mat-cell *matCellDef="let view"> {{view.processedSequence}} </td>
</ng-container>
<ng-container matColumnDef="timestamp">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.TIMESTAMP' | translate }} </th>
<ng-container matColumnDef="eventTimestamp">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.EVENTTIMESTAMP' | translate }} </th>
<td mat-cell *matCellDef="let view">
<span>{{view?.viewTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
<span>{{view?.eventTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
</td>
</ng-container>
<ng-container matColumnDef="lastSuccessfulSpoolerRun">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.LASTSPOOL' | translate }} </th>
<td mat-cell *matCellDef="let view">
<span>{{view?.lastSuccessfulSpoolerRun | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
</td>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let view">
@ -41,4 +48,4 @@
<mat-paginator class="paginator" [pageSize]="10" #paginator [pageSizeOptions]="[10, 20, 100, 250]">
</mat-paginator>
</app-refresh-table>
</div>
</div>

View File

@ -21,7 +21,7 @@ export class IamViewsComponent implements AfterViewInit {
@ViewChild(MatPaginator) public paginator!: MatPaginator;
public dataSource!: MatTableDataSource<View.AsObject>;
public displayedColumns: string[] = ['viewName', 'database', 'sequence', 'timestamp', 'actions'];
public displayedColumns: string[] = ['viewName', 'database', 'sequence', 'eventTimestamp', 'lastSuccessfulSpoolerRun', 'actions'];
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();

View File

@ -164,8 +164,8 @@
"OTP_DIALOG_DESCRIPTION": "Scanne den QR-Code mit einer Authenticator App und verifiziere den erhaltenen Code, um OTP zu aktivieren.",
"TYPE": {
"0":"Keine MFA definiert",
"1":"SMS",
"2":"OTP"
"1":"OTP",
"2":"U2F"
},
"STATE": {
"0": "Kein Status",
@ -392,7 +392,8 @@
"VIEWNAME":"Name",
"DATABASE":"Datenbank",
"SEQUENCE":"Sequenz",
"TIMESTAMP":"Zeitstempel",
"EVENTTIMESTAMP":"Event Zeitstempel",
"LASTSPOOL": "Erfolgreicher Durchlauf",
"ACTIONS":"Aktionen",
"CLEAR":"Aufräumen",
"CLEARED":"View wurde erfolgreich zurückgesetzt!",

View File

@ -164,8 +164,8 @@
"OTP_DIALOG_DESCRIPTION": "Scan the QR code with an authenticator app and enter the code below to verify and activate the OTP method.",
"TYPE": {
"0": "No MFA defined",
"1": "SMS",
"2": "OTP"
"1": "OTP",
"2": "U2F"
},
"STATE": {
"0": "No State",
@ -392,7 +392,8 @@
"VIEWNAME":"Name",
"DATABASE":"Database",
"SEQUENCE":"Sequence",
"TIMESTAMP":"Timestamp",
"EVENTTIMESTAMP":"Timestamp",
"LASTSPOOL": "Successful spool",
"ACTIONS":"Actions",
"CLEAR":"Clear",
"CLEARED":"View was successfully cleared!",

9
go.mod
View File

@ -15,14 +15,16 @@ require (
github.com/allegro/bigcache v1.2.1
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc
github.com/caos/logging v0.0.2
github.com/caos/oidc v0.13.0
github.com/caos/oidc v0.13.1
github.com/cockroachdb/cockroach-go/v2 v2.0.8
github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43
github.com/envoyproxy/protoc-gen-validate v0.4.1
github.com/ghodss/yaml v1.0.0
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.4.3
github.com/golang/snappy v0.0.2 // indirect
github.com/google/go-cmp v0.5.3 // indirect
github.com/gorilla/csrf v1.7.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
@ -45,6 +47,8 @@ require (
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/nicksnyder/go-i18n/v2 v2.1.1
github.com/pquerna/otp v1.2.0
github.com/prometheus/client_golang v1.8.0 // indirect
github.com/prometheus/common v0.15.0 // indirect
github.com/rakyll/statik v0.1.7
github.com/rs/cors v1.7.0
github.com/sony/sonyflake v1.0.0
@ -54,12 +58,13 @@ require (
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.13.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.13.0
go.opentelemetry.io/otel v0.13.0
go.opentelemetry.io/otel/exporters/metric/prometheus v0.13.0
go.opentelemetry.io/otel/exporters/otlp v0.13.0
go.opentelemetry.io/otel/exporters/stdout v0.13.0
go.opentelemetry.io/otel/sdk v0.13.0
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 // indirect
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // indirect
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
golang.org/x/text v0.3.4
golang.org/x/tools v0.0.0-20201103235415-b653051172e4
google.golang.org/appengine v1.6.7 // indirect

428
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ import (
type AdministratorRepository interface {
GetFailedEvents(context.Context) ([]*model.FailedEvent, error)
RemoveFailedEvent(context.Context, *model.FailedEvent) error
GetViews(context.Context) ([]*model.View, error)
ClearView(ctx context.Context, db, view string) error
GetViews() ([]*model.View, error)
GetSpoolerDiv(db, viewName string) int64
ClearView(ctx context.Context, db, viewName string) error
}

View File

@ -5,6 +5,7 @@ import (
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
view_model "github.com/caos/zitadel/internal/view/model"
"github.com/caos/zitadel/internal/view/repository"
"time"
)
var dbList = []string{"management", "auth", "authz", "adminapi", "notification"}
@ -31,7 +32,7 @@ func (repo *AdministratorRepo) RemoveFailedEvent(ctx context.Context, failedEven
return repo.View.RemoveFailedEvent(failedEvent.Database, repository.FailedEventFromModel(failedEvent))
}
func (repo *AdministratorRepo) GetViews(ctx context.Context) ([]*view_model.View, error) {
func (repo *AdministratorRepo) GetViews() ([]*view_model.View, error) {
views := make([]*view_model.View, 0)
for _, db := range dbList {
sequences, err := repo.View.AllCurrentSequences(db)
@ -45,6 +46,16 @@ func (repo *AdministratorRepo) GetViews(ctx context.Context) ([]*view_model.View
return views, nil
}
func (repo *AdministratorRepo) GetSpoolerDiv(database, view string) int64 {
sequence, err := repo.View.GetCurrentSequence(database, view)
if err != nil {
return 0
}
divDuration := time.Now().Sub(sequence.LastSuccessfulSpoolerRun)
return divDuration.Milliseconds()
}
func (repo *AdministratorRepo) ClearView(ctx context.Context, database, view string) error {
return repo.View.ClearView(database, view)
}

View File

@ -15,7 +15,7 @@ import (
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
@ -81,7 +81,7 @@ func (repo *IAMRepository) SearchIAMMembers(ctx context.Context, request *iam_mo
}
if err == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}
@ -206,7 +206,7 @@ func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
}
if err == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}
@ -298,7 +298,7 @@ func (repo *IAMRepository) SearchDefaultIDPProviders(ctx context.Context, reques
}
if err == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}

View File

@ -6,7 +6,7 @@ import (
"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/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/logging"
admin_model "github.com/caos/zitadel/internal/admin/model"
@ -101,7 +101,7 @@ func (repo *OrgRepo) SearchOrgs(ctx context.Context, query *org_model.OrgSearchR
}
if err == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}

View File

@ -41,7 +41,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
&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},
&IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), 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},
@ -49,7 +49,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
&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},
&ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount},
orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults},
}
}

View File

@ -72,14 +72,14 @@ func (m *IamMember) processIamMember(event *models.Event) (err error) {
if err != nil {
return err
}
return m.view.DeleteIAMMember(event.AggregateID, member.UserID, event.Sequence)
return m.view.DeleteIAMMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedIAMMemberSequence(event.Sequence)
return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutIAMMember(member, member.Sequence)
return m.view.PutIAMMember(member, member.Sequence, event.CreationDate)
}
func (m *IamMember) processUser(event *models.Event) (err error) {
@ -94,7 +94,7 @@ func (m *IamMember) processUser(event *models.Event) (err error) {
return err
}
if len(members) == 0 {
return m.view.ProcessedIAMMemberSequence(event.Sequence)
return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate)
}
user, err := m.userEvents.UserByID(context.Background(), event.AggregateID)
if err != nil {
@ -103,11 +103,11 @@ func (m *IamMember) processUser(event *models.Event) (err error) {
for _, member := range members {
m.fillUserData(member, user)
}
return m.view.PutIAMMembers(members, event.Sequence)
return m.view.PutIAMMembers(members, event.Sequence, event.CreationDate)
case usr_es_model.UserRemoved:
return m.view.DeleteIAMMembersByUserID(event.AggregateID, event.Sequence)
return m.view.DeleteIAMMembersByUserID(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedIAMMemberSequence(event.Sequence)
return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate)
}
return nil
}
@ -137,3 +137,7 @@ func (m *IamMember) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Ld9ow", "id", event.AggregateID).WithError(err).Warn("something went wrong in iammember handler")
return spooler.HandleError(event, err, m.view.GetLatestIAMMemberFailedEvent, m.view.ProcessedIAMMemberFailedEvent, m.view.ProcessedIAMMemberSequence, m.errorCountUntilSkip)
}
func (m *IamMember) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateIAMMemberSpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
idpConfigTable = "adminapi.idp_configs"
)
func (m *IDPConfig) ViewModel() string {
func (i *IDPConfig) ViewModel() string {
return idpConfigTable
}
func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestIDPConfigSequence()
func (i *IDPConfig) EventQuery() (*models.SearchQuery, error) {
sequence, err := i.view.GetLatestIDPConfigSequence()
if err != nil {
return nil, err
}
@ -33,15 +33,15 @@ func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *IDPConfig) Reduce(event *models.Event) (err error) {
func (i *IDPConfig) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate:
err = m.processIDPConfig(event)
err = i.processIDPConfig(event)
}
return err
}
func (m *IDPConfig) processIDPConfig(event *models.Event) (err error) {
func (i *IDPConfig) processIDPConfig(event *models.Event) (err error) {
idp := new(iam_view_model.IDPConfigView)
switch event.Type {
case model.IDPConfigAdded:
@ -53,7 +53,7 @@ func (m *IDPConfig) processIDPConfig(event *models.Event) (err error) {
if err != nil {
return err
}
idp, err = m.view.IDPConfigByID(idp.IDPConfigID)
idp, err = i.view.IDPConfigByID(idp.IDPConfigID)
if err != nil {
return err
}
@ -63,17 +63,21 @@ func (m *IDPConfig) processIDPConfig(event *models.Event) (err error) {
if err != nil {
return err
}
return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence)
return i.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedIDPConfigSequence(event.Sequence)
return i.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutIDPConfig(idp, idp.Sequence)
return i.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate)
}
func (m *IDPConfig) OnError(event *models.Event, err error) error {
func (i *IDPConfig) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Mslo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler")
return spooler.HandleError(event, err, m.view.GetLatestIDPConfigFailedEvent, m.view.ProcessedIDPConfigFailedEvent, m.view.ProcessedIDPConfigSequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip)
}
func (i *IDPConfig) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPConfigSpoolerRunTimestamp)
}

View File

@ -27,12 +27,12 @@ const (
idpProviderTable = "adminapi.idp_providers"
)
func (m *IDPProvider) ViewModel() string {
func (i *IDPProvider) ViewModel() string {
return idpProviderTable
}
func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestIDPProviderSequence()
func (i *IDPProvider) EventQuery() (*models.SearchQuery, error) {
sequence, err := i.view.GetLatestIDPProviderSequence()
if err != nil {
return nil, err
}
@ -41,15 +41,15 @@ func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *IDPProvider) Reduce(event *models.Event) (err error) {
func (i *IDPProvider) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate, org_es_model.OrgAggregate:
err = m.processIdpProvider(event)
err = i.processIdpProvider(event)
}
return err
}
func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) {
func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) {
provider := new(iam_view_model.IDPProviderView)
switch event.Type {
case model.LoginPolicyIDPProviderAdded, org_es_model.LoginPolicyIDPProviderAdded:
@ -57,64 +57,68 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) {
if err != nil {
return err
}
err = m.fillData(provider)
err = i.fillData(provider)
case model.LoginPolicyIDPProviderRemoved, model.LoginPolicyIDPProviderCascadeRemoved,
org_es_model.LoginPolicyIDPProviderRemoved, org_es_model.LoginPolicyIDPProviderCascadeRemoved:
err = provider.SetData(event)
if err != nil {
return err
}
return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence)
return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate)
case model.IDPConfigChanged, org_es_model.IDPConfigChanged:
esConfig := new(iam_view_model.IDPConfigView)
providerType := iam_model.IDPProviderTypeSystem
if event.AggregateID != m.systemDefaults.IamID {
if event.AggregateID != i.systemDefaults.IamID {
providerType = iam_model.IDPProviderTypeOrg
}
esConfig.AppendEvent(providerType, event)
providers, err := m.view.IDPProvidersByIdpConfigID(esConfig.IDPConfigID)
providers, err := i.view.IDPProvidersByIdpConfigID(esConfig.IDPConfigID)
if err != nil {
return err
}
config, err := m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err := i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
if err != nil {
return err
}
for _, provider := range providers {
m.fillConfigData(provider, config)
i.fillConfigData(provider, config)
}
return m.view.PutIDPProviders(event.Sequence, providers...)
return i.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...)
default:
return m.view.ProcessedIDPProviderSequence(event.Sequence)
return i.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutIDPProvider(provider, provider.Sequence)
return i.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate)
}
func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
var config *iam_model.IDPConfig
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, provider.IDPConfigID)
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, provider.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
config, err = i.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
}
if err != nil {
return err
}
m.fillConfigData(provider, config)
i.fillConfigData(provider, config)
return nil
}
func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) {
func (i *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)
}
func (m *IDPProvider) OnError(event *models.Event, err error) error {
func (i *IDPProvider) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Msj8c", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler")
return spooler.HandleError(event, err, m.view.GetLatestIDPProviderFailedEvent, m.view.ProcessedIDPProviderFailedEvent, m.view.ProcessedIDPProviderSequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, i.view.GetLatestIDPProviderFailedEvent, i.view.ProcessedIDPProviderFailedEvent, i.view.ProcessedIDPProviderSequence, i.errorCountUntilSkip)
}
func (i *IDPProvider) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp)
}

View File

@ -18,12 +18,12 @@ const (
labelPolicyTable = "adminapi.label_policies"
)
func (m *LabelPolicy) ViewModel() string {
func (p *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
func (p *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
@ -32,35 +32,39 @@ func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LabelPolicy) Reduce(event *models.Event) (err error) {
func (p *LabelPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate:
err = m.processLabelPolicy(event)
err = p.processLabelPolicy(event)
}
return err
}
func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.LabelPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
default:
return m.view.ProcessedLabelPolicySequence(event.Sequence)
return p.view.ProcessedLabelPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutLabelPolicy(policy, policy.Sequence)
return p.view.PutLabelPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *LabelPolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestLabelPolicyFailedEvent, p.view.ProcessedLabelPolicyFailedEvent, p.view.ProcessedLabelPolicySequence, p.errorCountUntilSkip)
}
func (p *LabelPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateLabelPolicySpoolerRunTimestamp)
}

View File

@ -18,12 +18,12 @@ const (
loginPolicyTable = "adminapi.login_policies"
)
func (m *LoginPolicy) ViewModel() string {
func (p *LoginPolicy) ViewModel() string {
return loginPolicyTable
}
func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLoginPolicySequence()
func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestLoginPolicySequence()
if err != nil {
return nil, err
}
@ -32,15 +32,15 @@ func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LoginPolicy) Reduce(event *models.Event) (err error) {
func (p *LoginPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate:
err = m.processLoginPolicy(event)
err = p.processLoginPolicy(event)
}
return err
}
func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
policy := new(iam_model.LoginPolicyView)
switch event.Type {
case model.LoginPolicyAdded:
@ -50,21 +50,25 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
model.LoginPolicySecondFactorRemoved,
model.LoginPolicyMultiFactorAdded,
model.LoginPolicyMultiFactorRemoved:
policy, err = m.view.LoginPolicyByAggregateID(event.AggregateID)
policy, err = p.view.LoginPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
default:
return m.view.ProcessedLoginPolicySequence(event.Sequence)
return p.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutLoginPolicy(policy, policy.Sequence)
return p.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *LoginPolicy) OnError(event *models.Event, err error) error {
func (p *LoginPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Wj8sf", "id", event.AggregateID).WithError(err).Warn("something went wrong in login policy handler")
return spooler.HandleError(event, err, m.view.GetLatestLoginPolicyFailedEvent, m.view.ProcessedLoginPolicyFailedEvent, m.view.ProcessedLoginPolicySequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, p.view.GetLatestLoginPolicyFailedEvent, p.view.ProcessedLoginPolicyFailedEvent, p.view.ProcessedLoginPolicySequence, p.errorCountUntilSkip)
}
func (p *LoginPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateLoginPolicySpoolerRunTimestamp)
}

View File

@ -53,13 +53,17 @@ func (o *Org) Reduce(event *es_models.Event) error {
return err
}
default:
return o.view.ProcessedOrgSequence(event.Sequence)
return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate)
}
return o.view.PutOrg(org)
return o.view.PutOrg(org, event.CreationDate)
}
func (o *Org) OnError(event *es_models.Event, spoolerErr error) error {
logging.LogWithFields("SPOOL-ls9ew", "id", event.AggregateID).WithError(spoolerErr).Warn("something went wrong in project app handler")
return spooler.HandleError(event, spoolerErr, o.view.GetLatestOrgFailedEvent, o.view.ProcessedOrgFailedEvent, o.view.ProcessedOrgSequence, o.errorCountUntilSkip)
}
func (o *Org) OnSuccess() error {
return spooler.HandleSuccess(o.view.UpdateOrgSpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
orgIAMPolicyTable = "adminapi.org_iam_policies"
)
func (m *OrgIAMPolicy) ViewModel() string {
func (p *OrgIAMPolicy) ViewModel() string {
return orgIAMPolicyTable
}
func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestOrgIAMPolicySequence()
func (p *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestOrgIAMPolicySequence()
if err != nil {
return nil, err
}
@ -33,37 +33,41 @@ func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *OrgIAMPolicy) Reduce(event *models.Event) (err error) {
func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processOrgIAMPolicy(event)
err = p.processOrgIAMPolicy(event)
}
return err
}
func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.OrgIAMPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.OrgIAMPolicyRemoved:
return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence)
return p.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedOrgIAMPolicySequence(event.Sequence)
return p.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutOrgIAMPolicy(policy, policy.Sequence)
return p.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicySequence, p.errorCountUntilSkip)
}
func (p *OrgIAMPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateOrgIAMPolicySpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
passwordAgePolicyTable = "adminapi.password_age_policies"
)
func (m *PasswordAgePolicy) ViewModel() string {
func (p *PasswordAgePolicy) ViewModel() string {
return passwordAgePolicyTable
}
func (m *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordAgePolicySequence()
func (p *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestPasswordAgePolicySequence()
if err != nil {
return nil, err
}
@ -33,37 +33,41 @@ func (m *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordAgePolicy) Reduce(event *models.Event) (err error) {
func (p *PasswordAgePolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordAgePolicy(event)
err = p.processPasswordAgePolicy(event)
}
return err
}
func (m *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.PasswordAgePolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordAgePolicyRemoved:
return m.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence)
return p.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedPasswordAgePolicySequence(event.Sequence)
return p.view.ProcessedPasswordAgePolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutPasswordAgePolicy(policy, policy.Sequence)
return p.view.PutPasswordAgePolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *PasswordAgePolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestPasswordAgePolicyFailedEvent, p.view.ProcessedPasswordAgePolicyFailedEvent, p.view.ProcessedPasswordAgePolicySequence, p.errorCountUntilSkip)
}
func (p *PasswordAgePolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateProcessedPasswordAgePolicySpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
passwordComplexityPolicyTable = "adminapi.password_complexity_policies"
)
func (m *PasswordComplexityPolicy) ViewModel() string {
func (p *PasswordComplexityPolicy) ViewModel() string {
return passwordComplexityPolicyTable
}
func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordComplexityPolicySequence()
func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestPasswordComplexityPolicySequence()
if err != nil {
return nil, err
}
@ -33,37 +33,41 @@ func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) {
func (p *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordComplexityPolicy(event)
err = p.processPasswordComplexityPolicy(event)
}
return err
}
func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.PasswordComplexityPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordComplexityPolicyRemoved:
return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence)
return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence)
return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence)
return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicySequence, p.errorCountUntilSkip)
}
func (p *PasswordComplexityPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdatePasswordComplexityPolicySpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
passwordLockoutPolicyTable = "adminapi.password_lockout_policies"
)
func (m *PasswordLockoutPolicy) ViewModel() string {
func (p *PasswordLockoutPolicy) ViewModel() string {
return passwordLockoutPolicyTable
}
func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordLockoutPolicySequence()
func (p *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestPasswordLockoutPolicySequence()
if err != nil {
return nil, err
}
@ -33,37 +33,41 @@ func (m *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) {
func (p *PasswordLockoutPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordLockoutPolicy(event)
err = p.processPasswordLockoutPolicy(event)
}
return err
}
func (m *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.PasswordLockoutPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordLockoutPolicyRemoved:
return m.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence)
return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedPasswordLockoutPolicySequence(event.Sequence)
return p.view.ProcessedPasswordLockoutPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutPasswordLockoutPolicy(policy, policy.Sequence)
return p.view.PutPasswordLockoutPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *PasswordLockoutPolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestPasswordLockoutPolicyFailedEvent, p.view.ProcessedPasswordLockoutPolicyFailedEvent, p.view.ProcessedPasswordLockoutPolicySequence, p.errorCountUntilSkip)
}
func (p *PasswordLockoutPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdatePasswordLockoutPolicySpoolerRunTimestamp)
}

View File

@ -92,6 +92,12 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
es_model.HumanMFAOTPAdded,
es_model.HumanMFAOTPVerified,
es_model.HumanMFAOTPRemoved,
es_model.HumanMFAU2FTokenAdded,
es_model.HumanMFAU2FTokenVerified,
es_model.HumanMFAU2FTokenRemoved,
es_model.HumanPasswordlessTokenAdded,
es_model.HumanPasswordlessTokenVerified,
es_model.HumanPasswordlessTokenRemoved,
es_model.MachineChanged:
user, err = u.view.UserByID(event.AggregateID)
if err != nil {
@ -110,14 +116,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
}
err = u.fillLoginNames(user)
case es_model.UserRemoved:
return u.view.DeleteUser(event.AggregateID, event.Sequence)
return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserSequence(event.Sequence)
return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return u.view.PutUser(user, user.Sequence)
return u.view.PutUser(user, user.Sequence, event.CreationDate)
}
func (u *User) ProcessOrg(event *models.Event) (err error) {
@ -131,7 +137,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
case org_es_model.OrgDomainPrimarySet:
return u.fillPreferredLoginNamesOnOrgUsers(event)
default:
return u.view.ProcessedUserSequence(event.Sequence)
return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate)
}
}
@ -154,7 +160,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
for _, user := range users {
user.SetLoginNames(policy, org.Domains)
}
return u.view.PutUsers(users, event.Sequence)
return u.view.PutUsers(users, event.Sequence, event.CreationDate)
}
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
@ -179,7 +185,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
for _, user := range users {
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
}
return u.view.PutUsers(users, event.Sequence)
return u.view.PutUsers(users, event.Sequence, event.CreationDate)
}
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
@ -203,3 +209,7 @@ func (u *User) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-vLmwQ", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler")
return spooler.HandleError(event, err, u.view.GetLatestUserFailedEvent, u.view.ProcessedUserFailedEvent, u.view.ProcessedUserSequence, u.errorCountUntilSkip)
}
func (u *User) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp)
}

View File

@ -30,12 +30,12 @@ const (
externalIDPTable = "adminapi.user_external_idps"
)
func (m *ExternalIDP) ViewModel() string {
func (i *ExternalIDP) ViewModel() string {
return externalIDPTable
}
func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestExternalIDPSequence()
func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) {
sequence, err := i.view.GetLatestExternalIDPSequence()
if err != nil {
return nil, err
}
@ -44,17 +44,17 @@ func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *ExternalIDP) Reduce(event *models.Event) (err error) {
func (i *ExternalIDP) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.UserAggregate:
err = m.processUser(event)
err = i.processUser(event)
case iam_es_model.IAMAggregate, org_es_model.OrgAggregate:
err = m.processIdpConfig(event)
err = i.processIdpConfig(event)
}
return err
}
func (m *ExternalIDP) processUser(event *models.Event) (err error) {
func (i *ExternalIDP) processUser(event *models.Event) (err error) {
externalIDP := new(usr_view_model.ExternalIDPView)
switch event.Type {
case model.HumanExternalIDPAdded:
@ -62,25 +62,25 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) {
if err != nil {
return err
}
err = m.fillData(externalIDP)
err = i.fillData(externalIDP)
case model.HumanExternalIDPRemoved, model.HumanExternalIDPCascadeRemoved:
err = externalIDP.SetData(event)
if err != nil {
return err
}
return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence)
return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate)
case model.UserRemoved:
return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence)
return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedExternalIDPSequence(event.Sequence)
return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutExternalIDP(externalIDP, externalIDP.Sequence)
return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate)
}
func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
func (i *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)
@ -90,45 +90,49 @@ func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
} else {
configView.AppendEvent(iam_model.IDPProviderTypeOrg, event)
}
exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID)
exterinalIDPs, err := i.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID)
if err != nil {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err
}
for _, provider := range exterinalIDPs {
m.fillConfigData(provider, config)
i.fillConfigData(provider, config)
}
return m.view.PutExternalIDPs(event.Sequence, exterinalIDPs...)
return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...)
default:
return m.view.ProcessedExternalIDPSequence(event.Sequence)
return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate)
}
return nil
}
func (m *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := m.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
if caos_errs.IsNotFound(err) {
config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, externalIDP.IDPConfigID)
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID)
}
if err != nil {
return err
}
m.fillConfigData(externalIDP, config)
i.fillConfigData(externalIDP, config)
return nil
}
func (m *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) {
func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) {
externalIDP.IDPName = config.Name
}
func (m *ExternalIDP) OnError(event *models.Event, err error) error {
func (i *ExternalIDP) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-4Rsu8", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler")
return spooler.HandleError(event, err, m.view.GetLatestExternalIDPFailedEvent, m.view.ProcessedExternalIDPFailedEvent, m.view.ProcessedExternalIDPSequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, i.view.GetLatestExternalIDPFailedEvent, i.view.ProcessedExternalIDPFailedEvent, i.view.ProcessedExternalIDPSequence, i.errorCountUntilSkip)
}
func (i *ExternalIDP) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp)
}

View File

@ -6,6 +6,7 @@ import (
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/zitadel/internal/user/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
"time"
)
const (
@ -32,44 +33,48 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) (
return view.SearchExternalIDPs(v.Db, externalIDPTable, request)
}
func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64) error {
func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP)
if err != nil {
return err
}
return v.ProcessedExternalIDPSequence(sequence)
return v.ProcessedExternalIDPSequence(sequence, eventTimestamp)
}
func (v *View) PutExternalIDPs(sequence uint64, externalIDPs ...*model.ExternalIDPView) error {
func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error {
err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...)
if err != nil {
return err
}
return v.ProcessedExternalIDPSequence(sequence)
return v.ProcessedExternalIDPSequence(sequence, eventTimestamp)
}
func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64) error {
func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedExternalIDPSequence(eventSequence)
return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp)
}
func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64) error {
func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID)
if err != nil {
return err
}
return v.ProcessedExternalIDPSequence(eventSequence)
return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp)
}
func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(externalIDPTable)
}
func (v *View) ProcessedExternalIDPSequence(eventSequence uint64) error {
return v.saveCurrentSequence(externalIDPTable, eventSequence)
func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(externalIDPTable)
}
func (v *View) GetLatestExternalIDPFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -6,6 +6,7 @@ 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"
"time"
)
const (
@ -24,44 +25,48 @@ func (v *View) IAMMembersByUserID(userID string) ([]*model.IAMMemberView, error)
return view.IAMMembersByUserID(v.Db, iamMemberTable, userID)
}
func (v *View) PutIAMMember(org *model.IAMMemberView, sequence uint64) error {
func (v *View) PutIAMMember(org *model.IAMMemberView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutIAMMember(v.Db, iamMemberTable, org)
if err != nil {
return err
}
return v.ProcessedIAMMemberSequence(sequence)
return v.ProcessedIAMMemberSequence(sequence, eventTimestamp)
}
func (v *View) PutIAMMembers(members []*model.IAMMemberView, sequence uint64) error {
func (v *View) PutIAMMembers(members []*model.IAMMemberView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutIAMMembers(v.Db, iamMemberTable, members...)
if err != nil {
return err
}
return v.ProcessedIAMMemberSequence(sequence)
return v.ProcessedIAMMemberSequence(sequence, eventTimestamp)
}
func (v *View) DeleteIAMMember(iamID, userID string, eventSequence uint64) error {
func (v *View) DeleteIAMMember(iamID, userID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteIAMMember(v.Db, iamMemberTable, iamID, userID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedIAMMemberSequence(eventSequence)
return v.ProcessedIAMMemberSequence(eventSequence, eventTimestamp)
}
func (v *View) DeleteIAMMembersByUserID(userID string, eventSequence uint64) error {
func (v *View) DeleteIAMMembersByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteIAMMembersByUserID(v.Db, iamMemberTable, userID)
if err != nil {
return err
}
return v.ProcessedIAMMemberSequence(eventSequence)
return v.ProcessedIAMMemberSequence(eventSequence, eventTimestamp)
}
func (v *View) GetLatestIAMMemberSequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(iamMemberTable)
}
func (v *View) ProcessedIAMMemberSequence(eventSequence uint64) error {
return v.saveCurrentSequence(iamMemberTable, eventSequence)
func (v *View) ProcessedIAMMemberSequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(iamMemberTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateIAMMemberSpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(iamMemberTable)
}
func (v *View) GetLatestIAMMemberFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -6,6 +6,7 @@ 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"
"time"
)
const (
@ -20,28 +21,32 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*m
return view.SearchIDPs(v.Db, idpConfigTable, request)
}
func (v *View) PutIDPConfig(idp *model.IDPConfigView, sequence uint64) error {
func (v *View) PutIDPConfig(idp *model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutIDP(v.Db, idpConfigTable, idp)
if err != nil {
return err
}
return v.ProcessedIDPConfigSequence(sequence)
return v.ProcessedIDPConfigSequence(sequence, eventTimestamp)
}
func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64) error {
func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteIDP(v.Db, idpConfigTable, idpID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedIDPConfigSequence(eventSequence)
return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp)
}
func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(idpConfigTable)
}
func (v *View) ProcessedIDPConfigSequence(eventSequence uint64) error {
return v.saveCurrentSequence(idpConfigTable, eventSequence)
func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(idpConfigTable)
}
func (v *View) GetLatestIDPConfigFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -6,6 +6,7 @@ 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"
"time"
)
const (
@ -24,36 +25,40 @@ func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) (
return view.SearchIDPProviders(v.Db, idpProviderTable, request)
}
func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64) error {
func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutIDPProvider(v.Db, idpProviderTable, provider)
if err != nil {
return err
}
return v.ProcessedIDPProviderSequence(sequence)
return v.ProcessedIDPProviderSequence(sequence, eventTimestamp)
}
func (v *View) PutIDPProviders(sequence uint64, providers ...*model.IDPProviderView) error {
func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error {
err := view.PutIDPProviders(v.Db, idpProviderTable, providers...)
if err != nil {
return err
}
return v.ProcessedIDPProviderSequence(sequence)
return v.ProcessedIDPProviderSequence(sequence, eventTimestamp)
}
func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64) error {
func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedIDPProviderSequence(eventSequence)
return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp)
}
func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(idpProviderTable)
}
func (v *View) ProcessedIDPProviderSequence(eventSequence uint64) error {
return v.saveCurrentSequence(idpProviderTable, eventSequence)
func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(idpProviderTable)
}
func (v *View) GetLatestIDPProviderFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -4,6 +4,7 @@ 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"
"time"
)
const (
@ -14,20 +15,24 @@ func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyV
return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID)
}
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64) error {
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(sequence)
return v.ProcessedLabelPolicySequence(sequence, eventTimestamp)
}
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) ProcessedLabelPolicySequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(labelPolicyTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(labelPolicyTable)
}
func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -5,6 +5,7 @@ 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"
"time"
)
const (
@ -15,28 +16,32 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV
return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID)
}
func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64) error {
func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLoginPolicySequence(sequence)
return v.ProcessedLoginPolicySequence(sequence, eventTimestamp)
}
func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64) error {
func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedLoginPolicySequence(eventSequence)
return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp)
}
func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(loginPolicyTable)
}
func (v *View) ProcessedLoginPolicySequence(eventSequence uint64) error {
return v.saveCurrentSequence(loginPolicyTable, eventSequence)
func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(loginPolicyTable)
}
func (v *View) GetLatestLoginPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -5,6 +5,7 @@ import (
org_view "github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/zitadel/internal/org/repository/view/model"
"github.com/caos/zitadel/internal/view/repository"
"time"
)
const (
@ -19,12 +20,12 @@ func (v *View) SearchOrgs(query *org_model.OrgSearchRequest) ([]*model.OrgView,
return org_view.SearchOrgs(v.Db, orgTable, query)
}
func (v *View) PutOrg(org *model.OrgView) error {
func (v *View) PutOrg(org *model.OrgView, eventTimestamp time.Time) error {
err := org_view.PutOrg(v.Db, orgTable, org)
if err != nil {
return err
}
return v.ProcessedOrgSequence(org.Sequence)
return v.ProcessedOrgSequence(org.Sequence, eventTimestamp)
}
func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) {
@ -35,10 +36,14 @@ func (v *View) ProcessedOrgFailedEvent(failedEvent *repository.FailedEvent) erro
return v.saveFailedEvent(failedEvent)
}
func (v *View) UpdateOrgSpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(orgTable)
}
func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) {
return v.latestSequence(orgTable)
}
func (v *View) ProcessedOrgSequence(eventSequence uint64) error {
return v.saveCurrentSequence(orgTable, eventSequence)
func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp)
}

View File

@ -5,6 +5,7 @@ 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"
"time"
)
const (
@ -15,28 +16,32 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic
return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID)
}
func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64) error {
func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedOrgIAMPolicySequence(sequence)
return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp)
}
func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64) error {
func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedOrgIAMPolicySequence(eventSequence)
return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp)
}
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) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(orgIAMPolicyTable)
}
func (v *View) GetLatestOrgIAMPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -5,6 +5,7 @@ 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"
"time"
)
const (
@ -15,28 +16,32 @@ func (v *View) PasswordAgePolicyByAggregateID(aggregateID string) (*model.Passwo
return view.GetPasswordAgePolicyByAggregateID(v.Db, passwordAgePolicyTable, aggregateID)
}
func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64) error {
func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutPasswordAgePolicy(v.Db, passwordAgePolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedPasswordAgePolicySequence(sequence)
return v.ProcessedPasswordAgePolicySequence(sequence, eventTimestamp)
}
func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64) error {
func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeletePasswordAgePolicy(v.Db, passwordAgePolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedPasswordAgePolicySequence(eventSequence)
return v.ProcessedPasswordAgePolicySequence(eventSequence, eventTimestamp)
}
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) ProcessedPasswordAgePolicySequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateProcessedPasswordAgePolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(passwordAgePolicyTable)
}
func (v *View) GetLatestPasswordAgePolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -5,6 +5,7 @@ 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"
"time"
)
const (
@ -15,28 +16,32 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model
return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID)
}
func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64) error {
func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedPasswordComplexityPolicySequence(sequence)
return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp)
}
func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64) error {
func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedPasswordComplexityPolicySequence(eventSequence)
return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp)
}
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) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp)
}
func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(passwordComplexityPolicyTable)
}
func (v *View) GetLatestPasswordComplexityPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -5,6 +5,7 @@ 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"
"time"
)
const (
@ -15,28 +16,32 @@ func (v *View) PasswordLockoutPolicyByAggregateID(aggregateID string) (*model.Pa
return view.GetPasswordLockoutPolicyByAggregateID(v.Db, passwordLockoutPolicyTable, aggregateID)
}
func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64) error {
func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutPasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedPasswordLockoutPolicySequence(sequence)
return v.ProcessedPasswordLockoutPolicySequence(sequence, eventTimestamp)
}
func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64) error {
func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeletePasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedPasswordLockoutPolicySequence(eventSequence)
return v.ProcessedPasswordLockoutPolicySequence(eventSequence, eventTimestamp)
}
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) ProcessedPasswordLockoutPolicySequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence, eventTimestamp)
}
func (v *View) UpdatePasswordLockoutPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(passwordLockoutPolicyTable)
}
func (v *View) GetLatestPasswordLockoutPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {

View File

@ -2,14 +2,15 @@ package view
import (
"github.com/caos/zitadel/internal/view/repository"
"time"
)
const (
sequencesTable = "adminapi.current_sequences"
)
func (v *View) saveCurrentSequence(viewName string, sequence uint64) error {
return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence)
func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimeStamp time.Time) error {
return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimeStamp)
}
func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) {
@ -20,6 +21,24 @@ func (v *View) AllCurrentSequences(db string) ([]*repository.CurrentSequence, er
return repository.AllCurrentSequences(v.Db, db+".current_sequences")
}
func (v *View) updateSpoolerRunSequence(viewName string) error {
currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName)
if err != nil {
return err
}
if currentSequence.ViewName == "" {
currentSequence.ViewName = viewName
}
currentSequence.LastSuccessfulSpoolerRun = time.Now()
return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence)
}
func (v *View) GetCurrentSequence(db, viewName string) (*repository.CurrentSequence, error) {
sequenceTable := db + ".current_sequences"
fullView := db + "." + viewName
return repository.LatestSequence(v.Db, sequenceTable, fullView)
}
func (v *View) ClearView(db, viewName string) error {
truncateView := db + "." + viewName
sequenceTable := db + ".current_sequences"

View File

@ -5,6 +5,7 @@ import (
"github.com/caos/zitadel/internal/user/repository/view"
"github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/view/repository"
"time"
)
const (
@ -35,43 +36,47 @@ func (v *View) IsUserUnique(userName, email string) (bool, error) {
return view.IsUserUnique(v.Db, userTable, userName, email)
}
func (v *View) UserMfas(userID string) ([]*usr_model.MultiFactor, error) {
return view.UserMfas(v.Db, userTable, userID)
func (v *View) UserMFAs(userID string) ([]*usr_model.MultiFactor, error) {
return view.UserMFAs(v.Db, userTable, userID)
}
func (v *View) PutUsers(user []*model.UserView, sequence uint64) error {
func (v *View) PutUsers(user []*model.UserView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutUsers(v.Db, userTable, user...)
if err != nil {
return err
}
return v.ProcessedUserSequence(sequence)
return v.ProcessedUserSequence(sequence, eventTimestamp)
}
func (v *View) PutUser(user *model.UserView, sequence uint64) error {
func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error {
err := view.PutUser(v.Db, userTable, user)
if err != nil {
return err
}
if sequence != 0 {
return v.ProcessedUserSequence(sequence)
return v.ProcessedUserSequence(sequence, eventTimestamp)
}
return nil
}
func (v *View) DeleteUser(userID string, eventSequence uint64) error {
func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error {
err := view.DeleteUser(v.Db, userTable, userID)
if err != nil {
return nil
}
return v.ProcessedUserSequence(eventSequence)
return v.ProcessedUserSequence(eventSequence, eventTimestamp)
}
func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) {
return v.latestSequence(userTable)
}
func (v *View) ProcessedUserSequence(eventSequence uint64) error {
return v.saveCurrentSequence(userTable, eventSequence)
func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error {
return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp)
}
func (v *View) UpdateUserSpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(userTable)
}
func (v *View) GetLatestUserFailedEvent(sequence uint64) (*repository.FailedEvent, error) {

View File

@ -2,6 +2,12 @@ package api
import (
"context"
admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing"
auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/metrics"
"github.com/caos/zitadel/internal/telemetry/metrics/otel"
view_model "github.com/caos/zitadel/internal/view/model"
"go.opentelemetry.io/otel/api/metric"
"net/http"
"github.com/caos/logging"
@ -16,7 +22,7 @@ import (
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
type Config struct {
@ -30,19 +36,33 @@ type API struct {
verifier *authz.TokenVerifier
serverPort string
health health
auth auth
admin admin
}
type health interface {
Health(ctx context.Context) error
IamByID(ctx context.Context) (*iam_model.IAM, error)
VerifierClientID(ctx context.Context, appName string) (string, error)
}
func Create(config Config, authZ authz.Config, authZRepo *authz_es.EsRepository, sd systemdefaults.SystemDefaults) *API {
type auth interface {
ActiveUserSessionCount() int64
}
type admin interface {
GetViews() ([]*view_model.View, error)
GetSpoolerDiv(database, viewName string) int64
}
func Create(config Config, authZ authz.Config, authZRepo *authz_es.EsRepository, authRepo *auth_es.EsRepository, adminRepo *admin_es.EsRepository, sd systemdefaults.SystemDefaults) *API {
api := &API{
serverPort: config.GRPC.ServerPort,
}
api.verifier = authz.Start(authZRepo)
api.health = authZRepo
api.auth = authRepo
api.admin = adminRepo
api.grpcServer = server.CreateServer(api.verifier, authZ, sd.DefaultLanguage)
api.gatewayHandler = server.CreateGatewayHandler(config.GRPC)
api.RegisterHandler("", api.healthHandler())
@ -92,6 +112,7 @@ func (a *API) healthHandler() http.Handler {
handler.HandleFunc("/ready", handleReadiness(checks))
handler.HandleFunc("/validate", handleValidate(checks))
handler.HandleFunc("/clientID", a.handleClientID)
handler.Handle("/metrics", a.handleMetrics())
return handler
}
@ -132,6 +153,48 @@ func (a *API) handleClientID(w http.ResponseWriter, r *http.Request) {
http_util.MarshalJSON(w, id, nil, http.StatusOK)
}
func (a *API) handleMetrics() http.Handler {
a.registerActiveSessionCounters()
a.registerSpoolerDivCounters()
return metrics.GetExporter()
}
func (a *API) registerActiveSessionCounters() {
metrics.RegisterValueObserver(
metrics.ActiveSessionCounter,
metrics.ActiveSessionCounterDescription,
func(ctx context.Context, result metric.Int64ObserverResult) {
result.Observe(
a.auth.ActiveUserSessionCount(),
)
},
)
}
func (a *API) registerSpoolerDivCounters() {
views, err := a.admin.GetViews()
if err != nil {
logging.Log("API-3M8sd").WithError(err).Error("could not read views for metrics")
return
}
metrics.RegisterValueObserver(
metrics.SpoolerDivCounter,
metrics.SpoolerDivCounterDescription,
func(ctx context.Context, result metric.Int64ObserverResult) {
for _, view := range views {
labels := map[string]interface{}{
metrics.Database: view.Database,
metrics.ViewName: view.ViewName,
}
result.Observe(
a.admin.GetSpoolerDiv(view.Database, view.ViewName),
otel.MapToKeyValue(labels)...,
)
}
},
)
}
type ValidationFunction func(ctx context.Context) error
func validate(ctx context.Context, validations []ValidationFunction) []error {

View File

@ -7,7 +7,7 @@ import (
"strings"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
const (

View File

@ -6,7 +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"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
type key int

View File

@ -4,7 +4,7 @@ import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPerm string, authConfig Config) (_ context.Context, _ []string, err error) {

View File

@ -6,7 +6,7 @@ import (
"sync"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
const (

View File

@ -10,7 +10,7 @@ import (
)
func (s *Server) GetViews(ctx context.Context, _ *empty.Empty) (_ *admin.Views, err error) {
views, err := s.administrator.GetViews(ctx)
views, err := s.administrator.GetViews()
if err != nil {
return nil, err
}

View File

@ -26,14 +26,17 @@ func failedEventsFromModel(failedEvents []*view_model.FailedEvent) []*admin.Fail
}
func viewFromModel(view *view_model.View) *admin.View {
timestamp, err := ptypes.TimestampProto(view.CurrentTimestamp)
eventTimestamp, err := ptypes.TimestampProto(view.EventTimestamp)
logging.Log("GRPC-KSo03").OnError(err).Debug("unable to parse timestamp")
lastSpool, err := ptypes.TimestampProto(view.EventTimestamp)
logging.Log("GRPC-KSo03").OnError(err).Debug("unable to parse timestamp")
return &admin.View{
Database: view.Database,
ViewName: view.ViewName,
ProcessedSequence: view.CurrentSequence,
ViewTimestamp: timestamp,
Database: view.Database,
ViewName: view.ViewName,
ProcessedSequence: view.CurrentSequence,
EventTimestamp: eventTimestamp,
LastSuccessfulSpoolerRun: lastSpool,
}
}

View File

@ -13,6 +13,7 @@ func loginPolicyToModel(policy *admin.DefaultLoginPolicyRequest) *iam_model.Logi
AllowExternalIdp: policy.AllowExternalIdp,
AllowRegister: policy.AllowRegister,
ForceMFA: policy.ForceMfa,
PasswordlessType: passwordlessTypeToModel(policy.PasswordlessType),
}
}
@ -28,6 +29,7 @@ func loginPolicyFromModel(policy *iam_model.LoginPolicy) *admin.DefaultLoginPoli
AllowExternalIdp: policy.AllowExternalIdp,
AllowRegister: policy.AllowRegister,
ForceMfa: policy.ForceMFA,
PasswordlessType: passwordlessTypeFromModel(policy.PasswordlessType),
CreationDate: creationDate,
ChangeDate: changeDate,
}
@ -45,6 +47,7 @@ func loginPolicyViewFromModel(policy *iam_model.LoginPolicyView) *admin.DefaultL
AllowExternalIdp: policy.AllowExternalIDP,
AllowRegister: policy.AllowRegister,
ForceMfa: policy.ForceMFA,
PasswordlessType: passwordlessTypeFromModel(policy.PasswordlessType),
CreationDate: creationDate,
ChangeDate: changeDate,
}
@ -145,6 +148,24 @@ func secondFactorTypeToModel(mfaType *admin.SecondFactor) iam_model.SecondFactor
}
}
func passwordlessTypeFromModel(passwordlessType iam_model.PasswordlessType) admin.PasswordlessType {
switch passwordlessType {
case iam_model.PasswordlessTypeAllowed:
return admin.PasswordlessType_PASSWORDLESSTYPE_ALLOWED
default:
return admin.PasswordlessType_PASSWORDLESSTYPE_NOT_ALLOWED
}
}
func passwordlessTypeToModel(passwordlessType admin.PasswordlessType) iam_model.PasswordlessType {
switch passwordlessType {
case admin.PasswordlessType_PASSWORDLESSTYPE_ALLOWED:
return iam_model.PasswordlessTypeAllowed
default:
return iam_model.PasswordlessTypeNotAllowed
}
}
func multiFactorResultFromModel(result *iam_model.MultiFactorsSearchResponse) *admin.MultiFactorsResult {
converted := make([]admin.MultiFactorType, len(result.Result))
for i, mfaType := range result.Result {

View File

@ -2,7 +2,6 @@ package admin
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
)

View File

@ -2,7 +2,6 @@ package auth
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"github.com/caos/zitadel/pkg/grpc/auth"
@ -54,7 +53,7 @@ func (s *Server) GetMyUserAddress(ctx context.Context, _ *empty.Empty) (*auth.Us
}
func (s *Server) GetMyMfas(ctx context.Context, _ *empty.Empty) (*auth.MultiFactors, error) {
mfas, err := s.repo.MyUserMfas(ctx)
mfas, err := s.repo.MyUserMFAs(ctx)
if err != nil {
return nil, err
}
@ -144,7 +143,7 @@ func (s *Server) GetMyPasswordComplexityPolicy(ctx context.Context, _ *empty.Emp
}
func (s *Server) AddMfaOTP(ctx context.Context, _ *empty.Empty) (_ *auth.MfaOtpResponse, err error) {
otp, err := s.repo.AddMyMfaOTP(ctx)
otp, err := s.repo.AddMyMFAOTP(ctx)
if err != nil {
return nil, err
}
@ -152,12 +151,42 @@ func (s *Server) AddMfaOTP(ctx context.Context, _ *empty.Empty) (_ *auth.MfaOtpR
}
func (s *Server) VerifyMfaOTP(ctx context.Context, request *auth.VerifyMfaOtp) (*empty.Empty, error) {
err := s.repo.VerifyMyMfaOTPSetup(ctx, request.Code)
err := s.repo.VerifyMyMFAOTPSetup(ctx, request.Code)
return &empty.Empty{}, err
}
func (s *Server) RemoveMfaOTP(ctx context.Context, _ *empty.Empty) (_ *empty.Empty, err error) {
s.repo.RemoveMyMfaOTP(ctx)
err = s.repo.RemoveMyMFAOTP(ctx)
return &empty.Empty{}, err
}
func (s *Server) AddMyMfaU2F(ctx context.Context, _ *empty.Empty) (_ *auth.WebAuthNResponse, err error) {
u2f, err := s.repo.AddMyMFAU2F(ctx)
return verifyWebAuthNFromModel(u2f), err
}
func (s *Server) VerifyMyMfaU2F(ctx context.Context, request *auth.VerifyWebAuthN) (*empty.Empty, error) {
err := s.repo.VerifyMyMFAU2FSetup(ctx, request.TokenName, request.PublicKeyCredential)
return &empty.Empty{}, err
}
func (s *Server) RemoveMyMfaU2F(ctx context.Context, id *auth.WebAuthNTokenID) (*empty.Empty, error) {
err := s.repo.RemoveMyMFAU2F(ctx, id.Id)
return &empty.Empty{}, err
}
func (s *Server) AddMyPasswordless(ctx context.Context, _ *empty.Empty) (_ *auth.WebAuthNResponse, err error) {
u2f, err := s.repo.AddMyPasswordless(ctx)
return verifyWebAuthNFromModel(u2f), err
}
func (s *Server) VerifyMyPasswordless(ctx context.Context, request *auth.VerifyWebAuthN) (*empty.Empty, error) {
err := s.repo.VerifyMyPasswordlessSetup(ctx, request.TokenName, request.PublicKeyCredential)
return &empty.Empty{}, err
}
func (s *Server) RemoveMyPasswordless(ctx context.Context, id *auth.WebAuthNTokenID) (*empty.Empty, error) {
err := s.repo.RemoveMyPasswordless(ctx, id.Id)
return &empty.Empty{}, err
}

View File

@ -12,7 +12,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/pkg/grpc/auth"
"github.com/caos/zitadel/pkg/grpc/message"
@ -358,11 +358,11 @@ func genderToModel(gender auth.Gender) usr_model.Gender {
}
}
func mfaStateFromModel(state usr_model.MfaState) auth.MFAState {
func mfaStateFromModel(state usr_model.MFAState) auth.MFAState {
switch state {
case usr_model.MfaStateReady:
case usr_model.MFAStateReady:
return auth.MFAState_MFASTATE_READY
case usr_model.MfaStateNotReady:
case usr_model.MFAStateNotReady:
return auth.MFAState_MFASTATE_NOT_READY
default:
return auth.MFAState_MFASTATE_UNSPECIFIED
@ -379,17 +379,18 @@ func mfasFromModel(mfas []*usr_model.MultiFactor) []*auth.MultiFactor {
func mfaFromModel(mfa *usr_model.MultiFactor) *auth.MultiFactor {
return &auth.MultiFactor{
State: mfaStateFromModel(mfa.State),
Type: mfaTypeFromModel(mfa.Type),
State: mfaStateFromModel(mfa.State),
Type: mfaTypeFromModel(mfa.Type),
Attribute: mfa.Attribute,
}
}
func mfaTypeFromModel(mfatype usr_model.MfaType) auth.MfaType {
switch mfatype {
case usr_model.MfaTypeOTP:
func mfaTypeFromModel(mfaType usr_model.MFAType) auth.MfaType {
switch mfaType {
case usr_model.MFATypeOTP:
return auth.MfaType_MFATYPE_OTP
case usr_model.MfaTypeSMS:
return auth.MfaType_MFATYPE_SMS
case usr_model.MFATypeU2F:
return auth.MfaType_MFATYPE_U2F
default:
return auth.MfaType_MFATYPE_UNSPECIFIED
}
@ -426,3 +427,11 @@ func userChangesToAPI(changes *usr_model.UserChanges) (_ []*auth.Change) {
return result
}
func verifyWebAuthNFromModel(u2f *usr_model.WebAuthNToken) *auth.WebAuthNResponse {
return &auth.WebAuthNResponse{
Id: u2f.WebAuthNTokenID,
PublicKey: u2f.PublicKey,
State: mfaStateFromModel(u2f.State),
}
}

View File

@ -13,6 +13,7 @@ func loginPolicyRequestToModel(policy *management.LoginPolicyRequest) *iam_model
AllowExternalIdp: policy.AllowExternalIdp,
AllowRegister: policy.AllowRegister,
ForceMFA: policy.ForceMfa,
PasswordlessType: passwordlessTypeToModel(policy.PasswordlessType),
}
}
@ -30,6 +31,7 @@ func loginPolicyFromModel(policy *iam_model.LoginPolicy) *management.LoginPolicy
CreationDate: creationDate,
ChangeDate: changeDate,
ForceMfa: policy.ForceMFA,
PasswordlessType: passwordlessTypeFromModel(policy.PasswordlessType),
}
}
@ -48,6 +50,7 @@ func loginPolicyViewFromModel(policy *iam_model.LoginPolicyView) *management.Log
CreationDate: creationDate,
ChangeDate: changeDate,
ForceMfa: policy.ForceMFA,
PasswordlessType: passwordlessTypeFromModel(policy.PasswordlessType),
}
}
@ -215,3 +218,21 @@ func multiFactorTypeToModel(mfaType *management.MultiFactor) iam_model.MultiFact
return iam_model.MultiFactorTypeUnspecified
}
}
func passwordlessTypeFromModel(passwordlessType iam_model.PasswordlessType) management.PasswordlessType {
switch passwordlessType {
case iam_model.PasswordlessTypeAllowed:
return management.PasswordlessType_PASSWORDLESSTYPE_ALLOWED
default:
return management.PasswordlessType_PASSWORDLESSTYPE_NOT_ALLOWED
}
}
func passwordlessTypeToModel(passwordlessType management.PasswordlessType) iam_model.PasswordlessType {
switch passwordlessType {
case management.PasswordlessType_PASSWORDLESSTYPE_ALLOWED:
return iam_model.PasswordlessTypeAllowed
default:
return iam_model.PasswordlessTypeNotAllowed
}
}

View File

@ -214,7 +214,7 @@ func (s *Server) RemoveExternalIDP(ctx context.Context, request *management.Exte
}
func (s *Server) GetUserMfas(ctx context.Context, userID *management.UserID) (*management.UserMultiFactors, error) {
mfas, err := s.user.UserMfas(ctx, userID.Id)
mfas, err := s.user.UserMFAs(ctx, userID.Id)
if err != nil {
return nil, err
}

View File

@ -572,22 +572,22 @@ func genderToModel(gender management.Gender) usr_model.Gender {
}
}
func mfaTypeFromModel(mfatype usr_model.MfaType) management.MfaType {
func mfaTypeFromModel(mfatype usr_model.MFAType) management.MfaType {
switch mfatype {
case usr_model.MfaTypeOTP:
case usr_model.MFATypeOTP:
return management.MfaType_MFATYPE_OTP
case usr_model.MfaTypeSMS:
return management.MfaType_MFATYPE_SMS
case usr_model.MFATypeU2F:
return management.MfaType_MFATYPE_U2F
default:
return management.MfaType_MFATYPE_UNSPECIFIED
}
}
func mfaStateFromModel(state usr_model.MfaState) management.MFAState {
func mfaStateFromModel(state usr_model.MFAState) management.MFAState {
switch state {
case usr_model.MfaStateReady:
case usr_model.MFAStateReady:
return management.MFAState_MFASTATE_READY
case usr_model.MfaStateNotReady:
case usr_model.MFAStateNotReady:
return management.MFAState_MFASTATE_NOT_READY
default:
return management.MFAState_MFASTATE_UNSPECIFIED

View File

@ -14,7 +14,7 @@ import (
client_middleware "github.com/caos/zitadel/internal/api/grpc/client/middleware"
http_util "github.com/caos/zitadel/internal/api/http"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
const (
@ -129,7 +129,8 @@ func createDialOptions(g Gateway) []grpc.DialOption {
}
func addInterceptors(handler http.Handler, g Gateway) http.Handler {
handler = http_mw.DefaultTraceHandler(handler)
handler = http_mw.DefaultMetricsHandler(handler)
handler = http_mw.DefaultTelemetryHandler(handler)
handler = http_mw.NoCacheInterceptor(handler)
if interceptor, ok := g.(grpcGatewayCustomInterceptor); ok {
handler = interceptor.GatewayHTTPInterceptor(handler)

View File

@ -10,7 +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"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor {

View File

@ -0,0 +1,86 @@
package middleware
import (
"context"
"strings"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/status"
_ "github.com/caos/zitadel/internal/statik"
"github.com/caos/zitadel/internal/telemetry/metrics"
)
const (
GrpcMethod = "grpc_method"
ReturnCode = "return_code"
GrpcRequestCounter = "grpc.server.request_counter"
GrpcRequestCounterDescription = "Grpc request counter"
TotalGrpcRequestCounter = "grpc.server.total_request_counter"
TotalGrpcRequestCounterDescription = "Total grpc request counter"
GrpcStatusCodeCounter = "grpc.server.grpc_status_code"
GrpcStatusCodeCounterDescription = "Grpc status code counter"
)
func MetricsHandler(metricTypes []metrics.MetricType, ignoredMethodSuffixes ...string) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
return RegisterMetrics(ctx, req, info, handler, metricTypes, ignoredMethodSuffixes...)
}
}
func RegisterMetrics(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, metricTypes []metrics.MetricType, ignoredMethodSuffixes ...string) (_ interface{}, err error) {
if len(metricTypes) == 0 {
return handler(ctx, req)
}
for _, ignore := range ignoredMethodSuffixes {
if strings.HasSuffix(info.FullMethod, ignore) {
return handler(ctx, req)
}
}
resp, err := handler(ctx, req)
if containsMetricsMethod(metrics.MetricTypeRequestCount, metricTypes) {
RegisterGrpcRequestCounter(ctx, info)
}
if containsMetricsMethod(metrics.MetricTypeTotalCount, metricTypes) {
RegisterGrpcTotalRequestCounter(ctx)
}
if containsMetricsMethod(metrics.MetricTypeStatusCode, metricTypes) {
RegisterGrpcRequestCodeCounter(ctx, info, err)
}
return resp, err
}
func RegisterGrpcRequestCounter(ctx context.Context, info *grpc.UnaryServerInfo) {
var labels = map[string]interface{}{
GrpcMethod: info.FullMethod,
}
metrics.RegisterCounter(GrpcRequestCounter, GrpcRequestCounterDescription)
metrics.AddCount(ctx, GrpcRequestCounter, 1, labels)
}
func RegisterGrpcTotalRequestCounter(ctx context.Context) {
metrics.RegisterCounter(TotalGrpcRequestCounter, TotalGrpcRequestCounterDescription)
metrics.AddCount(ctx, TotalGrpcRequestCounter, 1, nil)
}
func RegisterGrpcRequestCodeCounter(ctx context.Context, info *grpc.UnaryServerInfo, err error) {
statusCode := status.Code(err)
var labels = map[string]interface{}{
GrpcMethod: info.FullMethod,
ReturnCode: runtime.HTTPStatusFromCode(statusCode),
}
metrics.RegisterCounter(GrpcStatusCodeCounter, GrpcStatusCodeCounterDescription)
metrics.AddCount(ctx, GrpcStatusCodeCounter, 1, labels)
}
func containsMetricsMethod(metricType metrics.MetricType, metricTypes []metrics.MetricType) bool {
for _, m := range metricTypes {
if m == metricType {
return true
}
}
return false
}

View File

@ -9,7 +9,7 @@ import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/proto"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
type ValidationFunction func(ctx context.Context) error

View File

@ -2,6 +2,8 @@ package server
import (
"context"
grpc_api "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/telemetry/metrics"
"github.com/caos/logging"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
@ -11,7 +13,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/api/grpc/server/middleware"
"github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
const (
@ -27,10 +29,12 @@ type Server interface {
}
func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang language.Tag) *grpc.Server {
metricTypes := []metrics.MetricType{metrics.MetricTypeTotalCount, metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode}
return grpc.NewServer(
grpc.UnaryInterceptor(
grpc_middleware.ChainUnaryServer(
middleware.DefaultTracingServer(),
middleware.MetricsHandler(metricTypes, grpc_api.Probes...),
middleware.ErrorHandler(),
middleware.AuthorizationInterceptor(verifier, authConfig),
middleware.TranslationHandler(lang),

View File

@ -0,0 +1,19 @@
package middleware
import (
"github.com/caos/zitadel/internal/telemetry/metrics"
"net/http"
http_utils "github.com/caos/zitadel/internal/api/http"
)
func DefaultMetricsHandler(handler http.Handler) http.Handler {
metricTypes := []metrics.MetricType{metrics.MetricTypeTotalCount}
return MetricsHandler(metricTypes, http_utils.Probes...)(handler)
}
func MetricsHandler(metricTypes []metrics.MetricType, ignoredMethods ...string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return metrics.NewMetricsHandler(handler, metricTypes, ignoredMethods...)
}
}

View File

@ -0,0 +1,18 @@
package middleware
import (
"github.com/caos/zitadel/internal/telemetry"
"net/http"
http_utils "github.com/caos/zitadel/internal/api/http"
)
func DefaultTelemetryHandler(handler http.Handler) http.Handler {
return TelemetryHandler(http_utils.Probes...)(handler)
}
func TelemetryHandler(ignoredMethods ...string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return telemetry.TelemetryHandler(handler, ignoredMethods...)
}
}

View File

@ -1,18 +0,0 @@
package middleware
import (
"net/http"
http_utils "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/tracing"
)
func DefaultTraceHandler(handler http.Handler) http.Handler {
return TraceHandler(http_utils.Probes...)(handler)
}
func TraceHandler(ignoredMethods ...string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return tracing.TraceHandler(handler, ignoredMethods...)
}
}

View File

@ -5,7 +5,7 @@ import (
"net/http"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
func Serve(ctx context.Context, handler http.Handler, port, servername string) {

View File

@ -13,7 +13,7 @@ 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"
"github.com/caos/zitadel/internal/telemetry/tracing"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
)

View File

@ -15,9 +15,10 @@ import (
)
const (
amrPassword = "password"
amrMFA = "mfa"
amrOTP = "otp"
amrPassword = "password"
amrMFA = "mfa"
amrOTP = "otp"
amrUserPresence = "user"
)
type AuthRequest struct {
@ -38,11 +39,11 @@ func (a *AuthRequest) GetAMR() []string {
if a.PasswordVerified {
amr = append(amr, amrPassword)
}
if len(a.MfasVerified) > 0 {
if len(a.MFAsVerified) > 0 {
amr = append(amr, amrMFA)
for _, mfa := range a.MfasVerified {
if amrMfa := AMRFromMFAType(mfa); amrMfa != "" {
amr = append(amr, amrMfa)
for _, mfa := range a.MFAsVerified {
if amrMFA := AMRFromMFAType(mfa); amrMFA != "" {
amr = append(amr, amrMFA)
}
}
}
@ -247,6 +248,9 @@ func AMRFromMFAType(mfaType model.MFAType) string {
switch mfaType {
case model.MFATypeOTP:
return amrOTP
case model.MFATypeU2F,
model.MFATypeU2FUserVerification:
return amrUserPresence
default:
return ""
}

View File

@ -16,7 +16,7 @@ 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"
"github.com/caos/zitadel/internal/telemetry/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
)

View File

@ -2,6 +2,7 @@ package oidc
import (
"context"
"github.com/caos/zitadel/internal/telemetry/metrics"
"time"
"github.com/caos/logging"
@ -12,7 +13,7 @@ import (
"github.com/caos/zitadel/internal/auth/repository"
"github.com/caos/zitadel/internal/config/types"
"github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
type OPHandlerConfig struct {
@ -55,12 +56,14 @@ func NewProvider(ctx context.Context, config OPHandlerConfig, repo repository.Re
cookieHandler, err := middleware.NewUserAgentHandler(config.UserAgentCookieConfig, id.SonyFlakeGenerator, localDevMode)
logging.Log("OIDC-sd4fd").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Panic("cannot user agent handler")
config.OPConfig.CodeMethodS256 = true
metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount}
provider, err := op.NewOpenIDProvider(
ctx,
config.OPConfig,
newStorage(config.StorageConfig, repo),
op.WithHttpInterceptors(
middleware.TraceHandler(),
middleware.MetricsHandler(metricTypes),
middleware.TelemetryHandler(),
middleware.NoCacheInterceptor,
cookieHandler,
http_utils.CopyHeadersToContext,

View File

@ -2,10 +2,9 @@ package repository
import (
"context"
"github.com/caos/zitadel/internal/auth_request/model"
org_model "github.com/caos/zitadel/internal/org/model"
user_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/auth_request/model"
)
type AuthRequestRepository interface {
@ -15,14 +14,22 @@ type AuthRequestRepository interface {
AuthRequestByCode(ctx context.Context, code string) (*model.AuthRequest, error)
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, 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
VerifyMFAOTP(ctx context.Context, agentID, authRequestID, code, userAgentID string, info *model.BrowserInfo) error
BeginMFAU2FLogin(ctx context.Context, userID, authRequestID, userAgentID string) (*user_model.WebAuthNLogin, error)
VerifyMFAU2F(ctx context.Context, userID, authRequestID, userAgentID string, credentialData []byte, info *model.BrowserInfo) error
BeginPasswordlessLogin(ctx context.Context, userID, authRequestID, userAgentID string) (*user_model.WebAuthNLogin, error)
VerifyPasswordless(ctx context.Context, userID, authRequestID, userAgentID string, credentialData []byte, info *model.BrowserInfo) 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

@ -7,6 +7,7 @@ import (
"github.com/caos/zitadel/internal/project/model"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_view_model "github.com/caos/zitadel/internal/project/repository/view/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
type ApplicationRepo struct {
@ -22,7 +23,10 @@ func (a *ApplicationRepo) ApplicationByClientID(ctx context.Context, clientID st
return proj_view_model.ApplicationViewToModel(app), nil
}
func (a *ApplicationRepo) AuthorizeOIDCApplication(ctx context.Context, clientID, secret string) error {
func (a *ApplicationRepo) AuthorizeOIDCApplication(ctx context.Context, clientID, secret string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
app, err := a.View.ApplicationByClientID(ctx, clientID)
if err != nil {
return err

View File

@ -21,7 +21,7 @@ import (
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"
"github.com/caos/zitadel/internal/telemetry/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
@ -47,7 +47,7 @@ type AuthRequestRepo struct {
PasswordCheckLifeTime time.Duration
ExternalLoginCheckLifeTime time.Duration
MfaInitSkippedLifeTime time.Duration
MFAInitSkippedLifeTime time.Duration
SecondFactorCheckLifeTime time.Duration
MultiFactorCheckLifeTime time.Duration
@ -245,27 +245,62 @@ func (repo *AuthRequestRepo) SelectUser(ctx context.Context, id, userID, userAge
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)
request, err := repo.getAuthRequestEnsureUser(ctx, id, userAgentID, userID)
if err != nil {
return err
}
if request.UserID != userID {
return errors.ThrowPreconditionFailed(nil, "EVENT-ds35D", "Errors.User.NotMatchingUserID")
}
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) (err 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)
request, err := repo.getAuthRequestEnsureUser(ctx, authRequestID, userAgentID, userID)
if err != nil {
return err
}
if request.UserID != userID {
return errors.ThrowPreconditionFailed(nil, "EVENT-ADJ26", "Errors.User.NotMatchingUserID")
return repo.UserEvents.CheckMFAOTP(ctx, userID, code, request.WithCurrentInfo(info))
}
func (repo *AuthRequestRepo) BeginMFAU2FLogin(ctx context.Context, userID, authRequestID, userAgentID string) (login *user_model.WebAuthNLogin, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequestEnsureUser(ctx, authRequestID, userAgentID, userID)
if err != nil {
return nil, err
}
return repo.UserEvents.CheckMfaOTP(ctx, userID, code, request.WithCurrentInfo(info))
return repo.UserEvents.BeginU2FLogin(ctx, userID, request)
}
func (repo *AuthRequestRepo) VerifyMFAU2F(ctx context.Context, userID, authRequestID, userAgentID string, credentialData []byte, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequestEnsureUser(ctx, authRequestID, userAgentID, userID)
if err != nil {
return err
}
return repo.UserEvents.VerifyMFAU2F(ctx, userID, credentialData, request)
}
func (repo *AuthRequestRepo) BeginPasswordlessLogin(ctx context.Context, userID, authRequestID, userAgentID string) (login *user_model.WebAuthNLogin, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequestEnsureUser(ctx, authRequestID, userAgentID, userID)
if err != nil {
return nil, err
}
return repo.UserEvents.BeginPasswordlessLogin(ctx, userID, request)
}
func (repo *AuthRequestRepo) VerifyPasswordless(ctx context.Context, userID, authRequestID, userAgentID string, credentialData []byte, info *model.BrowserInfo) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
request, err := repo.getAuthRequestEnsureUser(ctx, authRequestID, userAgentID, userID)
if err != nil {
return err
}
return repo.UserEvents.VerifyPasswordless(ctx, userID, credentialData, request)
}
func (repo *AuthRequestRepo) LinkExternalUsers(ctx context.Context, authReqID, userAgentID string, info *model.BrowserInfo) (err error) {
@ -365,6 +400,17 @@ func (repo *AuthRequestRepo) getAuthRequestNextSteps(ctx context.Context, id, us
return request, nil
}
func (repo *AuthRequestRepo) getAuthRequestEnsureUser(ctx context.Context, authRequestID, userAgentID, userID string) (*model.AuthRequest, error) {
request, err := repo.getAuthRequest(ctx, authRequestID, userAgentID)
if err != nil {
return nil, err
}
if request.UserID != userID {
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-GBH32", "Errors.User.NotMatchingUserID")
}
return request, nil
}
func (repo *AuthRequestRepo) getAuthRequest(ctx context.Context, id, userAgentID string) (*model.AuthRequest, error) {
request, err := repo.AuthRequests.GetAuthRequestByID(ctx, id)
if err != nil {
@ -545,27 +591,19 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *model.AuthR
return nil, err
}
if (request.SelectedIDPConfigID != "" || userSession.SelectedIDPConfigID != "") && (request.LinkingUsers == nil || len(request.LinkingUsers) == 0) {
if !checkVerificationTime(userSession.ExternalLoginVerification, repo.ExternalLoginCheckLifeTime) {
selectedIDPConfigID := request.SelectedIDPConfigID
if selectedIDPConfigID == "" {
selectedIDPConfigID = userSession.SelectedIDPConfigID
}
return append(steps, &model.ExternalLoginStep{SelectedIDPConfigID: selectedIDPConfigID}), nil
isInternalLogin := request.SelectedIDPConfigID == "" && userSession.SelectedIDPConfigID == ""
if !isInternalLogin && len(request.LinkingUsers) == 0 && !checkVerificationTime(userSession.ExternalLoginVerification, repo.ExternalLoginCheckLifeTime) {
selectedIDPConfigID := request.SelectedIDPConfigID
if selectedIDPConfigID == "" {
selectedIDPConfigID = userSession.SelectedIDPConfigID
}
} 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
return append(steps, &model.ExternalLoginStep{SelectedIDPConfigID: selectedIDPConfigID}), nil
}
if isInternalLogin || (!isInternalLogin && len(request.LinkingUsers) > 0) {
step := repo.firstFactorChecked(request, user, userSession)
if step != nil {
return append(steps, step), nil
}
if !user.PasswordSet {
return append(steps, &model.InitPasswordStep{}), nil
}
if !checkVerificationTime(userSession.PasswordVerification, repo.PasswordCheckLifeTime) {
return append(steps, &model.PasswordStep{}), nil
}
request.PasswordVerified = true
request.AuthTime = userSession.PasswordVerification
}
step, ok, err := repo.mfaChecked(userSession, request, user)
@ -624,21 +662,46 @@ func (repo *AuthRequestRepo) usersForUserSelection(request *model.AuthRequest) (
return users, nil
}
func (repo *AuthRequestRepo) firstFactorChecked(request *model.AuthRequest, user *user_model.UserView, userSession *user_model.UserSessionView) model.NextStep {
if user.InitRequired {
return &model.InitUserStep{PasswordSet: user.PasswordSet}
}
if user.IsPasswordlessReady() {
if !checkVerificationTime(userSession.PasswordlessVerification, repo.MultiFactorCheckLifeTime) {
return &model.PasswordlessStep{}
}
request.AuthTime = userSession.PasswordlessVerification
return nil
}
if !user.PasswordSet {
return &model.InitPasswordStep{}
}
if !checkVerificationTime(userSession.PasswordVerification, repo.PasswordCheckLifeTime) {
return &model.PasswordStep{}
}
request.PasswordVerified = true
request.AuthTime = userSession.PasswordVerification
return nil
}
func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView, request *model.AuthRequest, user *user_model.UserView) (model.NextStep, bool, error) {
mfaLevel := request.MfaLevel()
allowedProviders, required := user.MfaTypesAllowed(mfaLevel, request.LoginPolicy)
promptRequired := (user.MfaMaxSetUp < mfaLevel) || (len(allowedProviders) == 0 && required)
mfaLevel := request.MFALevel()
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)
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{
return &model.MFAPromptStep{
Required: promptRequired,
MfaProviders: types,
MFAProviders: types,
}, false, nil
}
switch mfaLevel {
@ -651,28 +714,28 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView,
fallthrough
case model.MFALevelSecondFactor:
if checkVerificationTime(userSession.SecondFactorVerification, repo.SecondFactorCheckLifeTime) {
request.MfasVerified = append(request.MfasVerified, userSession.SecondFactorVerificationType)
request.MFAsVerified = append(request.MFAsVerified, userSession.SecondFactorVerificationType)
request.AuthTime = userSession.SecondFactorVerification
return nil, true, nil
}
fallthrough
case model.MFALevelMultiFactor:
if checkVerificationTime(userSession.MultiFactorVerification, repo.MultiFactorCheckLifeTime) {
request.MfasVerified = append(request.MfasVerified, userSession.MultiFactorVerificationType)
request.MFAsVerified = append(request.MFAsVerified, userSession.MultiFactorVerificationType)
request.AuthTime = userSession.MultiFactorVerification
return nil, true, nil
}
}
return &model.MfaVerificationStep{
MfaProviders: allowedProviders,
return &model.MFAVerificationStep{
MFAProviders: allowedProviders,
}, false, nil
}
func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView) bool {
if user.MfaMaxSetUp > model.MFALevelNotSetUp {
if user.MFAMaxSetUp > model.MFALevelNotSetUp {
return true
}
return checkVerificationTime(user.MfaInitSkipped, repo.MfaInitSkippedLifeTime)
return checkVerificationTime(user.MFAInitSkipped, repo.MFAInitSkippedLifeTime)
}
func (repo *AuthRequestRepo) getLoginPolicy(ctx context.Context, orgID string) (*iam_model.LoginPolicyView, error) {
@ -745,7 +808,11 @@ func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eve
es_model.HumanExternalLoginCheckSucceeded,
es_model.HumanMFAOTPCheckSucceeded,
es_model.HumanMFAOTPCheckFailed,
es_model.HumanSignedOut:
es_model.HumanSignedOut,
es_model.HumanPasswordlessTokenCheckSucceeded,
es_model.HumanPasswordlessTokenCheckFailed,
es_model.HumanMFAU2FTokenCheckSucceeded,
es_model.HumanMFAU2FTokenCheckFailed:
eventData, err := user_view_model.UserSessionFromEvent(event)
if err != nil {
logging.Log("EVENT-sdgT3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error getting event data")

View File

@ -48,8 +48,10 @@ func (m *mockViewErrUserSession) UserSessionsByAgentID(string) ([]*user_view_mod
type mockViewUserSession struct {
ExternalLoginVerification time.Time
PasswordlessVerification time.Time
PasswordVerification time.Time
SecondFactorVerification time.Time
MultiFactorVerification time.Time
Users []mockUser
}
@ -61,8 +63,10 @@ type mockUser struct {
func (m *mockViewUserSession) UserSessionByIDs(string, string) (*user_view_model.UserSessionView, error) {
return &user_view_model.UserSessionView{
ExternalLoginVerification: m.ExternalLoginVerification,
PasswordlessVerification: m.PasswordlessVerification,
PasswordVerification: m.PasswordVerification,
SecondFactorVerification: m.SecondFactorVerification,
MultiFactorVerification: m.MultiFactorVerification,
}, nil
}
@ -115,8 +119,9 @@ type mockViewUser struct {
PasswordChangeRequired bool
IsEmailVerified bool
OTPState int32
MfaMaxSetUp int32
MfaInitSkipped time.Time
MFAMaxSetUp int32
MFAInitSkipped time.Time
PasswordlessTokens user_view_model.WebAuthNTokens
}
type mockLoginPolicy struct {
@ -138,8 +143,9 @@ func (m *mockViewUser) UserByID(string) (*user_view_model.UserView, error) {
PasswordChangeRequired: m.PasswordChangeRequired,
IsEmailVerified: m.IsEmailVerified,
OTPState: m.OTPState,
MfaMaxSetUp: m.MfaMaxSetUp,
MfaInitSkipped: m.MfaInitSkipped,
MFAMaxSetUp: m.MFAMaxSetUp,
MFAInitSkipped: m.MFAInitSkipped,
PasswordlessTokens: m.PasswordlessTokens,
},
}, nil
}
@ -200,7 +206,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
loginPolicyProvider loginPolicyViewProvider
PasswordCheckLifeTime time.Duration
ExternalLoginCheckLifeTime time.Duration
MfaInitSkippedLifeTime time.Duration
MFAInitSkippedLifeTime time.Duration
SecondFactorCheckLifeTime time.Duration
MultiFactorCheckLifeTime time.Duration
}
@ -413,6 +419,49 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
}},
nil,
},
{
"passwordless not verified, passwordless check step",
fields{
userSessionViewProvider: &mockViewUserSession{},
userViewProvider: &mockViewUser{
PasswordSet: true,
PasswordlessTokens: user_view_model.WebAuthNTokens{&user_view_model.WebAuthNView{ID: "id", State: int32(user_model.MFAStateReady)}},
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MultiFactorCheckLifeTime: 10 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID"}, false},
[]model.NextStep{&model.PasswordlessStep{}},
nil,
},
{
"passwordless verified, email not verified, email verification step",
fields{
userSessionViewProvider: &mockViewUserSession{
PasswordlessVerification: time.Now().Add(-5 * time.Minute),
MultiFactorVerification: time.Now().Add(-5 * time.Minute),
},
userViewProvider: &mockViewUser{
PasswordSet: true,
PasswordlessTokens: user_view_model.WebAuthNTokens{&user_view_model.WebAuthNView{ID: "id", State: int32(user_model.MFAStateReady)}},
PasswordChangeRequired: false,
IsEmailVerified: false,
MFAMaxSetUp: int32(model.MFALevelMultiFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MultiFactorCheckLifeTime: 10 * time.Hour,
},
args{&model.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
MultiFactors: []iam_model.MultiFactorType{iam_model.MultiFactorTypeU2FWithPIN},
},
}, false},
[]model.NextStep{&model.VerifyEMailStep{}},
nil,
},
{
"password not set, init password step",
fields{
@ -433,7 +482,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userViewProvider: &mockViewUser{
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -452,7 +501,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userViewProvider: &mockViewUser{
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -499,7 +548,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -525,8 +574,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userViewProvider: &mockViewUser{
PasswordSet: true,
OTPState: int32(user_model.MfaStateReady),
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
OTPState: int32(user_model.MFAStateReady),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -540,8 +589,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.MfaVerificationStep{
MfaProviders: []model.MFAType{model.MFATypeOTP},
[]model.NextStep{&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
}},
nil,
},
@ -554,8 +603,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userViewProvider: &mockViewUser{
PasswordSet: true,
OTPState: int32(user_model.MfaStateReady),
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
OTPState: int32(user_model.MFAStateReady),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -571,8 +620,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.MfaVerificationStep{
MfaProviders: []model.MFAType{model.MFATypeOTP},
[]model.NextStep{&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
}},
nil,
},
@ -587,7 +636,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordSet: true,
PasswordChangeRequired: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -613,7 +662,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userViewProvider: &mockViewUser{
PasswordSet: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -639,7 +688,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
PasswordChangeRequired: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -665,7 +714,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -693,7 +742,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -722,7 +771,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -754,7 +803,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -785,7 +834,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -810,7 +859,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewUser{
PasswordSet: true,
IsEmailVerified: true,
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
MFAMaxSetUp: int32(model.MFALevelSecondFactor),
},
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
@ -844,7 +893,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
LoginPolicyViewProvider: tt.fields.loginPolicyProvider,
PasswordCheckLifeTime: tt.fields.PasswordCheckLifeTime,
ExternalLoginCheckLifeTime: tt.fields.ExternalLoginCheckLifeTime,
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
MFAInitSkippedLifeTime: tt.fields.MFAInitSkippedLifeTime,
SecondFactorCheckLifeTime: tt.fields.SecondFactorCheckLifeTime,
MultiFactorCheckLifeTime: tt.fields.MultiFactorCheckLifeTime,
}
@ -860,7 +909,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
func TestAuthRequestRepo_mfaChecked(t *testing.T) {
type fields struct {
MfaInitSkippedLifeTime time.Duration
MFAInitSkippedLifeTime time.Duration
SecondFactorCheckLifeTime time.Duration
MultiFactorCheckLifeTime time.Duration
}
@ -884,7 +933,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
// args{
// request: &model.AuthRequest{PossibleLOAs: []model.LevelOfAssurance{}},
// user: &user_model.UserView{
// OTPState: user_model.MfaStateReady,
// OTPState: user_model.MFAStateReady,
// },
// },
// false,
@ -892,7 +941,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
{
"not set up, forced by policy, no mfas configured, error",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
@ -902,7 +951,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelNotSetUp,
MFAMaxSetUp: model.MFALevelNotSetUp,
},
},
},
@ -913,7 +962,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
{
"not set up, no mfas configured, no prompt and true",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
@ -921,7 +970,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelNotSetUp,
MFAMaxSetUp: model.MFALevelNotSetUp,
},
},
},
@ -932,7 +981,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
{
"not set up, prompt and false",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
@ -942,12 +991,12 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelNotSetUp,
MFAMaxSetUp: model.MFALevelNotSetUp,
},
},
},
&model.MfaPromptStep{
MfaProviders: []model.MFAType{
&model.MFAPromptStep{
MFAProviders: []model.MFAType{
model.MFATypeOTP,
},
},
@ -957,7 +1006,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
{
"not set up, forced by org, true",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
@ -968,13 +1017,13 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelNotSetUp,
MFAMaxSetUp: model.MFALevelNotSetUp,
},
},
},
&model.MfaPromptStep{
&model.MFAPromptStep{
Required: true,
MfaProviders: []model.MFAType{
MFAProviders: []model.MFAType{
model.MFATypeOTP,
},
},
@ -984,7 +1033,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
{
"not set up and skipped, true",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
@ -992,8 +1041,8 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelNotSetUp,
MfaInitSkipped: time.Now().UTC(),
MFAMaxSetUp: model.MFALevelNotSetUp,
MFAInitSkipped: time.Now().UTC(),
},
},
},
@ -1014,8 +1063,8 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelSecondFactor,
OTPState: user_model.MfaStateReady,
MFAMaxSetUp: model.MFALevelSecondFactor,
OTPState: user_model.MFAStateReady,
},
},
userSession: &user_model.UserSessionView{SecondFactorVerification: time.Now().UTC().Add(-5 * time.Hour)},
@ -1037,15 +1086,15 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelSecondFactor,
OTPState: user_model.MfaStateReady,
MFAMaxSetUp: model.MFALevelSecondFactor,
OTPState: user_model.MFAStateReady,
},
},
userSession: &user_model.UserSessionView{},
},
&model.MfaVerificationStep{
MfaProviders: []model.MFAType{model.MFATypeOTP},
&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
},
false,
nil,
@ -1054,7 +1103,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := &AuthRequestRepo{
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
MFAInitSkippedLifeTime: tt.fields.MFAInitSkippedLifeTime,
SecondFactorCheckLifeTime: tt.fields.SecondFactorCheckLifeTime,
MultiFactorCheckLifeTime: tt.fields.MultiFactorCheckLifeTime,
}
@ -1073,7 +1122,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
type fields struct {
MfaInitSkippedLifeTime time.Duration
MFAInitSkippedLifeTime time.Duration
}
type args struct {
user *user_model.UserView
@ -1090,7 +1139,7 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
args{
&user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: model.MFALevelSecondFactor,
MFAMaxSetUp: model.MFALevelSecondFactor,
},
},
},
@ -1099,13 +1148,13 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
{
"mfa skipped active, true",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
&user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: -1,
MfaInitSkipped: time.Now().UTC().Add(-10 * time.Hour),
MFAMaxSetUp: -1,
MFAInitSkipped: time.Now().UTC().Add(-10 * time.Hour),
},
},
},
@ -1114,13 +1163,13 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
{
"mfa skipped inactive, false",
fields{
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
&user_model.UserView{
HumanView: &user_model.HumanView{
MfaMaxSetUp: -1,
MfaInitSkipped: time.Now().UTC().Add(-40 * 24 * time.Hour),
MFAMaxSetUp: -1,
MFAInitSkipped: time.Now().UTC().Add(-40 * 24 * time.Hour),
},
},
},
@ -1130,7 +1179,7 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := &AuthRequestRepo{
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
MFAInitSkippedLifeTime: tt.fields.MFAInitSkippedLifeTime,
}
if got := repo.mfaSkippedOrSetUp(tt.args.user); got != tt.want {
t.Errorf("mfaSkippedOrSetUp() = %v, want %v", got, tt.want)

View File

@ -9,7 +9,7 @@ import (
"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"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
auth_model "github.com/caos/zitadel/internal/auth/model"
auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
@ -50,7 +50,7 @@ func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.Or
}
if err == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}

View File

@ -3,17 +3,18 @@ package eventstore
import (
"context"
"strings"
"time"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
auth_req_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/user/repository/view/model"
"time"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
)
type TokenRepo struct {

View File

@ -16,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"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
@ -124,7 +124,7 @@ func (repo *UserRepo) SearchMyExternalIDPs(ctx context.Context, request *model.E
}
if seqErr == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}
@ -253,18 +253,22 @@ func (repo *UserRepo) ChangePassword(ctx context.Context, userID, old, new strin
return err
}
func (repo *UserRepo) MyUserMfas(ctx context.Context) ([]*model.MultiFactor, error) {
func (repo *UserRepo) MyUserMFAs(ctx context.Context) ([]*model.MultiFactor, error) {
user, err := repo.UserByID(ctx, authz.GetCtxData(ctx).UserID)
if err != nil {
return nil, err
}
if user.OTPState == model.MfaStateUnspecified {
return []*model.MultiFactor{}, nil
mfas := make([]*model.MultiFactor, 0)
if user.OTPState != model.MFAStateUnspecified {
mfas = append(mfas, &model.MultiFactor{Type: model.MFATypeOTP, State: user.OTPState})
}
return []*model.MultiFactor{{Type: model.MfaTypeOTP, State: user.OTPState}}, nil
for _, u2f := range user.U2FTokens {
mfas = append(mfas, &model.MultiFactor{Type: model.MFATypeU2F, State: u2f.State, Attribute: u2f.Name})
}
return mfas, nil
}
func (repo *UserRepo) AddMfaOTP(ctx context.Context, userID string) (*model.OTP, error) {
func (repo *UserRepo) AddMFAOTP(ctx context.Context, userID string) (*model.OTP, error) {
accountName := ""
user, err := repo.UserByID(ctx, userID)
if err != nil {
@ -275,7 +279,7 @@ func (repo *UserRepo) AddMfaOTP(ctx context.Context, userID string) (*model.OTP,
return repo.UserEvents.AddOTP(ctx, userID, accountName)
}
func (repo *UserRepo) AddMyMfaOTP(ctx context.Context) (*model.OTP, error) {
func (repo *UserRepo) AddMyMFAOTP(ctx context.Context) (*model.OTP, error) {
accountName := ""
user, err := repo.UserByID(ctx, authz.GetCtxData(ctx).UserID)
if err != nil {
@ -286,18 +290,66 @@ func (repo *UserRepo) AddMyMfaOTP(ctx context.Context) (*model.OTP, error) {
return repo.UserEvents.AddOTP(ctx, authz.GetCtxData(ctx).UserID, accountName)
}
func (repo *UserRepo) VerifyMfaOTPSetup(ctx context.Context, userID, code string) error {
return repo.UserEvents.CheckMfaOTPSetup(ctx, userID, code)
func (repo *UserRepo) VerifyMFAOTPSetup(ctx context.Context, userID, code string) error {
return repo.UserEvents.CheckMFAOTPSetup(ctx, userID, code)
}
func (repo *UserRepo) VerifyMyMfaOTPSetup(ctx context.Context, code string) error {
return repo.UserEvents.CheckMfaOTPSetup(ctx, authz.GetCtxData(ctx).UserID, code)
func (repo *UserRepo) VerifyMyMFAOTPSetup(ctx context.Context, code string) error {
return repo.UserEvents.CheckMFAOTPSetup(ctx, authz.GetCtxData(ctx).UserID, code)
}
func (repo *UserRepo) RemoveMyMfaOTP(ctx context.Context) error {
func (repo *UserRepo) RemoveMyMFAOTP(ctx context.Context) error {
return repo.UserEvents.RemoveOTP(ctx, authz.GetCtxData(ctx).UserID)
}
func (repo *UserRepo) AddMFAU2F(ctx context.Context, userID string) (*model.WebAuthNToken, error) {
return repo.UserEvents.AddU2F(ctx, userID)
}
func (repo *UserRepo) AddMyMFAU2F(ctx context.Context) (*model.WebAuthNToken, error) {
return repo.UserEvents.AddU2F(ctx, authz.GetCtxData(ctx).UserID)
}
func (repo *UserRepo) VerifyMFAU2FSetup(ctx context.Context, userID, tokenName string, credentialData []byte) error {
return repo.UserEvents.VerifyU2FSetup(ctx, userID, tokenName, credentialData)
}
func (repo *UserRepo) VerifyMyMFAU2FSetup(ctx context.Context, tokenName string, credentialData []byte) error {
return repo.UserEvents.VerifyU2FSetup(ctx, authz.GetCtxData(ctx).UserID, tokenName, credentialData)
}
func (repo *UserRepo) RemoveMFAU2F(ctx context.Context, userID, webAuthNTokenID string) error {
return repo.UserEvents.RemoveU2FToken(ctx, userID, webAuthNTokenID)
}
func (repo *UserRepo) RemoveMyMFAU2F(ctx context.Context, webAuthNTokenID string) error {
return repo.UserEvents.RemoveU2FToken(ctx, authz.GetCtxData(ctx).UserID, webAuthNTokenID)
}
func (repo *UserRepo) AddPasswordless(ctx context.Context, userID string) (*model.WebAuthNToken, error) {
return repo.UserEvents.AddPasswordless(ctx, userID)
}
func (repo *UserRepo) AddMyPasswordless(ctx context.Context) (*model.WebAuthNToken, error) {
return repo.UserEvents.AddPasswordless(ctx, authz.GetCtxData(ctx).UserID)
}
func (repo *UserRepo) VerifyPasswordlessSetup(ctx context.Context, userID, tokenName string, credentialData []byte) error {
return repo.UserEvents.VerifyPasswordlessSetup(ctx, userID, tokenName, credentialData)
}
func (repo *UserRepo) VerifyMyPasswordlessSetup(ctx context.Context, tokenName string, credentialData []byte) error {
return repo.UserEvents.VerifyPasswordlessSetup(ctx, authz.GetCtxData(ctx).UserID, tokenName, credentialData)
}
func (repo *UserRepo) RemovePasswordless(ctx context.Context, userID, webAuthNTokenID string) error {
return repo.UserEvents.RemovePasswordlessToken(ctx, userID, webAuthNTokenID)
}
func (repo *UserRepo) RemoveMyPasswordless(ctx context.Context, webAuthNTokenID string) error {
return repo.UserEvents.RemovePasswordlessToken(ctx, authz.GetCtxData(ctx).UserID, webAuthNTokenID)
}
func (repo *UserRepo) ChangeMyUsername(ctx context.Context, username string) error {
ctxData := authz.GetCtxData(ctx)
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(ctxData.OrgID)
@ -327,8 +379,8 @@ func (repo *UserRepo) VerifyInitCode(ctx context.Context, userID, code, password
return repo.UserEvents.VerifyInitCode(ctx, pwPolicyView, userID, code, password)
}
func (repo *UserRepo) SkipMfaInit(ctx context.Context, userID string) error {
return repo.UserEvents.SkipMfaInit(ctx, userID)
func (repo *UserRepo) SkipMFAInit(ctx context.Context, userID string) error {
return repo.UserEvents.SkipMFAInit(ctx, userID)
}
func (repo *UserRepo) RequestPasswordReset(ctx context.Context, loginname string) error {

View File

@ -12,7 +12,7 @@ import (
global_model "github.com/caos/zitadel/internal/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_view_model "github.com/caos/zitadel/internal/org/repository/view/model"
"github.com/caos/zitadel/internal/tracing"
"github.com/caos/zitadel/internal/telemetry/tracing"
user_model "github.com/caos/zitadel/internal/user/model"
user_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
@ -44,7 +44,7 @@ func (repo *UserGrantRepo) SearchMyUserGrants(ctx context.Context, request *gran
}
if err == nil {
result.Sequence = sequence.CurrentSequence
result.Timestamp = sequence.CurrentTimestamp
result.Timestamp = sequence.LastSuccessfulSpoolerRun
}
return result, nil
}

View File

@ -20,3 +20,8 @@ func (repo *UserSessionRepo) GetMyUserSessions(ctx context.Context) ([]*usr_mode
}
return model.UserSessionsToModel(userSessions), nil
}
func (repo *UserSessionRepo) ActiveUserSessionCount() int64 {
userSessions, _ := repo.View.ActiveUserSessions()
return int64(len(userSessions))
}

View File

@ -22,12 +22,12 @@ const (
applicationTable = "auth.applications"
)
func (p *Application) ViewModel() string {
func (a *Application) ViewModel() string {
return applicationTable
}
func (p *Application) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestApplicationSequence()
func (a *Application) EventQuery() (*models.SearchQuery, error) {
sequence, err := a.view.GetLatestApplicationSequence()
if err != nil {
return nil, err
}
@ -65,33 +65,37 @@ func (a *Application) Reduce(event *models.Event) (err error) {
if err != nil {
return err
}
return a.view.DeleteApplication(app.ID, event.Sequence)
return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate)
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)
return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate)
}
for _, app := range apps {
if err := app.AppendEvent(event); err != nil {
return err
}
}
return a.view.PutApplications(apps, event.Sequence)
return a.view.PutApplications(apps, event.Sequence, event.CreationDate)
case es_model.ProjectRemoved:
return a.view.DeleteApplicationsByProjectID(event.AggregateID)
default:
return a.view.ProcessedApplicationSequence(event.Sequence)
return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return a.view.PutApplication(app)
return a.view.PutApplication(app, event.CreationDate)
}
func (p *Application) OnError(event *models.Event, spoolerError error) error {
func (a *Application) OnError(event *models.Event, spoolerError error) error {
logging.LogWithFields("SPOOL-ls9ew", "id", event.AggregateID).WithError(spoolerError).Warn("something went wrong in project app handler")
return spooler.HandleError(event, spoolerError, p.view.GetLatestApplicationFailedEvent, p.view.ProcessedApplicationFailedEvent, p.view.ProcessedApplicationSequence, p.errorCountUntilSkip)
return spooler.HandleError(event, spoolerError, a.view.GetLatestApplicationFailedEvent, a.view.ProcessedApplicationFailedEvent, a.view.ProcessedApplicationSequence, a.errorCountUntilSkip)
}
func (a *Application) OnSuccess() error {
return spooler.HandleSuccess(a.view.UpdateApplicationSpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
idpConfigTable = "auth.idp_configs"
)
func (m *IDPConfig) ViewModel() string {
func (i *IDPConfig) ViewModel() string {
return idpConfigTable
}
func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestIDPConfigSequence()
func (i *IDPConfig) EventQuery() (*models.SearchQuery, error) {
sequence, err := i.view.GetLatestIDPConfigSequence()
if err != nil {
return nil, err
}
@ -33,17 +33,17 @@ func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *IDPConfig) Reduce(event *models.Event) (err error) {
func (i *IDPConfig) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate:
err = m.processIdpConfig(iam_model.IDPProviderTypeOrg, event)
err = i.processIdpConfig(iam_model.IDPProviderTypeOrg, event)
case iam_es_model.IAMAggregate:
err = m.processIdpConfig(iam_model.IDPProviderTypeSystem, event)
err = i.processIdpConfig(iam_model.IDPProviderTypeSystem, event)
}
return err
}
func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, event *models.Event) (err error) {
func (i *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, event *models.Event) (err error) {
idp := new(iam_view_model.IDPConfigView)
switch event.Type {
case model.IDPConfigAdded,
@ -56,7 +56,7 @@ func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve
if err != nil {
return err
}
idp, err = m.view.IDPConfigByID(idp.IDPConfigID)
idp, err = i.view.IDPConfigByID(idp.IDPConfigID)
if err != nil {
return err
}
@ -66,17 +66,21 @@ func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve
if err != nil {
return err
}
return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence)
return i.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedIDPConfigSequence(event.Sequence)
return i.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutIDPConfig(idp, idp.Sequence)
return i.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate)
}
func (m *IDPConfig) OnError(event *models.Event, err error) error {
func (i *IDPConfig) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Ejf8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler")
return spooler.HandleError(event, err, m.view.GetLatestIDPConfigFailedEvent, m.view.ProcessedIDPConfigFailedEvent, m.view.ProcessedIDPConfigSequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip)
}
func (i *IDPConfig) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPConfigSpoolerRunTimestamp)
}

View File

@ -27,12 +27,12 @@ const (
idpProviderTable = "auth.idp_providers"
)
func (m *IDPProvider) ViewModel() string {
func (i *IDPProvider) ViewModel() string {
return idpProviderTable
}
func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestIDPProviderSequence()
func (i *IDPProvider) EventQuery() (*models.SearchQuery, error) {
sequence, err := i.view.GetLatestIDPProviderSequence()
if err != nil {
return nil, err
}
@ -41,15 +41,15 @@ func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *IDPProvider) Reduce(event *models.Event) (err error) {
func (i *IDPProvider) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate, org_es_model.OrgAggregate:
err = m.processIdpProvider(event)
err = i.processIdpProvider(event)
}
return err
}
func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) {
func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) {
provider := new(iam_view_model.IDPProviderView)
switch event.Type {
case model.LoginPolicyIDPProviderAdded, org_es_model.LoginPolicyIDPProviderAdded:
@ -57,71 +57,75 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) {
if err != nil {
return err
}
err = m.fillData(provider)
err = i.fillData(provider)
case model.LoginPolicyIDPProviderRemoved, model.LoginPolicyIDPProviderCascadeRemoved,
org_es_model.LoginPolicyIDPProviderRemoved, org_es_model.LoginPolicyIDPProviderCascadeRemoved:
err = provider.SetData(event)
if err != nil {
return err
}
return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence)
return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate)
case model.IDPConfigChanged, org_es_model.IDPConfigChanged:
esConfig := new(iam_view_model.IDPConfigView)
providerType := iam_model.IDPProviderTypeSystem
if event.AggregateID != m.systemDefaults.IamID {
if event.AggregateID != i.systemDefaults.IamID {
providerType = iam_model.IDPProviderTypeOrg
}
esConfig.AppendEvent(providerType, event)
providers, err := m.view.IDPProvidersByIDPConfigID(esConfig.IDPConfigID)
providers, err := i.view.IDPProvidersByIDPConfigID(esConfig.IDPConfigID)
if err != nil {
return err
}
config := new(iam_model.IDPConfig)
if event.AggregateID == m.systemDefaults.IamID {
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
if event.AggregateID == i.systemDefaults.IamID {
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, esConfig.IDPConfigID)
}
if err != nil {
return err
}
for _, provider := range providers {
m.fillConfigData(provider, config)
i.fillConfigData(provider, config)
}
return m.view.PutIDPProviders(event.Sequence, providers...)
return i.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...)
case org_es_model.LoginPolicyRemoved:
return m.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence)
return i.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedIDPProviderSequence(event.Sequence)
return i.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutIDPProvider(provider, provider.Sequence)
return i.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate)
}
func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
var config *iam_model.IDPConfig
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, provider.IDPConfigID)
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, provider.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
config, err = i.orgEvents.GetIDPConfig(context.Background(), provider.AggregateID, provider.IDPConfigID)
}
if err != nil {
return err
}
m.fillConfigData(provider, config)
i.fillConfigData(provider, config)
return nil
}
func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) {
func (i *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)
}
func (m *IDPProvider) OnError(event *models.Event, err error) error {
func (i *IDPProvider) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-Fjd89", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler")
return spooler.HandleError(event, err, m.view.GetLatestIDPProviderFailedEvent, m.view.ProcessedIDPProviderFailedEvent, m.view.ProcessedIDPProviderSequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, i.view.GetLatestIDPProviderFailedEvent, i.view.ProcessedIDPProviderFailedEvent, i.view.ProcessedIDPProviderSequence, i.errorCountUntilSkip)
}
func (i *IDPProvider) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp)
}

View File

@ -41,11 +41,11 @@ func (k *Key) Reduce(event *models.Event) error {
return err
}
if privateKey.Expiry.Before(time.Now()) && publicKey.Expiry.Before(time.Now()) {
return k.view.ProcessedKeySequence(event.Sequence)
return k.view.ProcessedKeySequence(event.Sequence, event.CreationDate)
}
return k.view.PutKeys(privateKey, publicKey, event.Sequence)
return k.view.PutKeys(privateKey, publicKey, event.Sequence, event.CreationDate)
default:
return k.view.ProcessedKeySequence(event.Sequence)
return k.view.ProcessedKeySequence(event.Sequence, event.CreationDate)
}
}
@ -53,3 +53,9 @@ func (k *Key) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-GHa3a", "id", event.AggregateID).WithError(err).Warn("something went wrong in key handler")
return spooler.HandleError(event, err, k.view.GetLatestKeyFailedEvent, k.view.ProcessedKeyFailedEvent, k.view.ProcessedKeySequence, k.errorCountUntilSkip)
}
func (k *Key) OnSuccess() error {
err := spooler.HandleSuccess(k.view.UpdateKeySpoolerRunTimestamp)
logging.LogWithFields("SPOOL-vM9sd", "table", keyTable).OnError(err).Warn("could not process on success func")
return err
}

View File

@ -19,12 +19,12 @@ const (
loginPolicyTable = "auth.login_policies"
)
func (m *LoginPolicy) ViewModel() string {
func (p *LoginPolicy) ViewModel() string {
return loginPolicyTable
}
func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLoginPolicySequence()
func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestLoginPolicySequence()
if err != nil {
return nil, err
}
@ -33,15 +33,15 @@ func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LoginPolicy) Reduce(event *models.Event) (err error) {
func (p *LoginPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processLoginPolicy(event)
err = p.processLoginPolicy(event)
}
return err
}
func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
policy := new(iam_model.LoginPolicyView)
switch event.Type {
case iam_es_model.LoginPolicyAdded, model.LoginPolicyAdded:
@ -51,23 +51,27 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
iam_es_model.LoginPolicySecondFactorRemoved, model.LoginPolicySecondFactorRemoved,
iam_es_model.LoginPolicyMultiFactorAdded, model.LoginPolicyMultiFactorAdded,
iam_es_model.LoginPolicyMultiFactorRemoved, model.LoginPolicyMultiFactorRemoved:
policy, err = m.view.LoginPolicyByAggregateID(event.AggregateID)
policy, err = p.view.LoginPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.LoginPolicyRemoved:
return m.view.DeleteLoginPolicy(event.AggregateID, event.Sequence)
return p.view.DeleteLoginPolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedLoginPolicySequence(event.Sequence)
return p.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutLoginPolicy(policy, policy.Sequence)
return p.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *LoginPolicy) OnError(event *models.Event, err error) error {
func (p *LoginPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-5id9s", "id", event.AggregateID).WithError(err).Warn("something went wrong in login policy handler")
return spooler.HandleError(event, err, m.view.GetLatestLoginPolicyFailedEvent, m.view.ProcessedLoginPolicyFailedEvent, m.view.ProcessedLoginPolicySequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, p.view.GetLatestLoginPolicyFailedEvent, p.view.ProcessedLoginPolicyFailedEvent, p.view.ProcessedLoginPolicySequence, p.errorCountUntilSkip)
}
func (p *LoginPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateLoginPolicySpoolerRunTimestamp)
}

View File

@ -48,26 +48,30 @@ func (d *MachineKeys) processMachineKeys(event *models.Event) (err error) {
case model.MachineKeyAdded:
err = key.AppendEvent(event)
if key.ExpirationDate.Before(time.Now()) {
return d.view.ProcessedMachineKeySequence(event.Sequence)
return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate)
}
case model.MachineKeyRemoved:
err = key.SetData(event)
if err != nil {
return err
}
return d.view.DeleteMachineKey(key.ID, event.Sequence)
return d.view.DeleteMachineKey(key.ID, event.Sequence, event.CreationDate)
case model.UserRemoved:
return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence)
return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence, event.CreationDate)
default:
return d.view.ProcessedMachineKeySequence(event.Sequence)
return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return d.view.PutMachineKey(key, key.Sequence)
return d.view.PutMachineKey(key, key.Sequence, event.CreationDate)
}
func (d *MachineKeys) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-S9fe", "id", event.AggregateID).WithError(err).Warn("something went wrong in machine key handler")
return spooler.HandleError(event, err, d.view.GetLatestMachineKeyFailedEvent, d.view.ProcessedMachineKeyFailedEvent, d.view.ProcessedMachineKeySequence, d.errorCountUntilSkip)
}
func (d *MachineKeys) OnSuccess() error {
return spooler.HandleSuccess(d.view.UpdateMachineKeySpoolerRunTimestamp)
}

View File

@ -58,16 +58,20 @@ func (o *Org) Reduce(event *es_models.Event) (err error) {
}
org.Domain = domain.Domain
default:
return o.view.ProcessedOrgSequence(event.Sequence)
return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return o.view.PutOrg(org)
return o.view.PutOrg(org, event.CreationDate)
}
func (o *Org) OnError(event *es_models.Event, spoolerErr error) error {
logging.LogWithFields("SPOOL-8siWS", "id", event.AggregateID).WithError(spoolerErr).Warn("something went wrong in org handler")
return spooler.HandleError(event, spoolerErr, o.view.GetLatestOrgFailedEvent, o.view.ProcessedOrgFailedEvent, o.view.ProcessedOrgSequence, o.errorCountUntilSkip)
}
func (o *Org) OnSuccess() error {
return spooler.HandleSuccess(o.view.UpdateOrgSpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
orgIAMPolicyTable = "auth.org_iam_policies"
)
func (m *OrgIAMPolicy) ViewModel() string {
func (p *OrgIAMPolicy) ViewModel() string {
return orgIAMPolicyTable
}
func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestOrgIAMPolicySequence()
func (p *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestOrgIAMPolicySequence()
if err != nil {
return nil, err
}
@ -33,37 +33,41 @@ func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *OrgIAMPolicy) Reduce(event *models.Event) (err error) {
func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processOrgIAMPolicy(event)
err = p.processOrgIAMPolicy(event)
}
return err
}
func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.OrgIAMPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.OrgIAMPolicyRemoved:
return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence)
return p.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedOrgIAMPolicySequence(event.Sequence)
return p.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutOrgIAMPolicy(policy, policy.Sequence)
return p.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicySequence, p.errorCountUntilSkip)
}
func (p *OrgIAMPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateOrgIAMPolicySpoolerRunTimestamp)
}

View File

@ -19,12 +19,12 @@ const (
passwordComplexityPolicyTable = "auth.password_complexity_policies"
)
func (m *PasswordComplexityPolicy) ViewModel() string {
func (p *PasswordComplexityPolicy) ViewModel() string {
return passwordComplexityPolicyTable
}
func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestPasswordComplexityPolicySequence()
func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := p.view.GetLatestPasswordComplexityPolicySequence()
if err != nil {
return nil, err
}
@ -33,37 +33,41 @@ func (m *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) {
func (p *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processPasswordComplexityPolicy(event)
err = p.processPasswordComplexityPolicy(event)
}
return err
}
func (m *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) {
func (p *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)
policy, err = p.view.PasswordComplexityPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.PasswordComplexityPolicyRemoved:
return m.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence)
return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedPasswordComplexityPolicySequence(event.Sequence)
return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutPasswordComplexityPolicy(policy, policy.Sequence)
return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate)
}
func (m *PasswordComplexityPolicy) OnError(event *models.Event, err error) error {
func (p *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)
return spooler.HandleError(event, err, p.view.GetLatestPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicySequence, p.errorCountUntilSkip)
}
func (p *PasswordComplexityPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdatePasswordComplexityPolicySpoolerRunTimestamp)
}

View File

@ -52,19 +52,23 @@ func (p *ProjectRole) Reduce(event *models.Event) (err error) {
if err != nil {
return err
}
return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence)
return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence, event.CreationDate)
case es_model.ProjectRemoved:
return p.view.DeleteProjectRolesByProjectID(event.AggregateID)
default:
return p.view.ProcessedProjectRoleSequence(event.Sequence)
return p.view.ProcessedProjectRoleSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return p.view.PutProjectRole(role)
return p.view.PutProjectRole(role, event.CreationDate)
}
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)
}
func (p *ProjectRole) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateProjectRoleSpoolerRunTimestamp)
}

View File

@ -49,7 +49,7 @@ func (t *Token) Reduce(event *models.Event) (err error) {
if err != nil {
return err
}
return t.view.PutToken(token)
return t.view.PutToken(token, event.CreationDate)
case user_es_model.UserProfileChanged,
user_es_model.HumanProfileChanged:
user := new(view_model.UserView)
@ -61,25 +61,25 @@ func (t *Token) Reduce(event *models.Event) (err error) {
for _, token := range tokens {
token.PreferredLanguage = user.PreferredLanguage
}
return t.view.PutTokens(tokens, event.Sequence)
return t.view.PutTokens(tokens, event.Sequence, event.CreationDate)
case user_es_model.SignedOut,
user_es_model.HumanSignedOut:
id, err := agentIDFromSession(event)
if err != nil {
return err
}
return t.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence)
return t.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence, event.CreationDate)
case user_es_model.UserLocked,
user_es_model.UserDeactivated,
user_es_model.UserRemoved:
return t.view.DeleteUserTokens(event.AggregateID, event.Sequence)
return t.view.DeleteUserTokens(event.AggregateID, event.Sequence, event.CreationDate)
case project_es_model.ApplicationDeactivated,
project_es_model.ApplicationRemoved:
application, err := applicationFromSession(event)
if err != nil {
return err
}
return t.view.DeleteApplicationTokens(event.Sequence, application.AppID)
return t.view.DeleteApplicationTokens(event.Sequence, event.CreationDate, application.AppID)
case project_es_model.ProjectDeactivated,
project_es_model.ProjectRemoved:
project, err := t.ProjectEvents.ProjectByID(context.Background(), event.AggregateID)
@ -90,9 +90,9 @@ func (t *Token) Reduce(event *models.Event) (err error) {
for _, app := range project.Applications {
applicationsIDs = append(applicationsIDs, app.AppID)
}
return t.view.DeleteApplicationTokens(event.Sequence, applicationsIDs...)
return t.view.DeleteApplicationTokens(event.Sequence, event.CreationDate, applicationsIDs...)
default:
return t.view.ProcessedTokenSequence(event.Sequence)
return t.view.ProcessedTokenSequence(event.Sequence, event.CreationDate)
}
}
@ -118,3 +118,7 @@ func applicationFromSession(event *models.Event) (*project_es_model.Application,
}
return application, nil
}
func (t *Token) OnSuccess() error {
return spooler.HandleSuccess(t.view.UpdateTokenSpoolerRunTimestamp)
}

View File

@ -67,7 +67,7 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
if err != nil {
return err
}
u.fillLoginNames(user)
err = u.fillLoginNames(user)
case es_model.UserProfileChanged,
es_model.UserEmailChanged,
es_model.UserEmailVerified,
@ -94,6 +94,12 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
es_model.HumanMFAOTPAdded,
es_model.HumanMFAOTPVerified,
es_model.HumanMFAOTPRemoved,
es_model.HumanMFAU2FTokenAdded,
es_model.HumanMFAU2FTokenVerified,
es_model.HumanMFAU2FTokenRemoved,
es_model.HumanPasswordlessTokenAdded,
es_model.HumanPasswordlessTokenVerified,
es_model.HumanPasswordlessTokenRemoved,
es_model.HumanMFAInitSkipped,
es_model.MachineChanged,
es_model.HumanPasswordChanged:
@ -114,14 +120,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) {
}
err = u.fillLoginNames(user)
case es_model.UserRemoved:
return u.view.DeleteUser(event.AggregateID, event.Sequence)
return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserSequence(event.Sequence)
return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return u.view.PutUser(user, user.Sequence)
return u.view.PutUser(user, user.Sequence, event.CreationDate)
}
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
@ -152,7 +158,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) {
case org_es_model.OrgDomainPrimarySet:
return u.fillPreferredLoginNamesOnOrgUsers(event)
default:
return u.view.ProcessedUserSequence(event.Sequence)
return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate)
}
}
@ -175,7 +181,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error {
for _, user := range users {
user.SetLoginNames(policy, org.Domains)
}
return u.view.PutUsers(users, event.Sequence)
return u.view.PutUsers(users, event.Sequence, event.CreationDate)
}
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
@ -200,10 +206,14 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error {
for _, user := range users {
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
}
return u.view.PutUsers(users, 0)
return u.view.PutUsers(users, 0, event.CreationDate)
}
func (u *User) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-is8aAWima", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler")
return spooler.HandleError(event, err, u.view.GetLatestUserFailedEvent, u.view.ProcessedUserFailedEvent, u.view.ProcessedUserSequence, u.errorCountUntilSkip)
}
func (u *User) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserSpoolerRunTimestamp)
}

View File

@ -29,12 +29,12 @@ const (
externalIDPTable = "auth.user_external_idps"
)
func (m *ExternalIDP) ViewModel() string {
func (i *ExternalIDP) ViewModel() string {
return externalIDPTable
}
func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestExternalIDPSequence()
func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) {
sequence, err := i.view.GetLatestExternalIDPSequence()
if err != nil {
return nil, err
}
@ -43,17 +43,17 @@ func (m *ExternalIDP) EventQuery() (*models.SearchQuery, error) {
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *ExternalIDP) Reduce(event *models.Event) (err error) {
func (i *ExternalIDP) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.UserAggregate:
err = m.processUser(event)
err = i.processUser(event)
case iam_es_model.IAMAggregate, org_es_model.OrgAggregate:
err = m.processIdpConfig(event)
err = i.processIdpConfig(event)
}
return err
}
func (m *ExternalIDP) processUser(event *models.Event) (err error) {
func (i *ExternalIDP) processUser(event *models.Event) (err error) {
externalIDP := new(usr_view_model.ExternalIDPView)
switch event.Type {
case model.HumanExternalIDPAdded:
@ -61,25 +61,25 @@ func (m *ExternalIDP) processUser(event *models.Event) (err error) {
if err != nil {
return err
}
err = m.fillData(externalIDP)
err = i.fillData(externalIDP)
case model.HumanExternalIDPRemoved, model.HumanExternalIDPCascadeRemoved:
err = externalIDP.SetData(event)
if err != nil {
return err
}
return m.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence)
return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate)
case model.UserRemoved:
return m.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence)
return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedExternalIDPSequence(event.Sequence)
return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutExternalIDP(externalIDP, externalIDP.Sequence)
return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate)
}
func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
func (i *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)
@ -89,45 +89,49 @@ func (m *ExternalIDP) processIdpConfig(event *models.Event) (err error) {
} else {
configView.AppendEvent(iam_model.IDPProviderTypeOrg, event)
}
exterinalIDPs, err := m.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID)
exterinalIDPs, err := i.view.ExternalIDPsByIDPConfigID(configView.IDPConfigID)
if err != nil {
return err
}
if event.AggregateType == iam_es_model.IAMAggregate {
config, err = m.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.iamEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
} else {
config, err = m.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
config, err = i.orgEvents.GetIDPConfig(context.Background(), event.AggregateID, configView.IDPConfigID)
}
if err != nil {
return err
}
for _, provider := range exterinalIDPs {
m.fillConfigData(provider, config)
i.fillConfigData(provider, config)
}
return m.view.PutExternalIDPs(event.Sequence, exterinalIDPs...)
return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...)
default:
return m.view.ProcessedExternalIDPSequence(event.Sequence)
return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate)
}
return nil
}
func (m *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := m.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) error {
config, err := i.orgEvents.GetIDPConfig(context.Background(), externalIDP.ResourceOwner, externalIDP.IDPConfigID)
if caos_errs.IsNotFound(err) {
config, err = m.iamEvents.GetIDPConfig(context.Background(), m.systemDefaults.IamID, externalIDP.IDPConfigID)
config, err = i.iamEvents.GetIDPConfig(context.Background(), i.systemDefaults.IamID, externalIDP.IDPConfigID)
}
if err != nil {
return err
}
m.fillConfigData(externalIDP, config)
i.fillConfigData(externalIDP, config)
return nil
}
func (m *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) {
func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) {
externalIDP.IDPName = config.Name
}
func (m *ExternalIDP) OnError(event *models.Event, err error) error {
func (i *ExternalIDP) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-4Rsu8", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler")
return spooler.HandleError(event, err, m.view.GetLatestExternalIDPFailedEvent, m.view.ProcessedExternalIDPFailedEvent, m.view.ProcessedExternalIDPSequence, m.errorCountUntilSkip)
return spooler.HandleError(event, err, i.view.GetLatestExternalIDPFailedEvent, i.view.ProcessedExternalIDPFailedEvent, i.view.ProcessedExternalIDPSequence, i.errorCountUntilSkip)
}
func (i *ExternalIDP) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp)
}

View File

@ -97,14 +97,14 @@ func (u *UserGrant) processUserGrant(event *models.Event) (err error) {
}
err = grant.AppendEvent(event)
case grant_es_model.UserGrantRemoved, grant_es_model.UserGrantCascadeRemoved:
return u.view.DeleteUserGrant(event.AggregateID, event.Sequence)
return u.view.DeleteUserGrant(event.AggregateID, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return u.view.PutUserGrant(grant, grant.Sequence)
return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate)
}
func (u *UserGrant) processUser(event *models.Event) (err error) {
@ -119,7 +119,7 @@ func (u *UserGrant) processUser(event *models.Event) (err error) {
return err
}
if len(grants) == 0 {
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
user, err := u.userEvents.UserByID(context.Background(), event.AggregateID)
if err != nil {
@ -128,9 +128,9 @@ func (u *UserGrant) processUser(event *models.Event) (err error) {
for _, grant := range grants {
u.fillUserData(grant, user)
}
return u.view.PutUserGrants(grants, event.Sequence)
return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
}
@ -148,7 +148,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) {
for _, grant := range grants {
u.fillProjectData(grant, project)
}
return u.view.PutUserGrants(grants, event.Sequence)
return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate)
case proj_es_model.ProjectMemberAdded, proj_es_model.ProjectMemberChanged, proj_es_model.ProjectMemberRemoved:
member := new(proj_es_model.ProjectMember)
member.SetData(event)
@ -158,7 +158,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) {
member.SetData(event)
return u.processMember(event, "PROJECT_GRANT", member.GrantID, member.UserID, member.Roles)
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
}
@ -169,7 +169,7 @@ func (u *UserGrant) processOrg(event *models.Event) (err error) {
member.SetData(event)
return u.processMember(event, "ORG", "", member.UserID, member.Roles)
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
}
@ -207,16 +207,16 @@ func (u *UserGrant) processIAMMember(event *models.Event, rolePrefix string, suf
}
grant.Sequence = event.Sequence
grant.ChangeDate = event.CreationDate
return u.view.PutUserGrant(grant, grant.Sequence)
return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate)
case iam_es_model.IAMMemberRemoved:
member.SetData(event)
grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID)
if err != nil {
return err
}
return u.view.DeleteUserGrant(grant.ID, event.Sequence)
return u.view.DeleteUserGrant(grant.ID, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
}
@ -252,7 +252,7 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st
}
grant.Sequence = event.Sequence
grant.ChangeDate = event.CreationDate
return u.view.PutUserGrant(grant, event.Sequence)
return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate)
case org_es_model.OrgMemberRemoved,
proj_es_model.ProjectMemberRemoved,
proj_es_model.ProjectGrantMemberRemoved:
@ -262,18 +262,18 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st
return err
}
if errors.IsNotFound(err) {
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
if roleSuffix != "" {
roleKeys = suffixRoles(roleSuffix, roleKeys)
}
if grant.RoleKeys == nil {
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil)
return u.view.PutUserGrant(grant, event.Sequence)
return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserGrantSequence(event.Sequence)
return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate)
}
}
@ -367,3 +367,7 @@ func (u *UserGrant) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-UZmc7", "id", event.AggregateID).WithError(err).Warn("something went wrong in user grant handler")
return spooler.HandleError(event, err, u.view.GetLatestUserGrantFailedEvent, u.view.ProcessedUserGrantFailedEvent, u.view.ProcessedUserGrantSequence, u.errorCountUntilSkip)
}
func (u *UserGrant) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserGrantSpoolerRunTimestamp)
}

View File

@ -74,14 +74,14 @@ func (m *UserMembership) processIam(event *models.Event) (err error) {
}
err = member.AppendEvent(event)
case iam_es_model.IAMMemberRemoved:
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence)
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutUserMembership(member, event.Sequence)
return m.view.PutUserMembership(member, event.Sequence, event.CreationDate)
}
func (m *UserMembership) fillIamDisplayName(member *usr_es_model.UserMembershipView) {
@ -105,16 +105,16 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) {
}
err = member.AppendEvent(event)
case org_es_model.OrgMemberRemoved:
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence)
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence, event.CreationDate)
case org_es_model.OrgChanged:
return m.updateOrgName(event)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutUserMembership(member, event.Sequence)
return m.view.PutUserMembership(member, event.Sequence, event.CreationDate)
}
func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (err error) {
@ -145,7 +145,7 @@ func (m *UserMembership) updateOrgName(event *models.Event) error {
membership.DisplayName = org.Name
}
}
return m.view.BulkPutUserMemberships(memberships, event.Sequence)
return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate)
}
func (m *UserMembership) processProject(event *models.Event) (err error) {
@ -168,7 +168,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) {
}
err = member.AppendEvent(event)
case proj_es_model.ProjectMemberRemoved:
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence)
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence, event.CreationDate)
case proj_es_model.ProjectGrantMemberChanged:
member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant)
if err != nil {
@ -176,20 +176,20 @@ func (m *UserMembership) processProject(event *models.Event) (err error) {
}
err = member.AppendEvent(event)
case proj_es_model.ProjectGrantMemberRemoved:
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence)
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence, event.CreationDate)
case proj_es_model.ProjectChanged:
return m.updateProjectDisplayName(event)
case proj_es_model.ProjectRemoved:
return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence)
return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence, event.CreationDate)
case proj_es_model.ProjectGrantRemoved:
return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence)
return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate)
}
if err != nil {
return err
}
return m.view.PutUserMembership(member, event.Sequence)
return m.view.PutUserMembership(member, event.Sequence, event.CreationDate)
}
func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) {
@ -214,15 +214,15 @@ func (m *UserMembership) updateProjectDisplayName(event *models.Event) error {
for _, membership := range memberships {
membership.DisplayName = project.Name
}
return m.view.BulkPutUserMemberships(memberships, event.Sequence)
return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate)
}
func (m *UserMembership) processUser(event *models.Event) (err error) {
switch event.Type {
case model.UserRemoved:
return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence)
return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence, event.CreationDate)
default:
return m.view.ProcessedUserMembershipSequence(event.Sequence)
return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate)
}
}
@ -230,3 +230,7 @@ func (m *UserMembership) OnError(event *models.Event, err error) error {
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)
}
func (m *UserMembership) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateUserMembershipSpoolerRunTimestamp)
}

View File

@ -48,6 +48,10 @@ func (u *UserSession) Reduce(event *models.Event) (err error) {
es_model.HumanExternalLoginCheckSucceeded,
es_model.HumanMFAOTPCheckSucceeded,
es_model.HumanMFAOTPCheckFailed,
es_model.HumanMFAU2FTokenCheckSucceeded,
es_model.HumanMFAU2FTokenCheckFailed,
es_model.HumanPasswordlessTokenCheckSucceeded,
es_model.HumanPasswordlessTokenCheckFailed,
es_model.HumanSignedOut:
eventData, err := view_model.UserSessionFromEvent(event)
if err != nil {
@ -78,13 +82,15 @@ func (u *UserSession) Reduce(event *models.Event) (err error) {
es_model.DomainClaimed,
es_model.UserUserNameChanged,
es_model.HumanExternalIDPRemoved,
es_model.HumanExternalIDPCascadeRemoved:
es_model.HumanExternalIDPCascadeRemoved,
es_model.HumanPasswordlessTokenRemoved,
es_model.HumanMFAU2FTokenRemoved:
sessions, err := u.view.UserSessionsByUserID(event.AggregateID)
if err != nil {
return err
}
if len(sessions) == 0 {
return u.view.ProcessedUserSessionSequence(event.Sequence)
return u.view.ProcessedUserSessionSequence(event.Sequence, event.CreationDate)
}
for _, session := range sessions {
session.AppendEvent(event)
@ -92,11 +98,11 @@ func (u *UserSession) Reduce(event *models.Event) (err error) {
return err
}
}
return u.view.PutUserSessions(sessions, event.Sequence)
return u.view.PutUserSessions(sessions, event.Sequence, event.CreationDate)
case es_model.UserRemoved:
return u.view.DeleteUserSessions(event.AggregateID, event.Sequence)
return u.view.DeleteUserSessions(event.AggregateID, event.Sequence, event.CreationDate)
default:
return u.view.ProcessedUserSessionSequence(event.Sequence)
return u.view.ProcessedUserSessionSequence(event.Sequence, event.CreationDate)
}
}
@ -105,12 +111,16 @@ func (u *UserSession) OnError(event *models.Event, err error) error {
return spooler.HandleError(event, err, u.view.GetLatestUserSessionFailedEvent, u.view.ProcessedUserSessionFailedEvent, u.view.ProcessedUserSessionSequence, u.errorCountUntilSkip)
}
func (u *UserSession) OnSuccess() error {
return spooler.HandleSuccess(u.view.UpdateUserSessionSpoolerRunTimestamp)
}
func (u *UserSession) updateSession(session *view_model.UserSessionView, event *models.Event) error {
session.AppendEvent(event)
if err := u.fillUserInfo(session, event.AggregateID); err != nil {
return err
}
return u.view.PutUserSession(session)
return u.view.PutUserSession(session, event.CreationDate)
}
func (u *UserSession) fillUserInfo(session *view_model.UserSessionView, id string) error {

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