feat: cascade changes and removes (#1239)

* chore(site): dependabot deps (#1148)

* chore(deps): bump highlight.js from 10.4.1 to 10.5.0 in /site (#1143)

Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 10.4.1 to 10.5.0.
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/master/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/10.4.1...10.5.0)

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

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

* chore(deps-dev): bump @babel/plugin-transform-runtime in /site (#1144)

Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.12.1 to 7.12.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.10/packages/babel-plugin-transform-runtime)

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

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

* chore(deps): bump sirv from 1.0.7 to 1.0.10 in /site (#1145)

Bumps [sirv](https://github.com/lukeed/sirv) from 1.0.7 to 1.0.10.
- [Release notes](https://github.com/lukeed/sirv/releases)
- [Commits](https://github.com/lukeed/sirv/compare/v1.0.7...v1.0.10)

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

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

* chore(deps-dev): bump rollup from 2.34.0 to 2.35.1 in /site (#1142)

Bumps [rollup](https://github.com/rollup/rollup) from 2.34.0 to 2.35.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.34.0...v2.35.1)

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

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

* chore(deps-dev): bump @rollup/plugin-node-resolve in /site (#1141)

Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins) from 10.0.0 to 11.0.1.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Commits](https://github.com/rollup/plugins/compare/node-resolve-v10.0.0...commonjs-v11.0.1)

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

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

* chore(deps): bump marked from 1.2.5 to 1.2.7 in /site (#1140)

Bumps [marked](https://github.com/markedjs/marked) from 1.2.5 to 1.2.7.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/release.config.js)
- [Commits](https://github.com/markedjs/marked/compare/v1.2.5...v1.2.7)

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

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

* chore(deps-dev): bump @babel/core from 7.12.9 to 7.12.10 in /site (#1139)

Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.9 to 7.12.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.10/packages/babel-core)

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

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

* chore(deps-dev): bump rollup-plugin-svelte from 6.1.1 to 7.0.0 in /site (#1138)

Bumps [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) from 6.1.1 to 7.0.0.
- [Release notes](https://github.com/sveltejs/rollup-plugin-svelte/releases)
- [Changelog](https://github.com/sveltejs/rollup-plugin-svelte/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/rollup-plugin-svelte/compare/v6.1.1...v7.0.0)

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

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

* chore(deps-dev): bump @babel/preset-env from 7.12.1 to 7.12.11 in /site (#1137)

Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.12.1 to 7.12.11.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.11/packages/babel-preset-env)

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

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

* downgrade svelte plugin

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

* chore(console): dependabot deps (#1147)

* chore(deps-dev): bump @types/node from 14.14.13 to 14.14.19 in /console (#1146)

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.13 to 14.14.19.
- [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: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

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

Bumps [ts-protoc-gen](https://github.com/improbable-eng/ts-protoc-gen) from 0.13.0 to 0.14.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.13.0...0.14.0)

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

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

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

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.0.4 to 11.0.5.
- [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.0.5/packages/language-service)

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

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

* chore(deps-dev): bump @angular/cli from 11.0.4 to 11.0.5 in /console (#1127)

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.0.4 to 11.0.5.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.0.4...v11.0.5)

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

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

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#1126)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1100.4 to 0.1100.5.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

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

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

* audit

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

* feat: e-mail templates (#1158)

* View definition added

* Get templates and texts from the database.

* Fill in texts in templates

* Fill in texts in templates

* Client API added

* Weekly backup

* Weekly backup

* Daily backup

* Weekly backup

* Tests added

* Corrections from merge branch

* Fixes from pull request review

* chore(console): dependencies (#1189)

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

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.0.5 to 11.0.9.
- [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.0.9/packages/language-service)

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

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

* chore(deps): bump google-proto-files from 2.3.0 to 2.4.0 in /console (#1186)

Bumps [google-proto-files](https://github.com/googleapis/nodejs-proto-files) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/googleapis/nodejs-proto-files/releases)
- [Changelog](https://github.com/googleapis/nodejs-proto-files/blob/master/CHANGELOG.md)
- [Commits](https://github.com/googleapis/nodejs-proto-files/compare/v2.3.0...v2.4.0)

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

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

* chore(deps-dev): bump @types/node from 14.14.19 to 14.14.21 in /console (#1185)

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.19 to 14.14.21.
- [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: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @angular/cli from 11.0.5 to 11.0.7 in /console (#1184)

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.0.5 to 11.0.7.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.0.5...v11.0.7)

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

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

* chore(deps-dev): bump karma from 5.2.3 to 6.0.0 in /console (#1183)

Bumps [karma](https://github.com/karma-runner/karma) from 5.2.3 to 6.0.0.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v5.2.3...v6.0.0)

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

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

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#1182)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1100.5 to 0.1100.7.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

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

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

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

* feat: change login to command side

* feat: change login to command side

* fix: fix push on user

* fix(console): trigger unauthenticated dialog only once (#1170)

* fix: trigger dialog once

* remove log

* typed trigger

* chore(console): dependencies (#1205)

* chore(deps-dev): bump stylelint from 13.8.0 to 13.9.0 in /console (#1204)

Bumps [stylelint](https://github.com/stylelint/stylelint) from 13.8.0 to 13.9.0.
- [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.8.0...13.9.0)

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

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

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

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.0.9 to 11.1.0.
- [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.1.0/packages/language-service)

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

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

* chore(deps-dev): bump karma from 6.0.0 to 6.0.1 in /console (#1202)

Bumps [karma](https://github.com/karma-runner/karma) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.0.0...v6.0.1)

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

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

* chore(deps-dev): bump @angular/cli from 11.0.7 to 11.1.1 in /console (#1201)

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.0.7 to 11.1.1.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.0.7...v11.1.1)

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

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

* chore(deps-dev): bump @types/jasmine from 3.6.2 to 3.6.3 in /console (#1200)

Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.6.2 to 3.6.3.
- [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>
Co-authored-by: Max Peintner <max@caos.ch>

* chore(deps-dev): bump @types/node from 14.14.21 to 14.14.22 in /console (#1199)

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.21 to 14.14.22.
- [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: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#1198)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1100.7 to 0.1101.1.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

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

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

* chore(deps): bump angularx-qrcode from 10.0.11 to 11.0.0 in /console (#1197)

Bumps [angularx-qrcode](https://github.com/cordobo/angularx-qrcode) from 10.0.11 to 11.0.0.
- [Release notes](https://github.com/cordobo/angularx-qrcode/releases)
- [Commits](https://github.com/cordobo/angularx-qrcode/compare/10.0.11...11.0.0)

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

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

* fix pack lock

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

* fix: handle sequence correctly in subscription (#1209)

* feat: user command side

* feat: sign out

* feat: command side login

* feat: command side login

* feat: fix register user

* feat: fix register user

* feat: fix web auth n events

* feat: add machine keys

* feat: send codes

* feat: move authrequest to domain

* feat: move authrequest to domain

* feat: webauthn working

* fix: correct master after merges again (#1230)

* chore(docs): correct `iss` claim of jwt profile (#1229)

* core(docs): correct `iss` claim of jwt profile

* fix: correct master after merges again (#1230)

* feat(login): new palette based styles (#1149)

* chore(deps-dev): bump rollup from 2.33.2 to 2.34.0 in /site (#1040)

Bumps [rollup](https://github.com/rollup/rollup) from 2.33.2 to 2.34.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.33.2...v2.34.0)

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

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

* chore(deps): bump svelte-i18n from 3.2.5 to 3.3.0 in /site (#1039)

Bumps [svelte-i18n](https://github.com/kaisermann/svelte-i18n) from 3.2.5 to 3.3.0.
- [Release notes](https://github.com/kaisermann/svelte-i18n/releases)
- [Changelog](https://github.com/kaisermann/svelte-i18n/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kaisermann/svelte-i18n/compare/v3.2.5...v3.3.0)

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

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

* chore(deps-dev): bump @rollup/plugin-url from 5.0.1 to 6.0.0 in /site (#1038)

Bumps [@rollup/plugin-url](https://github.com/rollup/plugins) from 5.0.1 to 6.0.0.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Commits](https://github.com/rollup/plugins/compare/url-v5.0.1...url-v6.0.0)

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

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

* chore(deps-dev): bump svelte from 3.29.7 to 3.30.1 in /site (#1037)

Bumps [svelte](https://github.com/sveltejs/svelte) from 3.29.7 to 3.30.1.
- [Release notes](https://github.com/sveltejs/svelte/releases)
- [Changelog](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/svelte/compare/v3.29.7...v3.30.1)

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

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

* chore(deps): bump marked from 1.2.4 to 1.2.5 in /site (#1036)

Bumps [marked](https://github.com/markedjs/marked) from 1.2.4 to 1.2.5.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/release.config.js)
- [Commits](https://github.com/markedjs/marked/compare/v1.2.4...v1.2.5)

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

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

* chore(deps-dev): bump @babel/core from 7.12.3 to 7.12.9 in /site (#1035)

Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.3 to 7.12.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.9/packages/babel-core)

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

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

* chore(deps-dev): bump rollup-plugin-svelte from 6.1.1 to 7.0.0 in /site (#1034)

Bumps [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) from 6.1.1 to 7.0.0.
- [Release notes](https://github.com/sveltejs/rollup-plugin-svelte/releases)
- [Changelog](https://github.com/sveltejs/rollup-plugin-svelte/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/rollup-plugin-svelte/compare/v6.1.1...v7.0.0)

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

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

* chore(deps-dev): bump @rollup/plugin-commonjs in /site (#1033)

Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins) from 15.1.0 to 17.0.0.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Commits](https://github.com/rollup/plugins/compare/commonjs-v15.1.0...commonjs-v17.0.0)

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

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

* chore(deps-dev): bump @rollup/plugin-node-resolve in /site (#1032)

Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins) from 10.0.0 to 11.0.0.
- [Release notes](https://github.com/rollup/plugins/releases)
- [Commits](https://github.com/rollup/plugins/compare/node-resolve-v10.0.0...commonjs-v11.0.0)

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

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

* chore(deps-dev): bump @babel/preset-env from 7.12.1 to 7.12.7 in /site (#1031)

Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.12.1 to 7.12.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.7/packages/babel-preset-env)

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

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

* go

* bundle files, lgn-color, legacy theme

* remove old references

* light dark context, button styles, zitadel brand

* button theme, edit templates

* typography theme mixins

* input styles, container, extend light dark palette

* footer, palette, container

* container, label, assets, header

* action container, input, typography label, adapt button theme

* a and footer styles, adapt palette

* user log profile, resourcetempurl

* postinstall againnn

* wrochage

* rm local grpc

* button elevation, helper for components

* radio

* radio button mixins, bundle

* qr code styles, secret clipboard, icon pack

* stroked buttons, icon buttons, header action, typography

* fix password policy styles

* account selection

* account selection, lgn avatar

* mocks

* template fixes, animations scss

* checkbox, register temp

* checkbox appr

* fix checkbox, remove input interference

* select theme

* avatar script, user selection, password policy validation fix

* fix formfield state for register and change pwd

* footer, main style, qr code fix, mfa type fix, account sel, checkbox

* fotter tos, user select

* reverse buttons for intial submit action

* theme script, themed error messages, header img source

* content wrapper, i18n, mobile

* emptyline

* idp mixins, fix unstyled html

* register container

* register layout, list themes, policy theme, register org

* massive asset cleanup

* fix source path, add missing icon, fix complexity refs, prefix

* remove material icons, unused assets, fix icon font

* move icon pack

* avatar, contrast theme, error fix

* zitadel css map

* revert go mod

* fix mfa verify actions

* add idp styles

* fix google colors, idp styles

* fix: bugs

* fix register options, google

* fix script, mobile layout

* precompile font selection

* go mod tidy

* assets and cleanup

* input suffix, fix alignment, actions, add progress bar themes

* progress bar mixins, layout fixes

* remove test from loginname

* cleanup comments, scripts

* clear comments

* fix external back button

* fix mfa alignment

* fix actions layout, on dom change listener for suffix

* free tier change, success label

* fix: button font line-height

* remove tabindex

* remove comment

* remove comment

* Update internal/ui/login/handler/password_handler.go

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Maximilian Peintner <csaq7175@uibk.ac.at>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* feat: external users

* chore(console): dependencies (#1233)

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#1214)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1101.1 to 0.1101.2.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

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

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

* chore(deps-dev): bump karma from 6.0.1 to 6.0.3 in /console (#1215)

Bumps [karma](https://github.com/karma-runner/karma) from 6.0.1 to 6.0.3.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.0.1...v6.0.3)

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

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

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

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.1.0 to 11.1.1.
- [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.1.1/packages/language-service)

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

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

* chore(deps-dev): bump @angular/cli from 11.1.1 to 11.1.2 in /console (#1217)

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.1.1 to 11.1.2.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.1.1...v11.1.2)

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

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

* lock

* site deps

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

* feat: external users login

* feat: notify users

* fix: tests

* feat: cascade remove user grants on project remove

* feat: cascade remove user grants on user remove

* feat: cascade remove roles

* feat: verified domain

* feat: cascade remove on idp config remove

* feat: cascade remove on system idp config remove

* fix: get email texts with default language (#1238)

* fix: login policy

* fix: login policy

* fix: cascade delete on remove idp from default policy

* fix(login): mail verification (#1237)

* fix: mail verification

* not block, stroked

* fix: issues of new login ui (#1241)

* fix: i18n of register

* fix: autofocus

* feat(operator): zitadel and database operator (#1208)

* feat(operator): add base for zitadel operator

* fix(operator): changed pipeline to release operator

* fix(operator): fmt with only one parameter

* fix(operator): corrected workflow job name

* fix(zitadelctl): added restore and backuplist command

* fix(zitadelctl): scale for restore

* chore(container): use scratch for deploy container

* fix(zitadelctl): limit image to scratch

* fix(migration): added migration scripts for newer version

* fix(operator): changed handling of kubeconfig in operator logic

* fix(operator): changed handling of secrets in operator logic

* fix(operator): use new version of zitadel

* fix(operator): added path for migrations

* fix(operator): delete doublets of migration scripts

* fix(operator): delete subpaths and integrate logic into init container

* fix(operator): corrected path in dockerfile for local migrations

* fix(operator): added migrations for cockroachdb-secure

* fix(operator): delete logic for ambassador module

* fix(operator): added read and write secret commands

* fix(operator): correct and align operator pipeline with zitadel pipeline

* fix(operator): correct yaml error in operator pipeline

* fix(operator): correct action name in operator pipeline

* fix(operator): correct case-sensitive filename in operator pipeline

* fix(operator): upload artifacts from buildx output

* fix(operator): corrected attribute spelling error

* fix(operator): combined jobs for operator binary and image

* fix(operator): added missing comma in operator pipeline

* fix(operator): added codecov for operator image

* fix(operator): added codecov for operator image

* fix(testing): code changes for testing and several unit-tests (#1009)

* fix(operator): usage of interface of kubernetes client for testing and several unit-tests

* fix(operator): several unit-tests

* fix(operator): several unit-tests

* fix(operator): changed order for the operator logic

* fix(operator): added version of zitadelctl from semantic release

* fix(operator): corrected function call with version of zitadelctl

* fix(operator): corrected function call with version of zitadelctl

* fix(operator): add check output to operator release pipeline

* fix(operator): set --short length everywhere to 12

* fix(operator): zitadel setup in job instead of exec with several unit tests

* fix(operator): fixes to combine newest zitadel and testing branch

* fix(operator): corrected path in Dockerfile

* fix(operator): fixed unit-test that was ignored during changes

* fix(operator): fixed unit-test that was ignored during changes

* fix(operator): corrected Dockerfile to correctly use env variable

* fix(operator): quickfix takeoff deployment

* fix(operator): corrected the clusterrolename in the applied artifacts

* fix: update secure migrations

* fix(operator): migrations (#1057)

* fix(operator): copied migrations from orbos repository

* fix(operator): newest migrations

* chore: use cockroach-secure

* fix: rename migration

* fix: remove insecure cockroach migrations

Co-authored-by: Stefan Benz <stefan@caos.ch>

* fix: finalize labels

* fix(operator): cli logging concurrent and fixe deployment of operator during restore

* fix: finalize labels and cli commands

* fix: restore

* chore: cockroachdb is always secure

* chore: use orbos consistent-labels latest commit

* test: make tests compatible with new labels

* fix: default to sa token for start command

* fix: use cockroachdb v12.02

* fix: don't delete flyway user

* test: fix migration test

* fix: use correct table qualifiers

* fix: don't alter sequence ownership

* fix: upgrade flyway

* fix: change ownership of all dbs and tables to admin user

* fix: change defaultdb user

* fix: treat clientid status codes >= 400 as errors

* fix: reconcile specified ZITADEL version, not binary version

* fix: add ca-certs

* fix: use latest orbos code

* fix: use orbos with fixed race condition

* fix: use latest ORBOS code

* fix: use latest ORBOS code

* fix: make migration and scaling around restoring work

* fix(operator): move zitadel operator

* chore(migrations): include owner change migration

* feat(db): add code base for database operator

* fix(db): change used image registry for database operator

* fix(db): generated mock

* fix(db): add accidentally ignored file

* fix(db): add cockroachdb backup image to pipeline

* fix(db): correct pipeline and image versions

* fix(db): correct version of used orbos

* fix(db): correct database import

* fix(db): go mod tidy

* fix(db): use new version for orbos

* fix(migrations): include migrations into zitadelctl binary (#1211)

* fix(db): use statik to integrate migrations into binary

* fix(migrations): corrections unit tests and pipeline for integrated migrations into zitadelctl binary

* fix(migrations): correction in dockerfile for pipeline build

* fix(migrations): correction in dockerfile for pipeline build

* fix(migrations):  dockerfile changes for cache optimization

* fix(database): correct used part-of label in database operator

* fix(database): correct used selectable label in zitadel operator

* fix(operator): correct lables for user secrets in zitadel operator

* fix(operator): correct lables for service test in zitadel operator

* fix: don't enable database features for user operations (#1227)

* fix: don't enable database features for user operations

* fix: omit database feature for connection info adapter

* fix: use latest orbos version

* fix: update ORBOS (#1240)

Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: Elio Bischof <eliobischof@gmail.com>

* Merge branch 'new-eventstore' into cascades

# Conflicts:
#	internal/auth/repository/auth_request.go
#	internal/auth/repository/eventsourcing/eventstore/auth_request.go
#	internal/management/repository/eventsourcing/eventstore/user_grant.go
#	internal/management/repository/user_grant.go
#	internal/ui/login/handler/external_login_handler.go
#	internal/ui/login/handler/external_register_handler.go
#	internal/ui/login/handler/init_password_handler.go
#	internal/ui/login/handler/register_handler.go
#	internal/user/repository/view/model/notify_user.go
#	internal/v2/command/org_policy_login.go
#	internal/v2/command/project.go
#	internal/v2/command/user.go
#	internal/v2/command/user_human.go
#	internal/v2/command/user_human_externalidp.go
#	internal/v2/command/user_human_init.go
#	internal/v2/command/user_human_password.go
#	internal/v2/command/user_human_webauthn.go
#	internal/v2/domain/next_step.go
#	internal/v2/domain/policy_login.go
#	internal/v2/domain/request.go

* Merge branch 'new-eventstore' into cascades

# Conflicts:
#	internal/auth/repository/auth_request.go
#	internal/auth/repository/eventsourcing/eventstore/auth_request.go
#	internal/management/repository/eventsourcing/eventstore/user_grant.go
#	internal/management/repository/user_grant.go
#	internal/ui/login/handler/external_login_handler.go
#	internal/ui/login/handler/external_register_handler.go
#	internal/ui/login/handler/init_password_handler.go
#	internal/ui/login/handler/register_handler.go
#	internal/user/repository/view/model/notify_user.go
#	internal/v2/command/org_policy_login.go
#	internal/v2/command/project.go
#	internal/v2/command/user.go
#	internal/v2/command/user_human.go
#	internal/v2/command/user_human_externalidp.go
#	internal/v2/command/user_human_init.go
#	internal/v2/command/user_human_password.go
#	internal/v2/command/user_human_webauthn.go
#	internal/v2/domain/next_step.go
#	internal/v2/domain/policy_login.go
#	internal/v2/domain/request.go

* chore: add local migrate_local.go again (#1261)

* fix: logging on cascade removes

* fix: migrations

* fix: tests

* fix: tests

* chore: pass params in migrate_local.go

* migrations

* fix query

* fix tests

* fix tests

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Waeger <49439088+michaelulrichwaeger@users.noreply.github.com>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Maximilian Peintner <csaq7175@uibk.ac.at>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: Elio Bischof <eliobischof@gmail.com>
This commit is contained in:
Fabi 2021-02-09 10:14:40 +01:00 committed by GitHub
parent db11cf1da3
commit b0bcc13a92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 1381 additions and 426 deletions

12
go.sum
View File

@ -155,6 +155,7 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
@ -308,6 +309,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -442,6 +444,7 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -522,6 +525,7 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
@ -565,6 +569,7 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@ -574,6 +579,7 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4=
github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
@ -603,6 +609,7 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@ -615,6 +622,7 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
@ -759,6 +767,7 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU=
github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@ -907,6 +916,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1108,12 +1118,14 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201030143252-cf7a54d06671/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201103235415-b653051172e4 h1:Qe0EMgvVYb6tmJhJHljCj3gS96hvSTkGNaIzp/ivq10=
golang.org/x/tools v0.0.0-20201103235415-b653051172e4/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=

View File

@ -2,6 +2,7 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/user/repository/view/model"
"strings"
caos_errs "github.com/caos/zitadel/internal/errors"
@ -111,6 +112,39 @@ func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID stri
return es_sdk.PushAggregates(ctx, repo.Eventstore.PushAggregates, nil, aggregates...)
}
func (repo *IAMRepository) IDPProvidersByIDPConfigID(ctx context.Context, idpConfigID string) ([]*iam_model.IDPProviderView, error) {
providers, err := repo.View.IDPProvidersByIdpConfigID(idpConfigID)
if err != nil {
return nil, err
}
return iam_es_model.IDPProviderViewsToModel(providers), nil
}
func (repo *IAMRepository) ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error) {
externalIDPs, err := repo.View.ExternalIDPsByIDPConfigID(idpConfigID)
if err != nil {
return nil, err
}
return model.ExternalIDPViewsToModel(externalIDPs), nil
}
func (repo *IAMRepository) ExternalIDPsByIDPConfigIDFromDefaultPolicy(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error) {
policies, err := repo.View.AllDefaultLoginPolicies()
if err != nil {
return nil, err
}
resourceOwners := make([]string, len(policies))
for i, policy := range policies {
resourceOwners[i] = policy.AggregateID
}
externalIDPs, err := repo.View.ExternalIDPsByIDPConfigIDAndResourceOwners(idpConfigID, resourceOwners)
if err != nil {
return nil, err
}
return model.ExternalIDPViewsToModel(externalIDPs), nil
}
func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_model.IDPConfigSearchRequest) (*iam_model.IDPConfigSearchResponse, error) {
request.EnsureLimit(repo.SearchLimit)
sequence, err := repo.View.GetLatestIDPConfigSequence()

View File

@ -1,14 +1,19 @@
package handler
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -44,7 +49,7 @@ func (p *LoginPolicy) ViewModel() string {
}
func (p *LoginPolicy) AggregateTypes() []models.AggregateType {
return []models.AggregateType{model.IAMAggregate}
return []models.AggregateType{iam_es_model.IAMAggregate, model.OrgAggregate}
}
func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) {
@ -67,7 +72,7 @@ func (p *LoginPolicy) CurrentSequence() (uint64, error) {
func (p *LoginPolicy) Reduce(event *models.Event) (err error) {
switch event.AggregateType {
case model.IAMAggregate:
case model.OrgAggregate, iam_es_model.IAMAggregate:
err = p.processLoginPolicy(event)
}
return err
@ -76,8 +81,31 @@ func (p *LoginPolicy) Reduce(event *models.Event) (err error) {
func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
policy := new(iam_model.LoginPolicyView)
switch event.Type {
case model.LoginPolicyAdded:
case model.OrgAdded:
policy, err = p.getDefaultLoginPolicy()
if err != nil {
return err
}
policy.AggregateID = event.AggregateID
policy.Default = true
case iam_es_model.LoginPolicyAdded, model.LoginPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.LoginPolicyChanged,
iam_es_model.LoginPolicySecondFactorAdded,
iam_es_model.LoginPolicySecondFactorRemoved,
iam_es_model.LoginPolicyMultiFactorAdded,
iam_es_model.LoginPolicyMultiFactorRemoved:
policies, err := p.view.AllDefaultLoginPolicies()
if err != nil {
return err
}
for _, policy := range policies {
err = policy.AppendEvent(event)
if err != nil {
return err
}
}
return p.view.PutLoginPolicies(policies, event)
case model.LoginPolicyChanged,
model.LoginPolicySecondFactorAdded,
model.LoginPolicySecondFactorRemoved,
@ -88,6 +116,13 @@ func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
return err
}
err = policy.AppendEvent(event)
case model.LoginPolicyRemoved:
policy, err = p.getDefaultLoginPolicy()
if err != nil {
return err
}
policy.AggregateID = event.AggregateID
policy.Default = true
default:
return p.view.ProcessedLoginPolicySequence(event)
}
@ -105,3 +140,33 @@ func (p *LoginPolicy) OnError(event *models.Event, err error) error {
func (p *LoginPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateLoginPolicySpoolerRunTimestamp)
}
func (p *LoginPolicy) getDefaultLoginPolicy() (*iam_model.LoginPolicyView, error) {
policy, policyErr := p.view.LoginPolicyByAggregateID(domain.IAMID)
if policyErr != nil && !caos_errs.IsNotFound(policyErr) {
return nil, policyErr
}
if policy == nil {
policy = &iam_model.LoginPolicyView{}
}
events, err := p.getIAMEvents(policy.Sequence)
if err != nil {
return policy, policyErr
}
policyCopy := *policy
for _, event := range events {
if err := policyCopy.AppendEvent(event); err != nil {
return policy, nil
}
}
return &policyCopy, nil
}
func (p *LoginPolicy) getIAMEvents(sequence uint64) ([]*models.Event, error) {
query, err := eventsourcing.IAMByIDQuery(domain.IAMID, sequence)
if err != nil {
return nil, err
}
return p.es.FilterEvents(context.Background(), query)
}

View File

@ -25,6 +25,10 @@ func (v *View) ExternalIDPsByIDPConfigID(idpConfigID string) ([]*model.ExternalI
return view.ExternalIDPsByIDPConfigID(v.Db, externalIDPTable, idpConfigID)
}
func (v *View) ExternalIDPsByIDPConfigIDAndResourceOwners(idpConfigID string, resourceOwners []string) ([]*model.ExternalIDPView, error) {
return view.ExternalIDPsByIDPConfigIDAndResourceOwners(v.Db, externalIDPTable, idpConfigID, resourceOwners)
}
func (v *View) ExternalIDPsByUserID(userID string) ([]*model.ExternalIDPView, error) {
return view.ExternalIDPsByUserID(v.Db, externalIDPTable, userID)
}

View File

@ -12,6 +12,10 @@ const (
loginPolicyTable = "adminapi.login_policies"
)
func (v *View) AllDefaultLoginPolicies() ([]*model.LoginPolicyView, error) {
return view.GetDefaultLoginPolicies(v.Db, loginPolicyTable)
}
func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyView, error) {
return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID)
}
@ -24,6 +28,14 @@ func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event
return v.ProcessedLoginPolicySequence(event)
}
func (v *View) PutLoginPolicies(policies []*model.LoginPolicyView, event *models.Event) error {
err := view.PutLoginPolicies(v.Db, loginPolicyTable, policies...)
if err != nil {
return err
}
return v.ProcessedLoginPolicySequence(event)
}
func (v *View) DeleteLoginPolicy(aggregateID string, event *models.Event) error {
err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {

View File

@ -2,6 +2,7 @@ package repository
import (
"context"
usr_model "github.com/caos/zitadel/internal/user/model"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
@ -18,6 +19,10 @@ type IAMRepository interface {
SearchDefaultSecondFactors(ctx context.Context) (*iam_model.SecondFactorsSearchResponse, error)
SearchDefaultMultiFactors(ctx context.Context) (*iam_model.MultiFactorsSearchResponse, error)
IDPProvidersByIDPConfigID(ctx context.Context, idpConfigID string) ([]*iam_model.IDPProviderView, error)
ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error)
ExternalIDPsByIDPConfigIDFromDefaultPolicy(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error)
GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)

View File

@ -42,7 +42,15 @@ func (s *Server) ReactivateIdpConfig(ctx context.Context, id *admin.IdpID) (*emp
}
func (s *Server) RemoveIdpConfig(ctx context.Context, id *admin.IdpID) (*empty.Empty, error) {
err := s.command.RemoveDefaultIDPConfig(ctx, id.Id)
idpProviders, err := s.iam.IDPProvidersByIDPConfigID(ctx, id.Id)
if err != nil {
return &empty.Empty{}, err
}
externalIDPs, err := s.iam.ExternalIDPsByIDPConfigID(ctx, id.Id)
if err != nil {
return &empty.Empty{}, err
}
err = s.command.RemoveDefaultIDPConfig(ctx, id.Id, idpProviderViewsToDomain(idpProviders), externalIDPViewsToDomain(externalIDPs)...)
return &empty.Empty{}, err
}

View File

@ -2,6 +2,7 @@ package admin
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/pkg/grpc/admin"
@ -257,3 +258,26 @@ func idpConfigStylingTypeToDomain(stylingType admin.IdpStylingType) domain.IDPCo
return domain.IDPConfigStylingTypeUnspecified
}
}
func idpConfigTypeToDomain(idpType iam_model.IDPProviderType) domain.IdentityProviderType {
switch idpType {
case iam_model.IDPProviderTypeOrg:
return domain.IdentityProviderTypeOrg
default:
return domain.IdentityProviderTypeSystem
}
}
func idpProviderViewsToDomain(idps []*iam_model.IDPProviderView) []*domain.IDPProvider {
idpProvider := make([]*domain.IDPProvider, len(idps))
for i, idp := range idps {
idpProvider[i] = &domain.IDPProvider{
ObjectRoot: models.ObjectRoot{
AggregateID: idp.AggregateID,
},
IDPConfigID: idp.IDPConfigID,
Type: idpConfigTypeToDomain(idp.IDPProviderType),
}
}
return idpProvider
}

View File

@ -39,7 +39,11 @@ func (s *Server) AddIdpProviderToDefaultLoginPolicy(ctx context.Context, provide
}
func (s *Server) RemoveIdpProviderFromDefaultLoginPolicy(ctx context.Context, provider *admin.IdpProviderID) (*empty.Empty, error) {
err := s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, idpProviderToDomain(provider))
externalIDPs, err := s.iam.ExternalIDPsByIDPConfigIDFromDefaultPolicy(ctx, provider.IdpConfigId)
if err != nil {
return &empty.Empty{}, err
}
err = s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, idpProviderToDomain(provider), externalIDPViewsToDomain(externalIDPs)...)
return &empty.Empty{}, err
}

View File

@ -2,6 +2,7 @@ package admin
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/pkg/grpc/admin"
@ -194,3 +195,19 @@ func humanFromModel(user *usr_model.Human) *admin.HumanResponse {
}
return human
}
func externalIDPViewsToDomain(idps []*usr_model.ExternalIDPView) []*domain.ExternalIDP {
externalIDPs := make([]*domain.ExternalIDP, len(idps))
for i, idp := range idps {
externalIDPs[i] = &domain.ExternalIDP{
ObjectRoot: models.ObjectRoot{
AggregateID: idp.UserID,
ResourceOwner: idp.ResourceOwner,
},
IDPConfigID: idp.IDPConfigID,
ExternalUserID: idp.ExternalUserID,
DisplayName: idp.UserDisplayName,
}
}
return externalIDPs
}

View File

@ -44,7 +44,15 @@ func (s *Server) ReactivateIdpConfig(ctx context.Context, id *management.IdpID)
}
func (s *Server) RemoveIdpConfig(ctx context.Context, id *management.IdpID) (*empty.Empty, error) {
err := s.command.RemoveIDPConfig(ctx, id.Id, authz.GetCtxData(ctx).OrgID)
externalIdps, err := s.user.ExternalIDPsByIDPConfigIDAndResourceOwner(ctx, id.Id, authz.GetCtxData(ctx).OrgID)
if err != nil {
return &empty.Empty{}, err
}
providers, err := s.org.GetIDPProvidersByIDPConfigID(ctx, authz.GetCtxData(ctx).OrgID, id.Id)
if err != nil {
return &empty.Empty{}, err
}
err = s.command.RemoveIDPConfig(ctx, id.Id, authz.GetCtxData(ctx).OrgID, len(providers) > 0, externalIDPViewsToDomain(externalIdps)...)
return &empty.Empty{}, err
}

View File

@ -2,6 +2,7 @@ package management
import (
"context"
"github.com/caos/zitadel/internal/user/model"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
@ -328,3 +329,19 @@ func idpProviderTypeStringToModel(providerType string) (iam_model.IDPProviderTyp
return 0, caos_errors.ThrowPreconditionFailed(nil, "MGMT-6is9f", "Errors.Org.IDP.InvalidSearchQuery")
}
}
func externalIDPViewsToDomain(idps []*model.ExternalIDPView) []*domain.ExternalIDP {
externalIDPs := make([]*domain.ExternalIDP, len(idps))
for i, idp := range idps {
externalIDPs[i] = &domain.ExternalIDP{
ObjectRoot: models.ObjectRoot{
AggregateID: idp.UserID,
ResourceOwner: idp.ResourceOwner,
},
IDPConfigID: idp.IDPConfigID,
ExternalUserID: idp.ExternalUserID,
DisplayName: idp.UserDisplayName,
}
}
return externalIDPs
}

View File

@ -63,7 +63,11 @@ func (s *Server) AddIdpProviderToLoginPolicy(ctx context.Context, provider *mana
}
func (s *Server) RemoveIdpProviderFromLoginPolicy(ctx context.Context, provider *management.IdpProviderID) (*empty.Empty, error) {
err := s.command.RemoveIDPProviderFromLoginPolicy(ctx, idpProviderIDToDomain(ctx, provider))
externalIDPs, err := s.user.ExternalIDPsByIDPConfigIDAndResourceOwner(ctx, provider.IdpConfigId, authz.GetCtxData(ctx).OrgID)
if err != nil {
return &empty.Empty{}, err
}
err = s.command.RemoveIDPProviderFromLoginPolicy(ctx, idpProviderIDToDomain(ctx, provider), externalIDPViewsToDomain(externalIDPs)...)
return &empty.Empty{}, err
}

View File

@ -101,7 +101,15 @@ func (s *Server) ChangeProjectRole(ctx context.Context, in *management.ProjectRo
}
func (s *Server) RemoveProjectRole(ctx context.Context, in *management.ProjectRoleRemove) (*empty.Empty, error) {
err := s.command.RemoveProjectRole(ctx, in.Id, in.Key, authz.GetCtxData(ctx).OrgID)
userGrants, err := s.usergrant.UserGrantsByProjectIDAndRoleKey(ctx, in.Id, in.Key)
if err != nil {
return &empty.Empty{}, err
}
projectGrants, err := s.project.ProjectGrantsByProjectIDAndRoleKey(ctx, in.Id, in.Key)
if err != nil {
return &empty.Empty{}, err
}
err = s.command.RemoveProjectRole(ctx, in.Id, in.Key, authz.GetCtxData(ctx).OrgID, projectGrantsToIDs(projectGrants), userGrantsToIDs(userGrants)...)
return &empty.Empty{}, err
}

View File

@ -36,7 +36,11 @@ func (s *Server) CreateProjectGrant(ctx context.Context, in *management.ProjectG
return projectGrantFromDomain(grant), nil
}
func (s *Server) UpdateProjectGrant(ctx context.Context, in *management.ProjectGrantUpdate) (*management.ProjectGrant, error) {
grant, err := s.command.ChangeProjectGrant(ctx, projectGrantUpdateToDomain(in), authz.GetCtxData(ctx).OrgID)
userGrants, err := s.usergrant.UserGrantsByProjectAndGrantID(ctx, in.ProjectId, in.Id)
if err != nil {
return nil, err
}
grant, err := s.command.ChangeProjectGrant(ctx, projectGrantUpdateToDomain(in), authz.GetCtxData(ctx).OrgID, userGrantsToIDs(userGrants)...)
if err != nil {
return nil, err
}

View File

@ -180,3 +180,11 @@ func projectGrantStateFromProjectStateModel(state proj_model.ProjectState) manag
return management.ProjectGrantState_PROJECTGRANTSTATE_UNSPECIFIED
}
}
func projectGrantsToIDs(projectGrants []*proj_model.ProjectGrantView) []string {
converted := make([]string, len(projectGrants))
for i, grant := range projectGrants {
converted[i] = grant.GrantID
}
return converted
}

View File

@ -88,7 +88,11 @@ func (s *Server) UnlockUser(ctx context.Context, in *management.UserID) (*empty.
}
func (s *Server) DeleteUser(ctx context.Context, in *management.UserID) (*empty.Empty, error) {
err := s.command.RemoveUser(ctx, in.Id, authz.GetCtxData(ctx).OrgID)
grants, err := s.usergrant.UserGrantsByUserID(ctx, in.Id)
if err != nil {
return &empty.Empty{}, err
}
err = s.command.RemoveUser(ctx, in.Id, authz.GetCtxData(ctx).OrgID, userGrantsToIDs(grants)...)
return &empty.Empty{}, err
}

View File

@ -696,13 +696,6 @@ func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView) bool {
func (repo *AuthRequestRepo) getLoginPolicy(ctx context.Context, orgID string) (*iam_model.LoginPolicyView, error) {
policy, err := repo.View.LoginPolicyByAggregateID(orgID)
if errors.IsNotFound(err) {
policy, err = repo.View.LoginPolicyByAggregateID(repo.IAMID)
if err != nil {
return nil, err
}
policy.Default = true
}
if err != nil {
return nil, err
}

View File

@ -3,6 +3,7 @@ package eventstore
import (
"context"
"encoding/json"
"github.com/caos/zitadel/internal/v2/domain"
"testing"
"time"
@ -213,14 +214,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
MultiFactorCheckLifeTime time.Duration
}
type args struct {
request *model.AuthRequest
request *domain.AuthRequest
checkLoggedIn bool
}
tests := []struct {
name string
fields fields
args args
want []model.NextStep
want []domain.NextStep
wantErr func(error) bool
}{
{
@ -233,8 +234,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
{
"prompt none and checkLoggedIn false, callback step",
fields{},
args{&model.AuthRequest{Prompt: model.PromptNone}, false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
args{&domain.AuthRequest{Prompt: domain.PromptNone}, false},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
{
@ -242,8 +243,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
fields{
userSessionViewProvider: &mockViewNoUserSession{},
},
args{&model.AuthRequest{}, false},
[]model.NextStep{&model.LoginStep{}},
args{&domain.AuthRequest{}, false},
[]domain.NextStep{&domain.LoginStep{}},
nil,
},
{
@ -251,8 +252,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
fields{
userSessionViewProvider: &mockViewNoUserSession{},
},
args{&model.AuthRequest{LinkingUsers: []*model.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "ExternalUserID"}}}, false},
[]model.NextStep{&model.ExternalNotFoundOptionStep{}},
args{&domain.AuthRequest{LinkingUsers: []*domain.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "ExternalUserID"}}}, false},
[]domain.NextStep{&domain.ExternalNotFoundOptionStep{}},
nil,
},
{
@ -260,7 +261,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
fields{
userSessionViewProvider: &mockViewErrUserSession{},
},
args{&model.AuthRequest{Prompt: model.PromptSelectAccount}, false},
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount}, false},
nil,
errors.IsInternal,
},
@ -283,11 +284,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
},
args{&model.AuthRequest{Prompt: model.PromptSelectAccount}, false},
[]model.NextStep{
&model.LoginStep{},
&model.SelectUserStep{
Users: []model.UserSelection{
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount}, false},
[]domain.NextStep{
&domain.LoginStep{},
&domain.SelectUserStep{
Users: []domain.UserSelection{
{
UserID: "id1",
LoginName: "loginname1",
@ -321,11 +322,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
},
args{&model.AuthRequest{Prompt: model.PromptSelectAccount, RequestedOrgID: "orgID1"}, false},
[]model.NextStep{
&model.LoginStep{},
&model.SelectUserStep{
Users: []model.UserSelection{
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount, RequestedOrgID: "orgID1"}, false},
[]domain.NextStep{
&domain.LoginStep{},
&domain.SelectUserStep{
Users: []domain.UserSelection{
{
UserID: "id1",
LoginName: "loginname1",
@ -348,11 +349,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
userEventProvider: &mockEventUser{},
},
args{&model.AuthRequest{Prompt: model.PromptSelectAccount}, false},
[]model.NextStep{
&model.LoginStep{},
&model.SelectUserStep{
Users: []model.UserSelection{},
args{&domain.AuthRequest{Prompt: domain.PromptSelectAccount}, false},
[]domain.NextStep{
&domain.LoginStep{},
&domain.SelectUserStep{
Users: []domain.UserSelection{},
}},
nil,
},
@ -362,7 +363,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userViewProvider: &mockViewNoUser{},
userEventProvider: &mockEventUser{},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&domain.AuthRequest{UserID: "UserID"}, false},
nil,
errors.IsNotFound,
},
@ -378,7 +379,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&domain.AuthRequest{UserID: "UserID"}, false},
nil,
errors.IsPreconditionFailed,
},
@ -394,7 +395,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&domain.AuthRequest{UserID: "UserID"}, false},
nil,
errors.IsPreconditionFailed,
},
@ -405,7 +406,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewErrOrg{},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&domain.AuthRequest{UserID: "UserID"}, false},
nil,
errors.IsInternal,
},
@ -416,7 +417,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateInactive},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&domain.AuthRequest{UserID: "UserID"}, false},
nil,
errors.IsPreconditionFailed,
},
@ -430,8 +431,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
},
args{&model.AuthRequest{UserID: "UserID", LoginPolicy: &iam_model.LoginPolicyView{}}, false},
[]model.NextStep{&model.PasswordStep{}},
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
[]domain.NextStep{&domain.PasswordStep{}},
nil,
},
{
@ -442,7 +443,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
args{&domain.AuthRequest{UserID: "UserID"}, false},
nil,
errors.IsInternal,
},
@ -457,8 +458,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
},
args{&model.AuthRequest{UserID: "UserID"}, false},
[]model.NextStep{&model.InitUserStep{
args{&domain.AuthRequest{UserID: "UserID"}, false},
[]domain.NextStep{&domain.InitUserStep{
PasswordSet: true,
}},
nil,
@ -475,8 +476,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MultiFactorCheckLifeTime: 10 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", LoginPolicy: &iam_model.LoginPolicyView{PasswordlessType: iam_model.PasswordlessTypeAllowed}}, false},
[]model.NextStep{&model.PasswordlessStep{}},
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
[]domain.NextStep{&domain.PasswordlessStep{}},
nil,
},
{
@ -497,14 +498,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
MultiFactorCheckLifeTime: 10 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
PasswordlessType: iam_model.PasswordlessTypeAllowed,
MultiFactors: []iam_model.MultiFactorType{iam_model.MultiFactorTypeU2FWithPIN},
LoginPolicy: &domain.LoginPolicy{
PasswordlessType: domain.PasswordlessTypeAllowed,
MultiFactors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN},
},
}, false},
[]model.NextStep{&model.VerifyEMailStep{}},
[]domain.NextStep{&domain.VerifyEMailStep{}},
nil,
},
{
@ -515,8 +516,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
userEventProvider: &mockEventUser{},
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
},
args{&model.AuthRequest{UserID: "UserID", LoginPolicy: &iam_model.LoginPolicyView{}}, false},
[]model.NextStep{&model.InitPasswordStep{}},
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
[]domain.NextStep{&domain.InitPasswordStep{}},
nil,
},
{
@ -533,8 +534,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
[]model.NextStep{&model.ExternalLoginStep{SelectedIDPConfigID: "IDPConfigID"}},
args{&domain.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
[]domain.NextStep{&domain.ExternalLoginStep{SelectedIDPConfigID: "IDPConfigID"}},
nil,
},
{
@ -558,14 +559,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
SelectedIDPConfigID: "IDPConfigID",
Request: &model.AuthRequestOIDC{},
LoginPolicy: &iam_model.LoginPolicyView{},
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{},
},
false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
{
@ -579,8 +580,8 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
PasswordCheckLifeTime: 10 * 24 * time.Hour,
},
args{&model.AuthRequest{UserID: "UserID", LoginPolicy: &iam_model.LoginPolicyView{}}, false},
[]model.NextStep{&model.PasswordStep{}},
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
[]domain.NextStep{&domain.PasswordStep{}},
nil,
},
{
@ -602,13 +603,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
SelectedIDPConfigID: "IDPConfigID",
Request: &model.AuthRequestOIDC{},
LoginPolicy: &iam_model.LoginPolicyView{},
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{},
}, false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
{
@ -629,14 +630,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
[]domain.NextStep{&domain.MFAVerificationStep{
MFAProviders: []domain.MFAType{domain.MFATypeOTP},
}},
nil,
},
@ -657,14 +658,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
[]domain.NextStep{&domain.MFAVerificationStep{
MFAProviders: []domain.MFAType{domain.MFATypeOTP},
}},
nil,
},
@ -687,15 +688,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
SelectedIDPConfigID: "IDPConfigID",
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
[]domain.NextStep{&domain.MFAVerificationStep{
MFAProviders: []domain.MFAType{domain.MFATypeOTP},
}},
nil,
},
@ -718,13 +719,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.ChangePasswordStep{}},
[]domain.NextStep{&domain.ChangePasswordStep{}},
nil,
},
{
@ -743,13 +744,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.VerifyEMailStep{}},
[]domain.NextStep{&domain.VerifyEMailStep{}},
nil,
},
{
@ -769,13 +770,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.ChangePasswordStep{}, &model.VerifyEMailStep{}},
[]domain.NextStep{&domain.ChangePasswordStep{}, &domain.VerifyEMailStep{}},
nil,
},
{
@ -796,14 +797,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
Request: &model.AuthRequestOIDC{},
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.RedirectToCallbackStep{}},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
{
@ -824,15 +825,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
Prompt: model.PromptNone,
Request: &model.AuthRequestOIDC{},
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
Prompt: domain.PromptNone,
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, true},
[]model.NextStep{&model.RedirectToCallbackStep{}},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
{
@ -856,15 +857,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
Prompt: model.PromptNone,
Request: &model.AuthRequestOIDC{},
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
Prompt: domain.PromptNone,
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, true},
[]model.NextStep{&model.GrantRequiredStep{}},
[]domain.NextStep{&domain.GrantRequiredStep{}},
nil,
},
{
@ -888,15 +889,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{&model.AuthRequest{
args{&domain.AuthRequest{
UserID: "UserID",
Prompt: model.PromptNone,
Request: &model.AuthRequestOIDC{},
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
Prompt: domain.PromptNone,
Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, true},
[]model.NextStep{&model.RedirectToCallbackStep{}},
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
nil,
},
{
@ -915,13 +916,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
LoginPolicy: &iam_model.LoginPolicyView{},
LoginPolicy: &domain.LoginPolicy{},
SelectedIDPConfigID: "IDPConfigID",
LinkingUsers: []*model.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
LinkingUsers: []*domain.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
}, false},
[]model.NextStep{&model.PasswordStep{}},
[]domain.NextStep{&domain.PasswordStep{}},
nil,
},
{
@ -942,15 +943,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
PasswordCheckLifeTime: 10 * 24 * time.Hour,
},
args{
&model.AuthRequest{
&domain.AuthRequest{
UserID: "UserID",
SelectedIDPConfigID: "IDPConfigID",
LinkingUsers: []*model.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
LinkingUsers: []*domain.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
}, false},
[]model.NextStep{&model.LinkUsersStep{}},
[]domain.NextStep{&domain.LinkUsersStep{}},
nil,
},
}
@ -990,7 +991,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
}
type args struct {
userSession *user_model.UserSessionView
request *model.AuthRequest
request *domain.AuthRequest
user *user_model.UserView
policy *iam_model.LoginPolicyView
}
@ -998,7 +999,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
name string
fields fields
args args
want model.NextStep
want domain.NextStep
wantChecked bool
errFunc func(err error) bool
}{
@ -1006,7 +1007,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
// "required, prompt and false", //TODO: enable when LevelsOfAssurance is checked
// fields{},
// args{
// request: &model.AuthRequest{PossibleLOAs: []model.LevelOfAssurance{}},
// request: &domain.AuthRequest{PossibleLOAs: []model.LevelOfAssurance{}},
// user: &user_model.UserView{
// OTPState: user_model.MFAStateReady,
// },
@ -1019,8 +1020,8 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{
ForceMFA: true,
},
},
@ -1040,8 +1041,8 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{},
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{},
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
@ -1059,9 +1060,9 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
},
user: &user_model.UserView{
@ -1070,9 +1071,9 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
},
},
&model.MFAPromptStep{
MFAProviders: []model.MFAType{
model.MFATypeOTP,
&domain.MFAPromptStep{
MFAProviders: []domain.MFAType{
domain.MFATypeOTP,
},
},
false,
@ -1084,10 +1085,10 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{
ForceMFA: true,
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
},
user: &user_model.UserView{
@ -1096,10 +1097,10 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
},
},
},
&model.MFAPromptStep{
&domain.MFAPromptStep{
Required: true,
MFAProviders: []model.MFAType{
model.MFATypeOTP,
MFAProviders: []domain.MFAType{
domain.MFATypeOTP,
},
},
false,
@ -1111,8 +1112,8 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{},
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{},
},
user: &user_model.UserView{
HumanView: &user_model.HumanView{
@ -1131,9 +1132,9 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
},
user: &user_model.UserView{
@ -1154,9 +1155,9 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
SecondFactorCheckLifeTime: 18 * time.Hour,
},
args{
request: &model.AuthRequest{
LoginPolicy: &iam_model.LoginPolicyView{
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
},
},
user: &user_model.UserView{
@ -1168,8 +1169,8 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
userSession: &user_model.UserSessionView{},
},
&model.MFAVerificationStep{
MFAProviders: []model.MFAType{model.MFATypeOTP},
&domain.MFAVerificationStep{
MFAProviders: []domain.MFAType{domain.MFATypeOTP},
},
false,
nil,

View File

@ -1,9 +1,13 @@
package handler
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
@ -78,20 +82,48 @@ func (p *LoginPolicy) Reduce(event *models.Event) (err error) {
func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
policy := new(iam_model.LoginPolicyView)
switch event.Type {
case model.OrgAdded:
policy, err = p.getDefaultLoginPolicy()
if err != nil {
return err
}
policy.AggregateID = event.AggregateID
policy.Default = true
case iam_es_model.LoginPolicyAdded, model.LoginPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.LoginPolicyChanged, model.LoginPolicyChanged,
iam_es_model.LoginPolicySecondFactorAdded, model.LoginPolicySecondFactorAdded,
iam_es_model.LoginPolicySecondFactorRemoved, model.LoginPolicySecondFactorRemoved,
iam_es_model.LoginPolicyMultiFactorAdded, model.LoginPolicyMultiFactorAdded,
iam_es_model.LoginPolicyMultiFactorRemoved, model.LoginPolicyMultiFactorRemoved:
case iam_es_model.LoginPolicyChanged,
iam_es_model.LoginPolicySecondFactorAdded,
iam_es_model.LoginPolicySecondFactorRemoved,
iam_es_model.LoginPolicyMultiFactorAdded,
iam_es_model.LoginPolicyMultiFactorRemoved:
policies, err := p.view.AllDefaultLoginPolicies()
if err != nil {
return err
}
for _, policy := range policies {
err = policy.AppendEvent(event)
if err != nil {
return err
}
}
return p.view.PutLoginPolicies(policies, event)
case model.LoginPolicyChanged,
model.LoginPolicySecondFactorAdded,
model.LoginPolicySecondFactorRemoved,
model.LoginPolicyMultiFactorAdded,
model.LoginPolicyMultiFactorRemoved:
policy, err = p.view.LoginPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.LoginPolicyRemoved:
return p.view.DeleteLoginPolicy(event.AggregateID, event)
policy, err = p.getDefaultLoginPolicy()
if err != nil {
return err
}
policy.AggregateID = event.AggregateID
policy.Default = true
default:
return p.view.ProcessedLoginPolicySequence(event)
}
@ -109,3 +141,33 @@ func (p *LoginPolicy) OnError(event *models.Event, err error) error {
func (p *LoginPolicy) OnSuccess() error {
return spooler.HandleSuccess(p.view.UpdateLoginPolicySpoolerRunTimestamp)
}
func (p *LoginPolicy) getDefaultLoginPolicy() (*iam_model.LoginPolicyView, error) {
policy, policyErr := p.view.LoginPolicyByAggregateID(domain.IAMID)
if policyErr != nil && !caos_errs.IsNotFound(policyErr) {
return nil, policyErr
}
if policy == nil {
policy = &iam_model.LoginPolicyView{}
}
events, err := p.getIAMEvents(policy.Sequence)
if err != nil {
return policy, policyErr
}
policyCopy := *policy
for _, event := range events {
if err := policyCopy.AppendEvent(event); err != nil {
return policy, nil
}
}
return &policyCopy, nil
}
func (p *LoginPolicy) getIAMEvents(sequence uint64) ([]*models.Event, error) {
query, err := eventsourcing.IAMByIDQuery(domain.IAMID, sequence)
if err != nil {
return nil, err
}
return p.es.FilterEvents(context.Background(), query)
}

View File

@ -16,6 +16,10 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV
return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID)
}
func (v *View) AllDefaultLoginPolicies() ([]*model.LoginPolicyView, error) {
return view.GetDefaultLoginPolicies(v.Db, loginPolicyTable)
}
func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event) error {
err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy)
if err != nil {
@ -24,6 +28,14 @@ func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event
return v.ProcessedLoginPolicySequence(event)
}
func (v *View) PutLoginPolicies(policies []*model.LoginPolicyView, event *models.Event) error {
err := view.PutLoginPolicies(v.Db, loginPolicyTable, policies...)
if err != nil {
return err
}
return v.ProcessedLoginPolicySequence(event)
}
func (v *View) DeleteLoginPolicy(aggregateID string, event *models.Event) error {
err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {

View File

@ -6,7 +6,7 @@ package mock
import (
context "context"
model "github.com/caos/zitadel/internal/auth_request/model"
domain "github.com/caos/zitadel/internal/v2/domain"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
@ -49,10 +49,10 @@ func (mr *MockAuthRequestCacheMockRecorder) DeleteAuthRequest(arg0, arg1 interfa
}
// GetAuthRequestByCode mocks base method
func (m *MockAuthRequestCache) GetAuthRequestByCode(arg0 context.Context, arg1 string) (*model.AuthRequest, error) {
func (m *MockAuthRequestCache) GetAuthRequestByCode(arg0 context.Context, arg1 string) (*domain.AuthRequest, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAuthRequestByCode", arg0, arg1)
ret0, _ := ret[0].(*model.AuthRequest)
ret0, _ := ret[0].(*domain.AuthRequest)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -64,10 +64,10 @@ func (mr *MockAuthRequestCacheMockRecorder) GetAuthRequestByCode(arg0, arg1 inte
}
// GetAuthRequestByID mocks base method
func (m *MockAuthRequestCache) GetAuthRequestByID(arg0 context.Context, arg1 string) (*model.AuthRequest, error) {
func (m *MockAuthRequestCache) GetAuthRequestByID(arg0 context.Context, arg1 string) (*domain.AuthRequest, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAuthRequestByID", arg0, arg1)
ret0, _ := ret[0].(*model.AuthRequest)
ret0, _ := ret[0].(*domain.AuthRequest)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -93,7 +93,7 @@ func (mr *MockAuthRequestCacheMockRecorder) Health(arg0 interface{}) *gomock.Cal
}
// SaveAuthRequest mocks base method
func (m *MockAuthRequestCache) SaveAuthRequest(arg0 context.Context, arg1 *model.AuthRequest) error {
func (m *MockAuthRequestCache) SaveAuthRequest(arg0 context.Context, arg1 *domain.AuthRequest) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SaveAuthRequest", arg0, arg1)
ret0, _ := ret[0].(error)

View File

@ -3,6 +3,7 @@ package spooler
import (
"context"
"fmt"
es_v2 "github.com/caos/zitadel/internal/eventstore/v2"
"testing"
"time"
@ -105,6 +106,9 @@ func (es *eventstoreStub) PushAggregates(ctx context.Context, in ...*models.Aggr
func (es *eventstoreStub) LatestSequence(ctx context.Context, in *models.SearchQueryFactory) (uint64, error) {
return 0, nil
}
func (es *eventstoreStub) V2() *es_v2.Eventstore {
return nil
}
func TestSpooler_process(t *testing.T) {
type fields struct {

View File

@ -63,7 +63,7 @@ func (e *testEvent) Data() interface{} {
return e.data()
}
func (e *testEvent) UniqueConstraint() []*EventUniqueConstraint {
func (e *testEvent) UniqueConstraints() []*EventUniqueConstraint {
return nil
}
@ -1358,24 +1358,24 @@ func TestEventstore_mapEvents(t *testing.T) {
args args
res res
}{
{
name: "no mapper",
args: args{
events: []*repository.Event{
{
Type: "no.mapper.found",
},
},
},
fields: fields{
eventMapper: map[EventType]func(*repository.Event) (EventReader, error){},
},
res: res{
//TODO: as long as not all events are implemented in v2 eventstore doesn't return an error
// afterwards it will return an error on un
wantErr: true,
},
},
//{
// name: "no mapper",
// args: args{
// events: []*repository.Event{
// {
// Type: "no.mapper.found",
// },
// },
// },
// fields: fields{
// eventMapper: map[EventType]func(*repository.Event) (EventReader, error){},
// },
// res: res{
// //TODO: as long as not all events are implemented in v2 eventstore doesn't return an error
// // afterwards it will return an error on un
// wantErr: true,
// },
//},
{
name: "mapping failed",
args: args{

View File

@ -10,6 +10,7 @@ import (
"strconv"
"strings"
"testing"
"time"
"github.com/caos/logging"
"github.com/cockroachdb/cockroach-go/v2/testserver"
@ -49,12 +50,19 @@ func executeMigrations() error {
return err
}
sort.Sort(files)
if err = setPasswordNULL(); err != nil {
return err
}
if err = createFlywayHistory(); err != nil {
return err
}
for _, file := range files {
migration, err := ioutil.ReadFile(string(file))
migrationData, err := ioutil.ReadFile(file)
if err != nil {
return err
}
transactionInMigration := strings.Contains(string(migration), "BEGIN;")
migration := os.ExpandEnv(string(migrationData))
transactionInMigration := strings.Contains(migration, "BEGIN;")
exec := testCRDBClient.Exec
var tx *sql.Tx
if !transactionInMigration {
@ -64,18 +72,43 @@ func executeMigrations() error {
}
exec = tx.Exec
}
if _, err = exec(string(migration)); err != nil {
if _, err = exec(migration); err != nil {
return fmt.Errorf("exec file: %v || err: %w", file, err)
}
duration := 1 * time.Second
if !transactionInMigration {
if err = tx.Commit(); err != nil {
return fmt.Errorf("commit file: %v || err: %w", file, err)
}
duration = 0
}
time.Sleep(duration)
}
return nil
}
func setPasswordNULL() error {
passwordNames := []string{
"eventstorepassword",
"managementpassword",
"adminapipassword",
"authpassword",
"notificationpassword",
"authzpassword",
}
for _, name := range passwordNames {
if err := os.Setenv(name, "NULL"); err != nil {
return err
}
}
return nil
}
func createFlywayHistory() error {
_, err := testCRDBClient.Exec("CREATE TABLE defaultdb.flyway_schema_history(id TEXT, PRIMARY KEY(id));")
return err
}
type migrationPaths []string
type version struct {

View File

@ -638,33 +638,6 @@ func TestCRDB_Push_Parallel(t *testing.T) {
},
},
},
{
name: "clients push same aggregates",
args: args{
events: [][]*repository.Event{
{
generateEventWithData(t, "210", []byte(`{ "transaction": 1 }`)),
generateEventWithData(t, "210", []byte(`{ "transaction": 1.1 }`)),
},
{
generateEventWithData(t, "210", []byte(`{ "transaction": 2 }`)),
generateEventWithData(t, "210", []byte(`{ "transaction": 2.1 }`)),
},
{
generateEventWithData(t, "210", []byte(`{ "transaction": 3 }`)),
generateEventWithData(t, "210", []byte(`{ "transaction": 30.1 }`)),
},
},
},
res: res{
errCount: 2,
eventsRes: eventsRes{
aggIDs: []string{"210"},
pushedEventsCount: 2,
aggTypes: []repository.AggregateType{repository.AggregateType(t.Name())},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -10,6 +10,7 @@ import (
"strconv"
"strings"
"testing"
"time"
"github.com/caos/logging"
"github.com/cockroachdb/cockroach-go/v2/testserver"
@ -53,12 +54,19 @@ func executeMigrations() error {
return err
}
sort.Sort(files)
if err = setPasswordNULL(); err != nil {
return err
}
if err = createFlywayHistory(); err != nil {
return err
}
for _, file := range files {
migration, err := ioutil.ReadFile(string(file))
migrationData, err := ioutil.ReadFile(file)
if err != nil {
return err
}
transactionInMigration := strings.Contains(string(migration), "BEGIN;")
migration := os.ExpandEnv(string(migrationData))
transactionInMigration := strings.Contains(migration, "BEGIN;")
exec := testCRDBClient.Exec
var tx *sql.Tx
if !transactionInMigration {
@ -68,18 +76,43 @@ func executeMigrations() error {
}
exec = tx.Exec
}
if _, err = exec(string(migration)); err != nil {
if _, err = exec(migration); err != nil {
return fmt.Errorf("exec file: %v || err: %w", file, err)
}
duration := 1 * time.Second
if !transactionInMigration {
if err = tx.Commit(); err != nil {
return fmt.Errorf("commit file: %v || err: %w", file, err)
}
duration = 0
}
time.Sleep(duration)
}
return nil
}
func setPasswordNULL() error {
passwordNames := []string{
"eventstorepassword",
"managementpassword",
"adminapipassword",
"authpassword",
"notificationpassword",
"authzpassword",
}
for _, name := range passwordNames {
if err := os.Setenv(name, "NULL"); err != nil {
return err
}
}
return nil
}
func createFlywayHistory() error {
_, err := testCRDBClient.Exec("CREATE TABLE defaultdb.flyway_schema_history(id TEXT, PRIMARY KEY(id));")
return err
}
func fillUniqueData(unique_type, field string) error {
_, err := testCRDBClient.Exec("INSERT INTO eventstore.unique_constraints (unique_type, unique_field) VALUES ($1, $2)", unique_type, field)
return err

View File

@ -137,7 +137,7 @@ func (factory *SearchQueryBuilder) eventTypeFilter() *repository.Filter {
return nil
}
if len(factory.eventTypes) == 1 {
return repository.NewFilter(repository.FieldEventType, factory.eventTypes[0], repository.OperationEquals)
return repository.NewFilter(repository.FieldEventType, repository.EventType(factory.eventTypes[0]), repository.OperationEquals)
}
eventTypes := make([]repository.EventType, len(factory.eventTypes))
for i, eventType := range factory.eventTypes {
@ -148,7 +148,7 @@ func (factory *SearchQueryBuilder) eventTypeFilter() *repository.Filter {
func (factory *SearchQueryBuilder) aggregateTypeFilter() *repository.Filter {
if len(factory.aggregateTypes) == 1 {
return repository.NewFilter(repository.FieldAggregateType, factory.aggregateTypes[0], repository.OperationEquals)
return repository.NewFilter(repository.FieldAggregateType, repository.AggregateType(factory.aggregateTypes[0]), repository.OperationEquals)
}
aggregateTypes := make([]repository.AggregateType, len(factory.aggregateTypes))
for i, aggregateType := range factory.aggregateTypes {

View File

@ -231,7 +231,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
},
},
},
@ -250,7 +250,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, []AggregateType{"user", "org"}, repository.OperationIn),
repository.NewFilter(repository.FieldAggregateType, []repository.AggregateType{"user", "org"}, repository.OperationIn),
},
},
},
@ -273,7 +273,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: true,
Limit: 5,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldSequence, uint64(100), repository.OperationLess),
},
},
@ -297,7 +297,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 5,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldSequence, uint64(100), repository.OperationGreater),
},
},
@ -322,7 +322,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: true,
Limit: 5,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldSequence, uint64(100), repository.OperationLess),
},
},
@ -344,7 +344,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateID, "1234", repository.OperationEquals),
},
},
@ -366,7 +366,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateID, []string{"1234", "0815"}, repository.OperationIn),
},
},
@ -388,7 +388,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldSequence, uint64(8), repository.OperationGreater),
},
},
@ -410,8 +410,8 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldEventType, EventType("user.created"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldEventType, repository.EventType("user.created"), repository.OperationEquals),
},
},
},
@ -432,8 +432,8 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldEventType, []EventType{"user.created", "user.changed"}, repository.OperationIn),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldEventType, []repository.EventType{"user.created", "user.changed"}, repository.OperationIn),
},
},
},
@ -454,7 +454,7 @@ func TestSearchQueryFactoryBuild(t *testing.T) {
Desc: false,
Limit: 0,
Filters: []*repository.Filter{
repository.NewFilter(repository.FieldAggregateType, AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals),
repository.NewFilter(repository.FieldResourceOwner, "hodor", repository.OperationEquals),
},
},

View File

@ -36,6 +36,7 @@ type LoginPolicySearchKey int32
const (
LoginPolicySearchKeyUnspecified LoginPolicySearchKey = iota
LoginPolicySearchKeyAggregateID
LoginPolicySearchKeyDefault
)
type LoginPolicySearchQuery struct {

View File

@ -150,79 +150,6 @@ func TestIamByID(t *testing.T) {
// }
//}
func TestSetUpDone(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *IAMEventstore
ctx context.Context
iamID string
step iam_model.Step
}
type res struct {
iam *iam_model.IAM
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "setup done iam, ok",
args: args{
es: GetMockManipulateIAM(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
iamID: "iamID",
step: iam_model.Step1,
},
res: res{
iam: &iam_model.IAM{ObjectRoot: es_models.ObjectRoot{AggregateID: "iamID", Sequence: 1}, SetUpStarted: iam_model.Step1, SetUpDone: iam_model.Step1},
},
},
{
name: "setup iam no id",
args: args{
es: GetMockManipulateIAM(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
step: iam_model.Step1,
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "iam not found",
args: args{
es: GetMockManipulateIAMNotExisting(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
iamID: "iamID",
step: iam_model.Step1,
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.SetupDone(tt.args.ctx, tt.args.iamID, tt.args.step)
if (tt.res.errFunc != nil && !tt.res.errFunc(err)) || (err != nil && tt.res.errFunc == nil) {
t.Errorf("got wrong err: %v ", err)
return
}
if tt.res.errFunc != nil && tt.res.errFunc(err) {
return
}
if result.AggregateID == "" {
t.Errorf("result has no id")
}
if result.SetUpDone != tt.res.iam.SetUpDone {
t.Errorf("got wrong result SetUpDone: expected: %v, actual: %v ", tt.res.iam.SetUpDone, result.SetUpDone)
}
})
}
}
func TestSetGlobalOrg(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {

View File

@ -9,6 +9,19 @@ import (
"github.com/jinzhu/gorm"
)
func GetDefaultLoginPolicies(db *gorm.DB, table string) ([]*model.LoginPolicyView, error) {
loginPolicies := make([]*model.LoginPolicyView, 0)
queries := []*iam_model.LoginPolicySearchQuery{
{Key: iam_model.LoginPolicySearchKeyDefault, Value: true, Method: global_model.SearchMethodEquals},
}
query := repository.PrepareSearchQuery(table, model.LoginPolicySearchRequest{Queries: queries})
_, err := query(db, &loginPolicies)
if err != nil {
return nil, err
}
return loginPolicies, nil
}
func GetLoginPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.LoginPolicyView, error) {
policy := new(model.LoginPolicyView)
aggregateIDQuery := &model.LoginPolicySearchQuery{Key: iam_model.LoginPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
@ -25,6 +38,15 @@ func PutLoginPolicy(db *gorm.DB, table string, policy *model.LoginPolicyView) er
return save(db, policy)
}
func PutLoginPolicies(db *gorm.DB, table string, policies ...*model.LoginPolicyView) error {
save := repository.PrepareBulkSave(table)
u := make([]interface{}, len(policies))
for i, user := range policies {
u[i] = user
}
return save(db, u...)
}
func DeleteLoginPolicy(db *gorm.DB, table, aggregateID string) error {
delete := repository.PrepareDeleteByKey(table, model.LoginPolicySearchKey(iam_model.LoginPolicySearchKeyAggregateID), aggregateID)

View File

@ -16,6 +16,7 @@ import (
const (
LoginPolicyKeyAggregateID = "aggregate_id"
LoginPolicyKeyDefault = "default_policy"
)
type LoginPolicyView struct {
@ -31,7 +32,7 @@ type LoginPolicyView struct {
PasswordlessType int32 `json:"passwordlessType" gorm:"column:passwordless_type"`
SecondFactors pq.Int64Array `json:"-" gorm:"column:second_factors"`
MultiFactors pq.Int64Array `json:"-" gorm:"column:multi_factors"`
Default bool `json:"-" gorm:"-"`
Default bool `json:"-" gorm:"column:default_policy"`
Sequence uint64 `json:"-" gorm:"column:sequence"`
}
@ -106,10 +107,16 @@ func (p *LoginPolicyView) AppendEvent(event *models.Event) (err error) {
p.Sequence = event.Sequence
p.ChangeDate = event.CreationDate
switch event.Type {
case es_model.LoginPolicyAdded, org_es_model.LoginPolicyAdded:
case es_model.LoginPolicyAdded:
p.setRootData(event)
p.CreationDate = event.CreationDate
p.Default = true
err = p.SetData(event)
case org_es_model.LoginPolicyAdded:
p.setRootData(event)
p.CreationDate = event.CreationDate
err = p.SetData(event)
p.Default = false
case es_model.LoginPolicyChanged, org_es_model.LoginPolicyChanged:
err = p.SetData(event)
case es_model.LoginPolicySecondFactorAdded, org_es_model.LoginPolicySecondFactorAdded:
@ -118,7 +125,10 @@ func (p *LoginPolicyView) AppendEvent(event *models.Event) (err error) {
if err != nil {
return err
}
p.SecondFactors = append(p.SecondFactors, int64(mfa.MFAType))
if !existsMFA(p.SecondFactors, int64(mfa.MFAType)) {
p.SecondFactors = append(p.SecondFactors, int64(mfa.MFAType))
}
case es_model.LoginPolicySecondFactorRemoved, org_es_model.LoginPolicySecondFactorRemoved:
err = p.removeSecondFactor(event)
case es_model.LoginPolicyMultiFactorAdded, org_es_model.LoginPolicyMultiFactorAdded:
@ -127,7 +137,9 @@ func (p *LoginPolicyView) AppendEvent(event *models.Event) (err error) {
if err != nil {
return err
}
p.MultiFactors = append(p.MultiFactors, int64(mfa.MFAType))
if !existsMFA(p.MultiFactors, int64(mfa.MFAType)) {
p.MultiFactors = append(p.MultiFactors, int64(mfa.MFAType))
}
case es_model.LoginPolicyMultiFactorRemoved, org_es_model.LoginPolicyMultiFactorRemoved:
err = p.removeMultiFactor(event)
}
@ -179,3 +191,12 @@ func (p *LoginPolicyView) removeMultiFactor(event *models.Event) error {
}
return nil
}
func existsMFA(mfas []int64, mfaType int64) bool {
for _, m := range mfas {
if m == mfaType {
return true
}
}
return false
}

View File

@ -53,6 +53,8 @@ func (key LoginPolicySearchKey) ToColumnName() string {
switch iam_model.LoginPolicySearchKey(key) {
case iam_model.LoginPolicySearchKeyAggregateID:
return LoginPolicyKeyAggregateID
case iam_model.LoginPolicySearchKeyDefault:
return LoginPolicyKeyDefault
default:
return ""
}

View File

@ -2,6 +2,7 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/v2/domain"
"strings"
iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
@ -361,15 +362,23 @@ func (repo *OrgRepository) GetLoginPolicy(ctx context.Context) (*iam_model.Login
return iam_es_model.LoginPolicyViewToModel(policy), nil
}
func (repo *OrgRepository) GetIDPProvidersByIDPConfigID(ctx context.Context, aggregateID, idpConfigID string) ([]*iam_model.IDPProviderView, error) {
idpProviders, err := repo.View.IDPProvidersByIdpConfigID(aggregateID, idpConfigID)
if err != nil {
return nil, err
}
return iam_view_model.IDPProviderViewsToModel(idpProviders), err
}
func (repo *OrgRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
policy, viewErr := repo.View.LoginPolicyByAggregateID(repo.SystemDefaults.IamID)
policy, viewErr := repo.View.LoginPolicyByAggregateID(domain.IAMID)
if viewErr != nil && !errors.IsNotFound(viewErr) {
return nil, viewErr
}
if errors.IsNotFound(viewErr) {
policy = new(iam_es_model.LoginPolicyView)
}
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, domain.IAMID, policy.Sequence)
if errors.IsNotFound(viewErr) && len(events) == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.LoginPolicy.NotFound")
}
@ -405,11 +414,12 @@ func (repo *OrgRepository) RemoveLoginPolicy(ctx context.Context) error {
}
func (repo *OrgRepository) SearchIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error) {
_, err := repo.View.LoginPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
policy, err := repo.View.LoginPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
if err != nil {
if errors.IsNotFound(err) {
request.AppendAggregateIDQuery(repo.SystemDefaults.IamID)
}
return nil, err
}
if policy.Default {
request.AppendAggregateIDQuery(domain.IAMID)
} else {
request.AppendAggregateIDQuery(authz.GetCtxData(ctx).OrgID)
}

View File

@ -280,6 +280,14 @@ func (repo *ProjectRepo) ProjectGrantByID(ctx context.Context, grantID string) (
return model.ProjectGrantToModel(grant), nil
}
func (repo *ProjectRepo) ProjectGrantsByProjectIDAndRoleKey(ctx context.Context, projectID, roleKey string) ([]*proj_model.ProjectGrantView, error) {
grants, err := repo.View.ProjectGrantsByProjectIDAndRoleKey(projectID, roleKey)
if err != nil {
return nil, err
}
return model.ProjectGrantsToModel(grants), nil
}
func (repo *ProjectRepo) SearchProjectGrants(ctx context.Context, request *proj_model.ProjectGrantViewSearchRequest) (*proj_model.ProjectGrantViewSearchResponse, error) {
request.EnsureLimit(repo.SearchLimit)
sequence, sequenceErr := repo.View.GetLatestProjectGrantSequence()

View File

@ -78,6 +78,10 @@ func (repo *UserRepo) SearchUsers(ctx context.Context, request *usr_model.UserSe
return result, nil
}
func (repo *UserRepo) UserIDsByDomain(ctx context.Context, domain string) ([]string, error) {
return repo.View.UserIDsByDomain(domain)
}
func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*usr_model.UserChanges, error) {
changes, err := repo.UserEvents.UserChanges(ctx, id, lastSequence, limit, sortAscending)
if err != nil {
@ -164,6 +168,22 @@ func (repo *UserRepo) SearchExternalIDPs(ctx context.Context, request *usr_model
return result, nil
}
func (repo *UserRepo) ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*usr_model.ExternalIDPView, error) {
externalIDPs, err := repo.View.ExternalIDPsByIDPConfigID(idpConfigID)
if err != nil {
return nil, err
}
return model.ExternalIDPViewsToModel(externalIDPs), nil
}
func (repo *UserRepo) ExternalIDPsByIDPConfigIDAndResourceOwner(ctx context.Context, idpConfigID, resourceOwner string) ([]*usr_model.ExternalIDPView, error) {
externalIDPs, err := repo.View.ExternalIDPsByIDPConfigIDAndResourceOwner(idpConfigID, resourceOwner)
if err != nil {
return nil, err
}
return model.ExternalIDPViewsToModel(externalIDPs), nil
}
func (repo *UserRepo) GetMachineKey(ctx context.Context, userID, keyID string) (*usr_model.MachineKeyView, error) {
key, err := repo.View.MachineKeyByIDs(userID, keyID)
if err != nil {

View File

@ -35,6 +35,22 @@ func (repo *UserGrantRepo) UserGrantsByProjectID(ctx context.Context, projectID
return model.UserGrantsToModel(grants), nil
}
func (repo *UserGrantRepo) UserGrantsByProjectIDAndRoleKey(ctx context.Context, projectID, roleKey string) ([]*grant_model.UserGrantView, error) {
grants, err := repo.View.UserGrantsByProjectIDAndRoleKey(projectID, roleKey)
if err != nil {
return nil, err
}
return model.UserGrantsToModel(grants), nil
}
func (repo *UserGrantRepo) UserGrantsByProjectAndGrantID(ctx context.Context, projectID, grantID string) ([]*grant_model.UserGrantView, error) {
grants, err := repo.View.UserGrantsByProjectAndGrantID(projectID, grantID)
if err != nil {
return nil, err
}
return model.UserGrantsToModel(grants), nil
}
func (repo *UserGrantRepo) UserGrantsByUserID(ctx context.Context, userID string) ([]*grant_model.UserGrantView, error) {
grants, err := repo.View.UserGrantsByUserID(userID)
if err != nil {

View File

@ -1,15 +1,19 @@
package handler
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing"
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/v2/domain"
)
const (
@ -77,20 +81,48 @@ func (m *LoginPolicy) Reduce(event *models.Event) (err error) {
func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) {
policy := new(iam_model.LoginPolicyView)
switch event.Type {
case model.OrgAdded:
policy, err = m.getDefaultLoginPolicy()
if err != nil {
return err
}
policy.AggregateID = event.AggregateID
policy.Default = true
case iam_es_model.LoginPolicyAdded, model.LoginPolicyAdded:
err = policy.AppendEvent(event)
case iam_es_model.LoginPolicyChanged, model.LoginPolicyChanged,
iam_es_model.LoginPolicySecondFactorAdded, model.LoginPolicySecondFactorAdded,
iam_es_model.LoginPolicySecondFactorRemoved, model.LoginPolicySecondFactorRemoved,
iam_es_model.LoginPolicyMultiFactorAdded, model.LoginPolicyMultiFactorAdded,
iam_es_model.LoginPolicyMultiFactorRemoved, model.LoginPolicyMultiFactorRemoved:
case iam_es_model.LoginPolicyChanged,
iam_es_model.LoginPolicySecondFactorAdded,
iam_es_model.LoginPolicySecondFactorRemoved,
iam_es_model.LoginPolicyMultiFactorAdded,
iam_es_model.LoginPolicyMultiFactorRemoved:
policies, err := m.view.AllDefaultLoginPolicies()
if err != nil {
return err
}
for _, policy := range policies {
err = policy.AppendEvent(event)
if err != nil {
return err
}
}
return m.view.PutLoginPolicies(policies, event)
case model.LoginPolicyChanged,
model.LoginPolicySecondFactorAdded,
model.LoginPolicySecondFactorRemoved,
model.LoginPolicyMultiFactorAdded,
model.LoginPolicyMultiFactorRemoved:
policy, err = m.view.LoginPolicyByAggregateID(event.AggregateID)
if err != nil {
return err
}
err = policy.AppendEvent(event)
case model.LoginPolicyRemoved:
return m.view.DeleteLoginPolicy(event.AggregateID, event)
policy, err = m.getDefaultLoginPolicy()
if err != nil {
return err
}
policy.AggregateID = event.AggregateID
policy.Default = true
default:
return m.view.ProcessedLoginPolicySequence(event)
}
@ -108,3 +140,33 @@ func (m *LoginPolicy) OnError(event *models.Event, err error) error {
func (m *LoginPolicy) OnSuccess() error {
return spooler.HandleSuccess(m.view.UpdateLoginPolicySpoolerRunTimestamp)
}
func (p *LoginPolicy) getDefaultLoginPolicy() (*iam_model.LoginPolicyView, error) {
policy, policyErr := p.view.LoginPolicyByAggregateID(domain.IAMID)
if policyErr != nil && !caos_errs.IsNotFound(policyErr) {
return nil, policyErr
}
if policy == nil {
policy = &iam_model.LoginPolicyView{}
}
events, err := p.getIAMEvents(policy.Sequence)
if err != nil {
return policy, policyErr
}
policyCopy := *policy
for _, event := range events {
if err := policyCopy.AppendEvent(event); err != nil {
return policy, nil
}
}
return &policyCopy, nil
}
func (p *LoginPolicy) getIAMEvents(sequence uint64) ([]*models.Event, error) {
query, err := eventsourcing.IAMByIDQuery(domain.IAMID, sequence)
if err != nil {
return nil, err
}
return p.es.FilterEvents(context.Background(), query)
}

View File

@ -25,6 +25,9 @@ func (v *View) ExternalIDPsByIDPConfigID(idpConfigID string) ([]*model.ExternalI
return view.ExternalIDPsByIDPConfigID(v.Db, externalIDPTable, idpConfigID)
}
func (v *View) ExternalIDPsByIDPConfigIDAndResourceOwner(idpConfigID, resourceOwner string) ([]*model.ExternalIDPView, error) {
return view.ExternalIDPsByIDPConfigIDAndResourceOwner(v.Db, externalIDPTable, idpConfigID, resourceOwner)
}
func (v *View) ExternalIDPsByUserID(userID string) ([]*model.ExternalIDPView, error) {
return view.ExternalIDPsByUserID(v.Db, externalIDPTable, userID)
}

View File

@ -12,6 +12,10 @@ const (
loginPolicyTable = "management.login_policies"
)
func (v *View) AllDefaultLoginPolicies() ([]*model.LoginPolicyView, error) {
return view.GetDefaultLoginPolicies(v.Db, loginPolicyTable)
}
func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyView, error) {
return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID)
}
@ -24,6 +28,14 @@ func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event
return v.ProcessedLoginPolicySequence(event)
}
func (v *View) PutLoginPolicies(policies []*model.LoginPolicyView, event *models.Event) error {
err := view.PutLoginPolicies(v.Db, loginPolicyTable, policies...)
if err != nil {
return err
}
return v.ProcessedLoginPolicySequence(event)
}
func (v *View) DeleteLoginPolicy(aggregateID string, event *models.Event) error {
err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID)
if err != nil && !errors.IsNotFound(err) {

View File

@ -29,6 +29,10 @@ func (v *View) UserGrantsByProjectID(projectID string) ([]*model.UserGrantView,
return view.UserGrantsByProjectID(v.Db, userGrantTable, projectID)
}
func (v *View) UserGrantsByProjectAndGrantID(projectID, grantID string) ([]*model.UserGrantView, error) {
return view.UserGrantsByProjectAndGrantID(v.Db, userGrantTable, projectID, grantID)
}
func (v *View) UserGrantsByOrgID(orgID string) ([]*model.UserGrantView, error) {
return view.UserGrantsByOrgID(v.Db, userGrantTable, orgID)
}

View File

@ -27,6 +27,7 @@ type OrgRepository interface {
GetLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error)
GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error)
SearchIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error)
GetIDPProvidersByIDPConfigID(ctx context.Context, aggregateID, idpConfigID string) ([]*iam_model.IDPProviderView, error)
SearchSecondFactors(ctx context.Context) (*iam_model.SecondFactorsSearchResponse, error)
SearchMultiFactors(ctx context.Context) (*iam_model.MultiFactorsSearchResponse, error)

View File

@ -9,6 +9,8 @@ import (
type ProjectRepository interface {
ProjectByID(ctx context.Context, id string) (*model.ProjectView, error)
SearchProjects(ctx context.Context, request *model.ProjectViewSearchRequest) (*model.ProjectViewSearchResponse, error)
ProjectGrantsByProjectIDAndRoleKey(ctx context.Context, projectID, roleKey string) ([]*model.ProjectGrantView, error)
SearchProjectGrants(ctx context.Context, request *model.ProjectGrantViewSearchRequest) (*model.ProjectGrantViewSearchResponse, error)
SearchGrantedProjects(ctx context.Context, request *model.ProjectGrantViewSearchRequest) (*model.ProjectGrantViewSearchResponse, error)
ProjectGrantViewByID(ctx context.Context, grantID string) (*model.ProjectGrantView, error)

View File

@ -9,6 +9,7 @@ import (
type UserRepository interface {
UserByID(ctx context.Context, id string) (*model.UserView, error)
SearchUsers(ctx context.Context, request *model.UserSearchRequest) (*model.UserSearchResponse, error)
UserIDsByDomain(ctx context.Context, domain string) ([]string, error)
GetUserByLoginNameGlobal(ctx context.Context, email string) (*model.UserView, error)
IsUserUnique(ctx context.Context, userName, email string) (bool, error)
@ -22,6 +23,8 @@ type UserRepository interface {
GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error)
SearchExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error)
ExternalIDPsByIDPConfigID(ctx context.Context, idpConfigID string) ([]*model.ExternalIDPView, error)
ExternalIDPsByIDPConfigIDAndResourceOwner(ctx context.Context, idpConfigID, resourceOwner string) ([]*model.ExternalIDPView, error)
SearchMachineKeys(ctx context.Context, request *model.MachineKeySearchRequest) (*model.MachineKeySearchResponse, error)
GetMachineKey(ctx context.Context, userID, keyID string) (*model.MachineKeyView, error)

View File

@ -9,5 +9,7 @@ type UserGrantRepository interface {
UserGrantByID(ctx context.Context, grantID string) (*model.UserGrantView, error)
SearchUserGrants(ctx context.Context, request *model.UserGrantSearchRequest) (*model.UserGrantSearchResponse, error)
UserGrantsByProjectID(ctx context.Context, projectID string) ([]*model.UserGrantView, error)
UserGrantsByProjectAndGrantID(ctx context.Context, projectID, grantID string) ([]*model.UserGrantView, error)
UserGrantsByProjectIDAndRoleKey(ctx context.Context, projectID, roleKey string) ([]*model.UserGrantView, error)
UserGrantsByUserID(ctx context.Context, userID string) ([]*model.UserGrantView, error)
}

View File

@ -269,6 +269,7 @@ Errors:
NotActive: Benutzer Berechtigung ist nicht aktiv
NotInactive: Benutzer Berechtigung ist nicht deaktiviert
NoPermissionForProject: Benutzer hat keine Rechte auf diesem Projekt
RoleKeyNotFound: Rolle konnte nicht gefunden werden
IDPConfig:
AlreadyExists: IDP Konfiguration mit diesem Name existiert bereits
Changes:

View File

@ -265,6 +265,7 @@ Errors:
NotActive: User grant is not active
NotInactive: User grant is not deactivated
NoPermissionForProject: User has no permissions on this project
RoleKeyNotFound: Role not found
IDPConfig:
AlreadyExists: IDP Configuration with this name already exists
Changes:

View File

@ -70,6 +70,44 @@ func ExternalIDPsByIDPConfigID(db *gorm.DB, table, idpConfigID string) ([]*model
return externalIDPs, err
}
func ExternalIDPsByIDPConfigIDAndResourceOwner(db *gorm.DB, table, idpConfigID, resourceOwner string) ([]*model.ExternalIDPView, error) {
externalIDPs := make([]*model.ExternalIDPView, 0)
idpConfigIDQuery := &usr_model.ExternalIDPSearchQuery{
Key: usr_model.ExternalIDPSearchKeyIdpConfigID,
Method: global_model.SearchMethodEquals,
Value: idpConfigID,
}
orgIDQuery := &usr_model.ExternalIDPSearchQuery{
Key: usr_model.ExternalIDPSearchKeyResourceOwner,
Method: global_model.SearchMethodEquals,
Value: resourceOwner,
}
query := repository.PrepareSearchQuery(table, model.ExternalIDPSearchRequest{
Queries: []*usr_model.ExternalIDPSearchQuery{orgIDQuery, idpConfigIDQuery},
})
_, err := query(db, &externalIDPs)
return externalIDPs, err
}
func ExternalIDPsByIDPConfigIDAndResourceOwners(db *gorm.DB, table, idpConfigID string, resourceOwners []string) ([]*model.ExternalIDPView, error) {
externalIDPs := make([]*model.ExternalIDPView, 0)
idpConfigIDQuery := &usr_model.ExternalIDPSearchQuery{
Key: usr_model.ExternalIDPSearchKeyIdpConfigID,
Method: global_model.SearchMethodEquals,
Value: idpConfigID,
}
orgIDQuery := &usr_model.ExternalIDPSearchQuery{
Key: usr_model.ExternalIDPSearchKeyResourceOwner,
Method: global_model.SearchMethodIsOneOf,
Value: resourceOwners,
}
query := repository.PrepareSearchQuery(table, model.ExternalIDPSearchRequest{
Queries: []*usr_model.ExternalIDPSearchQuery{orgIDQuery, idpConfigIDQuery},
})
_, err := query(db, &externalIDPs)
return externalIDPs, err
}
func ExternalIDPsByUserID(db *gorm.DB, table, userID string) ([]*model.ExternalIDPView, error) {
externalIDPs := make([]*model.ExternalIDPView, 0)
orgIDQuery := &usr_model.ExternalIDPSearchQuery{

View File

@ -109,6 +109,20 @@ func UserGrantsByProjectAndUserID(db *gorm.DB, table, projectID, userID string)
return users, nil
}
func UserGrantsByProjectAndGrantID(db *gorm.DB, table, projectID, grantID string) ([]*model.UserGrantView, error) {
users := make([]*model.UserGrantView, 0)
queries := []*grant_model.UserGrantSearchQuery{
{Key: grant_model.UserGrantSearchKeyProjectID, Value: projectID, Method: global_model.SearchMethodEquals},
{Key: grant_model.UserGrantSearchKeyGrantID, Value: grantID, Method: global_model.SearchMethodEquals},
}
query := repository.PrepareSearchQuery(table, model.UserGrantSearchRequest{Queries: queries})
_, err := query(db, &users)
if err != nil {
return nil, err
}
return users, nil
}
func UserGrantsByProjectIDAndRole(db *gorm.DB, table, projectID, roleKey string) ([]*model.UserGrantView, error) {
users := make([]*model.UserGrantView, 0)
queries := []*grant_model.UserGrantSearchQuery{

View File

@ -2,6 +2,7 @@ package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
@ -21,7 +22,6 @@ func (r *CommandSide) AddDefaultIDPConfig(ctx context.Context, config *domain.ID
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
addedConfig := NewIAMIDPConfigWriteModel(idpConfigID)
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
@ -108,7 +108,7 @@ func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID stri
return r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
}
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string) error {
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string, idpProviders []*domain.IDPProvider, externalIDPs ...*domain.ExternalIDP) error {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
if err != nil {
return err
@ -116,10 +116,24 @@ func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string)
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
return caos_errs.ThrowNotFound(nil, "IAM-4M0xy", "Errors.IAM.IDPConfig.NotExisting")
}
aggregates := make([]eventstore.Aggregater, 0)
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(iam_repo.NewIDPConfigRemovedEvent(ctx, existingIDP.ResourceOwner, idpID, existingIDP.Name))
return r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
userAggregates := make([]eventstore.Aggregater, 0)
for _, idpProvider := range idpProviders {
if idpProvider.AggregateID == domain.IAMID {
userAggregates = r.removeIDPProviderFromDefaultLoginPolicy(ctx, iamAgg, idpProvider, true, externalIDPs...)
}
orgAgg := OrgAggregateFromWriteModel(&NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpID).WriteModel)
r.removeIDPProviderFromLoginPolicy(ctx, orgAgg, idpID, true)
}
aggregates = append(aggregates, iamAgg)
aggregates = append(aggregates, userAggregates...)
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) iamIDPConfigWriteModelByID(ctx context.Context, idpID string) (policy *IAMIDPConfigWriteModel, err error) {

View File

@ -2,6 +2,8 @@ package command
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/v2"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
@ -101,7 +103,7 @@ func (r *CommandSide) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, id
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
}
func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) error {
func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.ExternalIDP) error {
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
if err != nil {
@ -110,10 +112,35 @@ func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Contex
if idpModel.State == domain.IdentityProviderStateUnspecified || idpModel.State == domain.IdentityProviderStateRemoved {
return caos_errs.ThrowNotFound(nil, "IAM-39fjs", "Errors.IAM.LoginPolicy.IDP.NotExisting")
}
aggregates := make([]eventstore.Aggregater, 0)
iamAgg := IAMAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
return r.eventstore.PushAggregate(ctx, idpModel, iamAgg)
userAggregates := r.removeIDPProviderFromDefaultLoginPolicy(ctx, iamAgg, idpProvider, false, cascadeExternalIDPs...)
aggregates = append(aggregates, iamAgg)
aggregates = append(aggregates, userAggregates...)
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) removeIDPProviderFromDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, idpProvider *domain.IDPProvider, cascade bool, cascadeExternalIDPs ...*domain.ExternalIDP) []eventstore.Aggregater {
if cascade {
iamAgg.PushEvents(iam_repo.NewIdentityProviderCascadeRemovedEvent(ctx, idpProvider.IDPConfigID))
return nil
}
iamAgg.PushEvents(iam_repo.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
userAggregates := make([]eventstore.Aggregater, 0)
for _, idp := range cascadeExternalIDPs {
userAgg, _, err := r.removeHumanExternalIDP(ctx, idp, true)
if err != nil {
logging.LogWithFields("COMMAND-4nfsf", "userid", idp.AggregateID, "idp-id", idp.IDPConfigID).WithError(err).Warn("could not cascade remove externalidp in remove provider from policy")
continue
}
userAggregates = append(userAggregates, userAgg)
}
return userAggregates
}
func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType) (domain.SecondFactorType, error) {
@ -128,7 +155,7 @@ func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, s
return domain.SecondFactorTypeUnspecified, err
}
return domain.SecondFactorType(secondFactorModel.MFAType), nil
return secondFactorModel.MFAType, nil
}
func (r *CommandSide) addSecondFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, secondFactorModel *IAMSecondFactorWriteModel, secondFactor domain.SecondFactorType) error {

View File

@ -2,6 +2,7 @@ package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/v2/domain"
@ -32,17 +33,19 @@ func (r *CommandSide) checkOrgExists(ctx context.Context, orgID string) error {
}
func (r *CommandSide) SetUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human) error {
orgAgg, userAgg, orgMemberAgg, err := r.setUpOrg(ctx, organisation, admin)
orgAgg, userAgg, orgMemberAgg, claimedUsers, err := r.setUpOrg(ctx, organisation, admin)
if err != nil {
return err
}
_, err = r.eventstore.PushAggregates(ctx, orgAgg, userAgg, orgMemberAgg)
aggregates := make([]eventstore.Aggregater, 0)
aggregates = append(aggregates, orgAgg, userAgg, orgMemberAgg)
aggregates = append(aggregates, claimedUsers...)
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) AddOrg(ctx context.Context, name, userID, resourceOwner string) (*domain.Org, error) {
orgAgg, addedOrg, err := r.addOrg(ctx, &domain.Org{Name: name})
orgAgg, addedOrg, claimedUsers, err := r.addOrg(ctx, &domain.Org{Name: name})
if err != nil {
return nil, err
}
@ -56,7 +59,15 @@ func (r *CommandSide) AddOrg(ctx context.Context, name, userID, resourceOwner st
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedOrg, orgAgg)
aggregates := make([]eventstore.Aggregater, 0)
aggregates = append(aggregates, orgAgg)
aggregates = append(aggregates, claimedUsers...)
resEvents, err := r.eventstore.PushAggregates(ctx, aggregates...)
if err != nil {
return nil, err
}
addedOrg.AppendEvents(resEvents...)
err = addedOrg.Reduce()
if err != nil {
return nil, err
}
@ -97,46 +108,50 @@ func (r *CommandSide) ReactivateOrg(ctx context.Context, orgID string) error {
return r.eventstore.PushAggregate(ctx, orgWriteModel, orgAgg)
}
func (r *CommandSide) setUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human) (*org.Aggregate, *user.Aggregate, *org.Aggregate, error) {
orgAgg, _, err := r.addOrg(ctx, organisation)
func (r *CommandSide) setUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human) (*org.Aggregate, *user.Aggregate, *org.Aggregate, []eventstore.Aggregater, error) {
orgAgg, _, claimedUserAggregates, err := r.addOrg(ctx, organisation)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
userAgg, _, err := r.addHuman(ctx, orgAgg.ID(), admin)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
addedMember := NewOrgMemberWriteModel(orgAgg.ID(), userAgg.ID())
orgMemberAgg := OrgAggregateFromWriteModel(&addedMember.WriteModel)
err = r.addOrgMember(ctx, orgMemberAgg, addedMember, domain.NewMember(orgMemberAgg.ID(), userAgg.ID(), domain.RoleOrgOwner))
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
return orgAgg, userAgg, orgMemberAgg, nil
return orgAgg, userAgg, orgMemberAgg, claimedUserAggregates, nil
}
func (r *CommandSide) addOrg(ctx context.Context, organisation *domain.Org) (_ *org.Aggregate, _ *OrgWriteModel, err error) {
func (r *CommandSide) addOrg(ctx context.Context, organisation *domain.Org, claimedUserIDs ...string) (_ *org.Aggregate, _ *OrgWriteModel, _ []eventstore.Aggregater, err error) {
if organisation == nil || !organisation.IsValid() {
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMM-deLSk", "Errors.Org.Invalid")
return nil, nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMM-deLSk", "Errors.Org.Invalid")
}
organisation.AggregateID, err = r.idGenerator.Next()
if err != nil {
return nil, nil, caos_errs.ThrowInternal(err, "COMMA-OwciI", "Errors.Internal")
return nil, nil, nil, caos_errs.ThrowInternal(err, "COMMA-OwciI", "Errors.Internal")
}
organisation.AddIAMDomain(r.iamDomain)
addedOrg := NewOrgWriteModel(organisation.AggregateID)
orgAgg := OrgAggregateFromWriteModel(&addedOrg.WriteModel)
orgAgg.PushEvents(org.NewOrgAddedEvent(ctx, organisation.Name))
claimedUserAggregates := make([]eventstore.Aggregater, 0)
for _, orgDomain := range organisation.Domains {
if err := r.addOrgDomain(ctx, orgAgg, NewOrgDomainWriteModel(orgAgg.ID(), orgDomain.Domain), orgDomain); err != nil {
return nil, nil, err
aggregates, err := r.addOrgDomain(ctx, orgAgg, NewOrgDomainWriteModel(orgAgg.ID(), orgDomain.Domain), orgDomain, claimedUserIDs...)
if err != nil {
return nil, nil, nil, err
} else {
claimedUserAggregates = append(claimedUserAggregates, aggregates...)
}
}
return orgAgg, addedOrg, nil
return orgAgg, addedOrg, claimedUserAggregates, nil
}
func (r *CommandSide) getOrgWriteModelByID(ctx context.Context, orgID string) (*OrgWriteModel, error) {

View File

@ -2,6 +2,7 @@ package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/logging"
@ -15,14 +16,27 @@ import (
func (r *CommandSide) AddOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) (*domain.OrgDomain, error) {
domainWriteModel := NewOrgDomainWriteModel(orgDomain.AggregateID, orgDomain.Domain)
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
err := r.addOrgDomain(ctx, orgAgg, domainWriteModel, orgDomain)
userAggregates, err := r.addOrgDomain(ctx, orgAgg, domainWriteModel, orgDomain)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
if len(userAggregates) == 0 {
err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
if err != nil {
return nil, err
}
return orgDomainWriteModelToOrgDomain(domainWriteModel), nil
}
aggregates := make([]eventstore.Aggregater, 0)
aggregates = append(aggregates, orgAgg)
aggregates = append(aggregates, userAggregates...)
resultEvents, err := r.eventstore.PushAggregates(ctx, aggregates...)
if err != nil {
return nil, err
}
domainWriteModel.AppendEvents(resultEvents...)
domainWriteModel.Reduce()
return orgDomainWriteModelToOrgDomain(domainWriteModel), nil
}
@ -63,7 +77,7 @@ func (r *CommandSide) GenerateOrgDomainValidation(ctx context.Context, orgDomain
return token, url, nil
}
func (r *CommandSide) ValidateOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) error {
func (r *CommandSide) ValidateOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain, claimedUserIDs ...string) error {
if orgDomain == nil || !orgDomain.IsValid() {
return caos_errs.ThrowPreconditionFailed(nil, "ORG-R24hb", "Errors.Org.InvalidDomain")
}
@ -89,8 +103,20 @@ func (r *CommandSide) ValidateOrgDomain(ctx context.Context, orgDomain *domain.O
err = r.domainVerificationValidator(domainWriteModel.Domain, validationCode, validationCode, checkType)
orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel)
if err == nil {
aggregates := make([]eventstore.Aggregater, 0)
orgAgg.PushEvents(org.NewDomainVerifiedEvent(ctx, orgDomain.Domain))
return r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
aggregates = append(aggregates, orgAgg)
for _, userID := range claimedUserIDs {
userAgg, _, err := r.userDomainClaimed(ctx, userID)
if err != nil {
logging.LogWithFields("COMMAND-5m8fs", "userid", userID).WithError(err).Warn("could not claim user")
continue
}
aggregates = append(aggregates, userAgg)
}
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
orgAgg.PushEvents(org.NewDomainVerificationFailedEvent(ctx, orgDomain.Domain))
err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
@ -136,24 +162,33 @@ func (r *CommandSide) RemoveOrgDomain(ctx context.Context, orgDomain *domain.Org
return r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg)
}
func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *org.Aggregate, addedDomain *OrgDomainWriteModel, orgDomain *domain.OrgDomain) error {
func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *org.Aggregate, addedDomain *OrgDomainWriteModel, orgDomain *domain.OrgDomain, claimedUserIDs ...string) ([]eventstore.Aggregater, error) {
err := r.eventstore.FilterToQueryReducer(ctx, addedDomain)
if err != nil {
return err
return nil, err
}
if addedDomain.State == domain.OrgDomainStateActive {
return caos_errs.ThrowAlreadyExists(nil, "COMMA-Bd2jj", "Errors.Org.Domain.AlreadyExists")
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMA-Bd2jj", "Errors.Org.Domain.AlreadyExists")
}
orgAgg.PushEvents(org.NewDomainAddedEvent(ctx, orgDomain.Domain))
userAggregates := make([]eventstore.Aggregater, 0)
if orgDomain.Verified {
//TODO: uniqueness verified domain
//TODO: users with verified domain -> domain claimed
orgAgg.PushEvents(org.NewDomainVerifiedEvent(ctx, orgDomain.Domain))
for _, userID := range claimedUserIDs {
userAgg, _, err := r.userDomainClaimed(ctx, userID)
if err != nil {
logging.LogWithFields("COMMAND-nn8Jf", "userid", userID).WithError(err).Warn("could not claim user")
continue
}
userAggregates = append(userAggregates, userAgg)
}
}
if orgDomain.Primary {
orgAgg.PushEvents(org.NewDomainPrimarySetEvent(ctx, orgDomain.Domain))
}
return nil
return userAggregates, nil
}
func (r *CommandSide) getOrgDomainWriteModel(ctx context.Context, orgID, domain string) (*OrgDomainWriteModel, error) {

View File

@ -2,6 +2,7 @@ package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
@ -21,7 +22,6 @@ func (r *CommandSide) AddIDPConfig(ctx context.Context, config *domain.IDPConfig
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
addedConfig := NewOrgIDPConfigWriteModel(idpConfigID, config.AggregateID)
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
@ -109,7 +109,7 @@ func (r *CommandSide) ReactivateIDPConfig(ctx context.Context, idpID, orgID stri
return r.eventstore.PushAggregate(ctx, existingIDP, orgAgg)
}
func (r *CommandSide) RemoveIDPConfig(ctx context.Context, idpID, orgID string) error {
func (r *CommandSide) RemoveIDPConfig(ctx context.Context, idpID, orgID string, cascadeRemoveProvider bool, cascadeExternalIDPs ...*domain.ExternalIDP) error {
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
if err != nil {
return err
@ -121,10 +121,20 @@ func (r *CommandSide) RemoveIDPConfig(ctx context.Context, idpID, orgID string)
if existingIDP.State != domain.IDPConfigStateInactive {
return caos_errs.ThrowPreconditionFailed(nil, "Org-5Mo0d", "Errors.Org.IDPConfig.NotInactive")
}
aggregates := make([]eventstore.Aggregater, 0)
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
orgAgg.PushEvents(org_repo.NewIDPConfigRemovedEvent(ctx, existingIDP.ResourceOwner, idpID, existingIDP.Name))
return r.eventstore.PushAggregate(ctx, existingIDP, orgAgg)
userAggregates := make([]eventstore.Aggregater, 0)
if cascadeRemoveProvider {
userAggregates = r.removeIDPProviderFromLoginPolicy(ctx, orgAgg, idpID, true, cascadeExternalIDPs...)
}
aggregates = append(aggregates, orgAgg)
aggregates = append(aggregates, userAggregates...)
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) orgIDPConfigWriteModelByID(ctx context.Context, idpID, orgID string) (policy *OrgIDPConfigWriteModel, err error) {

View File

@ -2,6 +2,8 @@ package command
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/v2"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/v2/domain"
@ -38,7 +40,7 @@ func (r *CommandSide) ChangeLoginPolicy(ctx context.Context, policy *domain.Logi
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
return nil, caos_errs.ThrowNotFound(nil, "Org-M0sif", "Errors.Org.LoginPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIDP, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType))
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIDP, policy.ForceMFA, policy.PasswordlessType)
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-5M9vdd", "Errors.Org.LoginPolicy.NotChanged")
}
@ -89,7 +91,7 @@ func (r *CommandSide) AddIDPProviderToLoginPolicy(ctx context.Context, idpProvid
return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil
}
func (r *CommandSide) RemoveIDPProviderFromLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) error {
func (r *CommandSide) RemoveIDPProviderFromLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider, cascadeExternalIDPs ...*domain.ExternalIDP) error {
idpModel := NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
if err != nil {
@ -98,10 +100,36 @@ func (r *CommandSide) RemoveIDPProviderFromLoginPolicy(ctx context.Context, idpP
if idpModel.State == domain.IdentityProviderStateUnspecified || idpModel.State == domain.IdentityProviderStateRemoved {
return caos_errs.ThrowNotFound(nil, "Org-39fjs", "Errors.Org.LoginPolicy.IDP.NotExisting")
}
orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
orgAgg.PushEvents(org.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
return r.eventstore.PushAggregate(ctx, idpModel, orgAgg)
aggregates := make([]eventstore.Aggregater, 0)
orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
userAggregates := r.removeIDPProviderFromLoginPolicy(ctx, orgAgg, idpProvider.IDPConfigID, false, cascadeExternalIDPs...)
aggregates = append(aggregates, orgAgg)
aggregates = append(aggregates, userAggregates...)
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) removeIDPProviderFromLoginPolicy(ctx context.Context, orgAgg *org.Aggregate, idpConfigID string, cascade bool, cascadeExternalIDPs ...*domain.ExternalIDP) []eventstore.Aggregater {
if cascade {
orgAgg.PushEvents(org.NewIdentityProviderCascadeRemovedEvent(ctx, idpConfigID))
} else {
orgAgg.PushEvents(org.NewIdentityProviderRemovedEvent(ctx, idpConfigID))
}
userAggregates := make([]eventstore.Aggregater, 0)
for _, idp := range cascadeExternalIDPs {
userAgg, _, err := r.removeHumanExternalIDP(ctx, idp, true)
if err != nil {
logging.LogWithFields("COMMAND-n8RRf", "userid", idp.AggregateID, "idpconfigid", idp.IDPConfigID).WithError(err).Warn("could not cascade remove external idp")
continue
}
userAggregates = append(userAggregates, userAgg)
}
return userAggregates
}
func (r *CommandSide) AddSecondFactorToLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType, orgID string) (domain.SecondFactorType, error) {

View File

@ -2,6 +2,7 @@ package command
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/v2"
caos_errs "github.com/caos/zitadel/internal/errors"
@ -145,7 +146,7 @@ func (r *CommandSide) ReactivateProject(ctx context.Context, projectID string, r
return r.eventstore.PushAggregate(ctx, existingProject, projectAgg)
}
func (r *CommandSide) RemoveProject(ctx context.Context, projectID, resourceOwner string, cascadingGrantIDs ...string) error {
func (r *CommandSide) RemoveProject(ctx context.Context, projectID, resourceOwner string, cascadingUserGrantIDs ...string) error {
if projectID == "" || resourceOwner == "" {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-66hM9", "Errors.Project.ProjectIDMissing")
}
@ -163,10 +164,11 @@ func (r *CommandSide) RemoveProject(ctx context.Context, projectID, resourceOwne
projectAgg.PushEvents(project.NewProjectRemovedEvent(ctx, existingProject.Name, existingProject.ResourceOwner))
aggregates = append(aggregates, projectAgg)
for _, grantID := range cascadingGrantIDs {
for _, grantID := range cascadingUserGrantIDs {
grantAgg, _, err := r.removeUserGrant(ctx, grantID, "", true)
if err != nil {
return err
logging.LogWithFields("COMMAND-b8Djf", "usergrantid", grantID).WithError(err).Warn("could not cascade remove user grant")
continue
}
aggregates = append(aggregates, grantAgg)
}

View File

@ -2,10 +2,13 @@ package command
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/project"
"github.com/caos/zitadel/internal/v2/repository/usergrant"
"reflect"
)
@ -41,7 +44,7 @@ func (r *CommandSide) AddProjectGrant(ctx context.Context, grant *domain.Project
return projectGrantWriteModelToProjectGrant(addedGrant), nil
}
func (r *CommandSide) ChangeProjectGrant(ctx context.Context, grant *domain.ProjectGrant, resourceOwner string) (_ *domain.ProjectGrant, err error) {
func (r *CommandSide) ChangeProjectGrant(ctx context.Context, grant *domain.ProjectGrant, resourceOwner string, cascadeUserGrantIDs ...string) (_ *domain.ProjectGrant, err error) {
if grant.GrantID == "" {
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-1j83s", "Errors.IDMissing")
}
@ -58,16 +61,75 @@ func (r *CommandSide) ChangeProjectGrant(ctx context.Context, grant *domain.Proj
if reflect.DeepEqual(existingGrant.RoleKeys, grant.RoleKeys) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-0o0pL", "Errors.NoChangesFoundc")
}
projectAgg.PushEvents(project.NewGrantChangedEvent(ctx, grant.GrantID, grant.RoleKeys))
//TODO: Change UserGrants (if role removed should be removed from user grant)
err = r.eventstore.PushAggregate(ctx, existingGrant, projectAgg)
removedRoles := domain.GetRemovedRoles(existingGrant.RoleKeys, grant.RoleKeys)
if len(removedRoles) == 0 {
err = r.eventstore.PushAggregate(ctx, existingGrant, projectAgg)
if err != nil {
return nil, err
}
return projectGrantWriteModelToProjectGrant(existingGrant), nil
}
aggregates := make([]eventstore.Aggregater, 0)
aggregates = append(aggregates, projectAgg)
for _, userGrantID := range cascadeUserGrantIDs {
grantAgg, _, err := r.removeRoleFromUserGrant(ctx, userGrantID, removedRoles, true)
if err != nil {
continue
}
aggregates = append(aggregates, grantAgg)
}
resultEvents, err := r.eventstore.PushAggregates(ctx, aggregates...)
if err != nil {
return nil, err
}
existingGrant.AppendEvents(resultEvents...)
err = existingGrant.Reduce()
if err != nil {
return nil, err
}
return projectGrantWriteModelToProjectGrant(existingGrant), nil
}
func (r *CommandSide) removeRoleFromProjectGrant(ctx context.Context, projectAgg *project.Aggregate, projectID, projectGrantID, roleKey string, cascade bool) (_ *ProjectGrantWriteModel, err error) {
existingProjectGrant, err := r.projectGrantWriteModelByID(ctx, projectID, projectGrantID, "")
if err != nil {
return nil, err
}
if existingProjectGrant.State == domain.ProjectGrantStateUnspecified || existingProjectGrant.State == domain.ProjectGrantStateRemoved {
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.Grant.NotFound")
}
keyExists := false
for i, key := range existingProjectGrant.RoleKeys {
if key == roleKey {
keyExists = true
copy(existingProjectGrant.RoleKeys[i:], existingProjectGrant.RoleKeys[i+1:])
existingProjectGrant.RoleKeys[len(existingProjectGrant.RoleKeys)-1] = ""
existingProjectGrant.RoleKeys = existingProjectGrant.RoleKeys[:len(existingProjectGrant.RoleKeys)-1]
continue
}
}
if !keyExists {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5m8g9", "Errors.Project.Grant.RoleKeyNotFound")
}
changedProjectGrant := NewProjectGrantWriteModel(projectGrantID, projectID, existingProjectGrant.ResourceOwner)
if !cascade {
projectAgg.PushEvents(
project.NewGrantChangedEvent(ctx, projectGrantID, existingProjectGrant.RoleKeys),
)
} else {
projectAgg.PushEvents(
usergrant.NewUserGrantCascadeChangedEvent(ctx, existingProjectGrant.RoleKeys),
)
}
return changedProjectGrant, nil
}
func (r *CommandSide) DeactivateProjectGrant(ctx context.Context, projectID, grantID, resourceOwner string) (err error) {
if grantID == "" || projectID == "" {
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-p0s4V", "Errors.IDMissing")
@ -109,7 +171,7 @@ func (r *CommandSide) ReactivateProjectGrant(ctx context.Context, projectID, gra
return r.eventstore.PushAggregate(ctx, existingGrant, projectAgg)
}
func (r *CommandSide) RemoveProjectGrant(ctx context.Context, projectID, grantID, resourceOwner string) (err error) {
func (r *CommandSide) RemoveProjectGrant(ctx context.Context, projectID, grantID, resourceOwner string, cascadeUserGrantIDs ...string) (err error) {
if grantID == "" || projectID == "" {
return caos_errs.ThrowPreconditionFailed(nil, "PROJECT-1m9fJ", "Errors.IDMissing")
}
@ -121,10 +183,21 @@ func (r *CommandSide) RemoveProjectGrant(ctx context.Context, projectID, grantID
if err != nil {
return err
}
aggregates := make([]eventstore.Aggregater, 0)
projectAgg := ProjectAggregateFromWriteModel(&existingGrant.WriteModel)
projectAgg.PushEvents(project.NewGrantRemovedEvent(ctx, grantID, existingGrant.GrantedOrgID, projectID))
//TODO: Cascade Remove usergrants
return r.eventstore.PushAggregate(ctx, existingGrant, projectAgg)
aggregates = append(aggregates, projectAgg)
for _, userGrantID := range cascadeUserGrantIDs {
grantAgg, _, err := r.removeUserGrant(ctx, userGrantID, "", true)
if err != nil {
logging.LogWithFields("COMMAND-3m8sG", "usergrantid", grantID).WithError(err).Warn("could not cascade remove user grant")
continue
}
aggregates = append(aggregates, grantAgg)
}
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) projectGrantWriteModelByID(ctx context.Context, grantID, projectID, resourceOwner string) (member *ProjectGrantWriteModel, err error) {

View File

@ -90,15 +90,18 @@ func (wm *ProjectGrantWriteModel) Reduce() error {
}
func (wm *ProjectGrantWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
AggregateIDs(wm.AggregateID).
ResourceOwner(wm.ResourceOwner)
//EventTypes(
// project.GrantAddedType,
// project.GrantChangedType,
// project.GrantCascadeChangedType,
// project.GrantDeactivatedType,
// project.GrantReactivatedType,
// project.GrantRemovedType,
// project.ProjectRemovedType)
EventTypes(
project.GrantAddedType,
project.GrantChangedType,
project.GrantCascadeChangedType,
project.GrantDeactivatedType,
project.GrantReactivatedType,
project.GrantRemovedType,
project.ProjectRemovedType)
if wm.ResourceOwner != "" {
query.ResourceOwner(wm.ResourceOwner)
}
return query
}

View File

@ -2,7 +2,9 @@ package command
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/project"
)
@ -92,7 +94,7 @@ func (r *CommandSide) ChangeProjectRole(ctx context.Context, projectRole *domain
return roleWriteModelToRole(existingRole), nil
}
func (r *CommandSide) RemoveProjectRole(ctx context.Context, projectID, key, resourceOwner string) (err error) {
func (r *CommandSide) RemoveProjectRole(ctx context.Context, projectID, key, resourceOwner string, cascadingProjectGrantIds []string, cascadeUserGrantIDs ...string) (err error) {
if projectID == "" || key == "" {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4m9vS", "Errors.Project.Role.Invalid")
}
@ -103,12 +105,29 @@ func (r *CommandSide) RemoveProjectRole(ctx context.Context, projectID, key, res
if existingRole.State == domain.ProjectRoleStateUnspecified || existingRole.State == domain.ProjectRoleStateRemoved {
return caos_errs.ThrowNotFound(nil, "COMMAND-m9vMf", "Errors.Project.Role.NotExisting")
}
aggregates := make([]eventstore.Aggregater, 0)
projectAgg := ProjectAggregateFromWriteModel(&existingRole.WriteModel)
projectAgg.PushEvents(project.NewRoleRemovedEvent(ctx, key, projectID, existingRole.ResourceOwner))
//TODO: Update UserGrants (remove roles if on usergrants)
for _, projectGrantID := range cascadingProjectGrantIds {
_, err = r.removeRoleFromProjectGrant(ctx, projectAgg, projectID, projectGrantID, key, true)
if err != nil {
logging.LogWithFields("COMMAND-6n77g", "projectgrantid", projectGrantID).WithError(err).Warn("could not cascade remove role from project grant")
continue
}
}
aggregates = append(aggregates, projectAgg)
return r.eventstore.PushAggregate(ctx, existingRole, projectAgg)
for _, grantID := range cascadeUserGrantIDs {
grantAgg, _, err := r.removeRoleFromUserGrant(ctx, grantID, []string{key}, true)
if err != nil {
logging.LogWithFields("COMMAND-mK0of", "usergrantid", grantID).WithError(err).Warn("could not cascade remove role on user grant")
continue
}
aggregates = append(aggregates, grantAgg)
}
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) getProjectRoleWriteModelByID(ctx context.Context, key, projectID, resourceOwner string) (*ProjectRoleWriteModel, error) {

View File

@ -100,7 +100,7 @@ func (r *CommandSide) SetupStep1(ctx context.Context, step1 *Step1) error {
//create orgs
aggregates := make([]eventstore.Aggregater, 0)
for _, organisation := range step1.Orgs {
orgAgg, userAgg, orgMemberAgg, err := r.setUpOrg(ctx,
orgAgg, userAgg, orgMemberAgg, claimedUsers, err := r.setUpOrg(ctx,
&domain.Org{
Name: organisation.Name,
Domains: []*domain.OrgDomain{{Domain: organisation.Domain}},
@ -131,6 +131,7 @@ func (r *CommandSide) SetupStep1(ctx context.Context, step1 *Step1) error {
}
}
aggregates = append(aggregates, orgAgg, userAgg, orgMemberAgg)
aggregates = append(aggregates, claimedUsers...)
if organisation.Name == step1.GlobalOrg {
err = r.setGlobalOrg(ctx, iamAgg, iamWriteModel, orgAgg.ID())
if err != nil {

View File

@ -2,8 +2,11 @@ package command
import (
"context"
"fmt"
"github.com/caos/logging"
auth_req_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v2"
"strings"
"time"
@ -121,7 +124,7 @@ func (r *CommandSide) UnlockUser(ctx context.Context, userID, resourceOwner stri
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
}
func (r *CommandSide) RemoveUser(ctx context.Context, userID, resourceOwner string) error {
func (r *CommandSide) RemoveUser(ctx context.Context, userID, resourceOwner string, cascadingGrantIDs ...string) error {
if userID == "" {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M0ds", "Errors.User.UserIDMissing")
}
@ -136,11 +139,22 @@ func (r *CommandSide) RemoveUser(ctx context.Context, userID, resourceOwner stri
if err != nil {
return err
}
aggregates := make([]eventstore.Aggregater, 0)
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserRemovedEvent(ctx, existingUser.ResourceOwner, existingUser.UserName, orgIAMPolicy.UserLoginMustBeDomain))
//TODO: remove user grants
aggregates = append(aggregates, userAgg)
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
for _, grantID := range cascadingGrantIDs {
grantAgg, _, err := r.removeUserGrant(ctx, grantID, "", true)
if err != nil {
logging.LogWithFields("COMMAND-5m9oL", "usergrantid", grantID).WithError(err).Warn("could not cascade remove role on user grant")
continue
}
aggregates = append(aggregates, grantAgg)
}
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) CreateUserToken(ctx context.Context, orgID, agentID, clientID, userID string, audience, scopes []string, lifetime time.Duration) (*domain.Token, error) {
@ -193,6 +207,25 @@ func (r *CommandSide) CreateUserToken(ctx context.Context, orgID, agentID, clien
}, nil
}
func (r *CommandSide) userDomainClaimed(ctx context.Context, userID string) (_ *user.Aggregate, _ *UserWriteModel, err error) {
existingUser, err := r.userWriteModelByID(ctx, userID, "")
if err != nil {
return nil, nil, err
}
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-ii9K0", "Errors.User.NotFound")
}
changedUserGrant := NewUserWriteModel(userID, existingUser.ResourceOwner)
userAgg := UserAggregateFromWriteModel(&changedUserGrant.WriteModel)
id, err := r.idGenerator.Next()
if err != nil {
return nil, nil, err
}
userAgg.PushEvents(user.NewDomainClaimedEvent(ctx, fmt.Sprintf("%s@temporary.%s", id, r.iamDomain)))
return userAgg, changedUserGrant, nil
}
func (r *CommandSide) UserDomainClaimedSent(ctx context.Context, orgID, userID string) (err error) {
existingUser, err := r.userWriteModelByID(ctx, userID, orgID)
if err != nil {

View File

@ -108,6 +108,45 @@ func (r *CommandSide) changeUserGrant(ctx context.Context, userGrant *domain.Use
return userGrantAgg, changedUserGrant, nil
}
func (r *CommandSide) removeRoleFromUserGrant(ctx context.Context, userGrantID string, roleKeys []string, cascade bool) (_ *usergrant.Aggregate, _ *UserGrantWriteModel, err error) {
existingUserGrant, err := r.userGrantWriteModelByID(ctx, userGrantID, "")
if err != nil {
return nil, nil, err
}
if existingUserGrant.State == domain.UserGrantStateUnspecified || existingUserGrant.State == domain.UserGrantStateRemoved {
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.UserGrant.NotFound")
}
keyExists := false
for i, key := range existingUserGrant.RoleKeys {
for _, roleKey := range roleKeys {
if key == roleKey {
keyExists = true
copy(existingUserGrant.RoleKeys[i:], existingUserGrant.RoleKeys[i+1:])
existingUserGrant.RoleKeys[len(existingUserGrant.RoleKeys)-1] = ""
existingUserGrant.RoleKeys = existingUserGrant.RoleKeys[:len(existingUserGrant.RoleKeys)-1]
continue
}
}
}
if !keyExists {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5m8g9", "Errors.UserGrant.RoleKeyNotFound")
}
changedUserGrant := NewUserGrantWriteModel(userGrantID, "")
userGrantAgg := UserGrantAggregateFromWriteModel(&changedUserGrant.WriteModel)
if !cascade {
userGrantAgg.PushEvents(
usergrant.NewUserGrantChangedEvent(ctx, existingUserGrant.RoleKeys),
)
} else {
userGrantAgg.PushEvents(
usergrant.NewUserGrantCascadeChangedEvent(ctx, existingUserGrant.RoleKeys),
)
}
return userGrantAgg, changedUserGrant, nil
}
func (r *CommandSide) DeactivateUserGrant(ctx context.Context, grantID, resourceOwner string) (err error) {
if grantID == "" || resourceOwner == "" {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-M0dsf", "Errors.UserGrant.IDMissing")
@ -197,10 +236,13 @@ func (r *CommandSide) removeUserGrant(ctx context.Context, grantID, resourceOwne
if err != nil {
return nil, nil, err
}
err = checkExplicitProjectPermission(ctx, existingUserGrant.ProjectGrantID, existingUserGrant.ProjectID)
if err != nil {
return nil, nil, err
if !cascade {
err = checkExplicitProjectPermission(ctx, existingUserGrant.ProjectGrantID, existingUserGrant.ProjectID)
if err != nil {
return nil, nil, err
}
}
if existingUserGrant.State == domain.UserGrantStateUnspecified || existingUserGrant.State == domain.UserGrantStateRemoved {
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-1My0t", "Errors.UserGrant.NotFound")
}

View File

@ -10,7 +10,7 @@ import (
)
func (r *CommandSide) BulkAddedHumanExternalIDP(ctx context.Context, userID, resourceOwner string, externalIDPs []*domain.ExternalIDP) error {
if len(externalIDPs) == 0 {
if externalIDPs == nil || len(externalIDPs) == 0 {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Ek9s", "Errors.User.ExternalIDP.MinimumExternalIDPNeeded")
}
aggregates := make([]eventstore.Aggregater, len(externalIDPs))
@ -38,20 +38,24 @@ func (r *CommandSide) addHumanExternalIDP(ctx context.Context, userAgg *user.Agg
}
func (r *CommandSide) RemoveHumanExternalIDP(ctx context.Context, externalIDP *domain.ExternalIDP) error {
return r.removeHumanExternalIDP(ctx, externalIDP, false)
userAgg, writemodel, err := r.removeHumanExternalIDP(ctx, externalIDP, false)
if err != nil {
return err
}
return r.eventstore.PushAggregate(ctx, writemodel, userAgg)
}
func (r *CommandSide) removeHumanExternalIDP(ctx context.Context, externalIDP *domain.ExternalIDP, cascade bool) error {
func (r *CommandSide) removeHumanExternalIDP(ctx context.Context, externalIDP *domain.ExternalIDP, cascade bool) (*user.Aggregate, *HumanExternalIDPWriteModel, error) {
if externalIDP.IsValid() {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M9ds", "Errors.IDMissing")
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M9ds", "Errors.IDMissing")
}
existingExternalIDP, err := r.externalIDPWriteModelByID(ctx, externalIDP.AggregateID, externalIDP.IDPConfigID, externalIDP.ExternalUserID, externalIDP.ResourceOwner)
if err != nil {
return err
return nil, nil, err
}
if existingExternalIDP.State == domain.ExternalIDPStateUnspecified || existingExternalIDP.State == domain.ExternalIDPStateRemoved {
return caos_errs.ThrowNotFound(nil, "COMMAND-1M9xR", "Errors.User.ExternalIDP.NotFound")
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-1M9xR", "Errors.User.ExternalIDP.NotFound")
}
userAgg := UserAggregateFromWriteModel(&existingExternalIDP.WriteModel)
if !cascade {
@ -63,7 +67,7 @@ func (r *CommandSide) removeHumanExternalIDP(ctx context.Context, externalIDP *d
user.NewHumanExternalIDPCascadeRemovedEvent(ctx, externalIDP.IDPConfigID, externalIDP.ExternalUserID),
)
}
return r.eventstore.PushAggregate(ctx, existingExternalIDP, userAgg)
return userAgg, existingExternalIDP, nil
}
func (r *CommandSide) HumanExternalLoginChecked(ctx context.Context, orgID, userID string, authRequest *domain.AuthRequest) (err error) {

View File

@ -28,3 +28,22 @@ const (
func (p *ProjectGrant) IsValid() bool {
return p.GrantedOrgID != ""
}
func GetRemovedRoles(existingRoles, newRoles []string) []string {
removed := make([]string, 0)
for _, role := range existingRoles {
if !containsKey(newRoles, role) {
removed = append(removed, role)
}
}
return removed
}
func containsKey(roles []string, key string) bool {
for _, role := range roles {
if role == key {
return true
}
}
return false
}

View File

@ -29,5 +29,8 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(IDPConfigDeactivatedEventType, IDPConfigDeactivatedEventMapper).
RegisterFilterEventMapper(IDPConfigReactivatedEventType, IDPConfigReactivatedEventMapper).
RegisterFilterEventMapper(IDPOIDCConfigAddedEventType, IDPOIDCConfigAddedEventMapper).
RegisterFilterEventMapper(IDPOIDCConfigChangedEventType, IDPOIDCConfigChangedEventMapper)
RegisterFilterEventMapper(IDPOIDCConfigChangedEventType, IDPOIDCConfigChangedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderAddedEventType, IdentityProviderAddedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderRemovedEventType, IdentityProviderRemovedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderCascadeRemovedEventType, IdentityProviderCascadeRemovedEventMapper)
}

View File

@ -9,8 +9,9 @@ import (
)
var (
LoginPolicyIDPProviderAddedEventType = iamEventTypePrefix + policy.LoginPolicyIDPProviderAddedType
LoginPolicyIDPProviderRemovedEventType = iamEventTypePrefix + policy.LoginPolicyIDPProviderRemovedType
LoginPolicyIDPProviderAddedEventType = iamEventTypePrefix + policy.LoginPolicyIDPProviderAddedType
LoginPolicyIDPProviderRemovedEventType = iamEventTypePrefix + policy.LoginPolicyIDPProviderRemovedType
LoginPolicyIDPProviderCascadeRemovedEventType = iamEventTypePrefix + policy.LoginPolicyIDPProviderCascadeRemovedType
)
type IdentityProviderAddedEvent struct {
@ -67,3 +68,29 @@ func IdentityProviderRemovedEventMapper(event *repository.Event) (eventstore.Eve
IdentityProviderRemovedEvent: *e.(*policy.IdentityProviderRemovedEvent),
}, nil
}
type IdentityProviderCascadeRemovedEvent struct {
policy.IdentityProviderCascadeRemovedEvent
}
func NewIdentityProviderCascadeRemovedEvent(
ctx context.Context,
idpConfigID string,
) *IdentityProviderCascadeRemovedEvent {
return &IdentityProviderCascadeRemovedEvent{
IdentityProviderCascadeRemovedEvent: *policy.NewIdentityProviderCascadeRemovedEvent(
eventstore.NewBaseEventForPush(ctx, LoginPolicyIDPProviderCascadeRemovedEventType),
idpConfigID),
}
}
func IdentityProviderCascadeRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := policy.IdentityProviderCascadeRemovedEventMapper(event)
if err != nil {
return nil, err
}
return &IdentityProviderCascadeRemovedEvent{
IdentityProviderCascadeRemovedEvent: *e.(*policy.IdentityProviderCascadeRemovedEvent),
}, nil
}

View File

@ -12,6 +12,7 @@ import (
)
const (
uniqueOrgDomain = "org_domain"
domainEventPrefix = orgEventTypePrefix + "domain."
OrgDomainAddedEventType = domainEventPrefix + "added"
OrgDomainVerificationAddedEventType = domainEventPrefix + "verification.added"
@ -21,6 +22,19 @@ const (
OrgDomainRemovedEventType = domainEventPrefix + "removed"
)
func NewAddOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint(
uniqueOrgDomain,
orgDomain,
"Errors.Org.Domain.AlreadyExists")
}
func NewRemoveOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint(
uniqueOrgDomain,
orgDomain)
}
type DomainAddedEvent struct {
eventstore.BaseEvent `json:"-"`
@ -70,7 +84,7 @@ func (e *DomainVerificationAddedEvent) Data() interface{} {
}
func (e *DomainVerificationAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
return []*eventstore.EventUniqueConstraint{NewAddOrgDomainUniqueConstraint(e.Domain)}
}
func NewDomainVerificationAddedEvent(
@ -212,7 +226,8 @@ func DomainPrimarySetEventMapper(event *repository.Event) (eventstore.EventReade
type DomainRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
Domain string `json:"domain,omitempty"`
Domain string `json:"domain,omitempty"`
isVerified bool
}
func (e *DomainRemovedEvent) Data() interface{} {
@ -220,7 +235,10 @@ func (e *DomainRemovedEvent) Data() interface{} {
}
func (e *DomainRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
if !e.isVerified {
return nil
}
return []*eventstore.EventUniqueConstraint{NewRemoveOrgDomainUniqueConstraint(e.Domain)}
}
func NewDomainRemovedEvent(ctx context.Context, domain string) *DomainRemovedEvent {

View File

@ -31,6 +31,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(LoginPolicyMultiFactorRemovedEventType, MultiFactorRemovedEventEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderAddedEventType, IdentityProviderAddedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderRemovedEventType, IdentityProviderRemovedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderCascadeRemovedEventType, IdentityProviderCascadeRemovedEventMapper).
RegisterFilterEventMapper(OrgIAMPolicyAddedEventType, OrgIAMPolicyAddedEventMapper).
RegisterFilterEventMapper(OrgIAMPolicyChangedEventType, OrgIAMPolicyChangedEventMapper).
RegisterFilterEventMapper(OrgIAMPolicyRemovedEventType, OrgIAMPolicyRemovedEventMapper).

View File

@ -18,12 +18,6 @@ const (
OrgRemovedEventType = orgEventTypePrefix + "removed"
)
type OrgnameUniqueConstraint struct {
uniqueType string
orgName string
action eventstore.UniqueConstraintAction
}
func NewAddOrgNameUniqueConstraint(orgName string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint(
uniqueOrgname,

View File

@ -9,8 +9,9 @@ import (
)
var (
LoginPolicyIDPProviderAddedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderAddedType
LoginPolicyIDPProviderRemovedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderRemovedType
LoginPolicyIDPProviderAddedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderAddedType
LoginPolicyIDPProviderRemovedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderRemovedType
LoginPolicyIDPProviderCascadeRemovedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderCascadeRemovedType
)
type IdentityProviderAddedEvent struct {
@ -67,3 +68,29 @@ func IdentityProviderRemovedEventMapper(event *repository.Event) (eventstore.Eve
IdentityProviderRemovedEvent: *e.(*policy.IdentityProviderRemovedEvent),
}, nil
}
type IdentityProviderCascadeRemovedEvent struct {
policy.IdentityProviderCascadeRemovedEvent
}
func NewIdentityProviderCascadeRemovedEvent(
ctx context.Context,
idpConfigID string,
) *IdentityProviderCascadeRemovedEvent {
return &IdentityProviderCascadeRemovedEvent{
IdentityProviderCascadeRemovedEvent: *policy.NewIdentityProviderCascadeRemovedEvent(
eventstore.NewBaseEventForPush(ctx, LoginPolicyIDPProviderRemovedEventType),
idpConfigID),
}
}
func IdentityProviderCascadeRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := policy.IdentityProviderCascadeRemovedEventMapper(event)
if err != nil {
return nil, err
}
return &IdentityProviderCascadeRemovedEvent{
IdentityProviderCascadeRemovedEvent: *e.(*policy.IdentityProviderCascadeRemovedEvent),
}, nil
}

View File

@ -9,9 +9,10 @@ import (
)
const (
loginPolicyIDPProviderPrevix = loginPolicyPrefix + "idpprovider."
LoginPolicyIDPProviderAddedType = loginPolicyIDPProviderPrevix + "added"
LoginPolicyIDPProviderRemovedType = loginPolicyIDPProviderPrevix + "removed"
loginPolicyIDPProviderPrevix = loginPolicyPrefix + "idpprovider."
LoginPolicyIDPProviderAddedType = loginPolicyIDPProviderPrevix + "added"
LoginPolicyIDPProviderRemovedType = loginPolicyIDPProviderPrevix + "removed"
LoginPolicyIDPProviderCascadeRemovedType = loginPolicyIDPProviderPrevix + "cascade.removed"
)
type IdentityProviderAddedEvent struct {
@ -91,3 +92,40 @@ func IdentityProviderRemovedEventMapper(event *repository.Event) (eventstore.Eve
return e, nil
}
type IdentityProviderCascadeRemovedEvent struct {
eventstore.BaseEvent
IDPConfigID string `json:"idpConfigId"`
}
func (e *IdentityProviderCascadeRemovedEvent) Data() interface{} {
return e
}
func (e *IdentityProviderCascadeRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewIdentityProviderCascadeRemovedEvent(
base *eventstore.BaseEvent,
idpConfigID string,
) *IdentityProviderCascadeRemovedEvent {
return &IdentityProviderCascadeRemovedEvent{
BaseEvent: *base,
IDPConfigID: idpConfigID,
}
}
func IdentityProviderCascadeRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &IdentityProviderCascadeRemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "PROVI-7M9fs", "Errors.Internal")
}
return e, nil
}

View File

@ -0,0 +1,3 @@
ALTER TABLE management.login_policies ADD COLUMN default_policy BOOLEAN;
ALTER TABLE adminapi.login_policies ADD COLUMN default_policy BOOLEAN;
ALTER TABLE auth.login_policies ADD COLUMN default_policy BOOLEAN;

View File

@ -2,4 +2,4 @@
package migrations
//go:generate flyway -url=jdbc:postgresql://localhost:26257/defaultdb -user=root -password= -locations=filesystem:./ migrate
//go:generate flyway -url=jdbc:postgresql://localhost:26257/defaultdb -user=root -password= -locations=filesystem:./ -placeholders.eventstorepassword=NULL -placeholders.managementpassword=NULL -placeholders.adminapipassword=NULL -placeholders.authpassword=NULL -placeholders.notificationpassword=NULL -placeholders.authzpassword=NULL migrate