fix(queries): Label policy projection (#2479)

* job queue

* wg improvements

* start handler

* statement

* statements

* imporve handler

* improve statement

* statement in seperate file

* move handlers

* move query/old to query

* handler

* read models

* bulk works

* cleanup

* contrib

* rename readmodel to projection

* rename read_models schema to projections

* rename read_models schema to projections

* search query as func,
bulk iterates as long as new events

* add event sequence less query

* update checks for events between current sequence and sequence of first statement if it has previous sequence 0

* cleanup crdb projection

* refactor projection handler

* start with testing

* tests for handler

* remove todo

* refactor statement: remove table name,
add tests

* improve projection handler shutdown,
no savepoint if noop stmt,
tests for stmt handler

* tests

* start failed events

* seperate branch for contrib

* move statement constructors to crdb pkg

* correct import

* Subscribe for eventtypes (#1800)

* fix: is default (#1737)

* fix: use email as username on global org (#1738)

* fix: use email as username on global org

* Update user_human.go

* Update register_handler.go

* chore(deps): update docusaurus (#1739)

* chore: remove PAT and use GH Token (#1716)

* chore: remove PAT and use GH Token

* fix env

* fix env

* fix env

* md lint

* trigger ci

* change user

* fix GH bug

* replace login part

* chore: add GH Token to sem rel (#1746)

* chore: add GH Token to sem rel

* try branch

* add GH Token

* remove test branch again

* docs: changes acme to acme-caos (#1744)

* changes acme to acme-caos

* Apply suggestions from code review

Co-authored-by: Florian Forster <florian@caos.ch>

Co-authored-by: Maximilian Panne <maximilian.panne@gmail.com>
Co-authored-by: Florian Forster <florian@caos.ch>

* feat: add additional origins on applications (#1691)

* feat: add additional origins on applications

* app additional redirects

* chore(deps-dev): bump @angular/cli from 11.2.8 to 11.2.11 in /console (#1706)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump @angular/cli from 11.2.8 to 11.2.11 in /console

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.2.8 to 11.2.11.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.2.8...v11.2.11)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump stylelint from 13.10.0 to 13.13.1 in /console (#1703)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump stylelint from 13.10.0 to 13.13.1 in /console

Bumps [stylelint](https://github.com/stylelint/stylelint) from 13.10.0 to 13.13.1.
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/13.10.0...13.13.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @types/node from 14.14.37 to 15.0.1 in /console (#1702)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump @types/node from 14.14.37 to 15.0.1 in /console

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.37 to 15.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump ts-protoc-gen from 0.14.0 to 0.15.0 in /console (#1701)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps): bump ts-protoc-gen from 0.14.0 to 0.15.0 in /console

Bumps [ts-protoc-gen](https://github.com/improbable-eng/ts-protoc-gen) from 0.14.0 to 0.15.0.
- [Release notes](https://github.com/improbable-eng/ts-protoc-gen/releases)
- [Changelog](https://github.com/improbable-eng/ts-protoc-gen/blob/master/CHANGELOG.md)
- [Commits](https://github.com/improbable-eng/ts-protoc-gen/compare/0.14.0...0.15.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @types/jasmine from 3.6.9 to 3.6.10 in /console (#1682)

Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.6.9 to 3.6.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump @types/google-protobuf in /console (#1681)

Bumps [@types/google-protobuf](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/google-protobuf) from 3.7.4 to 3.15.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/google-protobuf)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump grpc from 1.24.5 to 1.24.7 in /console (#1666)

Bumps [grpc](https://github.com/grpc/grpc-node) from 1.24.5 to 1.24.7.
- [Release notes](https://github.com/grpc/grpc-node/releases)
- [Commits](https://github.com/grpc/grpc-node/compare/grpc@1.24.5...grpc@1.24.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* lock

* chore(deps-dev): bump @angular/language-service from 11.2.9 to 11.2.12 in /console (#1704)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump @angular/language-service in /console

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.2.9 to 11.2.12.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/11.2.12/packages/language-service)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* package lock

* downgrade grpc

* downgrade protobuf types

* revert npm packs 🥸

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Silvan <silvan.reusser@gmail.com>

* docs: update run and start section texts (#1745)

* update run and start section texts

* adds showcase

Co-authored-by: Maximilian Panne <maximilian.panne@gmail.com>

* fix: additional origin list (#1753)

* fix: handle api configs in authz handler (#1755)

* fix(console): add model for api keys, fix toast, binding (#1757)

* fix: add model for api keys, fix toast, binding

* show api clientid

* fix: missing patchvalue (#1758)

* feat: refresh token (#1728)

* begin refresh tokens

* refresh tokens

* list and revoke refresh tokens

* handle remove

* tests for refresh tokens

* uniqueness and default expiration

* rename oidc token methods

* cleanup

* migration version

* Update internal/static/i18n/en.yaml

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* fixes

* feat: update oidc pkg for refresh tokens

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* fix: correct json name of clientId in key.json (#1760)

* fix: migration version (#1767)

* start subscription

* eventtypes

* fix(login): links (#1778)

* fix(login): href for help

* fix(login): correct link to tos

* fix: access tokens for service users and refresh token infos (#1779)

* fix: access token for service user

* handle info from refresh request

* uniqueness

* postpone access token uniqueness change

* chore(coc): recommend code of conduct (#1782)

* subscribe for events

* feat(console): refresh toggle out of granttype context (#1785)

* refresh toggle

* disable if not code flow, lint

* lint

* fix: change oidc config order

* accept refresh option within flow

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: refresh token activation (#1795)

* fix: oidc grant type check

* docs: add offline_access scope

* docs: update refresh token status in supported grant types

* fix: update oidc pkg

* fix: check refresh token grant type (#1796)

* configuration structs

* org admins

* failed events

* fixes

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: mffap <mpa@caos.ch>
Co-authored-by: Maximilian Panne <maximilian.panne@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* remove comment

* aggregate reducer

* remove eventtypes

* add protoc-get-validate to mod

* fix transaltion

* upsert

* add gender on org admins,
allow to retry failed stmts after configurable time

* remove if

* sub queries

* fix: tests

* add builder to tests

* new search query

* rename searchquerybuilder to builder

* remove comment from code

* test with multiple queries

* add filters test

* current sequences

* make org and org_admins work again

* add aggregate type to current sequence

* fix(contibute): listing

* add validate module

* fix: search queries

* feat(eventstore): previous aggregate root sequence (#1810)

* feat(eventstore): previous aggregate root sequence

* fix tests

* fix: eventstore v1 test

* add col to all mocked rows

* next try

* fix mig

* rename aggregate root to aggregate type

* update comment

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* small refactorings

* allow update multiple current sequences

* unique log id

* fix migrations

* rename org admin to org owner

* improve error handling and logging

* fix(migration): optimize prev agg root seq

* fix: projection handler test

* fix: sub queries

* small fixes

* additional event types

* correct org owner projection

* fix primary key

* feat(eventstore): jobs for projections (#2026)

* fix: template names in login (#1974)

* fix: template names in login

* fix: error.html

* fix: check for features on mgmt only (#1976)

* fix: add sentry in ui, http and projection handlers (#1977)

* fix: add sentry in ui, http and projection handlers

* fix test

* fix(eventstore): sub queries (#1805)

* sub queries

* fix: tests

* add builder to tests

* new search query

* rename searchquerybuilder to builder

* remove comment from code

* test with multiple queries

* add filters test

* fix(contibute): listing

* add validate module

* fix: search queries

* remove unused event type in query

* ignore query if error in marshal

* go mod tidy

* update privacy policy query

* update queries

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* feat: Extend oidc idp with oauth endpoints (#1980)

* feat: add oauth attributes to oidc idp configuration

* feat: return idpconfig id on create idp

* feat: tests

* feat: descriptions

* feat: docs

* feat: tests

* docs: update to beta 3 (#1984)

* fix: role assertion (#1986)

* fix: enum to display access token role assertion

* improve assertion descriptions

* fix nil pointer

* docs: eventstore (#1982)

* docs: eventstore

* Apply suggestions from code review

Co-authored-by: Florian Forster <florian@caos.ch>

Co-authored-by: Florian Forster <florian@caos.ch>

* fix(sentry): trigger sentry release (#1989)

* feat(send sentry release): send sentry release

* fix(moved step and added releasetag): moved step and added releasetag

* fix: set version for sentry release (#1990)

* feat(send sentry release): send sentry release

* fix(moved step and added releasetag): moved step and added releasetag

* fix(corrected var name): corrected var name

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: log error reason on terminate session (#1973)

* fix: return default language file, if requested lang does not exist for default login texts (#1988)

* fix: return default language file, if requested lang doesnt exists

* feat: read default translation file

* feat: docs

* fix: race condition in auth request unmarshalling (#1993)

* feat: handle ui_locales in login (#1994)

* fix: handle ui_locales in login

* move supportedlanguage func into i18n package

* update oidc pkg

* fix: handle closed channels on unsubscribe (#1995)

* fix: give restore more time (#1997)

* fix: translation file read (#2009)

* feat: translation file read

* feat: readme

* fix: enable idp add button for iam users (#2010)

* fix: filter event_data (#2011)

* feat: Custom message files (#1992)

* feat: add get custom message text to admin api

* feat: read custom message texts from files

* feat: get languages in apis

* feat: get languages in apis

* feat: get languages in apis

* feat: pr feedback

* feat: docs

* feat: merge main

* fix: sms notification (#2013)

* fix: phone verifications

* feat: fix password reset as sms

* fix: phone verification

* fix: grpc status in sentry and validation interceptors (#2012)

* fix: remove oauth endpoints from oidc config proto (#2014)

* try with view

* fix(console): disable sw (#2021)

* fix: disable sw

* angular.json disable sw

* project projections

* fix typos

* customize projections

* customizable projections,
add change date to projects

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: mffap <mpa@caos.ch>
Co-authored-by: Christian Jakob <47860090+thesephirot@users.noreply.github.com>
Co-authored-by: Elio Bischof <eliobischof@gmail.com>

* env file

* typo

* correct users

* correct migration

* fix: merge fail

* fix test

* fix(tests): unordered matcher

* improve currentSequenceMatcher

* correct certs

* correct certs

* add zitadel database on database list

* refctor switch in match

* enable all handlers

* Delete io.env

* cleanup

* add handlers

* rename view to projection

* rename view to projection

* fix type typo

* remove unnecessary logs

* refactor stmts

* simplify interval calculation

* fix tests

* fix unlock test

* fix migration

* migs

* fix(operator): update cockroach and flyway versions (#2138)

* chore(deps): bump k8s.io/apiextensions-apiserver from 0.19.2 to 0.21.3

Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.19.2 to 0.21.3.
- [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases)
- [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.19.2...v0.21.3)

---
updated-dependencies:
- dependency-name: k8s.io/apiextensions-apiserver
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): bump google.golang.org/api from 0.34.0 to 0.52.0

Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.34.0 to 0.52.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/master/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.34.0...v0.52.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* start update dependencies

* update mods and otlp

* fix(build): update to go 1.16

* old version for k8s mods

* update k8s versions

* update orbos

* fix(operator): update cockroach and flyway version

* Update images.go

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Benz <stefan@caos.ch>

* fix import

* fix typo

* fix(migration): add org projection

* fix(projection): correct table for org events in org owners

* better insert stmt

* fix typo

* fix typo

* set max connection lifetime

* set max conns and conn lifetime in eventstore v1

* configure sql connection settings

* add mig for agg type index

* fix replace tab in yaml

* handler interfaces

* subscription

* first try

* handler

* move sql client initialization

* first part implemented

* removed all occurencies of org by id and search orgs

* fix merge issues

* cleanup code

* fix: queries implements orgviewprovider

* cleanup

* refactor text comparison

* remove unused file

* remove unused code

* log

* remove unused code

* remove unused field

* remove unused file

* refactor

* tests for search query

* remove try

* simplify state change mappers

* projection tests

* query functions

* move reusable objects to separate files

* rename domain column to primar_domain

* fix tests

* add current sequence

* remove log prints

* fix tests

* fix: verifier

* fix test

* rename domain col migrations

* simplify search response

* add custom column constructors

* fix: org projection table const

* fix: full column name

* feat: text query extension

* fix: tests for query

* number query

* add deprection message

* projection

* correct migration

* projection

* projection

* column in a single place (#2416)

* column in a single place

* use projection for columns

* query column with aliases

* rename methods

* remove unused code

* column for current sequences

* correct file name

* global counter column

* fix is org unique

* query

* fix wrong code

* remove unused code

* query

* remove unused code

* remove unused code

* query

* api

* remove unused cod

* remove unused code

* remove unused code

* remove unused code

* fix(queries): org iam policy

* fix: init provider

* tests

* tests

* tests

* tests

* tests

* add copy stmt

* label policy projection

* tests

* constant naming in test

* query

* fix nil pointer

* fix test

* refactor: remove useless file

* fix(configs): add options to setup

* fix: sql changes

* tests

* remove old comment

* rename label policy to styling

* fix where

* remove unused logs

* migration

* correct primary key

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: mffap <mpa@caos.ch>
Co-authored-by: Maximilian Panne <maximilian.panne@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Christian Jakob <47860090+thesephirot@users.noreply.github.com>
Co-authored-by: Elio Bischof <eliobischof@gmail.com>
Co-authored-by: Stefan Benz <stefan@caos.ch>
Co-authored-by: fabi <fabienne.gerschwiler@gmail.com>
This commit is contained in:
Silvan 2021-11-24 16:02:00 +01:00 committed by GitHub
parent b6449a2410
commit eac5045821
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 2245 additions and 770 deletions

4
.gitignore vendored
View File

@ -54,3 +54,7 @@ console/src/app/proto/generated/
openapi/**/*.json openapi/**/*.json
/internal/api/assets/authz.go /internal/api/assets/authz.go
/internal/api/assets/router.go /internal/api/assets/router.go
# local
build/local/cloud.env
migrations/cockroach/migrate_cloud.go

View File

@ -240,7 +240,7 @@ func startAPI(ctx context.Context, conf *Config, verifier *internal_authz.TokenV
apis.RegisterHandler("/oauth/v2", op.HttpHandler()) apis.RegisterHandler("/oauth/v2", op.HttpHandler())
} }
if *assetsEnabled { if *assetsEnabled {
assetsHandler := assets.NewHandler(command, verifier, conf.InternalAuthZ, id.SonyFlakeGenerator, static, managementRepo) assetsHandler := assets.NewHandler(command, verifier, conf.InternalAuthZ, id.SonyFlakeGenerator, static, managementRepo, query)
apis.RegisterHandler("/assets/v1", assetsHandler) apis.RegisterHandler("/assets/v1", assetsHandler)
} }

View File

@ -9,6 +9,7 @@ Eventstore:
User: 'eventstore' User: 'eventstore'
Database: 'eventstore' Database: 'eventstore'
Password: $CR_EVENTSTORE_PASSWORD Password: $CR_EVENTSTORE_PASSWORD
Options: $CR_OPTIONS
SSL: SSL:
Mode: $CR_SSL_MODE Mode: $CR_SSL_MODE
RootCert: $CR_ROOT_CERT RootCert: $CR_ROOT_CERT

View File

@ -167,22 +167,6 @@ func (repo *IAMRepository) SearchDefaultIDPProviders(ctx context.Context, reques
return result, nil return result, nil
} }
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStateActive))
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyViewToModel(policy), err
}
func (repo *IAMRepository) GetDefaultPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return nil, err
}
return iam_es_model.LabelPolicyViewToModel(policy), err
}
func (repo *IAMRepository) GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) { func (repo *IAMRepository) GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) {
template, err := repo.View.MailTemplateByAggregateID(repo.SystemDefaults.IamID) template, err := repo.View.MailTemplateByAggregateID(repo.SystemDefaults.IamID)
if err != nil { if err != nil {

View File

@ -37,8 +37,6 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount, es}), handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount, es}),
newIDPConfig( newIDPConfig(
handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}), handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}),
newLabelPolicy(
handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es}),
newIDPProvider( newIDPProvider(
handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es}, handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es},
defaults), defaults),

View File

@ -1,125 +0,0 @@
package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
)
const (
labelPolicyTable = "adminapi.label_policies"
)
type LabelPolicy struct {
handler
subscription *v1.Subscription
}
func newLabelPolicy(handler handler) *LabelPolicy {
h := &LabelPolicy{
handler: handler,
}
h.subscribe()
return h
}
func (p *LabelPolicy) subscribe() {
p.subscription = p.es.Subscribe(p.AggregateTypes()...)
go func() {
for event := range p.subscription.Events {
query.ReduceEvent(p, event)
}
}()
}
func (p *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (p *LabelPolicy) Subscription() *v1.Subscription {
return p.subscription
}
func (p *LabelPolicy) AggregateTypes() []es_models.AggregateType {
return []es_models.AggregateType{model.IAMAggregate}
}
func (p *LabelPolicy) EventQuery() (*es_models.SearchQuery, error) {
sequence, err := p.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(p.AggregateTypes()...).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (p *LabelPolicy) CurrentSequence() (uint64, error) {
sequence, err := p.view.GetLatestLabelPolicySequence()
if err != nil {
return 0, err
}
return sequence.CurrentSequence, nil
}
func (p *LabelPolicy) Reduce(event *es_models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate:
err = p.processLabelPolicy(event)
}
return err
}
func (p *LabelPolicy) processLabelPolicy(event *es_models.Event) (err error) {
policy := new(iam_model.LabelPolicyView)
switch event.Type {
case model.LabelPolicyAdded:
err = policy.AppendEvent(event)
case model.LabelPolicyChanged,
model.LabelPolicyLogoAdded,
model.LabelPolicyLogoRemoved,
model.LabelPolicyIconAdded,
model.LabelPolicyIconRemoved,
model.LabelPolicyLogoDarkAdded,
model.LabelPolicyLogoDarkRemoved,
model.LabelPolicyIconDarkAdded,
model.LabelPolicyIconDarkRemoved,
model.LabelPolicyFontAdded,
model.LabelPolicyFontRemoved,
model.LabelPolicyAssetsRemoved:
policy, err = p.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.LabelPolicyActivated:
policy, err = p.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return err
}
err = policy.AppendEvent(event)
default:
return p.view.ProcessedLabelPolicySequence(event)
}
if err != nil {
return err
}
return p.view.PutLabelPolicy(policy, event)
}
func (p *LabelPolicy) OnError(event *es_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, p.view.GetLatestLabelPolicyFailedEvent, p.view.ProcessedLabelPolicyFailedEvent, p.view.ProcessedLabelPolicySequence, p.errorCountUntilSkip)
}
func (p *LabelPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateLabelPolicySpoolerRunTimestamp)
}

View File

@ -12,7 +12,7 @@ import (
"github.com/muesli/gamut" "github.com/muesli/gamut"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore/v1" v1 "github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models" es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler" "github.com/caos/zitadel/internal/eventstore/v1/spooler"
@ -30,7 +30,6 @@ type Styling struct {
handler handler
static static.Storage static static.Storage
subscription *v1.Subscription subscription *v1.Subscription
devMode bool
resourceUrl string resourceUrl string
} }
@ -141,11 +140,11 @@ func (m *Styling) processLabelPolicy(event *es_models.Event) (err error) {
func (m *Styling) OnError(event *es_models.Event, err error) error { func (m *Styling) OnError(event *es_models.Event, err error) error {
logging.LogWithFields("SPOOL-2m9fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler") logging.LogWithFields("SPOOL-2m9fs", "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, m.view.GetLatestStylingFailedEvent, m.view.ProcessedStylingFailedEvent, m.view.ProcessedStylingSequence, m.errorCountUntilSkip)
} }
func (m *Styling) OnSuccess() error { func (m *Styling) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateLabelPolicySpoolerRunTimestamp) return spooler.HandleSuccess(m.view.UpdateStylingSpoolerRunTimestamp)
} }
func (m *Styling) generateStylingFile(policy *iam_model.LabelPolicyView) error { func (m *Styling) generateStylingFile(policy *iam_model.LabelPolicyView) error {
@ -158,7 +157,7 @@ func (m *Styling) generateStylingFile(policy *iam_model.LabelPolicyView) error {
func (m *Styling) writeFile(policy *iam_model.LabelPolicyView) (io.Reader, int64, error) { func (m *Styling) writeFile(policy *iam_model.LabelPolicyView) (io.Reader, int64, error) {
cssContent := "" cssContent := ""
cssContent += fmt.Sprint(":root {") cssContent += ":root {"
if policy.PrimaryColor != "" { if policy.PrimaryColor != "" {
palette := m.generateColorPaletteRGBA255(policy.PrimaryColor) palette := m.generateColorPaletteRGBA255(policy.PrimaryColor)
for i, color := range palette { for i, color := range palette {
@ -190,11 +189,11 @@ func (m *Styling) writeFile(policy *iam_model.LabelPolicyView) (io.Reader, int64
fontname = split[len(split)-1] fontname = split[len(split)-1]
cssContent += fmt.Sprintf("--zitadel-font-family: %s;", fontname) cssContent += fmt.Sprintf("--zitadel-font-family: %s;", fontname)
} }
cssContent += fmt.Sprint("}") cssContent += "}"
if policy.FontURL != "" { if policy.FontURL != "" {
cssContent += fmt.Sprintf(fontFaceTemplate, fontname, m.resourceUrl, policy.AggregateID, policy.FontURL) cssContent += fmt.Sprintf(fontFaceTemplate, fontname, m.resourceUrl, policy.AggregateID, policy.FontURL)
} }
cssContent += fmt.Sprint(".lgn-dark-theme {") cssContent += ".lgn-dark-theme {"
if policy.PrimaryColorDark != "" { if policy.PrimaryColorDark != "" {
palette := m.generateColorPaletteRGBA255(policy.PrimaryColorDark) palette := m.generateColorPaletteRGBA255(policy.PrimaryColorDark)
for i, color := range palette { for i, color := range palette {
@ -219,7 +218,7 @@ func (m *Styling) writeFile(policy *iam_model.LabelPolicyView) (io.Reader, int64
cssContent += fmt.Sprintf("--zitadel-color-text-%v: %s;", i, color) cssContent += fmt.Sprintf("--zitadel-color-text-%v: %s;", i, color)
} }
} }
cssContent += fmt.Sprint("}") cssContent += "}"
data := []byte(cssContent) data := []byte(cssContent)
buffer := bytes.NewBuffer(data) buffer := bytes.NewBuffer(data)

View File

@ -2,11 +2,12 @@ package handler
import ( import (
"context" "context"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" v1 "github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models" es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"

View File

@ -1,44 +0,0 @@
package view
import (
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
labelPolicyTable = "adminapi.label_policies"
)
func (v *View) LabelPolicyByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateIDAndState(v.Db, labelPolicyTable, aggregateID, state)
}
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(event)
}
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(labelPolicyTable)
}
func (v *View) ProcessedLabelPolicySequence(event *models.Event) error {
return v.saveCurrentSequence(labelPolicyTable, event)
}
func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(labelPolicyTable)
}
func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(labelPolicyTable, sequence)
}
func (v *View) ProcessedLabelPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@ -12,11 +12,11 @@ const (
) )
func (v *View) StylingByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) { func (v *View) StylingByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateIDAndState(v.Db, stylingTyble, aggregateID, state) return view.GetStylingByAggregateIDAndState(v.Db, stylingTyble, aggregateID, state)
} }
func (v *View) PutStyling(policy *model.LabelPolicyView, event *models.Event) error { func (v *View) PutStyling(policy *model.LabelPolicyView, event *models.Event) error {
err := view.PutLabelPolicy(v.Db, stylingTyble, policy) err := view.PutStyling(v.Db, stylingTyble, policy)
if err != nil { if err != nil {
return err return err
} }

View File

@ -25,9 +25,6 @@ type IAMRepository interface {
IDPProvidersByIDPConfigID(ctx context.Context, idpConfigID string) ([]*iam_model.IDPProviderView, error) IDPProvidersByIDPConfigID(ctx context.Context, idpConfigID string) ([]*iam_model.IDPProviderView, error)
ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error) ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error)
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
GetDefaultPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
GetDefaultMessageText(ctx context.Context, textType, language string) (*domain.CustomMessageText, error) GetDefaultMessageText(ctx context.Context, textType, language string) (*domain.CustomMessageText, error)

View File

@ -18,6 +18,7 @@ import (
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/id" "github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/management/repository" "github.com/caos/zitadel/internal/management/repository"
"github.com/caos/zitadel/internal/query"
"github.com/caos/zitadel/internal/static" "github.com/caos/zitadel/internal/static"
) )
@ -28,6 +29,7 @@ type Handler struct {
authInterceptor *http_mw.AuthInterceptor authInterceptor *http_mw.AuthInterceptor
idGenerator id.Generator idGenerator id.Generator
orgRepo repository.OrgRepository orgRepo repository.OrgRepository
query *query.Queries
} }
func (h *Handler) AuthInterceptor() *http_mw.AuthInterceptor { func (h *Handler) AuthInterceptor() *http_mw.AuthInterceptor {
@ -73,6 +75,7 @@ func NewHandler(
idGenerator id.Generator, idGenerator id.Generator,
storage static.Storage, storage static.Storage,
orgRepo repository.OrgRepository, orgRepo repository.OrgRepository,
queries *query.Queries,
) http.Handler { ) http.Handler {
h := &Handler{ h := &Handler{
commands: commands, commands: commands,
@ -81,6 +84,7 @@ func NewHandler(
idGenerator: idGenerator, idGenerator: idGenerator,
storage: storage, storage: storage,
orgRepo: orgRepo, orgRepo: orgRepo,
query: queries,
} }
verifier.RegisterServer("Management-API", "assets", AssetsService_AuthMethods) //TODO: separate api? verifier.RegisterServer("Management-API", "assets", AssetsService_AuthMethods) //TODO: separate api?

View File

@ -7,9 +7,8 @@ import (
"github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/command" "github.com/caos/zitadel/internal/command"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/id" "github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/management/repository" "github.com/caos/zitadel/internal/query"
) )
func (h *Handler) UploadDefaultLabelPolicyLogo() Uploader { func (h *Handler) UploadDefaultLabelPolicyLogo() Uploader {
@ -86,57 +85,57 @@ func (l *labelPolicyLogoUploader) Callback(ctx context.Context, info *domain.Ass
} }
func (h *Handler) GetDefaultLabelPolicyLogo() Downloader { func (h *Handler) GetDefaultLabelPolicyLogo() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: false} return &labelPolicyLogoDownloader{query: h.query, darkMode: false, defaultPolicy: true, preview: false}
} }
func (h *Handler) GetDefaultLabelPolicyLogoDark() Downloader { func (h *Handler) GetDefaultLabelPolicyLogoDark() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: false} return &labelPolicyLogoDownloader{query: h.query, darkMode: true, defaultPolicy: true, preview: false}
} }
func (h *Handler) GetPreviewDefaultLabelPolicyLogo() Downloader { func (h *Handler) GetPreviewDefaultLabelPolicyLogo() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: true} return &labelPolicyLogoDownloader{query: h.query, darkMode: false, defaultPolicy: true, preview: true}
} }
func (h *Handler) GetPreviewDefaultLabelPolicyLogoDark() Downloader { func (h *Handler) GetPreviewDefaultLabelPolicyLogoDark() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: true} return &labelPolicyLogoDownloader{query: h.query, darkMode: true, defaultPolicy: true, preview: true}
} }
func (h *Handler) GetOrgLabelPolicyLogo() Downloader { func (h *Handler) GetOrgLabelPolicyLogo() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: false} return &labelPolicyLogoDownloader{query: h.query, darkMode: false, defaultPolicy: false, preview: false}
} }
func (h *Handler) GetOrgLabelPolicyLogoDark() Downloader { func (h *Handler) GetOrgLabelPolicyLogoDark() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: false} return &labelPolicyLogoDownloader{query: h.query, darkMode: true, defaultPolicy: false, preview: false}
} }
func (h *Handler) GetPreviewOrgLabelPolicyLogo() Downloader { func (h *Handler) GetPreviewOrgLabelPolicyLogo() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: true} return &labelPolicyLogoDownloader{query: h.query, darkMode: false, defaultPolicy: false, preview: true}
} }
func (h *Handler) GetPreviewOrgLabelPolicyLogoDark() Downloader { func (h *Handler) GetPreviewOrgLabelPolicyLogoDark() Downloader {
return &labelPolicyLogoDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: true} return &labelPolicyLogoDownloader{query: h.query, darkMode: true, defaultPolicy: false, preview: true}
} }
type labelPolicyLogoDownloader struct { type labelPolicyLogoDownloader struct {
org repository.OrgRepository query *query.Queries
darkMode bool darkMode bool
defaultPolicy bool defaultPolicy bool
preview bool preview bool
} }
func (l *labelPolicyLogoDownloader) ObjectName(ctx context.Context, path string) (string, error) { func (l *labelPolicyLogoDownloader) ObjectName(ctx context.Context, path string) (string, error) {
policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.org) policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.query)
if err != nil { if err != nil {
return "", nil return "", nil
} }
if l.darkMode { if l.darkMode {
return policy.LogoDarkURL, nil return policy.Dark.LogoURL, nil
} }
return policy.LogoURL, nil return policy.Light.LogoURL, nil
} }
func (l *labelPolicyLogoDownloader) BucketName(ctx context.Context, id string) string { func (l *labelPolicyLogoDownloader) BucketName(ctx context.Context, id string) string {
return getLabelPolicyBucketName(ctx, l.defaultPolicy, l.preview, l.org) return getLabelPolicyBucketName(ctx, l.defaultPolicy, l.preview, l.query)
} }
func (h *Handler) UploadDefaultLabelPolicyIcon() Uploader { func (h *Handler) UploadDefaultLabelPolicyIcon() Uploader {
@ -214,57 +213,57 @@ func (l *labelPolicyIconUploader) Callback(ctx context.Context, info *domain.Ass
} }
func (h *Handler) GetDefaultLabelPolicyIcon() Downloader { func (h *Handler) GetDefaultLabelPolicyIcon() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: false} return &labelPolicyIconDownloader{query: h.query, darkMode: false, defaultPolicy: true, preview: false}
} }
func (h *Handler) GetDefaultLabelPolicyIconDark() Downloader { func (h *Handler) GetDefaultLabelPolicyIconDark() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: false} return &labelPolicyIconDownloader{query: h.query, darkMode: true, defaultPolicy: true, preview: false}
} }
func (h *Handler) GetPreviewDefaultLabelPolicyIcon() Downloader { func (h *Handler) GetPreviewDefaultLabelPolicyIcon() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: true, preview: true} return &labelPolicyIconDownloader{query: h.query, darkMode: false, defaultPolicy: true, preview: true}
} }
func (h *Handler) GetPreviewDefaultLabelPolicyIconDark() Downloader { func (h *Handler) GetPreviewDefaultLabelPolicyIconDark() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: true, preview: true} return &labelPolicyIconDownloader{query: h.query, darkMode: true, defaultPolicy: true, preview: true}
} }
func (h *Handler) GetOrgLabelPolicyIcon() Downloader { func (h *Handler) GetOrgLabelPolicyIcon() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: false} return &labelPolicyIconDownloader{query: h.query, darkMode: false, defaultPolicy: false, preview: false}
} }
func (h *Handler) GetOrgLabelPolicyIconDark() Downloader { func (h *Handler) GetOrgLabelPolicyIconDark() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: false} return &labelPolicyIconDownloader{query: h.query, darkMode: true, defaultPolicy: false, preview: false}
} }
func (h *Handler) GetPreviewOrgLabelPolicyIcon() Downloader { func (h *Handler) GetPreviewOrgLabelPolicyIcon() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: false, defaultPolicy: false, preview: true} return &labelPolicyIconDownloader{query: h.query, darkMode: false, defaultPolicy: false, preview: true}
} }
func (h *Handler) GetPreviewOrgLabelPolicyIconDark() Downloader { func (h *Handler) GetPreviewOrgLabelPolicyIconDark() Downloader {
return &labelPolicyIconDownloader{org: h.orgRepo, darkMode: true, defaultPolicy: false, preview: true} return &labelPolicyIconDownloader{query: h.query, darkMode: true, defaultPolicy: false, preview: true}
} }
type labelPolicyIconDownloader struct { type labelPolicyIconDownloader struct {
org repository.OrgRepository query *query.Queries
darkMode bool darkMode bool
defaultPolicy bool defaultPolicy bool
preview bool preview bool
} }
func (l *labelPolicyIconDownloader) ObjectName(ctx context.Context, path string) (string, error) { func (l *labelPolicyIconDownloader) ObjectName(ctx context.Context, path string) (string, error) {
policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.org) policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.query)
if err != nil { if err != nil {
return "", nil return "", nil
} }
if l.darkMode { if l.darkMode {
return policy.IconDarkURL, nil return policy.Dark.IconURL, nil
} }
return policy.IconURL, nil return policy.Light.IconURL, nil
} }
func (l *labelPolicyIconDownloader) BucketName(ctx context.Context, id string) string { func (l *labelPolicyIconDownloader) BucketName(ctx context.Context, id string) string {
return getLabelPolicyBucketName(ctx, l.defaultPolicy, l.preview, l.org) return getLabelPolicyBucketName(ctx, l.defaultPolicy, l.preview, l.query)
} }
func (h *Handler) UploadDefaultLabelPolicyFont() Uploader { func (h *Handler) UploadDefaultLabelPolicyFont() Uploader {
@ -321,29 +320,29 @@ func (l *labelPolicyFontUploader) Callback(ctx context.Context, info *domain.Ass
} }
func (h *Handler) GetDefaultLabelPolicyFont() Downloader { func (h *Handler) GetDefaultLabelPolicyFont() Downloader {
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: true, preview: false} return &labelPolicyFontDownloader{query: h.query, defaultPolicy: true, preview: false}
} }
func (h *Handler) GetPreviewDefaultLabelPolicyFont() Downloader { func (h *Handler) GetPreviewDefaultLabelPolicyFont() Downloader {
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: true, preview: true} return &labelPolicyFontDownloader{query: h.query, defaultPolicy: true, preview: true}
} }
func (h *Handler) GetOrgLabelPolicyFont() Downloader { func (h *Handler) GetOrgLabelPolicyFont() Downloader {
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: false, preview: false} return &labelPolicyFontDownloader{query: h.query, defaultPolicy: false, preview: false}
} }
func (h *Handler) GetPreviewOrgLabelPolicyFont() Downloader { func (h *Handler) GetPreviewOrgLabelPolicyFont() Downloader {
return &labelPolicyFontDownloader{org: h.orgRepo, defaultPolicy: true, preview: true} return &labelPolicyFontDownloader{query: h.query, defaultPolicy: true, preview: true}
} }
type labelPolicyFontDownloader struct { type labelPolicyFontDownloader struct {
org repository.OrgRepository query *query.Queries
defaultPolicy bool defaultPolicy bool
preview bool preview bool
} }
func (l *labelPolicyFontDownloader) ObjectName(ctx context.Context, path string) (string, error) { func (l *labelPolicyFontDownloader) ObjectName(ctx context.Context, path string) (string, error) {
policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.org) policy, err := getLabelPolicy(ctx, l.defaultPolicy, l.preview, l.query)
if err != nil { if err != nil {
return "", nil return "", nil
} }
@ -351,31 +350,31 @@ func (l *labelPolicyFontDownloader) ObjectName(ctx context.Context, path string)
} }
func (l *labelPolicyFontDownloader) BucketName(ctx context.Context, id string) string { func (l *labelPolicyFontDownloader) BucketName(ctx context.Context, id string) string {
return getLabelPolicyBucketName(ctx, l.defaultPolicy, l.preview, l.org) return getLabelPolicyBucketName(ctx, l.defaultPolicy, l.preview, l.query)
} }
func getLabelPolicy(ctx context.Context, defaultPolicy, preview bool, orgRepo repository.OrgRepository) (*model.LabelPolicyView, error) { func getLabelPolicy(ctx context.Context, defaultPolicy, preview bool, queries *query.Queries) (*query.LabelPolicy, error) {
if defaultPolicy { if defaultPolicy {
if preview { if preview {
return orgRepo.GetPreviewDefaultLabelPolicy(ctx) return queries.DefaultPreviewLabelPolicy(ctx)
} }
return orgRepo.GetDefaultLabelPolicy(ctx) return queries.DefaultActiveLabelPolicy(ctx)
} }
if preview { if preview {
return orgRepo.GetPreviewLabelPolicy(ctx) return queries.PreviewLabelPolicyByOrg(ctx, authz.GetCtxData(ctx).OrgID)
} }
return orgRepo.GetLabelPolicy(ctx) return queries.ActiveLabelPolicyByOrg(ctx, authz.GetCtxData(ctx).OrgID)
} }
func getLabelPolicyBucketName(ctx context.Context, defaultPolicy, preview bool, org repository.OrgRepository) string { func getLabelPolicyBucketName(ctx context.Context, defaultPolicy, preview bool, queries *query.Queries) string {
if defaultPolicy { if defaultPolicy {
return domain.IAMID return domain.IAMID
} }
policy, err := getLabelPolicy(ctx, defaultPolicy, preview, org) policy, err := getLabelPolicy(ctx, defaultPolicy, preview, queries)
if err != nil { if err != nil {
return "" return ""
} }
if policy.Default { if policy.IsDefault {
return domain.IAMID return domain.IAMID
} }
return authz.GetCtxData(ctx).OrgID return authz.GetCtxData(ctx).OrgID

View File

@ -9,7 +9,7 @@ import (
) )
func (s *Server) GetLabelPolicy(ctx context.Context, req *admin_pb.GetLabelPolicyRequest) (*admin_pb.GetLabelPolicyResponse, error) { func (s *Server) GetLabelPolicy(ctx context.Context, req *admin_pb.GetLabelPolicyRequest) (*admin_pb.GetLabelPolicyResponse, error) {
policy, err := s.iam.GetDefaultLabelPolicy(ctx) policy, err := s.query.DefaultActiveLabelPolicy(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -17,7 +17,7 @@ func (s *Server) GetLabelPolicy(ctx context.Context, req *admin_pb.GetLabelPolic
} }
func (s *Server) GetPreviewLabelPolicy(ctx context.Context, req *admin_pb.GetPreviewLabelPolicyRequest) (*admin_pb.GetPreviewLabelPolicyResponse, error) { func (s *Server) GetPreviewLabelPolicy(ctx context.Context, req *admin_pb.GetPreviewLabelPolicyRequest) (*admin_pb.GetPreviewLabelPolicyResponse, error) {
policy, err := s.iam.GetDefaultPreviewLabelPolicy(ctx) policy, err := s.query.DefaultPreviewLabelPolicy(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -10,23 +10,23 @@ import (
) )
func (s *Server) GetLabelPolicy(ctx context.Context, req *mgmt_pb.GetLabelPolicyRequest) (*mgmt_pb.GetLabelPolicyResponse, error) { func (s *Server) GetLabelPolicy(ctx context.Context, req *mgmt_pb.GetLabelPolicyRequest) (*mgmt_pb.GetLabelPolicyResponse, error) {
policy, err := s.org.GetLabelPolicy(ctx) policy, err := s.query.ActiveLabelPolicyByOrg(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &mgmt_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy), IsDefault: policy.Default}, nil return &mgmt_pb.GetLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy), IsDefault: policy.IsDefault}, nil
} }
func (s *Server) GetPreviewLabelPolicy(ctx context.Context, req *mgmt_pb.GetPreviewLabelPolicyRequest) (*mgmt_pb.GetPreviewLabelPolicyResponse, error) { func (s *Server) GetPreviewLabelPolicy(ctx context.Context, req *mgmt_pb.GetPreviewLabelPolicyRequest) (*mgmt_pb.GetPreviewLabelPolicyResponse, error) {
policy, err := s.org.GetPreviewLabelPolicy(ctx) policy, err := s.query.PreviewLabelPolicyByOrg(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &mgmt_pb.GetPreviewLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy)}, nil return &mgmt_pb.GetPreviewLabelPolicyResponse{Policy: policy_grpc.ModelLabelPolicyToPb(policy), IsDefault: policy.IsDefault}, nil
} }
func (s *Server) GetDefaultLabelPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLabelPolicyRequest) (*mgmt_pb.GetDefaultLabelPolicyResponse, error) { func (s *Server) GetDefaultLabelPolicy(ctx context.Context, req *mgmt_pb.GetDefaultLabelPolicyRequest) (*mgmt_pb.GetDefaultLabelPolicyResponse, error) {
policy, err := s.org.GetDefaultLabelPolicy(ctx) policy, err := s.query.DefaultActiveLabelPolicy(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,34 +2,34 @@ package policy
import ( import (
"github.com/caos/zitadel/internal/api/grpc/object" "github.com/caos/zitadel/internal/api/grpc/object"
"github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/query"
policy_pb "github.com/caos/zitadel/pkg/grpc/policy" policy_pb "github.com/caos/zitadel/pkg/grpc/policy"
) )
func ModelLabelPolicyToPb(policy *model.LabelPolicyView) *policy_pb.LabelPolicy { func ModelLabelPolicyToPb(policy *query.LabelPolicy) *policy_pb.LabelPolicy {
return &policy_pb.LabelPolicy{ return &policy_pb.LabelPolicy{
IsDefault: policy.Default, IsDefault: policy.IsDefault,
PrimaryColor: policy.PrimaryColor, PrimaryColor: policy.Light.PrimaryColor,
BackgroundColor: policy.BackgroundColor, BackgroundColor: policy.Light.BackgroundColor,
FontColor: policy.FontColor, FontColor: policy.Light.FontColor,
WarnColor: policy.WarnColor, WarnColor: policy.Light.WarnColor,
PrimaryColorDark: policy.PrimaryColorDark, PrimaryColorDark: policy.Dark.PrimaryColor,
BackgroundColorDark: policy.BackgroundColorDark, BackgroundColorDark: policy.Dark.BackgroundColor,
WarnColorDark: policy.WarnColorDark, WarnColorDark: policy.Dark.WarnColor,
FontColorDark: policy.FontColorDark, FontColorDark: policy.Dark.FontColor,
FontUrl: policy.FontURL, FontUrl: policy.FontURL,
LogoUrl: policy.LogoURL, LogoUrl: policy.Light.LogoURL,
LogoUrlDark: policy.LogoDarkURL, LogoUrlDark: policy.Dark.LogoURL,
IconUrl: policy.IconURL, IconUrl: policy.Light.IconURL,
IconUrlDark: policy.IconDarkURL, IconUrlDark: policy.Dark.IconURL,
DisableWatermark: policy.DisableWatermark, DisableWatermark: policy.WatermarkDisabled,
HideLoginNameSuffix: policy.HideLoginNameSuffix, HideLoginNameSuffix: policy.HideLoginNameSuffix,
Details: object.ToViewDetailsPb( Details: object.ToViewDetailsPb(
policy.Sequence, policy.Sequence,
policy.CreationDate, policy.CreationDate,
policy.ChangeDate, policy.ChangeDate,
"", //TODO: resourceowner policy.ResourceOwner,
), ),
} }
} }

View File

@ -33,6 +33,7 @@ type AuthRequestRepo struct {
View *view.View View *view.View
Eventstore v1.Eventstore Eventstore v1.Eventstore
LabelPolicyProvider labelPolicyProvider
UserSessionViewProvider userSessionViewProvider UserSessionViewProvider userSessionViewProvider
UserViewProvider userViewProvider UserViewProvider userViewProvider
UserCommandProvider userCommandProvider UserCommandProvider userCommandProvider
@ -56,6 +57,10 @@ type AuthRequestRepo struct {
IAMID string IAMID string
} }
type labelPolicyProvider interface {
ActiveLabelPolicyByOrg(context.Context, string) (*query.LabelPolicy, error)
}
type privacyPolicyProvider interface { type privacyPolicyProvider interface {
PrivacyPolicyByOrg(context.Context, string) (*query.PrivacyPolicy, error) PrivacyPolicyByOrg(context.Context, string) (*query.PrivacyPolicy, error)
} }
@ -931,18 +936,41 @@ func (repo *AuthRequestRepo) getLockoutPolicy(ctx context.Context, orgID string)
} }
func (repo *AuthRequestRepo) getLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error) { func (repo *AuthRequestRepo) getLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error) {
policy, err := repo.View.LabelPolicyByAggregateIDAndState(orgID, int32(domain.LabelPolicyStateActive)) policy, err := repo.LabelPolicyProvider.ActiveLabelPolicyByOrg(ctx, orgID)
if errors.IsNotFound(err) {
policy, err = repo.View.LabelPolicyByAggregateIDAndState(repo.IAMID, int32(domain.LabelPolicyStateActive))
if err != nil { if err != nil {
return nil, err return nil, err
} }
policy.Default = true return labelPolicyToDomain(policy), nil
}
func labelPolicyToDomain(p *query.LabelPolicy) *domain.LabelPolicy {
return &domain.LabelPolicy{
ObjectRoot: es_models.ObjectRoot{
AggregateID: p.ID,
Sequence: p.Sequence,
ResourceOwner: p.ResourceOwner,
CreationDate: p.CreationDate,
ChangeDate: p.ChangeDate,
},
State: p.State,
Default: p.IsDefault,
PrimaryColor: p.Light.PrimaryColor,
BackgroundColor: p.Light.BackgroundColor,
WarnColor: p.Light.WarnColor,
FontColor: p.Light.FontColor,
LogoURL: p.Light.LogoURL,
IconURL: p.Light.IconURL,
PrimaryColorDark: p.Dark.PrimaryColor,
BackgroundColorDark: p.Dark.BackgroundColor,
WarnColorDark: p.Dark.WarnColor,
FontColorDark: p.Dark.FontColor,
LogoDarkURL: p.Dark.LogoURL,
IconDarkURL: p.Dark.IconURL,
Font: p.FontURL,
HideLoginNameSuffix: p.HideLoginNameSuffix,
ErrorMsgPopup: p.ShouldErrorPopup,
DisableWatermark: p.WatermarkDisabled,
} }
if err != nil {
return nil, err
}
return policy.ToDomain(), err
} }
func (repo *AuthRequestRepo) getLoginTexts(ctx context.Context, aggregateID string) ([]*domain.CustomText, error) { func (repo *AuthRequestRepo) getLoginTexts(ctx context.Context, aggregateID string) ([]*domain.CustomText, error) {

View File

@ -7,7 +7,6 @@ import (
auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view" auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
eventstore "github.com/caos/zitadel/internal/eventstore/v1" eventstore "github.com/caos/zitadel/internal/eventstore/v1"
"github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/models"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
@ -16,10 +15,6 @@ import (
"github.com/caos/zitadel/internal/repository/iam" "github.com/caos/zitadel/internal/repository/iam"
) )
const (
orgOwnerRole = "ORG_OWNER"
)
type OrgRepository struct { type OrgRepository struct {
SearchLimit uint64 SearchLimit uint64
@ -45,17 +40,6 @@ func (repo *OrgRepository) GetMyPasswordComplexityPolicy(ctx context.Context) (*
return iam_view_model.PasswordComplexityViewToModel(policy), err return iam_view_model.PasswordComplexityViewToModel(policy), err
} }
func (repo *OrgRepository) GetLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error) {
orgPolicy, err := repo.View.LabelPolicyByAggregateIDAndState(orgID, int32(domain.LabelPolicyStateActive))
if errors.IsNotFound(err) {
orgPolicy, err = repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStateActive))
}
if err != nil {
return nil, err
}
return orgPolicy.ToDomain(), nil
}
func (repo *OrgRepository) GetLoginText(ctx context.Context, orgID string) ([]*domain.CustomText, error) { func (repo *OrgRepository) GetLoginText(ctx context.Context, orgID string) ([]*domain.CustomText, error) {
loginTexts, err := repo.View.CustomTextsByAggregateIDAndTemplate(domain.IAMID, domain.LoginCustomText) loginTexts, err := repo.View.CustomTextsByAggregateIDAndTemplate(domain.IAMID, domain.LoginCustomText)
if err != nil { if err != nil {

View File

@ -58,7 +58,6 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
newExternalIDP( newExternalIDP(
handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es}, handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es},
systemDefaults), systemDefaults),
newLabelPolicy(handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es}),
newRefreshToken(handler{view, bulkLimit, configs.cycleDuration("RefreshToken"), errorCount, es}), newRefreshToken(handler{view, bulkLimit, configs.cycleDuration("RefreshToken"), errorCount, es}),
newCustomText(handler{view, bulkLimit, configs.cycleDuration("CustomTexts"), errorCount, es}), newCustomText(handler{view, bulkLimit, configs.cycleDuration("CustomTexts"), errorCount, es}),
newMetadata(handler{view, bulkLimit, configs.cycleDuration("Metadata"), errorCount, es}), newMetadata(handler{view, bulkLimit, configs.cycleDuration("Metadata"), errorCount, es}),

View File

@ -1,123 +0,0 @@
package handler
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
v1 "github.com/caos/zitadel/internal/eventstore/v1"
"github.com/caos/zitadel/internal/eventstore/v1/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
)
const (
labelPolicyTable = "auth.label_policies"
)
type LabelPolicy struct {
handler
subscription *v1.Subscription
}
func newLabelPolicy(handler handler) *LabelPolicy {
h := &LabelPolicy{
handler: handler,
}
h.subscribe()
return h
}
func (m *LabelPolicy) subscribe() {
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
go func() {
for event := range m.subscription.Events {
query.ReduceEvent(m, event)
}
}()
}
func (m *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (p *LabelPolicy) Subscription() *v1.Subscription {
return p.subscription
}
func (_ *LabelPolicy) AggregateTypes() []models.AggregateType {
return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
}
func (m *LabelPolicy) CurrentSequence() (uint64, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return 0, err
}
return sequence.CurrentSequence, nil
}
func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(m.AggregateTypes()...).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LabelPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processLabelPolicy(event)
}
return err
}
func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) {
policy := new(iam_model.LabelPolicyView)
switch event.Type {
case iam_es_model.LabelPolicyAdded, model.LabelPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.LabelPolicyChanged, model.LabelPolicyChanged,
iam_es_model.LabelPolicyActivated, model.LabelPolicyActivated,
iam_es_model.LabelPolicyLogoAdded, model.LabelPolicyLogoAdded,
iam_es_model.LabelPolicyLogoRemoved, model.LabelPolicyLogoRemoved,
iam_es_model.LabelPolicyIconAdded, model.LabelPolicyIconAdded,
iam_es_model.LabelPolicyIconRemoved, model.LabelPolicyIconRemoved,
iam_es_model.LabelPolicyLogoDarkAdded, model.LabelPolicyLogoDarkAdded,
iam_es_model.LabelPolicyLogoDarkRemoved, model.LabelPolicyLogoDarkRemoved,
iam_es_model.LabelPolicyIconDarkAdded, model.LabelPolicyIconDarkAdded,
iam_es_model.LabelPolicyIconDarkRemoved, model.LabelPolicyIconDarkRemoved,
iam_es_model.LabelPolicyFontAdded, model.LabelPolicyFontAdded,
iam_es_model.LabelPolicyFontRemoved, model.LabelPolicyFontRemoved:
policy, err = m.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.LabelPolicyRemoved:
return m.view.DeleteLabelPolicy(event.AggregateID, event)
default:
return m.view.ProcessedLabelPolicySequence(event)
}
if err != nil {
return err
}
return m.view.PutLabelPolicy(policy, event)
}
func (m *LabelPolicy) OnError(event *models.Event, err error) error {
logging.LogWithFields("SPOOL-2ff7s", "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)
}
func (m *LabelPolicy) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateLabelPolicySpoolerRunTimestamp)
}

View File

@ -98,6 +98,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
userRepo, userRepo,
eventstore.AuthRequestRepo{ eventstore.AuthRequestRepo{
PrivacyPolicyProvider: queries, PrivacyPolicyProvider: queries,
LabelPolicyProvider: queries,
Command: command, Command: command,
OrgViewProvider: queries, OrgViewProvider: queries,
AuthRequests: authReq, AuthRequests: authReq,

View File

@ -1,53 +0,0 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
labelPolicyTable = "auth.label_policies"
)
func (v *View) LabelPolicyByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateIDAndState(v.Db, labelPolicyTable, aggregateID, state)
}
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(event)
}
func (v *View) DeleteLabelPolicy(aggregateID string, event *models.Event) error {
err := view.DeleteLabelPolicy(v.Db, labelPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedLabelPolicySequence(event)
}
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(labelPolicyTable)
}
func (v *View) ProcessedLabelPolicySequence(event *models.Event) error {
return v.saveCurrentSequence(labelPolicyTable, event)
}
func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(labelPolicyTable)
}
func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(labelPolicyTable, sequence)
}
func (v *View) ProcessedLabelPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@ -10,6 +10,5 @@ import (
type OrgRepository interface { type OrgRepository interface {
GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error) GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error)
GetMyPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) GetMyPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
GetLabelPolicy(ctx context.Context, orgID string) (*domain.LabelPolicy, error)
GetLoginText(ctx context.Context, orgID string) ([]*domain.CustomText, error) GetLoginText(ctx context.Context, orgID string) ([]*domain.CustomText, error)
} }

View File

@ -201,6 +201,66 @@ func NewArrayRemoveCol(column string, value interface{}) handler.Column {
} }
} }
//NewCopyStatement creates a new upsert statement which updates a column from an existing row
// cols represent the columns which are objective to change.
// if the value of a col is empty the data will be copied from the selected row
// if the value of a col is not empty the data will be set by the static value
// conds represent the conditions for the selection subquery
func NewCopyStatement(event eventstore.EventReader, cols []handler.Column, conds []handler.Condition, opts ...execOption) *handler.Statement {
columnNames := make([]string, len(cols))
selectColumns := make([]string, len(cols))
argCounter := 0
args := []interface{}{}
for i, col := range cols {
columnNames[i] = col.Name
selectColumns[i] = col.Name
if col.Value != nil {
argCounter++
selectColumns[i] = "$" + strconv.Itoa(argCounter)
args = append(args, col.Value)
}
}
wheres := make([]string, len(conds))
for i, cond := range conds {
argCounter++
wheres[i] = "copy_table." + cond.Name + " = $" + strconv.Itoa(argCounter)
args = append(args, cond.Value)
}
config := execConfig{
args: args,
}
if len(cols) == 0 {
config.err = handler.ErrNoValues
}
if len(conds) == 0 {
config.err = handler.ErrNoCondition
}
q := func(config execConfig) string {
return "UPSERT INTO " +
config.tableName +
" (" +
strings.Join(columnNames, ", ") +
") SELECT " +
strings.Join(selectColumns, ", ") +
" FROM " +
config.tableName + " AS copy_table WHERE " +
strings.Join(wheres, " AND ")
}
return &handler.Statement{
AggregateType: event.Aggregate().Type,
Sequence: event.Sequence(),
PreviousSequence: event.PreviousAggregateTypeSequence(),
Execute: exec(config, q, opts),
}
}
func columnsToQuery(cols []handler.Column) (names []string, parameters []string, values []interface{}) { func columnsToQuery(cols []handler.Column) (names []string, parameters []string, values []interface{}) {
names = make([]string, len(cols)) names = make([]string, len(cols))
values = make([]interface{}, len(cols)) values = make([]interface{}, len(cols))

View File

@ -795,6 +795,182 @@ func TestNewMultiStatement(t *testing.T) {
} }
} }
func TestNewCopyStatement(t *testing.T) {
type args struct {
table string
event *testEvent
cols []handler.Column
conds []handler.Condition
}
type want struct {
aggregateType eventstore.AggregateType
sequence uint64
previousSequence uint64
table string
executer *wantExecuter
isErr func(error) bool
}
tests := []struct {
name string
args args
want want
}{
{
name: "no table",
args: args{
table: "",
event: &testEvent{
aggregateType: "agg",
sequence: 1,
previousSequence: 0,
},
conds: []handler.Condition{
{
Name: "col2",
Value: 1,
},
},
},
want: want{
table: "",
aggregateType: "agg",
sequence: 1,
previousSequence: 0,
executer: &wantExecuter{
shouldExecute: false,
},
isErr: func(err error) bool {
return errors.Is(err, handler.ErrNoProjection)
},
},
},
{
name: "no conditions",
args: args{
table: "my_table",
event: &testEvent{
aggregateType: "agg",
sequence: 1,
previousSequence: 0,
},
conds: []handler.Condition{},
cols: []handler.Column{
{
Name: "col",
},
},
},
want: want{
table: "my_table",
aggregateType: "agg",
sequence: 1,
previousSequence: 1,
executer: &wantExecuter{
shouldExecute: false,
},
isErr: func(err error) bool {
return errors.Is(err, handler.ErrNoCondition)
},
},
},
{
name: "no values",
args: args{
table: "my_table",
event: &testEvent{
aggregateType: "agg",
sequence: 1,
previousSequence: 0,
},
conds: []handler.Condition{
{
Name: "col",
},
},
cols: []handler.Column{},
},
want: want{
table: "my_table",
aggregateType: "agg",
sequence: 1,
previousSequence: 1,
executer: &wantExecuter{
shouldExecute: false,
},
isErr: func(err error) bool {
return errors.Is(err, handler.ErrNoValues)
},
},
},
{
name: "correct",
args: args{
table: "my_table",
event: &testEvent{
aggregateType: "agg",
sequence: 1,
previousSequence: 0,
},
cols: []handler.Column{
{
Name: "state",
Value: 1,
},
{
Name: "id",
},
{
Name: "col_a",
},
{
Name: "col_b",
},
},
conds: []handler.Condition{
{
Name: "id",
Value: 2,
},
{
Name: "state",
Value: 3,
},
},
},
want: want{
table: "my_table",
aggregateType: "agg",
sequence: 1,
previousSequence: 1,
executer: &wantExecuter{
params: []params{
{
query: "UPSERT INTO my_table (state, id, col_a, col_b) SELECT $1, id, col_a, col_b FROM my_table AS copy_table WHERE copy_table.id = $2 AND copy_table.state = $3",
args: []interface{}{1, 2, 3},
},
},
shouldExecute: true,
},
isErr: func(err error) bool {
return err == nil
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.want.executer.t = t
stmt := NewCopyStatement(tt.args.event, tt.args.cols, tt.args.conds)
err := stmt.Execute(tt.want.executer, tt.args.table)
if !tt.want.isErr(err) {
t.Errorf("unexpected error: %v", err)
}
tt.want.executer.check(t)
})
}
}
func TestStatement_Execute(t *testing.T) { func TestStatement_Execute(t *testing.T) {
type fields struct { type fields struct {
execute func(ex handler.Executer, projectionName string) error execute func(ex handler.Executer, projectionName string) error

View File

@ -10,7 +10,7 @@ import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
) )
func GetLabelPolicyByAggregateIDAndState(db *gorm.DB, table, aggregateID string, state int32) (*model.LabelPolicyView, error) { func GetStylingByAggregateIDAndState(db *gorm.DB, table, aggregateID string, state int32) (*model.LabelPolicyView, error) {
policy := new(model.LabelPolicyView) policy := new(model.LabelPolicyView)
aggregateIDQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals} aggregateIDQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
stateQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyState, Value: state, Method: domain.SearchMethodEquals} stateQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyState, Value: state, Method: domain.SearchMethodEquals}
@ -22,12 +22,12 @@ func GetLabelPolicyByAggregateIDAndState(db *gorm.DB, table, aggregateID string,
return policy, err return policy, err
} }
func PutLabelPolicy(db *gorm.DB, table string, policy *model.LabelPolicyView) error { func PutStyling(db *gorm.DB, table string, policy *model.LabelPolicyView) error {
save := repository.PrepareSave(table) save := repository.PrepareSave(table)
return save(db, policy) return save(db, policy)
} }
func DeleteLabelPolicy(db *gorm.DB, table, aggregateID string) error { func DeleteStyling(db *gorm.DB, table, aggregateID string) error {
delete := repository.PrepareDeleteByKey(table, model.LabelPolicySearchKey(iam_model.LabelPolicySearchKeyAggregateID), aggregateID) delete := repository.PrepareDeleteByKey(table, model.LabelPolicySearchKey(iam_model.LabelPolicySearchKeyAggregateID), aggregateID)
return delete(db) return delete(db)

View File

@ -165,70 +165,6 @@ func (repo *OrgRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
return result, nil return result, nil
} }
func (repo *OrgRepository) GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateIDAndState(authz.GetCtxData(ctx).OrgID, int32(domain.LabelPolicyStateActive))
if errors.IsNotFound(err) {
policy, err = repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStateActive))
if err != nil {
return nil, err
}
policy.Default = true
}
if err != nil {
return nil, err
}
return iam_view_model.LabelPolicyViewToModel(policy), err
}
func (repo *OrgRepository) GetPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
policy, err := repo.View.LabelPolicyByAggregateIDAndState(authz.GetCtxData(ctx).OrgID, int32(domain.LabelPolicyStatePreview))
if errors.IsNotFound(err) {
policy, err = repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return nil, err
}
policy.Default = true
}
if err != nil {
return nil, err
}
return iam_view_model.LabelPolicyViewToModel(policy), err
}
func (repo *OrgRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
return repo.getDefaultLabelPolicy(ctx, domain.LabelPolicyStateActive)
}
func (repo *OrgRepository) GetPreviewDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
return repo.getDefaultLabelPolicy(ctx, domain.LabelPolicyStatePreview)
}
func (repo *OrgRepository) getDefaultLabelPolicy(ctx context.Context, state domain.LabelPolicyState) (*iam_model.LabelPolicyView, error) {
policy, viewErr := repo.View.LabelPolicyByAggregateIDAndState(repo.SystemDefaults.IamID, int32(state))
if viewErr != nil && !errors.IsNotFound(viewErr) {
return nil, viewErr
}
if errors.IsNotFound(viewErr) {
policy = new(iam_view_model.LabelPolicyView)
}
events, esErr := repo.getIAMEvents(ctx, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-3Nf8sd", "Errors.IAM.LabelPolicy.NotFound")
}
if esErr != nil {
logging.Log("EVENT-28uLp").WithError(esErr).Debug("error retrieving new events")
return iam_view_model.LabelPolicyViewToModel(policy), nil
}
policyCopy := *policy
for _, event := range events {
if err := policyCopy.AppendEvent(event); err != nil {
return iam_view_model.LabelPolicyViewToModel(policy), nil
}
}
policy.Default = true
return iam_view_model.LabelPolicyViewToModel(policy), nil
}
func (repo *OrgRepository) GetIDPProvidersByIDPConfigID(ctx context.Context, aggregateID, idpConfigID string) ([]*iam_model.IDPProviderView, error) { func (repo *OrgRepository) GetIDPProvidersByIDPConfigID(ctx context.Context, aggregateID, idpConfigID string) ([]*iam_model.IDPProviderView, error) {
idpProviders, err := repo.View.IDPProvidersByIdpConfigID(aggregateID, idpConfigID) idpProviders, err := repo.View.IDPProvidersByIdpConfigID(aggregateID, idpConfigID)
if err != nil { if err != nil {

View File

@ -47,9 +47,6 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("MachineKeys"), errorCount, es}), handler{view, bulkLimit, configs.cycleDuration("MachineKeys"), errorCount, es}),
newIDPConfig( newIDPConfig(
handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}), handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}),
newLabelPolicy(
handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es},
staticStorage),
newIDPProvider( newIDPProvider(
handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es}, handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es},
defaults), defaults),

View File

@ -1,160 +0,0 @@
package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/static"
)
const (
labelPolicyTable = "management.label_policies"
)
type LabelPolicy struct {
handler
subscription *v1.Subscription
static static.Storage
}
func newLabelPolicy(handler handler, static static.Storage) *LabelPolicy {
h := &LabelPolicy{
handler: handler,
static: static,
}
h.subscribe()
return h
}
func (m *LabelPolicy) subscribe() {
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
go func() {
for event := range m.subscription.Events {
query.ReduceEvent(m, event)
}
}()
}
func (m *LabelPolicy) ViewModel() string {
return labelPolicyTable
}
func (p *LabelPolicy) Subscription() *v1.Subscription {
return p.subscription
}
func (_ *LabelPolicy) AggregateTypes() []es_models.AggregateType {
return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
}
func (m *LabelPolicy) CurrentSequence() (uint64, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return 0, err
}
return sequence.CurrentSequence, nil
}
func (m *LabelPolicy) EventQuery() (*es_models.SearchQuery, error) {
sequence, err := m.view.GetLatestLabelPolicySequence()
if err != nil {
return nil, err
}
return es_models.NewSearchQuery().
AggregateTypeFilter(m.AggregateTypes()...).
LatestSequenceFilter(sequence.CurrentSequence), nil
}
func (m *LabelPolicy) Reduce(event *es_models.Event) (err error) {
switch event.AggregateType {
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = m.processLabelPolicy(event)
}
return err
}
func (m *LabelPolicy) processLabelPolicy(event *es_models.Event) (err error) {
policy := new(iam_model.LabelPolicyView)
switch event.Type {
case iam_es_model.LabelPolicyAdded, model.LabelPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.LabelPolicyChanged, model.LabelPolicyChanged,
iam_es_model.LabelPolicyLogoAdded, model.LabelPolicyLogoAdded,
iam_es_model.LabelPolicyLogoRemoved, model.LabelPolicyLogoRemoved,
iam_es_model.LabelPolicyIconAdded, model.LabelPolicyIconAdded,
iam_es_model.LabelPolicyIconRemoved, model.LabelPolicyIconRemoved,
iam_es_model.LabelPolicyLogoDarkAdded, model.LabelPolicyLogoDarkAdded,
iam_es_model.LabelPolicyLogoDarkRemoved, model.LabelPolicyLogoDarkRemoved,
iam_es_model.LabelPolicyIconDarkAdded, model.LabelPolicyIconDarkAdded,
iam_es_model.LabelPolicyIconDarkRemoved, model.LabelPolicyIconDarkRemoved,
iam_es_model.LabelPolicyFontAdded, model.LabelPolicyFontAdded,
iam_es_model.LabelPolicyFontRemoved, model.LabelPolicyFontRemoved:
policy, err = m.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.LabelPolicyRemoved:
return m.view.DeleteLabelPolicy(event.AggregateID, event)
case iam_es_model.LabelPolicyActivated, model.LabelPolicyActivated:
policy, err = m.view.LabelPolicyByAggregateIDAndState(event.AggregateID, int32(domain.LabelPolicyStatePreview))
if err != nil {
return err
}
go m.CleanUpBucket(policy)
err = policy.AppendEvent(event)
default:
return m.view.ProcessedLabelPolicySequence(event)
}
if err != nil {
return err
}
return m.view.PutLabelPolicy(policy, event)
}
func (m *LabelPolicy) OnError(event *es_models.Event, err error) error {
logging.LogWithFields("SPOOL-66Cs8", "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)
}
func (m *LabelPolicy) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateLabelPolicySpoolerRunTimestamp)
}
func (p *LabelPolicy) CleanUpBucket(policy *iam_model.LabelPolicyView) {
ctx := context.Background()
objects, err := p.static.ListObjectInfos(ctx, policy.AggregateID, domain.LabelPolicyPrefix+"/", false)
if err != nil {
return
}
for _, object := range objects {
if !deletableObject(object, policy) {
continue
}
err = p.static.RemoveObject(ctx, policy.AggregateID, object.Key)
logging.LogWithFields("SPOOL-ASd3g", "aggregate", policy.AggregateID, "key", object.Key).OnError(err).Warn("could not delete asset")
}
}
func deletableObject(object *domain.AssetInfo, policy *iam_model.LabelPolicyView) bool {
if object.Key == policy.LogoURL ||
object.Key == policy.LogoDarkURL ||
object.Key == policy.IconURL ||
object.Key == policy.IconDarkURL ||
object.Key == policy.FontURL ||
object.Key == domain.LabelPolicyPrefix+"/css/" {
return false
}
return true
}

View File

@ -1,53 +0,0 @@
package view
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/repository/view"
"github.com/caos/zitadel/internal/iam/repository/view/model"
global_view "github.com/caos/zitadel/internal/view/repository"
)
const (
labelPolicyTable = "management.label_policies"
)
func (v *View) LabelPolicyByAggregateIDAndState(aggregateID string, state int32) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateIDAndState(v.Db, labelPolicyTable, aggregateID, state)
}
func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error {
err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy)
if err != nil {
return err
}
return v.ProcessedLabelPolicySequence(event)
}
func (v *View) DeleteLabelPolicy(aggregateID string, event *models.Event) error {
err := view.DeleteLabelPolicy(v.Db, labelPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {
return err
}
return v.ProcessedLabelPolicySequence(event)
}
func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) {
return v.latestSequence(labelPolicyTable)
}
func (v *View) ProcessedLabelPolicySequence(event *models.Event) error {
return v.saveCurrentSequence(labelPolicyTable, event)
}
func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error {
return v.updateSpoolerRunSequence(labelPolicyTable)
}
func (v *View) GetLatestLabelPolicyFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
return v.latestFailedEvent(labelPolicyTable, sequence)
}
func (v *View) ProcessedLabelPolicyFailedEvent(failedEvent *global_view.FailedEvent) error {
return v.saveFailedEvent(failedEvent)
}

View File

@ -34,9 +34,4 @@ type OrgRepository interface {
GetDefaultLoginTexts(ctx context.Context, lang string) (*domain.CustomLoginText, error) GetDefaultLoginTexts(ctx context.Context, lang string) (*domain.CustomLoginText, error)
GetLoginTexts(ctx context.Context, orgID, lang string) (*domain.CustomLoginText, error) GetLoginTexts(ctx context.Context, orgID, lang string) (*domain.CustomLoginText, error)
GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
GetPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
GetPreviewDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
} }

View File

@ -15,7 +15,7 @@ import (
"github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" v1 "github.com/caos/zitadel/internal/eventstore/v1"
"github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler" "github.com/caos/zitadel/internal/eventstore/v1/spooler"
@ -408,10 +408,10 @@ func getSetNotifyContextData(orgID string) context.Context {
// Read organization specific colors // Read organization specific colors
func (n *Notification) getLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) { func (n *Notification) getLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
// read from Org // read from Org
policy, err := n.view.LabelPolicyByAggregateIDAndState(authz.GetCtxData(ctx).OrgID, labelPolicyTableOrg, int32(domain.LabelPolicyStateActive)) policy, err := n.view.StylingByAggregateIDAndState(authz.GetCtxData(ctx).OrgID, labelPolicyTableOrg, int32(domain.LabelPolicyStateActive))
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
// read from default // read from default
policy, err = n.view.LabelPolicyByAggregateIDAndState(n.systemDefaults.IamID, labelPolicyTableDef, int32(domain.LabelPolicyStateActive)) policy, err = n.view.StylingByAggregateIDAndState(n.systemDefaults.IamID, labelPolicyTableDef, int32(domain.LabelPolicyStateActive))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,6 +5,6 @@ import (
"github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/iam/repository/view/model"
) )
func (v *View) LabelPolicyByAggregateIDAndState(aggregateID, labelPolicyTableVar string, state int32) (*model.LabelPolicyView, error) { func (v *View) StylingByAggregateIDAndState(aggregateID, labelPolicyTableVar string, state int32) (*model.LabelPolicyView, error) {
return view.GetLabelPolicyByAggregateIDAndState(v.Db, labelPolicyTableVar, aggregateID, state) return view.GetStylingByAggregateIDAndState(v.Db, labelPolicyTableVar, aggregateID, state)
} }

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"database/sql" "database/sql"
errs "errors" errs "errors"
"log"
"time" "time"
sq "github.com/Masterminds/squirrel" sq "github.com/Masterminds/squirrel"
@ -216,7 +215,6 @@ func (q *Queries) SearchIDPs(ctx context.Context, resourceOwner string, queries
rows, err := q.client.QueryContext(ctx, stmt, args...) rows, err := q.client.QueryContext(ctx, stmt, args...)
if err != nil { if err != nil {
log.Println(err)
return nil, errors.ThrowInternal(err, "QUERY-YTug9", "Errors.Internal") return nil, errors.ThrowInternal(err, "QUERY-YTug9", "Errors.Internal")
} }
idps, err = scan(rows) idps, err = scan(rows)

View File

@ -0,0 +1,300 @@
package query
import (
"context"
"database/sql"
errs "errors"
"time"
sq "github.com/Masterminds/squirrel"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/query/projection"
)
type LabelPolicy struct {
ID string
CreationDate time.Time
ChangeDate time.Time
Sequence uint64
State domain.LabelPolicyState
IsDefault bool
ResourceOwner string
HideLoginNameSuffix bool
FontURL string
WatermarkDisabled bool
ShouldErrorPopup bool
Dark Theme
Light Theme
}
type Theme struct {
PrimaryColor string
WarnColor string
BackgroundColor string
FontColor string
LogoURL string
IconURL string
}
func (q *Queries) ActiveLabelPolicyByOrg(ctx context.Context, orgID string) (*LabelPolicy, error) {
stmt, scan := prepareLabelPolicyQuery()
query, args, err := stmt.Where(
sq.And{
sq.Or{
sq.Eq{
LabelPolicyColID.identifier(): orgID,
},
sq.Eq{
LabelPolicyColID.identifier(): q.iamID,
},
},
sq.Eq{
LabelPolicyColState.identifier(): domain.LabelPolicyStateActive,
},
}).
OrderBy(LabelPolicyColIsDefault.identifier()).
Limit(1).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-V22un", "unable to create sql stmt")
}
row := q.client.QueryRowContext(ctx, query, args...)
return scan(row)
}
func (q *Queries) PreviewLabelPolicyByOrg(ctx context.Context, orgID string) (*LabelPolicy, error) {
stmt, scan := prepareLabelPolicyQuery()
query, args, err := stmt.Where(
sq.And{
sq.Or{
sq.Eq{
LabelPolicyColID.identifier(): orgID,
},
sq.Eq{
LabelPolicyColID.identifier(): q.iamID,
},
},
sq.Eq{
LabelPolicyColState.identifier(): domain.LabelPolicyStatePreview,
},
}).
OrderBy(LabelPolicyColIsDefault.identifier()).
Limit(1).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-AG5eq", "unable to create sql stmt")
}
row := q.client.QueryRowContext(ctx, query, args...)
return scan(row)
}
func (q *Queries) DefaultActiveLabelPolicy(ctx context.Context) (*LabelPolicy, error) {
stmt, scan := prepareLabelPolicyQuery()
query, args, err := stmt.Where(sq.Eq{
LabelPolicyColID.identifier(): q.iamID,
LabelPolicyColState.identifier(): domain.LabelPolicyStateActive,
}).
OrderBy(LabelPolicyColIsDefault.identifier()).
Limit(1).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-mN0Ci", "unable to create sql stmt")
}
row := q.client.QueryRowContext(ctx, query, args...)
return scan(row)
}
func (q *Queries) DefaultPreviewLabelPolicy(ctx context.Context) (*LabelPolicy, error) {
stmt, scan := prepareLabelPolicyQuery()
query, args, err := stmt.Where(sq.Eq{
LabelPolicyColID.identifier(): q.iamID,
LabelPolicyColState.identifier(): domain.LabelPolicyStatePreview,
}).
OrderBy(LabelPolicyColIsDefault.identifier()).
Limit(1).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-B3JQR", "unable to create sql stmt")
}
row := q.client.QueryRowContext(ctx, query, args...)
return scan(row)
}
var (
labelPolicyTable = table{
name: projection.LabelPolicyTable,
}
LabelPolicyColCreationDate = Column{
name: projection.LabelPolicyCreationDateCol,
}
LabelPolicyColChangeDate = Column{
name: projection.LabelPolicyChangeDateCol,
}
LabelPolicyColSequence = Column{
name: projection.LabelPolicySequenceCol,
}
LabelPolicyColID = Column{
name: projection.LabelPolicyIDCol,
}
LabelPolicyColState = Column{
name: projection.LabelPolicyStateCol,
}
LabelPolicyColIsDefault = Column{
name: projection.LabelPolicyIsDefaultCol,
}
LabelPolicyColResourceOwner = Column{
name: projection.LabelPolicyResourceOwnerCol,
}
LabelPolicyColHideLoginNameSuffix = Column{
name: projection.LabelPolicyHideLoginNameSuffixCol,
}
LabelPolicyColFontURL = Column{
name: projection.LabelPolicyFontURLCol,
}
LabelPolicyColWatermarkDisabled = Column{
name: projection.LabelPolicyWatermarkDisabledCol,
}
LabelPolicyColShouldErrorPopup = Column{
name: projection.LabelPolicyShouldErrorPopupCol,
}
LabelPolicyColLightPrimaryColor = Column{
name: projection.LabelPolicyLightPrimaryColorCol,
}
LabelPolicyColLightWarnColor = Column{
name: projection.LabelPolicyLightWarnColorCol,
}
LabelPolicyColLightBackgroundColor = Column{
name: projection.LabelPolicyLightBackgroundColorCol,
}
LabelPolicyColLightFontColor = Column{
name: projection.LabelPolicyLightFontColorCol,
}
LabelPolicyColLightLogoURL = Column{
name: projection.LabelPolicyLightLogoURLCol,
}
LabelPolicyColLightIconURL = Column{
name: projection.LabelPolicyLightIconURLCol,
}
LabelPolicyColDarkPrimaryColor = Column{
name: projection.LabelPolicyDarkPrimaryColorCol,
}
LabelPolicyColDarkWarnColor = Column{
name: projection.LabelPolicyDarkWarnColorCol,
}
LabelPolicyColDarkBackgroundColor = Column{
name: projection.LabelPolicyDarkBackgroundColorCol,
}
LabelPolicyColDarkFontColor = Column{
name: projection.LabelPolicyDarkFontColorCol,
}
LabelPolicyColDarkLogoURL = Column{
name: projection.LabelPolicyDarkLogoURLCol,
}
LabelPolicyColDarkIconURL = Column{
name: projection.LabelPolicyDarkIconURLCol,
}
)
func prepareLabelPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy, error)) {
return sq.Select(
LabelPolicyColCreationDate.identifier(),
LabelPolicyColChangeDate.identifier(),
LabelPolicyColSequence.identifier(),
LabelPolicyColID.identifier(),
LabelPolicyColState.identifier(),
LabelPolicyColIsDefault.identifier(),
LabelPolicyColResourceOwner.identifier(),
LabelPolicyColHideLoginNameSuffix.identifier(),
LabelPolicyColFontURL.identifier(),
LabelPolicyColWatermarkDisabled.identifier(),
LabelPolicyColShouldErrorPopup.identifier(),
LabelPolicyColLightPrimaryColor.identifier(),
LabelPolicyColLightWarnColor.identifier(),
LabelPolicyColLightBackgroundColor.identifier(),
LabelPolicyColLightFontColor.identifier(),
LabelPolicyColLightLogoURL.identifier(),
LabelPolicyColLightIconURL.identifier(),
LabelPolicyColDarkPrimaryColor.identifier(),
LabelPolicyColDarkWarnColor.identifier(),
LabelPolicyColDarkBackgroundColor.identifier(),
LabelPolicyColDarkFontColor.identifier(),
LabelPolicyColDarkLogoURL.identifier(),
LabelPolicyColDarkIconURL.identifier(),
).
From(labelPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*LabelPolicy, error) {
policy := new(LabelPolicy)
var (
fontURL = sql.NullString{}
lightPrimaryColor = sql.NullString{}
lightWarnColor = sql.NullString{}
lightBackgroundColor = sql.NullString{}
lightFontColor = sql.NullString{}
lightLogoURL = sql.NullString{}
lightIconURL = sql.NullString{}
darkPrimaryColor = sql.NullString{}
darkWarnColor = sql.NullString{}
darkBackgroundColor = sql.NullString{}
darkFontColor = sql.NullString{}
darkLogoURL = sql.NullString{}
darkIconURL = sql.NullString{}
)
err := row.Scan(
&policy.CreationDate,
&policy.ChangeDate,
&policy.Sequence,
&policy.ID,
&policy.State,
&policy.IsDefault,
&policy.ResourceOwner,
&policy.HideLoginNameSuffix,
&fontURL,
&policy.WatermarkDisabled,
&policy.ShouldErrorPopup,
&lightPrimaryColor,
&lightWarnColor,
&lightBackgroundColor,
&lightFontColor,
&lightLogoURL,
&lightIconURL,
&darkPrimaryColor,
&darkWarnColor,
&darkBackgroundColor,
&darkFontColor,
&darkLogoURL,
&darkIconURL,
)
if err != nil {
if errs.Is(err, sql.ErrNoRows) {
return nil, errors.ThrowNotFound(err, "QUERY-bJEsm", "errors.policy.label.not_found")
}
return nil, errors.ThrowInternal(err, "QUERY-awLM6", "errors.internal")
}
policy.FontURL = fontURL.String
policy.Light.PrimaryColor = lightPrimaryColor.String
policy.Light.WarnColor = lightWarnColor.String
policy.Light.BackgroundColor = lightBackgroundColor.String
policy.Light.FontColor = lightFontColor.String
policy.Light.LogoURL = lightLogoURL.String
policy.Light.IconURL = lightIconURL.String
policy.Dark.PrimaryColor = darkPrimaryColor.String
policy.Dark.WarnColor = darkWarnColor.String
policy.Dark.BackgroundColor = darkBackgroundColor.String
policy.Dark.FontColor = darkFontColor.String
policy.Dark.LogoURL = darkLogoURL.String
policy.Dark.IconURL = darkIconURL.String
return policy, nil
}
}

View File

@ -0,0 +1,531 @@
package projection
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/handler"
"github.com/caos/zitadel/internal/eventstore/handler/crdb"
"github.com/caos/zitadel/internal/repository/iam"
"github.com/caos/zitadel/internal/repository/org"
"github.com/caos/zitadel/internal/repository/policy"
)
type LabelPolicyProjection struct {
crdb.StatementHandler
}
const (
LabelPolicyTable = "zitadel.projections.label_policies"
)
func NewLabelPolicyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *LabelPolicyProjection {
p := &LabelPolicyProjection{}
config.ProjectionName = LabelPolicyTable
config.Reducers = p.reducers()
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
return p
}
func (p *LabelPolicyProjection) reducers() []handler.AggregateReducer {
return []handler.AggregateReducer{
{
Aggregate: org.AggregateType,
EventRedusers: []handler.EventReducer{
{
Event: org.LabelPolicyAddedEventType,
Reduce: p.reduceAdded,
},
{
Event: org.LabelPolicyChangedEventType,
Reduce: p.reduceChanged,
},
{
Event: org.LabelPolicyRemovedEventType,
Reduce: p.reduceRemoved,
},
{
Event: org.LabelPolicyActivatedEventType,
Reduce: p.reduceActivated,
},
{
Event: org.LabelPolicyLogoAddedEventType,
Reduce: p.reduceLogoAdded,
},
{
Event: org.LabelPolicyLogoRemovedEventType,
Reduce: p.reduceLogoRemoved,
},
{
Event: org.LabelPolicyIconAddedEventType,
Reduce: p.reduceIconAdded,
},
{
Event: org.LabelPolicyIconRemovedEventType,
Reduce: p.reduceIconRemoved,
},
{
Event: org.LabelPolicyLogoDarkAddedEventType,
Reduce: p.reduceLogoAdded,
},
{
Event: org.LabelPolicyLogoDarkRemovedEventType,
Reduce: p.reduceLogoRemoved,
},
{
Event: org.LabelPolicyIconDarkAddedEventType,
Reduce: p.reduceIconAdded,
},
{
Event: org.LabelPolicyIconDarkRemovedEventType,
Reduce: p.reduceIconRemoved,
},
{
Event: org.LabelPolicyFontAddedEventType,
Reduce: p.reduceFontAdded,
},
{
Event: org.LabelPolicyFontRemovedEventType,
Reduce: p.reduceFontRemoved,
},
{
Event: org.LabelPolicyAssetsRemovedEventType,
Reduce: p.reduceAssetsRemoved,
},
},
},
{
Aggregate: iam.AggregateType,
EventRedusers: []handler.EventReducer{
{
Event: iam.LabelPolicyAddedEventType,
Reduce: p.reduceAdded,
},
{
Event: iam.LabelPolicyChangedEventType,
Reduce: p.reduceChanged,
},
{
Event: iam.LabelPolicyActivatedEventType,
Reduce: p.reduceActivated,
},
{
Event: iam.LabelPolicyLogoAddedEventType,
Reduce: p.reduceLogoAdded,
},
{
Event: iam.LabelPolicyLogoRemovedEventType,
Reduce: p.reduceLogoRemoved,
},
{
Event: iam.LabelPolicyIconAddedEventType,
Reduce: p.reduceIconAdded,
},
{
Event: iam.LabelPolicyIconRemovedEventType,
Reduce: p.reduceIconRemoved,
},
{
Event: iam.LabelPolicyLogoDarkAddedEventType,
Reduce: p.reduceLogoAdded,
},
{
Event: iam.LabelPolicyLogoDarkRemovedEventType,
Reduce: p.reduceLogoRemoved,
},
{
Event: iam.LabelPolicyIconDarkAddedEventType,
Reduce: p.reduceIconAdded,
},
{
Event: iam.LabelPolicyIconDarkRemovedEventType,
Reduce: p.reduceIconRemoved,
},
{
Event: iam.LabelPolicyFontAddedEventType,
Reduce: p.reduceFontAdded,
},
{
Event: iam.LabelPolicyFontRemovedEventType,
Reduce: p.reduceFontRemoved,
},
{
Event: iam.LabelPolicyAssetsRemovedEventType,
Reduce: p.reduceAssetsRemoved,
},
},
},
}
}
func (p *LabelPolicyProjection) reduceAdded(event eventstore.EventReader) (*handler.Statement, error) {
var policyEvent policy.LabelPolicyAddedEvent
var isDefault bool
switch e := event.(type) {
case *org.LabelPolicyAddedEvent:
policyEvent = e.LabelPolicyAddedEvent
isDefault = false
case *iam.LabelPolicyAddedEvent:
policyEvent = e.LabelPolicyAddedEvent
isDefault = true
default:
logging.LogWithFields("PROJE-zR6h0", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyAddedEventType, iam.LabelPolicyAddedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-CSE7A", "reduce.wrong.event.type")
}
return crdb.NewCreateStatement(
&policyEvent,
[]handler.Column{
handler.NewCol(LabelPolicyCreationDateCol, policyEvent.CreationDate()),
handler.NewCol(LabelPolicyChangeDateCol, policyEvent.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, policyEvent.Sequence()),
handler.NewCol(LabelPolicyIDCol, policyEvent.Aggregate().ID),
handler.NewCol(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
handler.NewCol(LabelPolicyIsDefaultCol, isDefault),
handler.NewCol(LabelPolicyResourceOwnerCol, policyEvent.Aggregate().ResourceOwner),
handler.NewCol(LabelPolicyLightPrimaryColorCol, policyEvent.PrimaryColor),
handler.NewCol(LabelPolicyLightBackgroundColorCol, policyEvent.BackgroundColor),
handler.NewCol(LabelPolicyLightWarnColorCol, policyEvent.WarnColor),
handler.NewCol(LabelPolicyLightFontColorCol, policyEvent.FontColor),
handler.NewCol(LabelPolicyDarkPrimaryColorCol, policyEvent.PrimaryColorDark),
handler.NewCol(LabelPolicyDarkBackgroundColorCol, policyEvent.BackgroundColorDark),
handler.NewCol(LabelPolicyDarkWarnColorCol, policyEvent.WarnColorDark),
handler.NewCol(LabelPolicyDarkFontColorCol, policyEvent.FontColorDark),
handler.NewCol(LabelPolicyHideLoginNameSuffixCol, policyEvent.HideLoginNameSuffix),
handler.NewCol(LabelPolicyShouldErrorPopupCol, policyEvent.ErrorMsgPopup),
handler.NewCol(LabelPolicyWatermarkDisabledCol, policyEvent.DisableWatermark),
}), nil
}
func (p *LabelPolicyProjection) reduceChanged(event eventstore.EventReader) (*handler.Statement, error) {
var policyEvent policy.LabelPolicyChangedEvent
switch e := event.(type) {
case *org.LabelPolicyChangedEvent:
policyEvent = e.LabelPolicyChangedEvent
case *iam.LabelPolicyChangedEvent:
policyEvent = e.LabelPolicyChangedEvent
default:
logging.LogWithFields("PROJE-2VrlG", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyChangedEventType, iam.LabelPolicyChangedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-qgVug", "reduce.wrong.event.type")
}
cols := []handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, policyEvent.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, policyEvent.Sequence()),
}
if policyEvent.PrimaryColor != nil {
cols = append(cols, handler.NewCol(LabelPolicyLightPrimaryColorCol, *policyEvent.PrimaryColor))
}
if policyEvent.BackgroundColor != nil {
cols = append(cols, handler.NewCol(LabelPolicyLightBackgroundColorCol, *policyEvent.BackgroundColor))
}
if policyEvent.WarnColor != nil {
cols = append(cols, handler.NewCol(LabelPolicyLightWarnColorCol, *policyEvent.WarnColor))
}
if policyEvent.FontColor != nil {
cols = append(cols, handler.NewCol(LabelPolicyLightFontColorCol, *policyEvent.FontColor))
}
if policyEvent.PrimaryColorDark != nil {
cols = append(cols, handler.NewCol(LabelPolicyDarkPrimaryColorCol, *policyEvent.PrimaryColorDark))
}
if policyEvent.BackgroundColorDark != nil {
cols = append(cols, handler.NewCol(LabelPolicyDarkBackgroundColorCol, *policyEvent.BackgroundColorDark))
}
if policyEvent.WarnColorDark != nil {
cols = append(cols, handler.NewCol(LabelPolicyDarkWarnColorCol, *policyEvent.WarnColorDark))
}
if policyEvent.FontColorDark != nil {
cols = append(cols, handler.NewCol(LabelPolicyDarkFontColorCol, *policyEvent.FontColorDark))
}
if policyEvent.HideLoginNameSuffix != nil {
cols = append(cols, handler.NewCol(LabelPolicyHideLoginNameSuffixCol, *policyEvent.HideLoginNameSuffix))
}
if policyEvent.ErrorMsgPopup != nil {
cols = append(cols, handler.NewCol(LabelPolicyShouldErrorPopupCol, *policyEvent.ErrorMsgPopup))
}
if policyEvent.DisableWatermark != nil {
cols = append(cols, handler.NewCol(LabelPolicyWatermarkDisabledCol, *policyEvent.DisableWatermark))
}
return crdb.NewUpdateStatement(
&policyEvent,
cols,
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, policyEvent.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceRemoved(event eventstore.EventReader) (*handler.Statement, error) {
policyEvent, ok := event.(*org.LabelPolicyRemovedEvent)
if !ok {
logging.LogWithFields("PROJE-izDbs", "seq", event.Sequence(), "expectedType", org.LabelPolicyRemovedEventType).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-ATMBz", "reduce.wrong.event.type")
}
return crdb.NewDeleteStatement(
policyEvent,
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, policyEvent.Aggregate().ID),
}), nil
}
func (p *LabelPolicyProjection) reduceActivated(event eventstore.EventReader) (*handler.Statement, error) {
switch event.(type) {
case *org.LabelPolicyActivatedEvent, *iam.LabelPolicyActivatedEvent:
// everything ok
default:
logging.LogWithFields("PROJE-ZQO7J", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyActivatedEventType, iam.LabelPolicyActivatedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-dldEU", "reduce.wrong.event.type")
}
return crdb.NewCopyStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
handler.NewCol(LabelPolicyStateCol, domain.LabelPolicyStateActive),
handler.NewCol(LabelPolicyCreationDateCol, nil),
handler.NewCol(LabelPolicyResourceOwnerCol, nil),
handler.NewCol(LabelPolicyIDCol, nil),
handler.NewCol(LabelPolicyIsDefaultCol, nil),
handler.NewCol(LabelPolicyHideLoginNameSuffixCol, nil),
handler.NewCol(LabelPolicyFontURLCol, nil),
handler.NewCol(LabelPolicyWatermarkDisabledCol, nil),
handler.NewCol(LabelPolicyShouldErrorPopupCol, nil),
handler.NewCol(LabelPolicyLightPrimaryColorCol, nil),
handler.NewCol(LabelPolicyLightWarnColorCol, nil),
handler.NewCol(LabelPolicyLightBackgroundColorCol, nil),
handler.NewCol(LabelPolicyLightFontColorCol, nil),
handler.NewCol(LabelPolicyLightLogoURLCol, nil),
handler.NewCol(LabelPolicyLightIconURLCol, nil),
handler.NewCol(LabelPolicyDarkPrimaryColorCol, nil),
handler.NewCol(LabelPolicyDarkWarnColorCol, nil),
handler.NewCol(LabelPolicyDarkBackgroundColorCol, nil),
handler.NewCol(LabelPolicyDarkFontColorCol, nil),
handler.NewCol(LabelPolicyDarkLogoURLCol, nil),
handler.NewCol(LabelPolicyDarkIconURLCol, nil),
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceLogoAdded(event eventstore.EventReader) (*handler.Statement, error) {
var storeKey handler.Column
switch e := event.(type) {
case *org.LabelPolicyLogoAddedEvent:
storeKey = handler.NewCol(LabelPolicyLightLogoURLCol, e.StoreKey)
case *iam.LabelPolicyLogoAddedEvent:
storeKey = handler.NewCol(LabelPolicyLightLogoURLCol, e.StoreKey)
case *org.LabelPolicyLogoDarkAddedEvent:
storeKey = handler.NewCol(LabelPolicyDarkLogoURLCol, e.StoreKey)
case *iam.LabelPolicyLogoDarkAddedEvent:
storeKey = handler.NewCol(LabelPolicyDarkLogoURLCol, e.StoreKey)
default:
logging.LogWithFields("PROJE-NHrbi", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyLogoAddedEventType, iam.LabelPolicyLogoAddedEventType, org.LabelPolicyLogoDarkAddedEventType, iam.LabelPolicyLogoDarkAddedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-4wbOI", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
storeKey,
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceLogoRemoved(event eventstore.EventReader) (*handler.Statement, error) {
var col string
switch event.(type) {
case *org.LabelPolicyLogoRemovedEvent:
col = LabelPolicyLightLogoURLCol
case *iam.LabelPolicyLogoRemovedEvent:
col = LabelPolicyLightLogoURLCol
case *org.LabelPolicyLogoDarkRemovedEvent:
col = LabelPolicyDarkLogoURLCol
case *iam.LabelPolicyLogoDarkRemovedEvent:
col = LabelPolicyDarkLogoURLCol
default:
logging.LogWithFields("PROJE-oUmnS", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyLogoRemovedEventType, iam.LabelPolicyLogoRemovedEventType, org.LabelPolicyLogoDarkRemovedEventType, iam.LabelPolicyLogoDarkRemovedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-kg8H4", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
handler.NewCol(col, nil),
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceIconAdded(event eventstore.EventReader) (*handler.Statement, error) {
var storeKey handler.Column
switch e := event.(type) {
case *org.LabelPolicyIconAddedEvent:
storeKey = handler.NewCol(LabelPolicyLightIconURLCol, e.StoreKey)
case *iam.LabelPolicyIconAddedEvent:
storeKey = handler.NewCol(LabelPolicyLightIconURLCol, e.StoreKey)
case *org.LabelPolicyIconDarkAddedEvent:
storeKey = handler.NewCol(LabelPolicyDarkIconURLCol, e.StoreKey)
case *iam.LabelPolicyIconDarkAddedEvent:
storeKey = handler.NewCol(LabelPolicyDarkIconURLCol, e.StoreKey)
default:
logging.LogWithFields("PROJE-6efFw", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyIconAddedEventType, iam.LabelPolicyIconAddedEventType, org.LabelPolicyIconDarkAddedEventType, iam.LabelPolicyIconDarkAddedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-e2JFz", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
storeKey,
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceIconRemoved(event eventstore.EventReader) (*handler.Statement, error) {
var col string
switch event.(type) {
case *org.LabelPolicyIconRemovedEvent:
col = LabelPolicyLightIconURLCol
case *iam.LabelPolicyIconRemovedEvent:
col = LabelPolicyLightIconURLCol
case *org.LabelPolicyIconDarkRemovedEvent:
col = LabelPolicyDarkIconURLCol
case *iam.LabelPolicyIconDarkRemovedEvent:
col = LabelPolicyDarkIconURLCol
default:
logging.LogWithFields("PROJE-0BiAZ", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyIconRemovedEventType, iam.LabelPolicyIconRemovedEventType, org.LabelPolicyIconDarkRemovedEventType, iam.LabelPolicyIconDarkRemovedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-gfgbY", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
handler.NewCol(col, nil),
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceFontAdded(event eventstore.EventReader) (*handler.Statement, error) {
var storeKey handler.Column
switch e := event.(type) {
case *org.LabelPolicyFontAddedEvent:
storeKey = handler.NewCol(LabelPolicyFontURLCol, e.StoreKey)
case *iam.LabelPolicyFontAddedEvent:
storeKey = handler.NewCol(LabelPolicyFontURLCol, e.StoreKey)
default:
logging.LogWithFields("PROJE-DCzfX", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyFontAddedEventType, iam.LabelPolicyFontAddedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-65i9W", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
storeKey,
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceFontRemoved(event eventstore.EventReader) (*handler.Statement, error) {
var col string
switch event.(type) {
case *org.LabelPolicyFontRemovedEvent:
col = LabelPolicyFontURLCol
case *iam.LabelPolicyFontRemovedEvent:
col = LabelPolicyFontURLCol
default:
logging.LogWithFields("PROJE-YKwG4", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyFontRemovedEventType, iam.LabelPolicyFontRemovedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-xf32J", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
handler.NewCol(col, nil),
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
func (p *LabelPolicyProjection) reduceAssetsRemoved(event eventstore.EventReader) (*handler.Statement, error) {
switch event.(type) {
case *org.LabelPolicyAssetsRemovedEvent, *iam.LabelPolicyAssetsRemovedEvent:
//ok
default:
logging.LogWithFields("PROJE-YKwG4", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{org.LabelPolicyAssetsRemovedEventType, iam.LabelPolicyAssetsRemovedEventType}).Error("was not an event")
return nil, errors.ThrowInvalidArgument(nil, "PROJE-qi39A", "reduce.wrong.event.type")
}
return crdb.NewUpdateStatement(
event,
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()),
handler.NewCol(LabelPolicySequenceCol, event.Sequence()),
handler.NewCol(LabelPolicyLightLogoURLCol, nil),
handler.NewCol(LabelPolicyLightIconURLCol, nil),
handler.NewCol(LabelPolicyDarkLogoURLCol, nil),
handler.NewCol(LabelPolicyDarkIconURLCol, nil),
handler.NewCol(LabelPolicyFontURLCol, nil),
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),
}), nil
}
const (
LabelPolicyCreationDateCol = "creation_date"
LabelPolicyChangeDateCol = "change_date"
LabelPolicySequenceCol = "sequence"
LabelPolicyIDCol = "id"
LabelPolicyStateCol = "state"
LabelPolicyIsDefaultCol = "is_default"
LabelPolicyResourceOwnerCol = "resource_owner"
LabelPolicyHideLoginNameSuffixCol = "hide_login_name_suffix"
LabelPolicyFontURLCol = "font_url"
LabelPolicyWatermarkDisabledCol = "watermark_disabled"
LabelPolicyShouldErrorPopupCol = "should_error_popup"
LabelPolicyLightPrimaryColorCol = "light_primary_color"
LabelPolicyLightWarnColorCol = "light_warn_color"
LabelPolicyLightBackgroundColorCol = "light_background_color"
LabelPolicyLightFontColorCol = "light_font_color"
LabelPolicyLightLogoURLCol = "light_logo_url"
LabelPolicyLightIconURLCol = "light_icon_url"
LabelPolicyDarkPrimaryColorCol = "dark_primary_color"
LabelPolicyDarkWarnColorCol = "dark_warn_color"
LabelPolicyDarkBackgroundColorCol = "dark_background_color"
LabelPolicyDarkFontColorCol = "dark_font_color"
LabelPolicyDarkLogoURLCol = "dark_logo_url"
LabelPolicyDarkIconURLCol = "dark_icon_url"
)

View File

@ -0,0 +1,981 @@
package projection
import (
"testing"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/handler"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/caos/zitadel/internal/repository/iam"
"github.com/caos/zitadel/internal/repository/org"
)
func TestLabelPolicyProjection_reduces(t *testing.T) {
type args struct {
event func(t *testing.T) eventstore.EventReader
}
tests := []struct {
name string
args args
reduce func(event eventstore.EventReader) (*handler.Statement, error)
want wantReduce
}{
{
name: "org.reduceAdded",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyAddedEventType),
org.AggregateType,
[]byte(`{"backgroundColor": "#141735", "fontColor": "#ffffff", "primaryColor": "#5282c1", "warnColor": "#ff3b5b"}`),
), org.LabelPolicyAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO zitadel.projections.label_policies (creation_date, change_date, sequence, id, state, is_default, resource_owner, light_primary_color, light_background_color, light_warn_color, light_font_color, dark_primary_color, dark_background_color, dark_warn_color, dark_font_color, hide_login_name_suffix, should_error_popup, watermark_disabled) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
uint64(15),
"agg-id",
domain.LabelPolicyStatePreview,
false,
"ro-id",
"#5282c1",
"#141735",
"#ff3b5b",
"#ffffff",
"",
"",
"",
"",
false,
false,
false,
},
},
},
},
},
},
{
name: "org.reduceChanged",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyChangedEventType),
org.AggregateType,
[]byte(`{"backgroundColor": "#141735", "fontColor": "#ffffff", "primaryColor": "#5282c1", "warnColor": "#ff3b5b"}`),
), org.LabelPolicyChangedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_primary_color, light_background_color, light_warn_color, light_font_color) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (state = $8)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"#5282c1",
"#141735",
"#ff3b5b",
"#ffffff",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceRemoved",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyRemovedEventType),
org.AggregateType,
nil,
), org.LabelPolicyRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM zitadel.projections.label_policies WHERE (id = $1)",
expectedArgs: []interface{}{
"agg-id",
},
},
},
},
},
},
{
name: "org.reduceActivated",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyActivatedEventType),
org.AggregateType,
nil,
), org.LabelPolicyActivatedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceActivated,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.label_policies (change_date, sequence, state, creation_date, resource_owner, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) SELECT $1, $2, $3, creation_date, resource_owner, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url FROM zitadel.projections.label_policies AS copy_table WHERE copy_table.id = $4 AND copy_table.state = $5",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.LabelPolicyStateActive,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceLogoAdded light",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyLogoAddedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), org.LabelPolicyLogoAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/logo.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceLogoAdded dark",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyLogoDarkAddedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), org.LabelPolicyLogoDarkAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/logo.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceIconAdded light",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyIconAddedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), org.LabelPolicyIconAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/icon.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceIconAdded dark",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyIconDarkAddedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), org.LabelPolicyIconDarkAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/icon.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceLogoRemoved light",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyLogoRemovedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), org.LabelPolicyLogoRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceLogoRemoved dark",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyLogoDarkRemovedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), org.LabelPolicyLogoDarkRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceIconRemoved light",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyIconRemovedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), org.LabelPolicyIconRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceIconRemoved dark",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyIconDarkRemovedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), org.LabelPolicyIconDarkRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceFontAdded",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyFontAddedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/font.ttf"}`),
), org.LabelPolicyFontAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceFontAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, font_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/font.ttf",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceFontRemoved",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyFontRemovedEventType),
org.AggregateType,
[]byte(`{"storeKey": "/path/to/font.ttf"}`),
), org.LabelPolicyFontRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceFontRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, font_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "org.reduceAssetsRemoved",
args: args{
event: getEvent(testEvent(
repository.EventType(org.LabelPolicyAssetsRemovedEventType),
org.AggregateType,
nil,
), org.LabelPolicyAssetsRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceAssetsRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("org"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_logo_url, light_icon_url, dark_logo_url, dark_icon_url, font_url) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (state = $9)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
nil,
nil,
nil,
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceAdded",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyAddedEventType),
iam.AggregateType,
[]byte(`{"backgroundColor": "#141735", "fontColor": "#ffffff", "primaryColor": "#5282c1", "warnColor": "#ff3b5b"}`),
), iam.LabelPolicyAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO zitadel.projections.label_policies (creation_date, change_date, sequence, id, state, is_default, resource_owner, light_primary_color, light_background_color, light_warn_color, light_font_color, dark_primary_color, dark_background_color, dark_warn_color, dark_font_color, hide_login_name_suffix, should_error_popup, watermark_disabled) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
uint64(15),
"agg-id",
domain.LabelPolicyStatePreview,
true,
"ro-id",
"#5282c1",
"#141735",
"#ff3b5b",
"#ffffff",
"",
"",
"",
"",
false,
false,
false,
},
},
},
},
},
},
{
name: "iam.reduceChanged",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyChangedEventType),
iam.AggregateType,
[]byte(`{"backgroundColor": "#141735", "fontColor": "#ffffff", "primaryColor": "#5282c1", "warnColor": "#ff3b5b", "primaryColorDark": "#ffffff","backgroundColorDark": "#ffffff", "warnColorDark": "#ffffff", "fontColorDark": "#ffffff", "hideLoginNameSuffix": true, "errorMsgPopup": true, "disableWatermark": true}`),
), iam.LabelPolicyChangedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_primary_color, light_background_color, light_warn_color, light_font_color, dark_primary_color, dark_background_color, dark_warn_color, dark_font_color, hide_login_name_suffix, should_error_popup, watermark_disabled) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) WHERE (id = $14) AND (state = $15)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"#5282c1",
"#141735",
"#ff3b5b",
"#ffffff",
"#ffffff",
"#ffffff",
"#ffffff",
"#ffffff",
true,
true,
true,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceActivated",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyActivatedEventType),
iam.AggregateType,
nil,
), iam.LabelPolicyActivatedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceActivated,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.label_policies (change_date, sequence, state, creation_date, resource_owner, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) SELECT $1, $2, $3, creation_date, resource_owner, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url FROM zitadel.projections.label_policies AS copy_table WHERE copy_table.id = $4 AND copy_table.state = $5",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.LabelPolicyStateActive,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceLogoAdded light",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyLogoAddedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), iam.LabelPolicyLogoAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/logo.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceLogoAdded dark",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyLogoDarkAddedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), iam.LabelPolicyLogoDarkAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/logo.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceIconAdded light",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyIconAddedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), iam.LabelPolicyIconAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/icon.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceIconAdded dark",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyIconDarkAddedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), iam.LabelPolicyIconDarkAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/icon.png",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceLogoRemoved light",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyLogoRemovedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), iam.LabelPolicyLogoRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceLogoRemoved dark",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyLogoDarkRemovedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/logo.png"}`),
), iam.LabelPolicyLogoDarkRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceLogoRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_logo_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceIconRemoved light",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyIconRemovedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), iam.LabelPolicyIconRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceIconRemoved dark",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyIconDarkRemovedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/icon.png"}`),
), iam.LabelPolicyIconDarkRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceIconRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, dark_icon_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceFontAdded",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyFontAddedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/font.ttf"}`),
), iam.LabelPolicyFontAddedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceFontAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, font_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"/path/to/font.ttf",
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceFontRemoved",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyFontRemovedEventType),
iam.AggregateType,
[]byte(`{"storeKey": "/path/to/font.ttf"}`),
), iam.LabelPolicyFontRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceFontRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, font_url) = ($1, $2, $3) WHERE (id = $4) AND (state = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
{
name: "iam.reduceAssetsRemoved",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.LabelPolicyAssetsRemovedEventType),
iam.AggregateType,
nil,
), iam.LabelPolicyAssetsRemovedEventMapper),
},
reduce: (&LabelPolicyProjection{}).reduceAssetsRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
projection: LabelPolicyTable,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE zitadel.projections.label_policies SET (change_date, sequence, light_logo_url, light_icon_url, dark_logo_url, dark_icon_url, font_url) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8) AND (state = $9)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
nil,
nil,
nil,
nil,
nil,
"agg-id",
domain.LabelPolicyStatePreview,
},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
event := baseEvent(t)
got, err := tt.reduce(event)
if _, ok := err.(errors.InvalidArgument); !ok {
t.Errorf("no wrong event mapping: %v, got: %v", err, got)
}
event = tt.args.event(t)
got, err = tt.reduce(event)
assertReduce(t, got, err, tt.want)
})
}
}

View File

@ -42,6 +42,7 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
NewLockoutPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["lockout_policy"])) NewLockoutPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["lockout_policy"]))
NewPrivacyPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["privacy_policy"])) NewPrivacyPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["privacy_policy"]))
NewOrgIAMPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["org_iam_policy"])) NewOrgIAMPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["org_iam_policy"]))
NewLabelPolicyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["label_policy"]))
NewProjectGrantProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["project_grants"])) NewProjectGrantProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["project_grants"]))
NewProjectRoleProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["project_roles"])) NewProjectRoleProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["project_roles"]))
// owner.NewOrgOwnerProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["org_owners"])) // owner.NewOrgOwnerProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["org_owners"]))

View File

@ -8,6 +8,8 @@ import (
http_mw "github.com/caos/zitadel/internal/api/http/middleware" http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/query"
) )
const ( const (
@ -111,9 +113,9 @@ func (l *Login) renderPasswordlessRegistration(w http.ResponseWriter, r *http.Re
} }
translator := l.getTranslator(authReq) translator := l.getTranslator(authReq)
if authReq == nil { if authReq == nil {
policy, err := l.authRepo.GetLabelPolicy(r.Context(), orgID) policy, err := l.query.ActiveLabelPolicyByOrg(r.Context(), orgID)
logging.Log("LOGIN-afgr2").OnError(err).Warn("could not get label policy") logging.Log("HANDL-XjWKE").OnError(err).Error("unable to get active label policy")
data.LabelPolicy = policy data.LabelPolicy = labelPolicyToDomain(policy)
translator, err = l.renderer.NewTranslator() translator, err = l.renderer.NewTranslator()
if err == nil { if err == nil {
@ -125,6 +127,36 @@ func (l *Login) renderPasswordlessRegistration(w http.ResponseWriter, r *http.Re
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplPasswordlessRegistration], data, nil) l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplPasswordlessRegistration], data, nil)
} }
func labelPolicyToDomain(p *query.LabelPolicy) *domain.LabelPolicy {
return &domain.LabelPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: p.ID,
Sequence: p.Sequence,
ResourceOwner: p.ResourceOwner,
CreationDate: p.CreationDate,
ChangeDate: p.ChangeDate,
},
State: p.State,
Default: p.IsDefault,
PrimaryColor: p.Light.PrimaryColor,
BackgroundColor: p.Light.BackgroundColor,
WarnColor: p.Light.WarnColor,
FontColor: p.Light.FontColor,
LogoURL: p.Light.LogoURL,
IconURL: p.Light.IconURL,
PrimaryColorDark: p.Dark.PrimaryColor,
BackgroundColorDark: p.Dark.BackgroundColor,
WarnColorDark: p.Dark.WarnColor,
FontColorDark: p.Dark.FontColor,
LogoDarkURL: p.Dark.LogoURL,
IconDarkURL: p.Dark.IconURL,
Font: p.FontURL,
HideLoginNameSuffix: p.HideLoginNameSuffix,
ErrorMsgPopup: p.ShouldErrorPopup,
DisableWatermark: p.WatermarkDisabled,
}
}
func (l *Login) handlePasswordlessRegistrationCheck(w http.ResponseWriter, r *http.Request) { func (l *Login) handlePasswordlessRegistrationCheck(w http.ResponseWriter, r *http.Request) {
formData := new(passwordlessRegistrationFormData) formData := new(passwordlessRegistrationFormData)
authReq, err := l.getAuthRequestAndParseData(r, formData) authReq, err := l.getAuthRequestAndParseData(r, formData)

View File

@ -0,0 +1,28 @@
CREATE TABLE zitadel.projections.label_policies (
id STRING NOT NULL,
creation_date TIMESTAMPTZ NOT NULL,
change_date TIMESTAMPTZ NOT NULL,
sequence INT8 NOT NULL,
state INT2 NOT NULL,
resource_owner TEXT NOT NULL,
is_default BOOLEAN NOT NULL DEFAULT false,
hide_login_name_suffix BOOLEAN NOT NULL DEFAULT false,
font_url STRING,
watermark_disabled BOOLEAN NOT NULL DEFAULT false,
should_error_popup BOOLEAN NOT NULL DEFAULT false,
light_primary_color STRING,
light_warn_color STRING,
light_background_color STRING,
light_font_color STRING,
light_logo_url STRING,
light_icon_url STRING,
dark_primary_color STRING,
dark_warn_color STRING,
dark_background_color STRING,
dark_font_color STRING,
dark_logo_url STRING,
dark_icon_url STRING,
PRIMARY KEY (id, state)
);