fix: merge master (#1306)

* 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>

* 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)

* 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>

* 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>

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

* 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>

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

* fix: usermemberships in authz (#1288)

* fix: usermemberships in authz

* fix: tests

* fix: migration

* fix: handler

* fix: my usermemberships (#1290)

* fix: my usermemberships

* frontend

Co-authored-by: Max Peintner <max@caos.ch>

* fix: my usermemberships (#1291)

* fix: my usermemberships

* fix: migration

* fix: migration (#1293)

* fix(login): chrome prefill, org register suffix offset, loginname overflow (#1292)

* fix: calculate offset, fix prefill

* fix loginname, displayname overflow

* feat: docs rehaul, fix missing context in console, quickstarts (#1212)

* onboarding components, routing, steps

* onboarding component, toc

* fix onboarding mixin

* header

* refactor docs

* fix layout

* cleanup routing

* docs routing

* fix conventions

* de en routing

* docs, guide contents, nav

* rem i18n support

* fix routing from docs

* rollup onwarn changes, preload

* update svelte plugin, update rollup config

* move docs

* revert img style, remove code table

* rem de completely

* rollup optim, template

* angular quickstart, quickstart overview page, update deps

* fix link

* pack, slug

* prefetch binding, hidden links

* export log

* guards route ch

* fix homepage

* angular docs

* docs

* resolve fsh

* overview

* docs

* docs

* packages fix race condition

* nav, home link

* add vue, aspnet

* doc optimizations

* embed status pal

* angular guide

* angular guide

* dotnet, angular guide

* viewbox

* typo

* block onboarding route for non iam writers

* set links from component data

* fix: fetch org context in guard, more main cnt (#1192)

* change get started guide, fix code blockquotes, typos

* flutter guide

* h2 spacing

* highlight strong

* plus

* rm start sublinks

* add proxy quickstart

* regex

* prevent outside click, fix project grant write

Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix(console): auth guard, i18n (#1296)

* fix: auth guard, i18n

* Update console/src/app/guards/auth.guard.ts

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

* feat(console): OIDC setup (#1272)

* feat: delete app

* radio button mods, i18n

* radio style, recommended flag

* fix form, emitter, module, styles

* app oidc

* form value change

* cleanup

* app grid, new app detail, redirect, i18n

* new uri format

* seperate uris

* cleanup export, create redirect

* fix custom two way binding, switch

* chore(deps): bump grpc from 1.24.3 to 1.24.5 in /console (#1287)

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

* chore(deps): bump grpc from 1.24.3 to 1.24.5 in /console

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

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

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

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

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

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.22 to 14.14.28.
- [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: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @angular-devkit/build-angular from 0.1101.2 to 0.1102.0 in /console (#1285)

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

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

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1101.2 to 0.1102.0.
- [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: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump typescript from 4.0.5 to 4.0.7 in /console (#1284)

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

* chore(deps-dev): bump typescript from 4.0.5 to 4.0.7 in /console

Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.5 to 4.0.7.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.5...v4.0.7)

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

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

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

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

Bumps [karma](https://github.com/karma-runner/karma) from 6.0.3 to 6.1.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.3...v6.1.1)

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @angular/language-service from 11.1.1 to 11.2.0 in /console (#1282)

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

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

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

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

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

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

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

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

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

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

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

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

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

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump stylelint-scss from 3.18.0 to 3.19.0 in /console (#1279)

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

* chore: pass params in migrate_local.go (#1264)

* fix: login policy bug (#1268)

* fix: permissions on login policy multifactors and secondfactors

* fix idp restriction

Co-authored-by: Max Peintner <max@caos.ch>

* fix: redirect after idp create (#1269)

* fix(pipeline): corrected and combined operator and zitadel release into combined workflow (#1273)

* fix(pipeline): combined operator and zitadel workflow to only release once

* fix(pipeline): add dev releases for zitadelctl

* fix(pipeline): delete unused name attribute

* fix(pipeline): corrected use of github token env-variable

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected download of artifacts to globally defined folder

* fix(pipeline): corrected ref to get branch name for release

* fix(pipeline): last corrections and use of different github action (#1270)

* fix(pipeline): corrected loop for dev release

* fix(pipeline): exclude tags from starting build workflow

* fix(pipeline): use different release create action for already existing release

* fix(pipeline): use correct name for release

* fix(pipeline): push image with branch name tag and replace slashes with underscores

* fix(pipeline): corrected indenting for yaml syntax

* fix(pipeline): corrected handling of branch name

* fix(pipeline): list artifacts after download

* fix(pipeline): use github env for artifacts folder

* fix(pipeline): replace slash with underscore in all jobs

* fix(pipeline): pre-calculate refs for all jobs

* fix(pipeline): corrected yaml indenting

* fix(pipeline): deleted missed step

* fix(pipeline): deleted unexpected input for dev-release

* fix(pipeline): corrected echo for version in refs job

* fix(pipeline): remove empty if in job

* chore(pipeline): use correct path to zitadelctl binaries (#1277)

* fix(pipeline): use correct version for zitadelctl build (#1278)

* chore(deps-dev): bump stylelint-scss from 3.18.0 to 3.19.0 in /console

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

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

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix custom change, highlight current config, links

* info app-detail

* app card component

* applications list, fix project-grant-owner

* fix member write

* colorize warn in app

* redirect warnings

* Update console/src/assets/i18n/de.json

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

* Update console/src/assets/i18n/de.json

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

* Update console/src/assets/i18n/en.json

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

* Update console/src/assets/i18n/de.json

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

* Update console/src/assets/i18n/de.json

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

* Update console/src/assets/i18n/de.json

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

* Update console/src/assets/i18n/de.json

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

* remove comments

* Update console/src/assets/i18n/de.json

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

* Update console/src/assets/i18n/de.json

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>

* fix: primary button color (#1297)

* fix: remove status, admin line width (#1298)

* feat: token introspection, api clients and auth method private_key_jwt (#1276)

* introspect

* testingapplication key

* date

* client keys

* fix client keys

* fix client keys

* access tokens only for users

* AuthMethodPrivateKeyJWT

* client keys

* set introspection info correctly

* managae apis

* update oidc pkg

* cleanup

* merge msater

* set current sequence in migration

* set current sequence in migration

* set current sequence in migration

* Apply suggestions from code review

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

* DeleteAuthNKeysByObjectID

* ensure authn keys uptodate

* update oidc version

* merge master

* merge master

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

* merge master

* fix: version of migration for auth keys

* merge master

* merge master

* fix step 11

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: Maximilian Peintner <csaq7175@uibk.ac.at>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
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:
Livio Amstutz 2021-02-18 13:41:55 +01:00 committed by GitHub
parent ee86eb4399
commit 027a6386c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
316 changed files with 9632 additions and 4919 deletions

View File

@ -1,91 +0,0 @@
name: Zitadel Release
on: push
env:
GITHUB_TOKEN: ${{ secrets.CR_PAT }}
REGISTRY: ghcr.io
NODE_VERSION: '12'
GO_VERSION: '1.15'
jobs:
container:
runs-on: ubuntu-18.04
steps:
- name: Source checkout
uses: actions/checkout@v2
- name: Set output
id: branch
run: echo ::set-output name=short_ref::${GITHUB_REF#refs/*/}
- name: Check output
run: echo ${{ steps.branch.outputs.short_ref }}
- name: Generate Short SHA Container Tag
id: vars
run: echo "::set-output name=sha_short::SHA-$(git rev-parse --short=12 HEAD)"
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ github.actor }}
password: ${{ secrets.CR_PAT }}
registry: ${{ env.REGISTRY }}
- uses: docker/build-push-action@v2
with:
context: .
file: ./build/dockerfile
platforms: linux/amd64
tags: ${{ env.REGISTRY }}/${{ github.repository }}:${{ steps.vars.outputs.sha_short }},${{ env.REGISTRY }}/${{ github.repository }}:${{ steps.branch.outputs.short_ref }}
push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache
release:
runs-on: ubuntu-18.04
needs: [container]
env:
DOCKER_USERNAME: ${{ github.actor }}
DOCKER_PASSWORD: ${{ secrets.CR_PAT }}
steps:
- name: Source checkout
uses: actions/checkout@v2
- name: Generate Short SHA Container Tag
id: vars
run: echo "::set-output name=sha_short::SHA-$(git rev-parse --short=12 HEAD)"
- name: Docker Login
run: docker login $REGISTRY -u $GITHUB_ACTOR -p $GITHUB_TOKEN
- name: Docker Pull short-sha
run: docker pull $REGISTRY/$GITHUB_REPOSITORY:${{ steps.vars.outputs.sha_short }}
- name: Semantic Release
id: semantic
uses: cycjimmy/semantic-release-action@v2
with:
dry_run: false
semantic_version: 17.0.4
- name: Do something when a new release published
if: steps.semantic.outputs.new_release_published == 'true'
run: |
echo ${{ steps.semantic.outputs.new_release_version }}
echo ${{ steps.semantic.outputs.new_release_major_version }}
echo ${{ steps.semantic.outputs.new_release_minor_version }}
echo ${{ steps.semantic.outputs.new_release_patch_version }}
- name: Docker Tag Version
run: docker tag $REGISTRY/$GITHUB_REPOSITORY:${{ steps.vars.outputs.sha_short }} $REGISTRY/$GITHUB_REPOSITORY:${{ steps.semantic.outputs.new_release_version }}
if: steps.semantic.outputs.new_release_published == 'true'
- name: Docker Tag Latest
run: docker tag $REGISTRY/$GITHUB_REPOSITORY:${{ steps.vars.outputs.sha_short }} $REGISTRY/$GITHUB_REPOSITORY:latest
if: steps.semantic.outputs.new_release_published == 'true'
- name: Docker Push Version
run: docker push $REGISTRY/$GITHUB_REPOSITORY:${{ steps.semantic.outputs.new_release_version }}
if: steps.semantic.outputs.new_release_published == 'true'
- name: Docker Push Latest
run: docker push $REGISTRY/$GITHUB_REPOSITORY:latest
if: steps.semantic.outputs.new_release_published == 'true'

View File

@ -6,15 +6,15 @@ module.exports = {
["@semantic-release/github", {
"assets": [
{
"path": ".artifacts/zitadel-darwin-amd64/zitadelctl",
"path": "./artifacts/zitadelctl-darwin-amd64/zitadelctl-darwin-amd64",
"label": "Zitadelctl Darwin x86_64"
},
{
"path": ".artifacts/zitadel-linux-amd64/zitadelctl",
"path": "./artifacts/zitadelctl-linux-amd64/zitadelctl-linux-amd64",
"label": "Zitadelctl Linux x86_64"
},
{
"path": ".artifacts/zitadel-windows-amd64/zitadelctl",
"path": "./artifacts/zitadelctl-windows-amd64/zitadelctl-windows-amd64.exe",
"label": "Zitadelctl Windows x86_64"
}
]

View File

@ -88,7 +88,7 @@ SetUp:
Step6:
DefaultLabelPolicy:
PrimaryColor: '#222324'
SecondaryColor: '#ffffff'
SecondaryColor: '#ffffff'
Step7:
OTP: true
Step8:
@ -180,4 +180,4 @@ SetUp:
Text: The domain {{.Domain}} has been claimed by an organisation. Your current user {{.Username}} is not part of this organisation. Therefore you'll have to change your email when you login. We have created a temporary username ({{.TempUsername}}) for this login.
ButtonText: Login
Step11:
MigrateV1EventstoreToV2: true
MigrateV1EventstoreToV2: $ZITADEL_MIGRATE_ES_V1

View File

@ -17,6 +17,7 @@ Metrics:
MeterName: 'github.com/caos/zitadel'
AuthZ:
Domain: $ZITADEL_DEFAULT_DOMAIN
Repository:
Eventstore:
ServiceName: 'AuthZ'
@ -186,6 +187,7 @@ API:
Issuer: $ZITADEL_ISSUER
DefaultLogoutRedirectURI: $ZITADEL_ACCOUNTS/logout/done
CodeMethodS256: true
AuthMethodPrivateKeyJWT: true
StorageConfig:
DefaultLoginURL: $ZITADEL_ACCOUNTS/login?authRequestID=
DefaultAccessTokenLifetime: 12h
@ -207,6 +209,9 @@ API:
Token:
Path: 'token'
URL: '$ZITADEL_OAUTH/token'
Introspection:
Path: 'introspect'
URL: '$ZITADEL_OAUTH/introspect'
EndSession:
Path: 'endsession'
URL: '$ZITADEL_AUTHORIZE/endsession'

View File

@ -45,6 +45,7 @@ SystemDefaults:
IncludeDigits: true
IncludeSymbols: false
MachineKeySize: 2048
ClientKeySize: 2048
Multifactors:
OTP:
Issuer: 'ZITADEL'

3781
console/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@
"file-saver": "^2.0.5",
"google-proto-files": "^2.4.0",
"google-protobuf": "^3.13.0",
"grpc": "^1.24.3",
"grpc": "^1.24.5",
"grpc-web": "^1.2.1",
"moment": "^2.29.1",
"ngx-quicklink": "^0.2.6",
@ -44,28 +44,28 @@
"zone.js": "~0.11.3"
},
"devDependencies": {
"@angular/cli": "~11.1.2",
"@angular-devkit/build-angular": "~0.1101.2",
"@angular/cli": "~11.2.0",
"@angular-devkit/build-angular": "~0.1102.0",
"@angular/compiler-cli": "~11.0.0",
"@types/jasmine": "~3.6.3",
"@angular/language-service": "~11.1.1",
"@angular/language-service": "~11.2.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^14.14.22",
"@types/node": "^14.14.28",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~6.0.0",
"karma": "~6.0.3",
"karma": "~6.1.1",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"prettier": "^2.2.1",
"protractor": "~7.0.0",
"stylelint": "^13.9.0",
"stylelint": "^13.10.0",
"stylelint-config-standard": "^20.0.0",
"stylelint-scss": "^3.18.0",
"stylelint-scss": "^3.19.0",
"ts-node": "~9.1.1",
"tslint": "~6.1.3",
"typescript": "^4.0.5"
"typescript": "^4.0.7"
}
}

View File

@ -11,6 +11,15 @@ const routes: Routes = [
loadChildren: () => import('./pages/home/home.module').then(m => m.HomeModule),
canActivate: [AuthGuard],
},
{
path: 'firststeps',
loadChildren: () => import('./modules/onboarding/onboarding.module')
.then(m => m.OnboardingModule),
canActivate: [AuthGuard, RoleGuard],
data: {
roles: ['iam.write'],
}
},
{
path: 'granted-projects',
loadChildren: () => import('./pages/projects/granted-projects/granted-projects.module')

View File

@ -1,19 +1,25 @@
<ng-container *ngIf="(authService.user | async) || {} as user">
<ng-container *ngIf="((['iam.read$','iam.write$'] | hasRole)) as iamuser$">
<mat-toolbar class="root-header">
<button aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()">
<button *ngIf="authenticationService.authenticated" aria-label="Toggle sidenav" mat-icon-button
(click)="drawer.toggle()">
<i class="icon las la-bars"></i>
</button>
<a *ngIf="(isHandset$ | async) == false" class="title" [routerLink]="['/']">
<a class="title" [routerLink]="['/']">
<img class="logo" alt="zitadel logo" *ngIf="componentCssClass == 'dark-theme'; else lighttheme"
src="../assets/images/zitadel-logo-light.svg" />
src="../assets/images/zitadel-logo-solo-light.svg" />
<ng-template #lighttheme>
<img alt="zitadel logo" class="logo" src="../assets/images/zitadel-logo-dark.svg" />
<img alt="zitadel logo" class="logo" src="../assets/images/zitadel-logo-solo-dark.svg" />
</ng-template>
</a>
<button (click)="loadOrgs()" *ngIf="profile?.id && org" mat-button [matMenuTriggerFor]="menu"
(menuOpened)="focusFilter()">{{org?.name ? org.name : 'NO NAME'}}
<svg class="slash" viewBox="0 0 24 24" width="32" height="32" stroke="currentColor" stroke-width="1"
stroke-linecap="round" stroke-linejoin="round" fill="none" shape-rendering="geometricPrecision">
<path d="M16.88 3.549L7.12 20.451"></path>
</svg>
<button class="org-button" (click)="loadOrgs()" *ngIf="profile?.id && org" mat-button
[matMenuTriggerFor]="menu" (menuOpened)="focusFilter()">{{org?.name ? org.name : 'NO NAME'}}
<mat-icon>
arrow_drop_down</mat-icon>
</button>
@ -37,8 +43,8 @@
</button>
</div>
<button class="show-all" mat-menu-item
[routerLink]="[ '/org/overview' ]">{{'MENU.SHOWORGS' | translate}}</button>
<button class="show-all" mat-menu-item [routerLink]="[ '/org/overview' ]">{{'MENU.SHOWORGS' |
translate}}</button>
<ng-template appHasRole [appHasRole]="['org.create','iam.write']">
<button mat-menu-item [routerLink]="[ '/org/create' ]">
@ -49,23 +55,29 @@
</mat-menu>
<span class="fill-space"></span>
<a class="doc-link" href="https://docs.zitadel.ch" mat-stroked-button
target="_blank">{{'MENU.DOCUMENTATION' | translate}}</a>
<a class="doc-link" href="https://docs.zitadel.ch" mat-stroked-button target="_blank">{{'MENU.DOCUMENTATION'
| translate}}</a>
<div (clickOutside)="closeAccountCard()" class="icon-container">
<app-avatar *ngIf="user && (user.displayName || (user.firstName && user.lastName))"
class="avatar dontcloseonclick" (click)="showAccount = !showAccount" [active]="showAccount"
[name]="user.displayName ? user.displayName : (user.firstName + ' '+ user.lastName)" [size]="38">
</app-avatar>
<app-accounts-card @accounts class="a_card mat-elevation-z5" *ngIf="showAccount"
<app-accounts-card @accounts class="a_card mat-elevation-z1" *ngIf="showAccount"
(close)="showAccount = false" [profile]="profile" [iamuser]="iamuser$ | async">
</app-accounts-card>
</div>
</mat-toolbar>
<mat-drawer-container class="main-container">
<mat-drawer #drawer class="sidenav" [mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="!(isHandset$ | async)">
[opened]="!(isHandset$ | async) && authenticationService.authenticated">
<div class="side-column">
<div class="list">
<a @navitem class="nav-item" [routerLinkActive]="['active']"
[routerLinkActiveOptions]="{ exact: true }" [routerLink]="['/']">
<i class="icon las la-home"></i>
<span class="label">{{ 'MENU.DASHBOARD' | translate }}</span>
</a>
<ng-container *ngIf="authenticationService.authenticationChanged | async">
<a @navitem matTooltip="{{'MENU.TOOLTIP.PERSONAL' | translate}}" class="nav-item"
[routerLinkActive]="['active']" [routerLinkActiveOptions]="{ exact: true }"
@ -163,6 +175,13 @@
</ng-container>
<span class="fill-space"></span>
<div class="toc-line">
<a class="toc" href="https://zitadel.ch/pdf/agb.pdf" alt="Terms and Conditions"
target="_blank">{{'MENU.TOC'
| translate}}</a>
<span>&nbsp;&nbsp;&nbsp;</span>
</div>
</div>
<span class="fill-space"></span>
</div>

View File

@ -11,9 +11,14 @@
left: 0;
right: 0;
.org-button {
font-weight: bold;
padding-right: .5rem;
}
.logo {
max-height: 50px;
width: 160px;
max-height: 40px;
width: 40px;
}
.title {
@ -22,7 +27,6 @@
font-size: 1.2rem;
font-weight: 400;
line-height: 1.2rem;
margin-right: 1rem;
}
.context-menu {
@ -82,7 +86,7 @@
padding-top: 60px;
.sidenav {
width: 300px;
width: 280px;
border-right: none;
.side-column {
@ -90,6 +94,7 @@
display: flex;
flex-direction: column;
align-items: stretch;
height: calc(100% - 60px);
.list {
width: 100%;
@ -123,7 +128,6 @@
.label {
margin-bottom: 0;
font-size: 14px;
letter-spacing: .05em;
}
.c_label {
@ -132,7 +136,6 @@
justify-content: space-between;
align-items: center;
font-size: 14px;
letter-spacing: .03em;
.count {
font-size: 12px;
@ -140,7 +143,7 @@
}
&:hover {
background-color: #00000010;
// background-color: #00000010;
border-top-right-radius: 1.5rem;
border-bottom-right-radius: 1.5rem;
}
@ -148,6 +151,7 @@
&.active {
border-top-right-radius: 1.5rem;
border-bottom-right-radius: 1.5rem;
font-weight: bold;
}
}
@ -160,6 +164,43 @@
flex: 1 1 auto;
}
.toc-line {
margin: 2rem 2rem;
.toc {
font-size: 12px;
color: var(--grey);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.sp-status {
font-size: 12px;
color: var(--grey);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.sp-status .sp-status-badge.sp-status-ok {
background: darkgreen;
}
.sp-status .sp-status-badge.sp-status-scheduled {
background: darkblue;
}
.sp-status .sp-status-badge.sp-status-minor {
background: darkorange;
}
.sp-status .sp-status-badge.sp-status-major {
background: darkred;
}
}
.logout-button {
margin-bottom: 1rem;
}

View File

@ -251,7 +251,7 @@ export class AppComponent implements OnDestroy {
}
private getProjectCount(): void {
this.authService.isAllowed(['project.read$']).subscribe((allowed) => {
this.authService.isAllowed(['project.read']).subscribe((allowed) => {
if (allowed) {
this.mgmtService.SearchProjects(0, 0);

View File

@ -23,6 +23,7 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { AuthConfig, OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
import { QuicklinkModule } from 'ngx-quicklink';
import { OnboardingModule } from 'src/app/modules/onboarding/onboarding.module';
import { RegExpPipeModule } from 'src/app/pipes/regexp-pipe/regexp-pipe.module';
import { environment } from '../environments/environment';
@ -121,6 +122,7 @@ const authConfig: AuthConfig = {
WarnDialogModule,
MatDialogModule,
RegExpPipeModule,
OnboardingModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
],
providers: [

View File

@ -3,18 +3,19 @@ import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angul
import { Observable } from 'rxjs';
import { AuthenticationService } from '../services/authentication.service';
import { GrpcAuthService } from '../services/grpc-auth.service';
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private auth: AuthenticationService) { }
constructor(private auth: AuthenticationService, private authService: GrpcAuthService) { }
public canActivate(
_: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> | Promise<boolean> | boolean {
): Observable<boolean> | Promise<boolean> | Promise<any> | boolean {
if (!this.auth.authenticated) {
return this.auth.authenticate();
}

View File

@ -0,0 +1,5 @@
<div class="cnsl-app-card" [ngClass]="{'web': type == OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB,
'useragent': type == OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT,
'native': type == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE}">
<ng-content></ng-content>
</div>

View File

@ -0,0 +1,49 @@
@import '~@angular/material/theming';
@mixin app-card-theme($theme) {
/* stylelint-disable */
$primary: map-get($theme, primary);
$primary-dark: mat-color($primary, A900);
$accent: map-get($theme, accent);
$is-dark-theme: map-get($theme, is-dark);
$accent-color: mat-color($primary, 500);
/* stylelint-enable */
.cnsl-app-card {
padding: 1rem;
box-sizing: border-box;
cursor: pointer;
animation: all .2s;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 2rem;
height: 80px;
width: 80px;
margin: 1rem;
text-transform: uppercase;
border-radius: .5rem;
font-weight: 800;
background-color: $primary-dark;
transition: background-color box-shadow .3s ease-in;
&.web {
background-color: rgb(80, 110, 110);
color: white;
border: none;
}
&.native {
background-color: #595d80;
color: white;
border: none;
}
&.useragent {
background-color: #6a506e;
color: white;
border: none;
}
}
}

View File

@ -0,0 +1,14 @@
import { Component, Input } from '@angular/core';
import { OIDCApplicationType } from 'src/app/proto/generated/management_pb';
@Component({
selector: 'cnsl-app-card',
templateUrl: './app-card.component.html',
styleUrls: ['./app-card.component.scss'],
})
export class AppCardComponent {
@Input() public outline: boolean = false;
@Input() public type!: OIDCApplicationType;
public OIDCApplicationType: any = OIDCApplicationType;
}

View File

@ -0,0 +1,15 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { AppCardComponent } from './app-card.component';
@NgModule({
declarations: [AppCardComponent],
imports: [
CommonModule,
],
exports: [
AppCardComponent,
],
})
export class AppCardModule { }

View File

@ -0,0 +1,35 @@
<div class="radio-button-wrapper">
<ng-container *ngFor="let method of authMethods; index as i">
<input type="radio" [disabled]="method.disabled" (change)="emitChange()" [value]="method.key" [id]="method.key"
[(ngModel)]="selected" />
<label class="cnsl-radio-button" [ngClass]="{'first': i == 0, 'last': i == authMethods.length - 1}"
[for]="method.key">
<div class="recommended" [ngClass]="{'not': method.notRecommended}"
*ngIf="method.recommended || method.notRecommended">
{{(method.recommended ?
'APP.OIDC.RECOMMENDED' : 'APP.OIDC.NOTRECOMMENDED') | translate }}</div>
<div class="cnsl-radio-header" [ngStyle]="{'background': method.background}">
<span>{{method.prefix}}</span>
<div class="current" *ngIf="current == method.key">{{'APP.OIDC.CURRENT' | translate}}</div>
</div>
<p>{{method.titleI18nKey | translate}}</p>
<p class="type-desc">{{method.descI18nKey | translate}}</p>
<span class="fill-space"></span>
<div class="app-specs">
<div class="row" *ngIf="method && method.responseType != undefined">
<span>{{'APP.OIDC.RESPONSE' | translate}}</span>
<span>{{('APP.OIDC.RESPONSE'+method.responseType.toString()) | translate}}</span>
</div>
<div class="row" *ngIf="method.grantType != undefined">
<span>{{'APP.GRANT' | translate}}</span>
<span>{{('APP.OIDC.GRANT'+method.grantType.toString()) | translate}}</span>
</div>
<div class="row" *ngIf="method.authMethod != undefined">
<span>{{'APP.OIDC.AUTHMETHOD' | translate}}</span>
<span>{{('APP.OIDC.AUTHMETHOD'+method.authMethod.toString()) | translate}}</span>
</div>
</div>
</label>
</ng-container>
</div>

View File

@ -0,0 +1,140 @@
@import '~@angular/material/theming';
.radio-button-wrapper {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
overflow-x: auto;
overflow-y: hidden;
margin: 0;
padding-bottom: .5rem;
padding-top: 1rem;
}
@mixin app-auth-method-radio-theme($theme) {
$primary: map-get($theme, primary);
$primary-color: mat-color($primary, 500);
$is-dark-theme: map-get($theme, is-dark);
input[type="radio"]{
appearance: none;
opacity: 0;
display: none;
}
input:checked + label {
border-color: if($is-dark-theme, white, var(--grey));
.cnsl-radio-header span {
color: if($is-dark-theme, white, white);
}
}
.cnsl-radio-button {
margin: .5rem;
border-radius: .5rem;
border: 1px solid if($is-dark-theme, var(--grey), white);
display: flex;
flex-direction: column;
flex: 0 1 230px;
cursor: pointer;
position: relative;
padding-bottom: 1rem;
box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
&.first {
margin-left: 0;
}
&.last {
margin-right: 0;
}
.recommended {
position: absolute;
bottom: 0;
left: 50%;
transform: translateY(50%) translateX(-50%);
border-radius: 50vw;
font-size: 11px;
background: white;
color: black;
padding: 3px 1rem;
box-shadow: 0 0 6px rgb(0 0 0 / 10%);
white-space: nowrap;
&.not {
background: rgb(144 75 75);
color: white;
}
}
.cnsl-radio-header {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background: rgb(80, 110, 110);
border-top-left-radius: 6px;
border-top-right-radius: 6px;
position: relative;
.current {
position: absolute;
bottom: .5rem;
left: 50%;
transform: translateX(-50%);
display: block;
color: #ffffff60;
white-space: nowrap;
font-size: 12px;
}
span {
margin: 2rem;
font-size: 30px;
color: if($is-dark-theme,#21222450, #ffffff50);
}
}
p {
text-align: center;
padding: 0 1rem;
}
.type-desc {
font-size: 14px;
color: var(--grey);
}
.fill-space {
flex: 1;
}
.app-specs {
display: block;
padding: 1rem 0;
margin: 0 1rem;
.row {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
color: var(--grey);
margin: 3px 0;
span {
white-space: nowrap;
}
:first-child {
margin-right: 1rem;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}

View File

@ -0,0 +1,32 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { OIDCAuthMethodType, OIDCGrantType, OIDCResponseType } from 'src/app/proto/generated/management_pb';
export interface RadioItemAuthType {
key: string;
titleI18nKey: string;
descI18nKey: string;
disabled: boolean,
prefix: string;
background: string;
responseType?: OIDCResponseType;
grantType?: OIDCGrantType;
authMethod?: OIDCAuthMethodType;
recommended?: boolean;
notRecommended?: boolean;
}
@Component({
selector: 'app-auth-method-radio',
templateUrl: './app-auth-method-radio.component.html',
styleUrls: ['./app-auth-method-radio.component.scss'],
})
export class AppAuthMethodRadioComponent {
@Input() current: string = '';
@Input() selected: string = '';
@Input() authMethods!: RadioItemAuthType[];
@Output() selectedMethod: EventEmitter<string> = new EventEmitter();
public emitChange(): void {
this.selectedMethod.emit(this.selected);
}
}

View File

@ -0,0 +1,27 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatRippleModule } from '@angular/material/core';
import { TranslateModule } from '@ngx-translate/core';
import { AppAuthMethodRadioComponent } from './app-auth-method-radio/app-auth-method-radio.component';
import { AppTypeRadioComponent } from './app-type-radio/app-type-radio.component';
@NgModule({
declarations: [
AppTypeRadioComponent,
AppAuthMethodRadioComponent,
],
imports: [
CommonModule,
FormsModule,
MatRippleModule,
TranslateModule,
],
exports: [
AppAuthMethodRadioComponent,
AppTypeRadioComponent,
],
})
export class AppRadioModule { }

View File

@ -0,0 +1,14 @@
<div class="radio-button-wrapper">
<ng-container *ngFor="let type of types">
<input type="radio" [disabled]="type.disabled" (change)="emitChange()" [value]="type.type"
[(ngModel)]="selected" [id]="type.type" />
<label class="cnsl-type-radio-button" [for]="type.type">
<div class="cnsl-type-radio-header" [ngStyle]="{'background': type.background}">
<span>{{type.prefix}}</span>
</div>
<p>{{type.titleI18nKey | translate}}</p>
<p class="type-desc">{{type.descI18nKey | translate}}</p>
<span class="fill-space"></span>
</label>
</ng-container>
</div>

View File

@ -0,0 +1,68 @@
@import '~@angular/material/theming';
.radio-button-wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 -0.5rem;
}
@mixin app-type-radio-theme($theme) {
$primary: map-get($theme, primary);
$primary-color: mat-color($primary, 500);
$is-dark-theme: map-get($theme, is-dark);
input[type="radio"]{
appearance: none;
opacity: 0;
display: none;
}
input:checked + label {
border-color: if($is-dark-theme, white, var(--grey));
.cnsl-type-radio-header span {
color: if($is-dark-theme, white, white);
}
}
.cnsl-type-radio-button {
margin: .5rem;
border-radius: .5rem;
border: 1px solid if($is-dark-theme, var(--grey), white);
display: flex;
flex-direction: column;
flex: 0 1 240px;
cursor: pointer;
position: relative;
padding-bottom: 1rem;
box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
.cnsl-type-radio-header {
display: flex;
align-items: center;
justify-content: center;
background: rgb(80, 110, 110);
margin-bottom: 1rem;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
span {
margin: 2rem;
font-size: 30px;
color: if($is-dark-theme,#21222450, #ffffff50);
}
}
p {
text-align: center;
padding: 0 1rem;
}
.type-desc {
font-size: 14px;
color: var(--grey);
}
}
}

View File

@ -0,0 +1,27 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { OIDCApplicationType } from 'src/app/proto/generated/management_pb';
export interface RadioItemAppType {
type: OIDCApplicationType;
titleI18nKey: string;
descI18nKey: string;
checked: boolean,
disabled: boolean,
prefix: string;
background: string;
}
@Component({
selector: 'app-type-radio',
templateUrl: './app-type-radio.component.html',
styleUrls: ['./app-type-radio.component.scss'],
})
export class AppTypeRadioComponent {
@Input() selected: OIDCApplicationType = OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB;
@Input() types!: RadioItemAppType[];
@Output() selectedType: EventEmitter<OIDCApplicationType> = new EventEmitter();
public emitChange(): void {
this.selectedType.emit(this.selected);
}
}

View File

@ -4,7 +4,8 @@
<h2 class="title">{{title}}</h2>
<span class="fill-space"></span>
<ng-content select="[card-actions]"></ng-content>
<button class="button" matTooltip="Expand or collapse" mat-icon-button (click)="expanded = !expanded">
<button class="button" type="button" matTooltip="Expand or collapse" mat-icon-button
(click)="expanded = !expanded">
<mat-icon *ngIf="!expanded">keyboard_arrow_down</mat-icon>
<mat-icon *ngIf="expanded">keyboard_arrow_up</mat-icon>
</button>

View File

@ -24,6 +24,8 @@
font-size: 16px;
text-transform: uppercase;
letter-spacing: .05em;
text-overflow: ellipsis;
overflow: hidden;
}
.fill-space {

View File

@ -18,7 +18,7 @@ import { Component, Input } from '@angular/core';
],
})
export class CardComponent {
public expanded: boolean = true;
@Input() public expanded: boolean = true;
@Input() public title: string = '';
@Input() public description: string = '';
@Input() public animate: boolean = false;

View File

@ -110,9 +110,9 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
setTimeout(() => {
this.loading = false;
this.router.navigate([
this.serviceType === PolicyComponentServiceType.MGMT ? 'org' :
this.serviceType === PolicyComponentServiceType.ADMIN ? 'iam' : '',
'idp', idp.getId()]);
(this.serviceType === PolicyComponentServiceType.MGMT ? 'org' :
this.serviceType === PolicyComponentServiceType.ADMIN ? 'iam' : ''),
'policy', 'login']);
}, 2000);
}).catch(error => {
this.toast.showError(error);

View File

@ -1,6 +1,6 @@
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
[emitRefreshOnPreviousRoutes]="['/iam/idp/create']" [timestamp]="idpResult?.viewTimestamp" [selection]="selection">
<ng-template appHasRole [appHasRole]="['iam.write']" actions>
<div actions>
<button (click)="deactivateSelectedIdps()" matTooltip="{{'IDP.DEACTIVATE' | translate}}" class="icon-button"
mat-icon-button *ngIf="selection.hasValue()" [disabled]="disabled">
<mat-icon>block</mat-icon>
@ -16,7 +16,7 @@
<a [routerLink]="createRouterLink" color="primary" mat-raised-button [disabled]="disabled">
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
</a>
</ng-template>
</div>
<div class="table-wrapper">
<table class="table" mat-table [dataSource]="dataSource">

View File

@ -1,5 +1,7 @@
<div class="info-section-row">
<i class="icon las la-info"></i>
<div class="info-section-row" [ngClass]="{'info': type == 'INFO', 'warn': type == 'WARN'}">
<i *ngIf="type == 'INFO'" class="icon las la-info"></i>
<i *ngIf="type == 'WARN'" class="las la-exclamation"></i>
<div class="info-section-content">
<ng-content></ng-content>
</div>

View File

@ -7,24 +7,36 @@
.info-section-row {
display: flex;
background-color: if($is-dark-theme, #ffffff13, #f3f3f3);
border-radius: 4px;
padding: .5rem 0;
padding-right: 1rem;
color: if($is-dark-theme, #d6d6d6, #3c4257);
font-size: 14px;
.icon {
margin-right: 1rem;
height: 1.2rem;
line-height: 1.2rem;
font-size: 1.2rem;
margin-left: .5rem;
color: $primary-color;
margin-right: 1rem;
height: 1.2rem;
line-height: 1.2rem;
font-size: 1.2rem;
margin-left: .5rem;
}
.info-section-content {
flex: 1;
flex: 1;
}
&.info {
background-color: if($is-dark-theme, #4f566b, #cbf4c9);
color: if($is-dark-theme, #cbf4c9, #0e6245);
.icon {
color: $primary-color;
}
}
&.warn {
background-color: if($is-dark-theme, #4f566b, #ffc1c1);
color: if($is-dark-theme, #ffc1c1, #620e0e);
}
}
}

View File

@ -1,8 +1,16 @@
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';
enum InfoSectionType {
INFO = 'INFO',
WARN = 'WARN',
}
@Component({
selector: 'cnsl-info-section',
templateUrl: './info-section.component.html',
styleUrls: ['./info-section.component.scss'],
})
export class InfoSectionComponent { }
export class InfoSectionComponent {
@Input() type = InfoSectionType.INFO;
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { OnboardingComponent } from './onboarding.component';
const routes: Routes = [
{
path: '',
component: OnboardingComponent,
data: { animation: 'AddPage' },
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class OnboardingRoutingModule { }

View File

@ -0,0 +1,27 @@
<div class="split">
<div class="left">
<p class="firststeps">{{'ONBOARDING.HEADER' | translate}}</p>
<h1>{{'ONBOARDING.TITLE' | translate}}</h1>
</div>
<div class="right">
<p class="desc">{{'ONBOARDING.DESCRIPTION' | translate}}</p>
<h2>{{'ONBOARDING.STEPS_TITLE' | translate}}</h2>
<div class="onboarding-row" *ngFor="let step of steps; index as i">
<div class="prev">{{i + 1}}</div>
<div>
<h3>{{step.titleI18nKey | translate}}</h3>
<p>{{step.descI18nKey | translate}}</p>
</div>
<span class="fill-space"></span>
<div class="action-row">
<a *ngIf="step?.docs" [href]="step.docs" alt="Zitadel Docs" target="_blank"
class="goto docs">{{'ONBOARDING.DOCS' |
translate}}
<i class="las la-external-link-alt"></i>
</a>
<a *ngIf="step.link" class="goto" [routerLink]="step.link">{{'ONBOARDING.START' | translate}}</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,147 @@
@import '~@angular/material/theming';
@mixin onboarding-theme($theme) {
/* stylelint-disable */
$primary: map-get($theme, primary);
$primary-color: mat-color($primary, 500);
$is-dark-theme: map-get($theme, is-dark);
/* stylelint-enable */
.onboarding-row {
box-shadow: inset 0 -1px if($is-dark-theme, #303131, #e3e8ee);
.prev {
background: $primary-color;
}
.goto {
text-decoration: none;
background: white;
border: 1px solid if($is-dark-theme, #303131, #e3e8ee);
&.docs {
background-color: $primary-color;
i {
font-size: 1rem;
margin-left: 3px;
}
}
}
}
}
.split {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
border-radius: 0.5rem;
box-shadow: 0 3px 8px 0 rgb(0 0 0 / 6%);
@media only screen and (min-width: 1024px) {
flex-direction: row;
.right {
overflow: auto;
}
}
.left {
flex-basis: 300px;
box-sizing: border-box;
padding: 1.5rem;
background: linear-gradient(40deg, rgb(80, 66, 121),rgb(177, 59, 122),rgb(225,53,81), rgb(230,107,86));
box-shadow: inset -2px 1px 15px -9px #000000;
h1 {
color: white;
}
.firststeps {
color: #fad6e3;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
p {
color: #fad6e3;
font-size: 12px;
font-weight: bold;
}
button {
width: 100%;
}
}
.right {
padding: 1.5rem;
flex: 1;
box-sizing: border-box;
.desc {
color: var(--grey);
font-size: 20px;
margin-top: .5rem;
}
.onboarding-row {
display: flex;
padding: 1rem 0;
align-items: center;
.prev {
height: 40px;
width: 40px;
min-width: 40px;
border-radius: .5rem;
display: flex;
align-items: center;
justify-content: center;
margin-right: 2rem;
color: white;
font-size: 1.2rem;
box-shadow: 0 3px 8px 0 rgb(0 0 0 / 6%);
}
h3 {
margin-top: 0;
margin-bottom: .5rem;
font-size: 15px;
}
p {
font-size: 12px;
margin: 0;
color: var(--grey);
}
.fill-space {
flex: 1;
}
.action-row {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-end;
.goto {
background-color: white;
padding: 2px 1rem;
color: black;
border-radius: 50vw;
font-size: 12px;
margin: .5rem 0 .5rem 1rem;
white-space: nowrap;
}
}
}
}
}

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { OnboardingComponent } from './onboarding.component';
describe('OnboardingComponent', () => {
let component: OnboardingComponent;
let fixture: ComponentFixture<OnboardingComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ OnboardingComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(OnboardingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
import { AuthenticationService } from 'src/app/services/authentication.service';
@Component({
selector: 'cnsl-onboarding',
templateUrl: './onboarding.component.html',
styleUrls: ['./onboarding.component.scss']
})
export class OnboardingComponent {
public steps = [
{ titleI18nKey: 'ONBOARDING.STEPS.1.TITLE', descI18nKey: 'ONBOARDING.STEPS.1.DESC', docs: "https://docs.zitadel.ch/use", link: ['/projects', 'create'] },
{ titleI18nKey: 'ONBOARDING.STEPS.2.TITLE', descI18nKey: 'ONBOARDING.STEPS.2.DESC', docs: "https://docs.zitadel.ch/use", link: ['/projects'] },
{ titleI18nKey: 'ONBOARDING.STEPS.3.TITLE', descI18nKey: 'ONBOARDING.STEPS.3.DESC', link: ['/iam', 'policies'] },
];
constructor() { }
}

View File

@ -0,0 +1,18 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { TranslateModule } from '@ngx-translate/core';
import { OnboardingRoutingModule } from './onboarding-routing.module';
import { OnboardingComponent } from './onboarding.component';
@NgModule({
declarations: [OnboardingComponent],
imports: [
CommonModule,
TranslateModule,
OnboardingRoutingModule,
MatButtonModule,
],
})
export class OnboardingModule { }

View File

@ -73,14 +73,14 @@
<p class="subdesc">{{ 'MFA.LIST.MULTIFACTORDESCRIPTION' | translate }}</p>
<app-mfa-table [service]="service" [serviceType]="serviceType"
[componentType]="LoginMethodComponentType.MultiFactor"
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'iam.policy.write' : ''] | hasRole | async) == false">
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) == false">
</app-mfa-table>
<h3 class="subheader">{{ 'MFA.LIST.SECONDFACTORTITLE' | translate }}</h3>
<p class="subdesc">{{ 'MFA.LIST.SECONDFACTORDESCRIPTION' | translate }}</p>
<app-mfa-table [service]="service" [serviceType]="serviceType"
[componentType]="LoginMethodComponentType.SecondFactor"
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'iam.policy.write' : ''] | hasRole | async) == false">
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) == false">
</app-mfa-table>
</ng-container>

View File

@ -16,12 +16,42 @@
</div>
<div class="container">
<ng-template appHasRole [appHasRole]="['iam.write']">
<a matRipple *ngIf="!firstStepsDismissed" class="onboard" [routerLink]="['/firststeps']">
<p class="first-steps">{{'ONBOARDING.HEADER' | translate}}</p>
<h2>{{'ONBOARDING.TITLE' | translate}}</h2>
<p class="desc">{{'ONBOARDING.DESCRIPTION' | translate}}</p>
<button matTooltip="{{'ACTIONS.CLOSE' | translate}}" (click)="dismissFirstSteps($event)" mat-icon-button
class="close">
<i class="las la-times"></i>
</button>
</a>
</ng-template>
<a matRipple *ngIf="!firstStepsDismissed" class="quickstart" target="_blank"
href="https://docs.zitadel.ch/quickstarts">
<p class="first-steps">{{'HOME.QUICKSTARTS.LABEL' | translate}}</p>
<h2>{{'HOME.QUICKSTARTS.TITLE' | translate}}</h2>
<p class="desc">{{'HOME.QUICKSTARTS.DESCRIPTION' | translate}}</p>
<div class="logo-cloud">
<i class="lab la-angular"></i>
<i class="lab la-react"></i>
<i class="lab la-android"></i>
<i class="lab la-app-store-ios"></i>
</div>
<button matTooltip="{{'ACTIONS.CLOSE' | translate}}" (click)="dismissQuickstarts($event)" mat-icon-button
class="close">
<i class="las la-times"></i>
</button>
</a>
<ng-template appHasRole [appHasRole]="['iam.write']">
<app-card class="item">
<div class="top">
<h2>
<i class="icon las la-gem"></i>
{{'HOME.IAM'| translate}}</h2>
{{'HOME.IAM'| translate}}
</h2>
<p>{{'HOME.IAM_DESC'| translate}}</p>
</div>
@ -30,15 +60,12 @@
class="las la-link"></i></a>
</ng-template>
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<a class="short-link"
[routerLink]="[ '/iam', 'policy','iam']">{{'HOME.IAM_POLICY_IAM' | translate}}<i
class="las la-link"></i></a>
<a class="short-link"
[routerLink]="[ '/iam', 'policy','complexity']">{{'HOME.IAM_POLICY_COMPLEXITY' | translate}}<i
class="las la-link"></i></a>
<a class="short-link"
[routerLink]="[ '/iam', 'policy','login']">{{'HOME.IAM_POLICY_LOGIN' | translate}}<i
class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/iam', 'policy','iam']">{{'HOME.IAM_POLICY_IAM' |
translate}}<i class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/iam', 'policy','complexity']">{{'HOME.IAM_POLICY_COMPLEXITY'
| translate}}<i class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/iam', 'policy','login']">{{'HOME.IAM_POLICY_LOGIN' |
translate}}<i class="las la-link"></i></a>
</ng-template>
<span class="fill-space"></span>
@ -59,8 +86,8 @@
<span class="fill-space"></span>
<div class="footer">
<a color="primary" mat-stroked-button
[routerLink]="['/users/me']">{{'HOME.SECURITYANDPRIVACY_BUTTON' | translate}}</a>
<a color="primary" mat-stroked-button [routerLink]="['/users/me']">{{'HOME.SECURITYANDPRIVACY_BUTTON' |
translate}}</a>
</div>
</app-card>
@ -69,18 +96,18 @@
<div class="top">
<h2>
<i class="icon las la-layer-group"></i>
{{'HOME.PROJECTS'| translate}}</h2>
{{'HOME.PROJECTS'| translate}}
</h2>
<p>{{'HOME.PROJECTS_DESC'| translate}}</p>
<ng-template appHasRole [appHasRole]="['project.create']">
<a class="short-link"
[routerLink]="[ '/projects', 'create']">{{'HOME.PROJECTS_NEW_LINK' | translate}}<i
class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/projects', 'create']">{{'HOME.PROJECTS_NEW_LINK' |
translate}}<i class="las la-link"></i></a>
</ng-template>
</div>
<span class="fill-space"></span>
<div class="footer">
<a color="primary" mat-stroked-button
[routerLink]="['/projects']">{{'HOME.PROJECTS_BUTTON' | translate}}</a>
<a color="primary" mat-stroked-button [routerLink]="['/projects']">{{'HOME.PROJECTS_BUTTON' |
translate}}</a>
</div>
</app-card>
</ng-template>
@ -92,23 +119,21 @@
{{'HOME.PROTECTION'| translate}}</h2>
<p>{{'HOME.PROTECTION_DESC'| translate}}</p>
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<a class="short-link"
[routerLink]="[ '/org', 'policy','iam']">{{'HOME.ORG_POLICY_IAM' | translate}}<i
class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/org', 'policy','iam']">{{'HOME.ORG_POLICY_IAM' |
translate}}<i class="las la-link"></i></a>
</ng-template>
<ng-template appHasRole [appHasRole]="['policy.read']">
<a class="short-link"
[routerLink]="[ '/org', 'policy','complexity']">{{'HOME.ORG_POLICY_COMPLEXITY' | translate}}<i
class="las la-link"></i></a>
<a class="short-link"
[routerLink]="[ '/org', 'policy','login']">{{'HOME.ORG_POLICY_LOGIN' | translate}}<i
class="las la-link"></i></a>
[routerLink]="[ '/org', 'policy','complexity']">{{'HOME.ORG_POLICY_COMPLEXITY' |
translate}}<i class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/org', 'policy','login']">{{'HOME.ORG_POLICY_LOGIN' |
translate}}<i class="las la-link"></i></a>
</ng-template>
</div>
<span class="fill-space"></span>
<div class="footer">
<a color="primary" mat-stroked-button
[routerLink]="['/org']">{{'HOME.PROTECTION_BUTTON' | translate}}</a>
<a color="primary" mat-stroked-button [routerLink]="['/org']">{{'HOME.PROTECTION_BUTTON' |
translate}}</a>
</div>
</app-card>
</ng-template>
@ -118,15 +143,14 @@
<div class="top">
<h2>
<i class="las la-users"></i>
{{'HOME.USERS'| translate}}</h2>
{{'HOME.USERS'| translate}}
</h2>
<p>{{'HOME.USERS_DESC'| translate}}</p>
<ng-template appHasRole [appHasRole]="['user.read(:[0-9]*)?']">
<a class="short-link"
[routerLink]="[ '/users', 'list', 'humans']">{{'HOME.USERS_HUMANS' | translate}}<i
class="las la-link"></i></a>
<a class="short-link"
[routerLink]="[ '/users', 'list', 'machines']">{{'HOME.USERS_MACHINES' | translate}}<i
class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/users', 'list', 'humans']">{{'HOME.USERS_HUMANS' |
translate}}<i class="las la-link"></i></a>
<a class="short-link" [routerLink]="[ '/users', 'list', 'machines']">{{'HOME.USERS_MACHINES' |
translate}}<i class="las la-link"></i></a>
</ng-template>
<ng-template appHasRole [appHasRole]="['user.read']">
<a class="short-link" [routerLink]="[ '/users', 'create']">{{'HOME.USERS_CREATE' | translate}}<i
@ -135,8 +159,8 @@
</div>
<span class="fill-space"></span>
<div class="footer">
<a color="primary" mat-stroked-button
[routerLink]="['/users/list/humans']">{{'HOME.USERS_BUTTON' | translate}}</a>
<a color="primary" mat-stroked-button [routerLink]="['/users/list/humans']">{{'HOME.USERS_BUTTON' |
translate}}</a>
</div>
</app-card>
</ng-template>

View File

@ -1,6 +1,7 @@
.wrapper {
padding-bottom: 100px;
position: relative;
.header {
display: flex;
@ -31,6 +32,78 @@
margin: -1rem;
justify-content: space-evenly;
.onboard,
.quickstart {
text-decoration: none;
cursor: pointer;
box-sizing: border-box;
flex: 1 0 45%;
position: relative;
border-radius: 0.5rem;
margin: 1rem;
padding: 1.5rem;
box-shadow: 0 3px 8px 0 rgb(0 0 0 / 6%);
h2 {
color: white;
}
.first-steps {
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
.close {
visibility: hidden;
position: absolute;
top: 0;
right: 0;
i {
color: white;
font-size: 1rem;
}
}
&:hover {
.close {
visibility: visible;
}
}
}
.onboard {
background: linear-gradient(40deg, rgb(80, 66, 121),rgb(177, 59, 122),rgb(225,53,81), rgb(230,107,86));
p {
color: #fad6e3;
}
}
.quickstart {
background: linear-gradient(30deg, #2283a6,#6c8f59);
p {
color: #d6f3fa;
}
.logo-cloud {
display: flex;
flex-wrap: wrap;
margin: -0.5rem;
i {
font-size: 40px;
padding: .5rem;
border: 1px solid #ffffff50;
border-radius: .5rem;
margin: 0.5rem;
color: white;
}
}
}
.item {
flex: 1 0 45%;
margin: 0 1rem;

View File

@ -8,8 +8,26 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
})
export class HomeComponent {
public dark: boolean = true;
public firstStepsDismissed: boolean = false;
public quickstartsDismissed: boolean = false;
constructor(public authService: GrpcAuthService) {
const theme = localStorage.getItem('theme');
this.dark = theme === 'dark-theme' ? true : theme === 'light-theme' ? false : true;
this.firstStepsDismissed = localStorage.getItem('firstStartDismissed') == 'true' ? true : false;
this.quickstartsDismissed = localStorage.getItem('quickstartsDismissed') == 'true' ? true : false;
}
dismissFirstSteps(event: Event): void {
event.preventDefault();
localStorage.setItem('firstStartDismissed', 'true');
this.firstStepsDismissed = true;
}
dismissQuickstarts(event: Event): void {
event.preventDefault();
localStorage.setItem('quickstartsDismissed', 'true');
this.firstStepsDismissed = true;
}
}

View File

@ -1,19 +1,20 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatRippleModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { AvatarModule } from 'src/app/modules/avatar/avatar.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { OnboardingModule } from 'src/app/modules/onboarding/onboarding.module';
import { SharedModule } from 'src/app/modules/shared/shared.module';
import { HomeRoutingModule } from './home-routing.module';
import { HomeComponent } from './home.component';
@NgModule({
declarations: [HomeComponent],
imports: [
@ -24,9 +25,12 @@ import { HomeComponent } from './home.component';
MatButtonModule,
TranslateModule,
AvatarModule,
MatTooltipModule,
SharedModule,
MatProgressSpinnerModule,
CardModule,
MatRippleModule,
OnboardingModule,
],
})
export class HomeModule { }

View File

@ -23,18 +23,14 @@
<p class="step-title">{{'APP.OIDC.TITLEFIRST' | translate}}</p>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
<input cnslInput cdkFocusInitial formControlName="name" />
<span cnsl-error *ngIf="name?.errors?.required">{{'PROJECT.APP.NAMEREQUIRED' | translate}}</span>
</cnsl-form-field>
<p class="step-title">{{'APP.OIDC.TYPETITLE' | translate}}</p>
<mat-radio-group color="primary" aria-labelledby="radio-group-label" class="radio-group"
formControlName="applicationType">
<mat-radio-button class="radio-button" *ngFor="let type of oidcAppTypes | keyvalue"
[value]="type.value">
<div>{{('APP.OIDC.APPTYPE'+type.key.toString()) | translate}}</div>
</mat-radio-button>
</mat-radio-group>
<app-type-radio [types]="oidcAppTypes" (selectedType)="changedAppType($event)"
[selected]="applicationType?.value"></app-type-radio>
<div class="actions">
<button mat-raised-button [disabled]="firstFormGroup.invalid" color="primary"
matStepperNext>{{'ACTIONS.CONTINUE' | translate}}</button>
@ -42,37 +38,19 @@
</form>
</mat-step>
<mat-step [editable]="true"
*ngIf="oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
<ng-template matStepLabel>{{'APP.OIDC.RESPONSESECTION' | translate}}</ng-template>
<div class="checkbox-container">
<mat-checkbox class="checkbox" *ngFor="let responsetype of oidcResponseTypes"
(change)="changeResponseType()" color="primary" [(ngModel)]="responsetype.checked"
[disabled]="responsetype.disabled">
{{'APP.OIDC.RESPONSE'+responsetype.type | translate}}
</mat-checkbox>
</div>
<div class="actions">
<button mat-stroked-button color="primary" matStepperPrevious>{{'ACTIONS.BACK' | translate}}</button>
<button mat-raised-button color="primary" matStepperNext>{{'ACTIONS.CONTINUE' | translate}}</button>
</div>
</mat-step>
<mat-step *ngIf="oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB"
<!-- skip for native applications -->
<mat-step *ngIf="oidcApp.applicationType !== OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE"
[stepControl]="secondFormGroup" [editable]="true">
<form [formGroup]="secondFormGroup">
<ng-template matStepLabel>{{'APP.OIDC.AUTHMETHODSECTION' | translate}}</ng-template>
<mat-radio-group color="primary" aria-labelledby="example-radio-group-label" class="radio-group"
formControlName="authMethodType">
<mat-radio-button class="radio-button" *ngFor="let authmethod of oidcAuthMethodType"
[disabled]="authmethod.disabled" [value]="authmethod.type">
{{'APP.OIDC.AUTHMETHOD'+authmethod.type | translate}}
</mat-radio-button>
</mat-radio-group>
<app-auth-method-radio [authMethods]="authMethods" [selected]="authMethod?.value"
(selectedMethod)="changedAppAuthMethod($event)">
</app-auth-method-radio>
<div class="actions">
<button mat-stroked-button color="primary"
matStepperPrevious>{{'ACTIONS.BACK' | translate}}</button>
<button mat-stroked-button color="primary" matStepperPrevious>{{'ACTIONS.BACK' |
translate}}</button>
<button mat-raised-button color="primary" [disabled]="secondFormGroup.invalid"
matStepperNext>{{'ACTIONS.CONTINUE' | translate}}</button>
</div>
@ -89,25 +67,10 @@
<p class="step-description" *ngIf="oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<form class="chip-form" (ngSubmit)="addUri(redInput, 'REDIRECT')">
<cnsl-form-field appearance="outline" class="full-width">
<cnsl-label>{{ 'APP.OIDC.REDIRECT' | translate }}</cnsl-label>
<input #redInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="redirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list #chipRedirectList aria-label="uri selection">
<mat-chip #redInput class="chip" *ngFor="let uri of oidcApp.redirectUrisList" selected removable
[matTooltip]="!uri?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!uri?.startsWith('https://') ? 'warn': 'white'" (removed)="removeUri(uri, 'REDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<p *ngIf="redirectControl.invalid" class="error">{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<cnsl-redirect-uris class="redirect-section" [canWrite]="true"
(changedUris)="oidcApp.redirectUrisList = $event" [urisList]="oidcApp.redirectUrisList"
title="{{ 'APP.OIDC.REDIRECT' | translate }}">
</cnsl-redirect-uris>
<p class="step-title">{{'APP.OIDC.POSTREDIRECTTITLE' | translate}}</p>
<p class="step-description"
@ -117,26 +80,10 @@
*ngIf="oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB || oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<form class="chip-form" (ngSubmit)="addUri(postInput, 'POSTREDIRECT')">
<cnsl-form-field appearance="outline" class="full-width">
<cnsl-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</cnsl-label>
<input #postInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="postRedirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list #chipPostRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.postLogoutRedirectUrisList"
[matTooltip]="!uri?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
removable (removed)="removeUri(uri, 'POSTREDIRECT')" selected
[color]="!uri?.startsWith('https://') ? 'warn': 'white'">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<p *ngIf="postRedirectControl.invalid" class="error">{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<cnsl-redirect-uris class="redirect-section" [canWrite]="true"
(changedUris)="oidcApp.postLogoutRedirectUrisList = $event"
[urisList]="oidcApp.postLogoutRedirectUrisList" title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}">
</cnsl-redirect-uris>
<div class="actions">
<button mat-stroked-button color="primary" matStepperPrevious>{{'ACTIONS.BACK' | translate}}</button>
@ -171,9 +118,8 @@
<span class="right" *ngIf="oidcApp.grantTypesList?.length > 0">
[<span *ngFor="let element of oidcApp.grantTypesList; index as i">
{{'APP.OIDC.GRANT'+element | translate}}
{{i < oidcApp.grantTypesList.length - 1 ? ', ': ''}}
</span>]
</span>
{{i < oidcApp.grantTypesList.length - 1 ? ', ' : '' }} </span>]
</span>
</div>
<div class="row">
<span class="left">
@ -182,9 +128,8 @@
<span class="right" *ngIf="oidcApp.responseTypesList?.length > 0">
[<span *ngFor="let element of oidcApp.responseTypesList; index as i">
{{('APP.OIDC.RESPONSE'+element | translate)}}
{{i < oidcApp.responseTypesList.length - 1 ? ', ': ''}}
</span>]
</span>
{{i < oidcApp.responseTypesList.length - 1 ? ', ' : '' }} </span>]
</span>
</div>
<div class="row">
@ -205,9 +150,8 @@
<span class="right" *ngIf="oidcApp.redirectUrisList?.length > 0">
[<span *ngFor="let redirect of oidcApp.redirectUrisList; index as i">
{{redirect}}
{{i < oidcApp.redirectUrisList.length - 1 ? ', ': ''}}
</span>]
</span>
{{i < oidcApp.redirectUrisList.length - 1 ? ', ' : '' }} </span>]
</span>
</div>
<div class="row">
@ -217,15 +161,14 @@
<span class="right" *ngIf="oidcApp.postLogoutRedirectUrisList?.length > 0">
[<span *ngFor="let redirect of oidcApp.postLogoutRedirectUrisList; index as i">
{{redirect}}
{{i < oidcApp.postLogoutRedirectUrisList.length - 1 ? ', ': ''}}
</span>]
</span>
{{i < oidcApp.postLogoutRedirectUrisList.length - 1 ? ', ' : '' }} </span>]
</span>
</div>
<div class="actions">
<button mat-stroked-button color="primary" matStepperPrevious>{{'ACTIONS.BACK' | translate}}</button>
<button mat-raised-button color="primary"
(click)="saveOIDCApp()">{{'ACTIONS.CREATE' | translate}}</button>
<button mat-raised-button color="primary" (click)="saveOIDCApp()">{{'ACTIONS.CREATE' |
translate}}</button>
</div>
</mat-step>
</mat-horizontal-stepper>
@ -241,8 +184,8 @@
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.APPTYPE' | translate }}</cnsl-label>
<mat-select formControlName="applicationType">
<mat-option *ngFor="let type of oidcAppTypes" [value]="type">
{{ 'APP.OIDC.APPTYPE'+type | translate }}
<mat-option *ngFor="let type of oidcAppTypes" [value]="type.type">
{{ 'APP.OIDC.APPTYPE'+type.type | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
@ -274,32 +217,18 @@
</mat-select>
</cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.REDIRECT' | translate }}</cnsl-label>
<mat-chip-list #chipRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.redirectUrisList" removable
(removed)="removeUri(uri, 'REDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input cnslInput [matChipInputFor]="chipRedirectList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addUri($event, 'REDIRECT')">
</mat-chip-list>
</cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</cnsl-label>
<mat-chip-list #chipPostRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.postLogoutRedirectUrisList" removable
(removed)="removeUri(uri, 'POSTREDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input cnslInput [matChipInputFor]="chipPostRedirectList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addUri($event, 'POSTREDIRECT')">
</mat-chip-list>
</cnsl-form-field>
<div class="formfield full-width">
<cnsl-redirect-uris class="redirect-section" [canWrite]="true"
(changedUris)="oidcApp.redirectUrisList = $event" [urisList]="oidcApp.redirectUrisList"
title="{{ 'APP.OIDC.REDIRECT' | translate }}">
</cnsl-redirect-uris>
<cnsl-redirect-uris class="redirect-section" [canWrite]="true"
(changedUris)="oidcApp.postLogoutRedirectUrisList = $event"
[urisList]="oidcApp.postLogoutRedirectUrisList"
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}">
</cnsl-redirect-uris>
</div>
</div>
<button color="primary" mat-raised-button class="continue-button" [disabled]="form.invalid" cdkFocusInitial

View File

@ -42,11 +42,6 @@ p.desc {
margin-right: .5rem;
}
.formfield {
width: 400px;
display: block;
}
.full-width {
width: 100%;
}
@ -55,6 +50,10 @@ p.desc {
background: inherit !important;
margin: 0 -1.5rem;
.formfield {
max-width: 400px;
}
.step-title {
font-size: 1rem;
text-transform: uppercase;
@ -65,44 +64,6 @@ p.desc {
font-size: .9rem;
color: var(--grey);
}
.chip-form {
width: 100%;
display: flex;
align-items: center;
.formfield {
flex: 1;
}
button {
margin-top: 1rem;
}
}
.error {
font-size: 13px;
color: #f44336;
margin-top: 0;
}
.chip {
border-radius: 4px;
height: 40px;
}
.chip[color='white'] {
background-color: #fafafa;
}
}
.radio-group {
display: flex;
flex-direction: column;
.radio-button {
margin: .5rem 0;
}
}
.checkbox-container {
@ -137,7 +98,6 @@ p.desc {
float: right;
margin-top: 1rem;
border-radius: .5rem;
padding: .5rem 1rem;
min-width: 100px;
}
}
@ -147,9 +107,11 @@ p.desc {
display: flex;
margin: 0 -.5rem;
flex-wrap: wrap;
flex-direction: row;
.formfield {
flex: 1 0 40%;
flex: 1;
box-sizing: border-box;
margin: 0 .5rem;
&.full-width {
@ -164,4 +126,4 @@ p.desc {
padding: .5rem 4rem;
float: right;
}
}
}

View File

@ -6,6 +6,7 @@ import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
import {
Application,
OIDCApplicationCreate,
@ -17,7 +18,15 @@ import {
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import {
WEB_TYPE,
NATIVE_TYPE,
USER_AGENT_TYPE
} from '../authtypes';
import { AppSecretDialogComponent } from '../app-secret-dialog/app-secret-dialog.component';
import { CODE_METHOD, getPartialConfigFromAuthMethod, IMPLICIT_METHOD, PKCE_METHOD, PK_JWT_METHOD, POST_METHOD } from '../authmethods';
@Component({
selector: 'app-app-create',
@ -37,10 +46,16 @@ export class AppCreateComponent implements OnInit, OnDestroy {
{ type: OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN_TOKEN, checked: false, disabled: false },
];
public oidcAppTypes: OIDCApplicationType[] = [
OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB,
OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT,
OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE,
public oidcAppTypes: any = [
WEB_TYPE,
NATIVE_TYPE,
USER_AGENT_TYPE,
];
public authMethods: RadioItemAuthType[] = [
PKCE_METHOD,
CODE_METHOD,
POST_METHOD,
];
public oidcAuthMethodType: { type: OIDCAuthMethodType, checked: boolean, disabled: boolean; }[] = [
@ -52,7 +67,6 @@ export class AppCreateComponent implements OnInit, OnDestroy {
// stepper
firstFormGroup!: FormGroup;
secondFormGroup!: FormGroup;
// thirdFormGroup!: FormGroup;
// devmode
public form!: FormGroup;
@ -72,9 +86,6 @@ export class AppCreateComponent implements OnInit, OnDestroy {
// TODO show when implemented
];
public redirectControl: FormControl = new FormControl('');
public postRedirectControl: FormControl = new FormControl('');
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
constructor(
@ -104,64 +115,58 @@ export class AppCreateComponent implements OnInit, OnDestroy {
this.firstFormGroup = this.fb.group({
name: ['', [Validators.required]],
applicationType: ['', [Validators.required]],
applicationType: [OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB, [Validators.required]],
});
this.firstFormGroup.valueChanges.subscribe(value => {
if (this.firstFormGroup.valid) {
switch (value.applicationType) {
case OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE:
this.oidcResponseTypes[0].checked = true;
this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE];
this.oidcApp.grantTypesList =
[OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE];
this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE;
// this.redirectControl = new FormControl('', [nativeValidator as ValidatorFn]);
// this.postRedirectControl = new FormControl('', [nativeValidator as ValidatorFn]);
break;
case OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB:
this.oidcAuthMethodType[0].disabled = false;
this.oidcAuthMethodType[1].disabled = false;
this.oidcAuthMethodType[2].disabled = false;
this.authMethodType?.setValue(OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC);
this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC;
this.oidcResponseTypes[0].checked = true;
this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE];
this.changeResponseType();
this.oidcApp.grantTypesList =
[OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE];
// this.redirectControl = new FormControl('', [webValidator as ValidatorFn]);
// this.postRedirectControl = new FormControl('', [webValidator as ValidatorFn]);
break;
case OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT:
this.oidcResponseTypes[0].checked = true;
this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE];
this.oidcApp.grantTypesList =
[OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDCGRANTTYPE_IMPLICIT];
this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE;
// this.redirectControl = new FormControl('', [webValidator as ValidatorFn]);
// this.postRedirectControl = new FormControl('', [webValidator as ValidatorFn]);
break;
}
this.oidcApp.name = this.name?.value;
this.oidcApp.applicationType = this.applicationType?.value;
switch (this.applicationType?.value) {
case OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE:
this.authMethods = [
PKCE_METHOD,
];
// automatically set to PKCE and skip step
this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE];
this.oidcApp.grantTypesList = [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE];
this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE;
break;
case OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB:
this.authMethods = [
PKCE_METHOD,
CODE_METHOD,
POST_METHOD,
];
this.authMethod?.setValue(PKCE_METHOD.key);
break;
case OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT:
this.authMethods = [
PKCE_METHOD,
IMPLICIT_METHOD,
];
this.authMethod?.setValue(PKCE_METHOD.key);
break;
}
}
});
this.secondFormGroup = this.fb.group({
authMethodType: [OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC, [Validators.required]],
authMethod: [this.authMethods[0].key, [Validators.required]],
});
this.secondFormGroup.valueChanges.subscribe(value => {
this.oidcApp.authMethodType = value.authMethodType;
this.secondFormGroup.valueChanges.subscribe(form => {
const partialConfig = getPartialConfigFromAuthMethod(form.authMethod);
if (partialConfig) {
this.oidcApp.responseTypesList = partialConfig.responseTypesList ?? [];
this.oidcApp.grantTypesList = partialConfig.grantTypesList ?? [];
this.oidcApp.authMethodType = partialConfig.authMethodType ?? OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE;
}
});
}
@ -173,6 +178,15 @@ export class AppCreateComponent implements OnInit, OnDestroy {
this.subscription?.unsubscribe();
}
public changedAppType(type: OIDCApplicationType) {
this.firstFormGroup.controls['applicationType'].setValue(type);
}
public changedAppAuthMethod(methodKey: string) {
console.log(methodKey);
this.secondFormGroup.controls['authMethod'].setValue(methodKey);
}
private async getData({ projectid }: Params): Promise<void> {
this.projectId = projectid;
this.oidcApp.projectId = projectid;
@ -215,66 +229,20 @@ export class AppCreateComponent implements OnInit, OnDestroy {
}
}
public addUri(input: any, target: string): void {
const value = input.value.trim();
if (value !== '') {
if (target === 'REDIRECT' && this.redirectControl.valid) {
this.oidcApp.redirectUrisList.push(value);
if (input) {
input.value = '';
}
} else if (target === 'POSTREDIRECT' && this.redirectControl.valid) {
this.oidcApp.postLogoutRedirectUrisList.push(value);
if (input) {
input.value = '';
}
}
}
}
public removeUri(uri: string, target: string): void {
if (target === 'REDIRECT') {
const index = this.oidcApp.redirectUrisList.indexOf(uri);
if (index !== undefined && index >= 0) {
this.oidcApp.redirectUrisList.splice(index, 1);
}
} else if (target === 'POSTREDIRECT') {
const index = this.oidcApp.postLogoutRedirectUrisList.indexOf(uri);
if (index !== undefined && index >= 0) {
this.oidcApp.postLogoutRedirectUrisList.splice(index, 1);
}
}
}
changeResponseType(): void {
this.oidcApp.responseTypesList = this.oidcResponseTypes.filter(gt => gt.checked).map(gt => gt.type);
}
moreThanOneOption(options: Array<{ type: OIDCGrantType, checked: boolean, disabled: boolean; }>): boolean {
return options.filter(option => option.disabled === false).length > 1;
}
get name(): AbstractControl | null {
return this.firstFormGroup.get('name');
}
get applicationType(): AbstractControl | null {
return this.firstFormGroup.get('applicationType');
}
public grantTypeChecked(type: OIDCGrantType): boolean {
return this.oidcGrantTypes.filter(gt => gt.checked).map(gt => gt.type).findIndex(t => t === type) > -1;
}
get responseTypesList(): AbstractControl | null {
return this.secondFormGroup.get('responseTypesList');
}
get authMethodType(): AbstractControl | null {
return this.secondFormGroup.get('authMethodType');
get authMethod(): AbstractControl | null {
return this.secondFormGroup.get('authMethod');
}
// devmode
@ -282,24 +250,17 @@ export class AppCreateComponent implements OnInit, OnDestroy {
get formname(): AbstractControl | null {
return this.form.get('name');
}
get formresponseTypesList(): AbstractControl | null {
return this.form.get('responseTypesList');
}
get formgrantTypesList(): AbstractControl | null {
return this.form.get('grantTypesList');
}
get formapplicationType(): AbstractControl | null {
return this.form.get('applicationType');
}
get formauthMethodType(): AbstractControl | null {
return this.form.get('authMethodType');
}
}
};

View File

@ -1,10 +1,32 @@
<app-meta-layout>
<div class="max-width-container">
<div class="enlarged-container">
<div class="head">
<a [routerLink]="['/projects', projectId]" mat-icon-button>
<mat-icon class="icon">arrow_back</mat-icon>
</a>
<h1>{{ 'APP.PAGES.TITLE' | translate }} {{app?.name}}</h1>
<div class="title-col">
<h1>{{app?.name}}</h1>
<span>{{'APP.OIDC.APPTYPE'+app?.oidcConfig?.applicationType | translate}}</span>
</div>
<ng-container *ngIf="isZitadel === false">
<ng-template appHasRole [appHasRole]="['project.app.write:'+projectId, 'project.app.write']">
<button *ngIf="!editState" matTooltip="{{'ACTIONS.EDIT' | translate}}" mat-icon-button
(click)="editState = !editState" aria-label="edit app name">
<i class="las la-edit"></i>
</button>
<button *ngIf="editState" (click)="saveApp()" [disabled]="appNameForm.invalid || name?.disabled"
mat-icon-button>
<i class="las la-save"></i>
</button>
</ng-template>
<ng-template appHasRole [appHasRole]="['project.app.delete:'+projectId, 'project.app.delete']">
<button matTooltip="{{'ACTIONS.DELETE' | translate}}" color="warn" mat-icon-button
(click)="deleteApp()" aria-label="delete app">
<i class="las la-trash"></i>
</button>
</ng-template>
</ng-container>
<p class="desc">{{ 'APP.PAGES.DESCRIPTION' | translate }}</p>
<p *ngIf="isZitadel" class="zitadel-warning">{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}</p>
@ -12,52 +34,85 @@
<span *ngIf="errorMessage" class="err-container">{{errorMessage}}</span>
<app-card title="{{ 'APP.PAGES.DETAIL.TITLE' | translate }}" *ngIf="app">
<form [formGroup]="appNameForm" (ngSubmit)="saveApp()">
<div class="name-content">
<mat-button-toggle-group formControlName="state" class="toggle" (change)="changeState($event)">
<mat-button-toggle [value]="AppState.APPSTATE_INACTIVE"
matTooltip="{{ 'ACTIONS.DEACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_INACTIVE | translate}}
</mat-button-toggle>
<mat-button-toggle [value]="AppState.APPSTATE_ACTIVE"
matTooltip="{{ 'ACTIONS.REACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_ACTIVE | translate}}
</mat-button-toggle>
</mat-button-toggle-group>
<form *ngIf="app && editState" [formGroup]="appNameForm">
<div class="name-content">
<mat-button-toggle-group formControlName="state" class="toggle" (change)="changeState($event)">
<mat-button-toggle [value]="AppState.APPSTATE_INACTIVE"
matTooltip="{{ 'ACTIONS.DEACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_INACTIVE | translate}}
</mat-button-toggle>
<mat-button-toggle [value]="AppState.APPSTATE_ACTIVE"
matTooltip="{{ 'ACTIONS.REACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_ACTIVE | translate}}
</mat-button-toggle>
</mat-button-toggle-group>
<cnsl-form-field class="name-field">
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
<cnsl-info-section class="docs-line" *ngIf="docs?.discoveryEndpoint">
<p><strong>Discovery Endpoint:</strong> {{docs.discoveryEndpoint}}</p>
<p><strong>Issuer:</strong> {{docs.issuer}}</p>
</cnsl-info-section>
</div>
<div class="btn-container">
<button type="submit" color="primary" [disabled]="appNameForm.invalid || name?.disabled"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</form>
</app-card>
<app-card title="{{ 'APP.OIDC.TITLE' | translate }}" *ngIf="app && app.oidcConfig">
<div card-actions *ngIf="app?.oidcConfig?.authMethodType !== OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE">
<button [disabled]="!canWrite" mat-stroked-button
(click)="regenerateOIDCClientSecret()">{{'APP.OIDC.REGENERATESECRET' | translate}}</button>
<cnsl-form-field class="name-field">
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
</div>
</form>
<!-- <cnsl-info-section class="docs-line" *ngIf="docs?.discoveryEndpoint">
<p><strong>Discovery Endpoint:</strong> {{docs.discoveryEndpoint}}</p>
<p><strong>Issuer:</strong> {{docs.issuer}}</p>
</cnsl-info-section> -->
<div class="compliance"
*ngIf="app?.oidcConfig?.complianceProblemsList && app.oidcConfig?.complianceProblemsList?.length">
<cnsl-info-section class="problem" type="WARN">
<ul style="margin: 0;">
<li style="margin: 0 0 .5rem 0;"
*ngFor="let problem of app.oidcConfig?.complianceProblemsList || []">
{{problem.localizedMessage}}</li>
</ul>
</cnsl-info-section>
</div>
<div class="content">
<h3 class="full-width section-title">{{'APP.OIDC.REDIRECTSECTIONTITLE' | translate}}</h3>
<mat-slide-toggle color="primary" class="devmode" [formControl]="devMode" name="devMode"
matTooltip="{{'APP.OIDC.DEVMODEDESC' | translate}}">
{{ 'APP.OIDC.DEVMODE' | translate }}
</mat-slide-toggle>
<cnsl-info-section class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE">
<span>{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</span>
</cnsl-info-section>
<p class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB || applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<div style="margin: .5rem" class="divider"></div>
<cnsl-redirect-uris class="redirect-section" [canWrite]="canWrite" [devMode]="devMode?.value"
(changedUris)="redirectUrisList = $event" [urisList]="redirectUrisList"
title="{{ 'APP.OIDC.REDIRECT' | translate }}">
</cnsl-redirect-uris>
<cnsl-redirect-uris class="redirect-section" [canWrite]="canWrite" [devMode]="devMode?.value"
(changedUris)="postLogoutRedirectUrisList = $event" [urisList]="postLogoutRedirectUrisList"
title="{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}">
</cnsl-redirect-uris>
</div>
<app-auth-method-radio *ngIf="authMethods && initialAuthMethod && app?.oidcConfig" [authMethods]="authMethods"
[selected]="initialAuthMethod" [current]="currentAuthMethod"
(selectedMethod)="setPartialConfigFromAuthMethod($event)">
</app-auth-method-radio>
<form *ngIf="appForm" [formGroup]="appForm" (ngSubmit)="saveOIDCApp()">
<app-card title=" {{ 'APP.OIDC.TITLE' | translate }}" *ngIf="app && app.oidcConfig" [expanded]="false">
<div card-actions
*ngIf="app?.oidcConfig?.authMethodType !== OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE">
<button [disabled]="!canWrite" mat-stroked-button
(click)="regenerateOIDCClientSecret()">{{'APP.OIDC.REGENERATESECRET' | translate}}</button>
</div>
<div class="compliance">
<cnsl-info-section class="problem">
<ul style="margin: 0;">
<li style="margin: 0 0 .5rem 0;" *ngFor="let problem of app.oidcConfig.complianceProblemsList">
{{problem.localizedMessage}}</li>
</ul>
</cnsl-info-section>
</div>
<form *ngIf="appForm" [formGroup]="appForm" (ngSubmit)="saveOIDCApp()">
<div class="content">
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'APP.OIDC.CLIENTID' | translate }}</cnsl-label>
@ -141,89 +196,46 @@
<cnsl-info-section class="full-width desc">
<span>{{'APP.OIDC.CLOCKSKEW' | translate}}</span>
</cnsl-info-section>
<div class="divider"></div>
<p class="full-width section-title">{{'APP.OIDC.REDIRECTSECTIONTITLE' | translate}}</p>
<mat-slide-toggle color="primary" class="devmode" formControlName="devMode" name="devMode">
{{ 'APP.OIDC.DEVMODE' | translate }}
</mat-slide-toggle>
<cnsl-info-section class="step-description">
<span style="margin-bottom: 2rem;">{{'APP.OIDC.DEVMODEDESC' | translate}}</span>
</cnsl-info-section>
<cnsl-info-section class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE">
<span>{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</span>
</cnsl-info-section>
<p class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB || applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<form class="chip-form" (ngSubmit)="add(redInput, RedirectType.REDIRECT)">
<cnsl-form-field class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.REDIRECT' | translate }}</cnsl-label>
<input #redInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="redirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button
[disabled]="redirectControl.invalid || !canWrite">
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list class="chiplist formfield full-width" [disabled]="!canWrite" #chipRedirectList>
<mat-chip class="chip" *ngFor="let redirect of redirectUrisList" selected
[matTooltip]="!redirect?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!redirect?.startsWith('https://') ? 'warn': 'green'"
(removed)="remove(redirect, RedirectType.REDIRECT)">
{{redirect}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<p *ngIf="redirectControl.value && redirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<form class="chip-form" (ngSubmit)="add(postInput, RedirectType.POSTREDIRECT)">
<cnsl-form-field class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</cnsl-label>
<input #postInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="postRedirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button
[disabled]="postRedirectControl.invalid || !canWrite">
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list class="chiplist formfield full-width" [disabled]="!canWrite" #chipPostRedirectList>
<mat-chip class="chip" *ngFor="let redirect of postLogoutRedirectUrisList" selected
(removed)="remove(redirect, RedirectType.POSTREDIRECT)"
[matTooltip]="!redirect?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!redirect?.startsWith('https://') ? 'warn': 'green'">
{{redirect}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<p *ngIf="postRedirectControl.value && postRedirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
</div>
<div class="btn-container">
</app-card>
<button class="submit-button" type="submit" color="primary"
[disabled]="appForm.invalid || !canWrite"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
<div class="btn-container">
<button class="submit-button" type="submit" color="primary" [disabled]="appForm.invalid || !canWrite"
mat-raised-button>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
</form>
<div class="next-steps">
<h5>{{'APP.PAGES.NEXTSTEPS.TITLE' | translate}}</h5>
<div class="row">
<div class="step">
<h6>{{ 'APP.PAGES.NEXTSTEPS.0.TITLE' | translate }}</h6>
<p>{{'APP.PAGES.NEXTSTEPS.0.DESC' | translate}}</p>
<span class="fill-space"></span>
<a [routerLink]="['/projects', this.projectId]" color="primary" mat-mini-fab><i
class="las la-angle-right"></i></a>
</div>
</form>
</app-card>
<div class="step">
<h6>{{ 'APP.PAGES.NEXTSTEPS.1.TITLE' | translate }}</h6>
<p>{{'APP.PAGES.NEXTSTEPS.1.DESC' | translate}}</p>
<span class="fill-space"></span>
<a [routerLink]="['/users', 'create']" color="primary" mat-mini-fab><i
class="las la-angle-right"></i></a>
</div>
<div class="step">
<h6>{{ 'APP.PAGES.NEXTSTEPS.2.TITLE' | translate }}</h6>
<p>{{'APP.PAGES.NEXTSTEPS.2.DESC' | translate}}</p>
<span class="fill-space"></span>
<a href="https://docs.zitadel.ch" color="primary" mat-mini-fab><i
class="las la-angle-right"></i></a>
</div>
</div>
</div>
</div>
<div class="side" metainfo>
<div class="meta-details">
<div class="meta-row">

View File

@ -8,11 +8,21 @@
display: block;
}
h1 {
font-size: 1.2rem;
margin: 0 1rem;
.title-col {
margin-left: 2rem;
font-weight: normal;
margin-right: 1rem;
min-width: 200px;
h1 {
font-size: 1.2rem;
margin: 0 0 0 0;
font-weight: normal;
}
span {
font-size: 12px;
color: var(--grey);
}
}
.desc {
@ -20,6 +30,7 @@
display: block;
font-size: .9rem;
color: var(--grey);
margin-top: 1.5rem;
}
.zitadel-warning {
@ -41,10 +52,10 @@
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
.toggle {
outline: none;
align-self: flex-start;
margin-top: 1rem;
margin-right: 1rem;
border-radius: .5rem;
@ -91,6 +102,11 @@
align-items: center;
}
.redirect-section {
flex: 1;
margin: 0 .5rem;
}
.formfield {
flex: 1 1 30%;
margin: 0 .5rem;
@ -99,27 +115,9 @@
flex-basis: 100%;
}
}
.chiplist {
margin-bottom: 1rem;
}
.chip-form {
width: 100%;
display: flex;
align-items: center;
.formfield {
flex: 1;
}
button {
margin-top: 1rem;
}
}
.section-title {
margin-bottom: 1.5rem;
margin: 1.5rem 0 0 0;
}
.full-width {
@ -142,7 +140,7 @@
.desc {
color: var(--grey);
font-size: 14px;
margin-bottom: 1rem;
margin-bottom: 1.5rem;
}
.devmode {
@ -170,18 +168,67 @@
margin-top: 1rem;
}
.chip {
border-radius: 4px;
height: 40px;
}
.chip[color='green'] {
background-color: #56a392 !important;
}
.divider {
flex-basis: 100%;
margin: 1.5rem .5rem;
height: 1px;
background-color: rgba(#8795a1, .2);
}
.next-steps {
h5 {
text-transform: uppercase;
font-size: 14px;
color: var(--grey);
}
.row {
width: 100%;
display: flex;
overflow-x: auto;
.step {
min-width: 220px;
max-width: 280px;
padding: 1rem;
margin: 0 .5rem;
border: 1px solid var(--grey);
border-radius: .5rem;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
flex: 1;
h6 {
font-size: 1rem;
text-align: center;
margin: 0 0 1rem 0;
}
p {
font-size: 14px;
text-align: center;
color: var(--grey);
}
.fill-space {
flex: 1;
}
button {
display: block;
margin: auto;
}
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
}
}

View File

@ -4,12 +4,14 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatButtonToggleChange } from '@angular/material/button-toggle';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params } from '@angular/router';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
import { Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
import { ChangeType } from 'src/app/modules/changes/changes.component';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import {
Application,
AppState,
@ -27,11 +29,7 @@ import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { AppSecretDialogComponent } from '../app-secret-dialog/app-secret-dialog.component';
enum RedirectType {
REDIRECT = 'redirect',
POSTREDIRECT = 'postredirect',
}
import { CODE_METHOD, getAuthMethodFromPartialConfig, getPartialConfigFromAuthMethod, IMPLICIT_METHOD, PKCE_METHOD, PK_JWT_METHOD, POST_METHOD, CUSTOM_METHOD } from '../authmethods';
@Component({
selector: 'app-app-detail',
@ -39,12 +37,20 @@ enum RedirectType {
styleUrls: ['./app-detail.component.scss'],
})
export class AppDetailComponent implements OnInit, OnDestroy {
public editState: boolean = false;
public currentAuthMethod: string = CUSTOM_METHOD.key;
public initialAuthMethod: string = CUSTOM_METHOD.key;
public canWrite: boolean = false;
public errorMessage: string = '';
public removable: boolean = true;
public addOnBlur: boolean = true;
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
public authMethods: RadioItemAuthType[] = [
PKCE_METHOD,
CODE_METHOD,
POST_METHOD,
];
private subscription?: Subscription;
public projectId: string = '';
public app!: Application.AsObject;
@ -78,11 +84,10 @@ export class AppDetailComponent implements OnInit, OnDestroy {
public AppState: any = AppState;
public appNameForm!: FormGroup;
public appForm!: FormGroup;
public redirectUrisList: string[] = [];
public postLogoutRedirectUrisList: string[] = [];
public RedirectType: any = RedirectType;
public isZitadel: boolean = false;
public docs!: ZitadelDocs.AsObject;
@ -90,9 +95,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
public OIDCAuthMethodType: any = OIDCAuthMethodType;
public OIDCTokenType: any = OIDCTokenType;
public redirectControl: FormControl = new FormControl({ value: '', disabled: true });
public postRedirectControl: FormControl = new FormControl({ value: '', disabled: true });
public ChangeType: any = ChangeType;
constructor(
public translate: TranslateService,
@ -103,6 +105,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
private dialog: MatDialog,
private mgmtService: ManagementService,
private authService: GrpcAuthService,
private router: Router,
) {
this.appNameForm = this.fb.group({
state: [{ value: '', disabled: true }, []],
@ -145,12 +148,23 @@ export class AppDetailComponent implements OnInit, OnDestroy {
this.mgmtService.GetApplicationById(projectid, id).then(app => {
this.app = app.toObject();
this.appNameForm.patchValue(this.app);
console.log(this.app);
this.getAuthMethodOptions();
if (this.app.oidcConfig) {
this.initialAuthMethod = this.authMethodFromPartialConfig(this.app.oidcConfig);
this.currentAuthMethod = this.initialAuthMethod;
if (this.initialAuthMethod === CUSTOM_METHOD.key) {
if (!this.authMethods.includes(CUSTOM_METHOD)) {
this.authMethods.push(CUSTOM_METHOD);
}
} else {
this.authMethods = this.authMethods.filter(element => element != CUSTOM_METHOD);
}
}
if (allowed) {
this.appNameForm.enable();
this.appForm.enable();
this.redirectControl.enable();
this.postRedirectControl.enable();
}
if (this.app.oidcConfig?.redirectUrisList) {
@ -161,12 +175,22 @@ export class AppDetailComponent implements OnInit, OnDestroy {
}
if (this.app.oidcConfig?.clockSkew) {
const inSecs = this.app.oidcConfig?.clockSkew.seconds + this.app.oidcConfig?.clockSkew.nanos / 100000;
console.log(inSecs);
this.appForm.controls['clockSkewSeconds'].setValue(inSecs);
}
if (this.app.oidcConfig) {
this.appForm.patchValue(this.app.oidcConfig);
}
this.appForm.valueChanges.subscribe(oidcConfig => {
this.initialAuthMethod = this.authMethodFromPartialConfig(oidcConfig);
if (this.initialAuthMethod === CUSTOM_METHOD.key) {
if (!this.authMethods.includes(CUSTOM_METHOD)) {
this.authMethods.push(CUSTOM_METHOD);
}
} else {
this.authMethods = this.authMethods.filter(element => element != CUSTOM_METHOD);
}
});
}).catch(error => {
console.error(error);
this.toast.showError(error);
@ -176,6 +200,69 @@ export class AppDetailComponent implements OnInit, OnDestroy {
this.docs = (await this.mgmtService.GetZitadelDocs()).toObject();
}
private getAuthMethodOptions(): void {
switch (this.app.oidcConfig?.applicationType) {
case OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE:
this.authMethods = [
PKCE_METHOD,
CUSTOM_METHOD,
];
break;
case OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB:
this.authMethods = [
PKCE_METHOD,
CODE_METHOD,
POST_METHOD,
];
break;
case OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT:
this.authMethods = [
PKCE_METHOD,
IMPLICIT_METHOD,
];
break;
}
}
public authMethodFromPartialConfig(config: OIDCConfig.AsObject): string {
const key = getAuthMethodFromPartialConfig(config);
return key;
}
public setPartialConfigFromAuthMethod(authMethod: string): void {
const partialConfig = getPartialConfigFromAuthMethod(authMethod);
if (partialConfig && this.app.oidcConfig) {
this.app.oidcConfig.responseTypesList = partialConfig.responseTypesList ?? [];
this.app.oidcConfig.grantTypesList = partialConfig.grantTypesList ?? [];
this.app.oidcConfig.authMethodType = partialConfig.authMethodType ?? OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE;
this.appForm.patchValue(this.app.oidcConfig);
}
}
public deleteApp(): void {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.DELETE',
cancelKey: 'ACTIONS.CANCEL',
titleKey: 'APP.PAGES.DIALOG.DELETE.TITLE',
descriptionKey: 'APP.PAGES.DIALOG.DELETE.DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().subscribe(resp => {
if (resp && this.projectId && this.app.id) {
this.mgmtService.RemoveApplication(this.projectId, this.app.id).then(() => {
this.toast.showInfo('APP.TOAST.DELETED', true);
this.router.navigate(['/projects', this.projectId]);
}).catch(error => {
this.toast.showError(error);
});
}
});
}
public changeState(event: MatButtonToggleChange): void {
if (event.value === AppState.APPSTATE_ACTIVE) {
this.mgmtService.ReactivateApplication(this.projectId, this.app.id).then(() => {
@ -192,40 +279,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
}
}
public add(input: any, target: RedirectType): void {
if (target === RedirectType.POSTREDIRECT && this.postRedirectControl.valid) {
if (input.value !== '' && input.value !== ' ' && input.value !== '/') {
this.postLogoutRedirectUrisList.push(input.value);
}
if (input) {
input.value = '';
}
} else if (target === RedirectType.REDIRECT && this.redirectControl.valid) {
if (input.value !== '' && input.value !== ' ' && input.value !== '/') {
this.redirectUrisList.push(input.value);
}
if (input) {
input.value = '';
}
}
}
public remove(redirect: any, target: RedirectType): void {
if (target === RedirectType.POSTREDIRECT) {
const index = this.postLogoutRedirectUrisList.indexOf(redirect);
if (index >= 0) {
this.postLogoutRedirectUrisList.splice(index, 1);
}
} else if (target === RedirectType.REDIRECT) {
const index = this.redirectUrisList.indexOf(redirect);
if (index >= 0) {
this.redirectUrisList.splice(index, 1);
}
}
}
public saveApp(): void {
if (this.appNameForm.valid) {
this.app.name = this.name?.value;
@ -234,6 +287,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
.UpdateApplication(this.projectId, this.app.id, this.name?.value)
.then(() => {
this.toast.showInfo('APP.TOAST.OIDCUPDATED', true);
this.editState = false;
})
.catch(error => {
this.toast.showError(error);
@ -282,10 +336,12 @@ export class AppDetailComponent implements OnInit, OnDestroy {
dur.setNanos((Math.floor(this.clockSkewSeconds?.value % 1) * 10000));
req.setClockSkew(dur);
}
console.log(req.toObject());
this.mgmtService
.UpdateOIDCAppConfig(req)
.then(() => {
if (this.app.oidcConfig) {
this.currentAuthMethod = this.authMethodFromPartialConfig(this.app.oidcConfig);
}
this.toast.showInfo('APP.TOAST.OIDCUPDATED', true);
})
.catch(error => {

View File

@ -19,6 +19,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { AppRadioModule } from 'src/app/modules/app-radio/app-radio.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { ChangesModule } from 'src/app/modules/changes/changes.module';
import { InfoSectionModule } from 'src/app/modules/info-section/info-section.module';
@ -29,15 +30,20 @@ import { AppCreateComponent } from './app-create/app-create.component';
import { AppDetailComponent } from './app-detail/app-detail.component';
import { AppSecretDialogComponent } from './app-secret-dialog/app-secret-dialog.component';
import { AppsRoutingModule } from './apps-routing.module';
import { A11yModule } from '@angular/cdk/a11y';
import { RedirectUrisComponent } from './redirect-uris/redirect-uris.component';
@NgModule({
declarations: [
AppCreateComponent,
AppDetailComponent,
AppSecretDialogComponent,
RedirectUrisComponent,
],
imports: [
CommonModule,
A11yModule,
AppRadioModule,
AppsRoutingModule,
FormsModule,
TranslateModule,

View File

@ -0,0 +1,166 @@
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
import { OIDCAuthMethodType, OIDCConfig, OIDCGrantType, OIDCResponseType } from 'src/app/proto/generated/management_pb';
export const CODE_METHOD: RadioItemAuthType = {
key: 'CODE',
titleI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.CODE.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.CODE.DESCRIPTION',
disabled: false,
prefix: 'CODE',
background: 'rgb(89 115 128)',
responseType: OIDCResponseType.OIDCRESPONSETYPE_CODE,
grantType: OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE,
authMethod: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC,
recommended: false,
};
export const PKCE_METHOD: RadioItemAuthType = {
key: 'PKCE',
titleI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.PKCE.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.PKCE.DESCRIPTION',
disabled: false,
prefix: 'PKCE',
background: 'rgb(80 110 92)',
responseType: OIDCResponseType.OIDCRESPONSETYPE_CODE,
grantType: OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE,
authMethod: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
recommended: true,
};
export const POST_METHOD: RadioItemAuthType = {
key: 'POST',
titleI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.POST.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.POST.DESCRIPTION',
disabled: false,
prefix: 'POST',
background: '#595d80',
responseType: OIDCResponseType.OIDCRESPONSETYPE_CODE,
grantType: OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE,
authMethod: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_POST,
notRecommended: true,
};
export const PK_JWT_METHOD: RadioItemAuthType = {
key: 'PK_JWT',
titleI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.ALTERNATIVE.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.ALTERNATIVE.DESCRIPTION',
disabled: false,
prefix: 'PK_JWT',
background: '#6a506e',
responseType: OIDCResponseType.OIDCRESPONSETYPE_CODE,
grantType: OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE,
authMethod: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_POST,
};
export const IMPLICIT_METHOD: RadioItemAuthType = {
key: 'IMPLICIT',
titleI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.IMPLICIT.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.IMPLICIT.DESCRIPTION',
disabled: false,
prefix: 'IMP',
background: 'rgb(144 75 75)',
responseType: OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN,
grantType: OIDCGrantType.OIDCGRANTTYPE_IMPLICIT,
authMethod: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
notRecommended: true,
};
export const CUSTOM_METHOD: RadioItemAuthType = {
key: 'CUSTOM',
titleI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.CUSTOM.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.AUTHMETHOD.CUSTOM.DESCRIPTION',
disabled: false,
prefix: 'CUSTOM',
background: '#333',
};
export function getPartialConfigFromAuthMethod(authMethod: string): Partial<OIDCConfig.AsObject> | undefined {
let config: Partial<OIDCConfig.AsObject>;
switch (authMethod) {
case CODE_METHOD.key:
config = {
responseTypesList: [OIDCResponseType.OIDCRESPONSETYPE_CODE],
grantTypesList: [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
authMethodType: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC,
};
return config;
case PKCE_METHOD.key:
config = {
responseTypesList: [OIDCResponseType.OIDCRESPONSETYPE_CODE],
grantTypesList: [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
authMethodType: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
};
return config;
case POST_METHOD.key:
config = {
responseTypesList: [OIDCResponseType.OIDCRESPONSETYPE_CODE],
grantTypesList: [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
authMethodType: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_POST,
};
return config;
// case PK_JWT_METHOD.key:
// config = {
// responseTypesList: [OIDCResponseType.OIDCRESPONSETYPE_CODE],
// grantTypesList: [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
// authMethodType: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
// };
// return config;
case IMPLICIT_METHOD.key:
config = {
responseTypesList: [OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN_TOKEN],
grantTypesList: [OIDCGrantType.OIDCGRANTTYPE_IMPLICIT],
authMethodType: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
};
return config;
default:
return undefined;
}
}
export function getAuthMethodFromPartialConfig(config: Partial<OIDCConfig.AsObject> | OIDCConfig.AsObject): string {
const toCheck = [config.responseTypesList, config.grantTypesList, config.authMethodType];
const code = JSON.stringify(
[
[OIDCResponseType.OIDCRESPONSETYPE_CODE],
[OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC,
]
);
const pkce = JSON.stringify(
[
[OIDCResponseType.OIDCRESPONSETYPE_CODE],
[OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
]
);
const post = JSON.stringify(
[
[OIDCResponseType.OIDCRESPONSETYPE_CODE],
[OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
OIDCAuthMethodType.OIDCAUTHMETHODTYPE_POST,
]
);
// const pk_jwt = JSON.stringify(
// [
// [OIDCResponseType.OIDCRESPONSETYPE_CODE],
// [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE],
// OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC,
// ]
// );
const implicit = JSON.stringify(
[
[OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN_TOKEN],
[OIDCGrantType.OIDCGRANTTYPE_IMPLICIT],
OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE,
]
);
switch (JSON.stringify(toCheck)) {
case code: return CODE_METHOD.key;
case pkce: return PKCE_METHOD.key;
case post: return POST_METHOD.key;
// case pk_jwt: return PK_JWT_METHOD.key;
case implicit: return IMPLICIT_METHOD.key;
default:
return CUSTOM_METHOD.key;
}
}

View File

@ -0,0 +1,25 @@
import { OIDCApplicationType } from 'src/app/proto/generated/management_pb';
export const WEB_TYPE = {
titleI18nKey: 'APP.OIDC.SELECTION.APPTYPE.WEB.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.APPTYPE.WEB.DESCRIPTION',
type: OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB,
prefix: 'WEB',
background: 'rgb(80, 110, 110)',
};
export const USER_AGENT_TYPE = {
titleI18nKey: 'APP.OIDC.SELECTION.APPTYPE.USERAGENT.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.APPTYPE.USERAGENT.DESCRIPTION',
type: OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT,
prefix: 'UA',
background: '#6a506e',
};
export const NATIVE_TYPE = {
titleI18nKey: 'APP.OIDC.SELECTION.APPTYPE.NATIVE.TITLE',
descI18nKey: 'APP.OIDC.SELECTION.APPTYPE.NATIVE.DESCRIPTION',
type: OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE,
prefix: 'N',
background: '#595d80',
};

View File

@ -0,0 +1,28 @@
<form class="form" (ngSubmit)="add(redInput)">
<cnsl-form-field class="formfield">
<cnsl-label>{{ title }}</cnsl-label>
<input #redInput cnslInput placeholder="ex. https://" [formControl]="redirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button
[disabled]="redirectControl.invalid || !canWrite">
<mat-icon>add</mat-icon>
</button>
</form>
<div class="uri-list">
<div *ngFor="let uri of urisList" class="uri-line">
<span class="uri"
[ngClass]="{'green': !devMode && uri?.startsWith('https://'), 'red': !devMode && !uri?.startsWith('https://')}">{{uri}}</span>
<span class="fill-space"></span>
<i *ngIf="!devMode && !uri?.startsWith('https://')" class="las la-exclamation red"></i>
<!-- <i *ngIf="!devMode && uri?.startsWith('https://')" class="las la-check green"></i> -->
<button matTooltip="{{'ACTIONS.DELETE' | translate}}" mat-icon-button (click)="remove(uri)" class="icon-button">
<mat-icon>cancel</mat-icon>
</button>
</div>
</div>
<p *ngIf="redirectControl.value && redirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>

View File

@ -0,0 +1,61 @@
.form {
display: flex;
align-items: flex-end;
min-width: 320px;
.formfield {
flex: 1;
}
button {
margin-bottom: 14px;
margin-right: -0.5rem;
}
}
.uri-list {
margin: 0 .5rem;
width: 100%;
.uri-line {
display: flex;
align-items: center;
.uri {
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 14px;
}
.fill-space {
flex: 1;
}
i.green {
font-size: 1rem;
line-height: 35px;
height: 30px;
}
i.red {
font-size: 1.2rem;
}
.icon-button {
height: 30px;
line-height: 30px;
mat-icon {
font-size: 1rem !important;
}
&:not(:hover) {
color: var(--grey);
}
}
}
}
.error {
font-size: 13px;
color: #f44336;
margin: 0 .5rem 1.5rem .5rem;
}

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RedirectUrisComponent } from './redirect-uris.component';
describe('RedirectUrisComponent', () => {
let component: RedirectUrisComponent;
let fixture: ComponentFixture<RedirectUrisComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RedirectUrisComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RedirectUrisComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,43 @@
import { Component, EventEmitter, Input, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'cnsl-redirect-uris',
templateUrl: './redirect-uris.component.html',
styleUrls: ['./redirect-uris.component.scss']
})
export class RedirectUrisComponent implements OnInit {
@Input() title: string = '';
@Input() devMode: boolean = false;
@Input() canWrite: boolean = false;
@Input() public urisList: string[] = [];
@Input() public redirectControl: FormControl = new FormControl({ value: '', disabled: true });
@Input() public changedUris: EventEmitter<string[]> = new EventEmitter();
constructor() { }
ngOnInit(): void {
if (this.canWrite) {
this.redirectControl.enable();
}
}
public add(input: any): void {
if (this.redirectControl.valid) {
if (input.value !== '' && input.value !== ' ' && input.value !== '/') {
this.urisList.push(input.value);
}
if (input) {
input.value = '';
}
}
}
public remove(redirect: any): void {
console.log(redirect);
const index = this.urisList.indexOf(redirect);
if (index >= 0) {
this.urisList.splice(index, 1);
}
}
}

View File

@ -11,18 +11,27 @@
</div>
<div [routerLink]="['/projects', projectId, 'apps', app.id ]" class="app-wrap"
*ngFor="let app of appsSubject | async">
<div class="morph-card" matRipple>
*ngFor="let app of appsSubject | async"
matTooltip="{{'APP.OIDC.APPTYPE'+app.oidcConfig.applicationType | translate}}">
<cnsl-app-card class="grid-card" matRipple [type]="app.oidcConfig?.applicationType">
{{ app.name.charAt(0)}}
</div>
<i *ngIf="app.oidcConfig.applicationType == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE"
class="las la-mobile"></i>
<i *ngIf="app.oidcConfig.applicationType == OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB"
class="las la-code"></i>
<i *ngIf="app.oidcConfig.applicationType == OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT"
class="las la-code"></i>
</cnsl-app-card>
<span class="name">{{app.name}}</span>
<span class="type">{{'APP.OIDC.APPTYPE'+app.oidcConfig.applicationType | translate}}</span>
</div>
<ng-template appHasRole [appHasRole]="['project.app.write']">
<div class="app-wrap" *ngIf="!disabled" [routerLink]="[ '/projects', projectId, 'apps', 'create']">
<div class="morph-card add" matRipple>
<cnsl-app-card class="grid-card add" matRipple>
<mat-icon>add</mat-icon>
</div>
</cnsl-app-card>
<span class="name">{{ 'ACTIONS.NEW' | translate }}</span>
</div>
</ng-template>

View File

@ -1,82 +1,62 @@
@import '~@angular/material/theming';
@mixin application-grid-theme($theme) {
/* stylelint-disable */
$primary: map-get($theme, primary);
$primary-dark: mat-color($primary, A900);
$accent: map-get($theme, accent);
$accent-color: mat-color($primary, 500);
/* stylelint-enable */
.app-grid-header {
.app-grid-header {
display: flex;
align-items: center;
.fill-space {
flex: 1;
flex: 1;
}
}
}
.app-container {
.app-container {
display: flex;
flex-wrap: wrap;
margin: 0 -1rem;
padding-bottom: 2rem;
.sp-container {
display: flex;
justify-content: center;
align-items: center;
width: calc(82px + 2rem);
height: calc(82px + 2rem);
}
.app-wrap {
outline: none;
display: flex;
flex-direction: column;
align-items: center;
max-width: 150px;
.morph-card {
cursor: pointer;
animation: all .2s;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
height: 80px;
width: 80px;
margin: 1rem;
text-transform: uppercase;
border-radius: .5rem;
border: 2px solid $accent-color;
font-weight: 800;
background-color: $primary-dark;
transition: background-color box-shadow .3s ease-in;
background-image:
linear-gradient(transparent 11px, rgba($accent-color, .5) 12px, transparent 12px),
linear-gradient(90deg, transparent 11px, rgba($accent-color, .5) 12px, transparent 12px);
background-size: 100% 12px, 12px 100%;
&:hover {
background-color: rgba($accent-color, .1);
}
&.add {
background: $accent-color;
color: white;
&:hover {
background-color: rgba($accent-color, .8);
}
}
}
.name {
font-size: .8rem;
color: #8a868a;
}
width: calc(82px + 2rem);
height: calc(82px + 2rem);
}
.app-wrap {
outline: none;
display: flex;
flex-direction: column;
align-items: center;
max-width: 150px;
.grid-card {
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 2rem;
height: 80px;
width: 80px;
margin: 1rem;
text-transform: uppercase;
border-radius: .5rem;
font-weight: 800;
box-sizing: border-box;
&.add {
border: 2px solid var(--grey);
}
}
.name {
font-size: 14px;
}
.type {
font-size: 12px;
color: #8a868a;
}
}
}
}

View File

@ -1,8 +1,9 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { BehaviorSubject, from, Observable, of } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';
import { Application } from 'src/app/proto/generated/management_pb';
import { Application, OIDCApplicationType, OIDCResponseType } from 'src/app/proto/generated/management_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
import { NATIVE_TYPE, USER_AGENT_TYPE, WEB_TYPE } from '../../../apps/authtypes';
@Component({
selector: 'app-application-grid',
@ -16,6 +17,11 @@ export class ApplicationGridComponent implements OnInit {
public appsSubject: BehaviorSubject<Application.AsObject[]> = new BehaviorSubject<Application.AsObject[]>([]);
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
public OIDCApplicationType: any = OIDCApplicationType;
public NATIVE_TYPE: any = NATIVE_TYPE;
public WEB_TYPE: any = WEB_TYPE;
public USER_AGENT_TYPE: any = USER_AGENT_TYPE;
constructor(private mgmtService: ManagementService) { }

View File

@ -24,10 +24,17 @@
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.ROLE.NAME' | translate }} </th>
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', role.id ]" mat-cell
*matCellDef="let role">
{{role.name}} </td>
<th mat-header-cell *matHeaderCellDef> {{ 'APP.NAME' | translate }} </th>
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id ]" mat-cell
*matCellDef="let app">
{{app.name}} </td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef> {{ 'APP.OIDC.APPTYPE' | translate }} </th>
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id ]" mat-cell
*matCellDef="let app">
{{'APP.OIDC.APPTYPE'+app?.oidcConfig?.applicationType | translate}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>

View File

@ -26,7 +26,7 @@ export class ApplicationsComponent implements AfterViewInit, OnInit {
public dataSource!: ProjectApplicationsDataSource;
public selection: SelectionModel<Application.AsObject> = new SelectionModel<Application.AsObject>(true, []);
public displayedColumns: string[] = ['select', 'name'];
public displayedColumns: string[] = ['select', 'name', 'type'];
constructor(private mgmtService: ManagementService, private toast: ToastService) { }

View File

@ -8,7 +8,7 @@
<ng-template appHasRole [appHasRole]="['project.write:'+projectId, 'project.write']">
<button matTooltip="{{'ACTIONS.EDIT' | translate}}" mat-icon-button (click)="editstate = !editstate"
aria-label="Edit project name" *ngIf="isZitadel === false">
<mat-icon *ngIf="!editstate">edit</mat-icon>
<i *ngIf="!editstate" class="las la-edit"></i>
<mat-icon *ngIf="editstate">close</mat-icon>
</button>
</ng-template>
@ -24,11 +24,13 @@
<button mat-stroked-button color="warn"
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.projectId]| hasRole | async) == false"
*ngIf="project?.state === ProjectState.PROJECTSTATE_ACTIVE"
(click)="changeState(ProjectState.PROJECTSTATE_INACTIVE)">{{'PROJECT.TABLE.DEACTIVATE' | translate}}</button>
(click)="changeState(ProjectState.PROJECTSTATE_INACTIVE)">{{'PROJECT.TABLE.DEACTIVATE' |
translate}}</button>
<button mat-stroked-button color="warn"
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.projectId]| hasRole | async) == false"
*ngIf="project?.state === ProjectState.PROJECTSTATE_INACTIVE"
(click)="changeState(ProjectState.PROJECTSTATE_ACTIVE)">{{'PROJECT.TABLE.ACTIVATE' | translate}}</button>
(click)="changeState(ProjectState.PROJECTSTATE_ACTIVE)">{{'PROJECT.TABLE.ACTIVATE' |
translate}}</button>
<div class="full-width">
<div class="line">
@ -78,7 +80,7 @@
</ng-template>
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.projectId, 'project.role.read']">
<app-card title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
<app-card id="roles" title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
<p>{{'PROJECT.ROLE.OPTIONS' | translate}}</p>
<mat-checkbox [(ngModel)]="project.projectRoleAssertion" (change)="saveProject()"
@ -118,7 +120,8 @@
<div class="meta-row">
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
<span *ngIf="project && project.state !== undefined" class="state"
[ngClass]="{'active': project.state === ProjectState.PROJECTSTATE_ACTIVE, 'inactive': project.state === ProjectState.PROJECTSTATE_INACTIVE}">{{'PROJECT.STATE.'+project.state | translate}}</span>
[ngClass]="{'active': project.state === ProjectState.PROJECTSTATE_ACTIVE, 'inactive': project.state === ProjectState.PROJECTSTATE_INACTIVE}">{{'PROJECT.STATE.'+project.state
| translate}}</span>
</div>
</div>

View File

@ -14,6 +14,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { MemberCreateDialogModule } from 'src/app/modules/add-member-dialog/member-create-dialog.module';
import { AppCardModule } from 'src/app/modules/app-card/app-card.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { ChangesModule } from 'src/app/modules/changes/changes.module';
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
@ -43,6 +44,7 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen
imports: [
CommonModule,
FormsModule,
AppCardModule,
OwnedProjectDetailRoutingModule,
TranslateModule,
ReactiveFormsModule,

View File

@ -39,7 +39,7 @@
<h1 class="h1">{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}</h1>
<p class="desc">{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}</p>
<app-members-table *ngIf="grant" style="width: 100%;" [dataSource]="dataSource"
<app-members-table *ngIf="grant" style="width: 100%;" [dataSource]="dataSource" [canWrite]="['project.grant.member.write','project.grant.member.write:' + grant.id] | hasRole | async"
[memberRoleOptions]="memberRoleOptions" (updateRoles)="updateMemberRoles($event.member, $event.change)"
[factoryLoadFunc]="changePageFactory" (changedSelection)="selection = $event" [refreshTrigger]="changePage">
<button selectactions (click)="removeProjectMemberSelection()"

View File

@ -7,8 +7,9 @@
</ng-template>
<p>{{'USER.SIGNEDOUT' | translate}}</p>
<button color="primary" mat-raised-button
[routerLink]="[ '/users/me' ]">{{'USER.SIGNEDOUT_BTN' | translate}}</button>
<button matTooltip="{{'ACTIONS.LOGIN' | translate}}" color="primary" mat-raised-button
[routerLink]="[ '/users/me' ]">{{'USER.SIGNEDOUT_BTN' |
translate}} <i class="las la-sign-in-alt"></i></button>
</div>
</div>
</div>

View File

@ -17,19 +17,24 @@
p {
color: var(--grey);
text-align: center;
font-size: 1rem;
font-size: 14px;
margin: 0;
margin-bottom: 3rem;
}
img {
height: 100px;
max-width: 170px;
margin-bottom: 2rem;
}
button {
display: block;
padding: .5rem 4rem;
i {
margin-left: .5rem;
}
}
}
}

View File

@ -77,7 +77,7 @@
</div>
</div>
<ng-template appHasRole [appHasRole]="['user.membership.read']">
<app-memberships [user]="user"></app-memberships>
<app-memberships [auth]="true" [user]="user"></app-memberships>
</ng-template>
<app-changes class="changes" [refresh]="refreshChanges$" [changeType]="ChangeType.MYUSER" [id]="user.id">

View File

@ -3,8 +3,10 @@ import { Component, Input, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
import { AuthServiceClient } from 'src/app/proto/generated/auth_grpc_web_pb';
import { MemberType, UserMembershipSearchResponse, UserView } from 'src/app/proto/generated/management_pb';
import { AdminService } from 'src/app/services/admin.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
@ -33,12 +35,14 @@ export class MembershipsComponent implements OnInit {
public loading: boolean = false;
public memberships!: UserMembershipSearchResponse.AsObject;
@Input() public auth: boolean = false;
@Input() public user!: UserView.AsObject;
@Input() public disabled: boolean = false;
public MemberType: any = MemberType;
constructor(
private authService: GrpcAuthService,
private mgmtService: ManagementService,
private adminService: AdminService,
private dialog: MatDialog,
@ -51,10 +55,17 @@ export class MembershipsComponent implements OnInit {
}
public async loadManager(userId: string): Promise<void> {
this.mgmtService.SearchUserMemberships(userId, 100, 0, []).then(response => {
this.memberships = response.toObject();
this.loading = false;
});
if (this.auth) {
this.authService.SearchUserMemberships(100, 0, []).then(response => {
this.memberships = response.toObject();
this.loading = false;
});
} else {
this.mgmtService.SearchUserMemberships(userId, 100, 0, []).then(response => {
this.memberships = response.toObject();
this.loading = false;
});
}
}
public navigateToObject(): void {

View File

@ -1,7 +1,6 @@
.head {
display: flex;
align-items: center;
border-bottom: 1px solid #ffffff20;
flex-wrap: wrap;
padding-bottom: .5rem;

View File

@ -26,6 +26,9 @@ import {
UpdateUserProfileRequest,
UserAddress,
UserEmail,
UserMembershipSearchQuery,
UserMembershipSearchRequest,
UserMembershipSearchResponse,
UserPhone,
UserProfile,
UserProfileView,
@ -241,6 +244,16 @@ export class GrpcAuthService {
);
}
public SearchUserMemberships(limit: number, offset: number, queryList?: UserMembershipSearchQuery[]): Promise<UserMembershipSearchResponse> {
const req = new UserMembershipSearchRequest();
req.setLimit(limit);
req.setOffset(offset);
if (queryList) {
req.setQueriesList(queryList);
}
return this.grpcService.auth.searchMyUserMemberships(req);
}
public GetMyUserEmail(): Promise<UserEmail> {
return this.grpcService.auth.getMyUserEmail(
new Empty(),

View File

@ -55,6 +55,7 @@ export class AuthInterceptor<TReq = unknown, TResp = unknown> implements UnaryIn
titleKey: 'ERRORS.TOKENINVALID.TITLE',
descriptionKey: 'ERRORS.TOKENINVALID.DESCRIPTION',
},
disableClose: true,
width: '400px',
});

View File

@ -1362,4 +1362,11 @@ export class ManagementService {
public UpdateOIDCAppConfig(req: OIDCConfigUpdate): Promise<OIDCConfig> {
return this.grpcService.mgmt.updateApplicationOIDCConfig(req);
}
public RemoveApplication(projectId: string, appId: string): Promise<Empty> {
const req = new ApplicationID();
req.setId(appId);
req.setProjectId(projectId);
return this.grpcService.mgmt.removeApplication(req);
}
}

View File

@ -1,5 +1,29 @@
{
"APP_NAME": "ZITADEL",
"ONBOARDING": {
"HEADER":"Erste Schritte",
"TITLE":"Lernen Sie unsere ZITADEL Console kennen.",
"LOGINDESC":"Melden Sie sich an um Zugriff auf Funktionen von Zitadel zu erhalten",
"LOGIN":"Anmelden",
"DESCRIPTION":"Führen Sie die folgenden Schritte aus und passen Sie ZITADEL optimal an Ihre Bedürfnisse an.",
"STEPS_TITLE":"Führen Sie die folgenden Schritte in gewünschter Reihenfolge aus:",
"STEPS": {
"1": {
"TITLE":"Projekt erstellen",
"DESC":"Erstellen Sie Ihr erstes Projekt und legen Sie Zugangsberechtigungen eventueller Mitarbeiter fest."
},
"2": {
"TITLE":"Applikation erstellen",
"DESC":"Erstellen Sie eine Applikation innerhalb Ihres Projektes und legen Sie dessen Eigenschaften fest."
},
"3": {
"TITLE":"Sicherheit verbessern",
"DESC":"Erweitern Sie die Zugangsrichtlinien und erhöhen Sie dadurch die Sicherheit ihrer Benutzer."
}
},
"START":"Start",
"DOCS":"Docs"
},
"HOME": {
"TITLE": "ZITADEL",
"SECURITYANDPRIVACY": "Datenschutz und Personalisierung",
@ -32,9 +56,15 @@
"WELCOME":"Willkommen",
"WELCOMESENTENCE":"Hier findest Du die empfohlenen Aktionen basierend auf Deinen zuletzt erworbenen Berechtigungen. Beachte bitte, dass Du möglicherweise Deine Organisation in der Kopfzeile wechseln musst.",
"DISCLAIMER":"Du kannst nur die Einstellungen Deiner aktuellen Organisation, die in der Kopfzeile angegeben ist, sehen. ZITADEL behandelt Deine Daten vertraulich und sicher.",
"DISCLAIMERLINK":"Mehr Informationen zur Sicherheit"
"DISCLAIMERLINK":"Mehr Informationen zur Sicherheit",
"QUICKSTARTS": {
"LABEL":"Erste Schritte",
"TITLE":"Quickstarts",
"DESCRIPTION":"Mit ZITADEL schnell durchstarten."
}
},
"MENU": {
"DASHBOARD":"Übersicht",
"PERSONAL_INFO": "Persönliche Informationen",
"DOCUMENTATION":"Dokumentation",
"IAMPOLICIES":"IAM",
@ -54,6 +84,7 @@
"SHOWORGS":"Alle Organisationen anzeigen",
"GRANTSECTION":"Berechtigungssektion",
"GRANTS":"Berechtigungen",
"TOC":"Datenschutz und AGB",
"TOOLTIP": {
"PERSONAL":"Verwalte deinen persönlichen Account, deine IDPs, Login Methoden, Faktoren und Berechtigungen",
"IAMPOLICIES":"Verwalte ZITADELs globale Zugangsrichtlinien und verwalte ZITADEL Manager",
@ -930,12 +961,34 @@
"1": "Aktiv",
"2": "Inaktiv"
}
},
"DIALOG": {
"DELETE": {
"TITLE": "App löschen",
"DESCRIPTION":"Wollen Sie diese App wirklich löschen?"
}
},
"NEXTSTEPS": {
"TITLE":"Nächste Schritte",
"0": {
"TITLE":"Rollen festlegen",
"DESC":"Erfassen Sie Rollen für ihr Projekt"
},
"1": {
"TITLE":"Benutzer hinzufügen",
"DESC":"Fügen Sie Nutzer ihrer Organisation hinzu"
},
"2": {
"TITLE":"Hilfe & Support",
"DESC":"Lesen Sie unsere Dokumentation zum Erstellen von Applikation oder kontaktieren Sie unseren Support"
}
}
},
"NAME": "Name",
"TYPE":"Anwendungstyp",
"GRANT":"Berechtigungstypen",
"OIDC": {
"CURRENT":"Aktuelle Konfiguration",
"TOKENSECTIONTITLE":"AuthToken Optionen",
"REDIRECTSECTIONTITLE":"Weiterleitungseinstellungen",
"PROSWITCH":"Konfigurator überspringen",
@ -991,13 +1044,58 @@
"IDTOKENROLEASSERTION_DESCRIPTION":"Bei Auswahl werden dem Id Token die Rollen des Authentifizierten Benutzers hinzugefügt.",
"IDTOKENUSERINFOASSERTION":"User Info im ID Token",
"IDTOKENUSERINFOASSERTION_DESCRIPTION":"Ermöglich OIDC clients claims von profile, email, phone und address direkt vom ID Token zu beziehen.",
"CLOCKSKEW":"ermöglicht Clients, den Taktversatz von OP und Client zu verarbeiten. Die Dauer (0-5s) wird der exp addiert und von iats, auth_time und nbf abgezogen."
"CLOCKSKEW":"ermöglicht Clients, den Taktversatz von OP und Client zu verarbeiten. Die Dauer (0-5s) wird der exp addiert und von iats, auth_time und nbf abgezogen.",
"RECOMMENDED":"Empfohlen",
"NOTRECOMMENDED":"nicht empfohlen",
"SELECTION":{
"APPTYPE": {
"WEB": {
"TITLE":"Web",
"DESCRIPTION":"Standard Web applications wie .net, PHP, Node.js, Java, etc."
},
"NATIVE": {
"TITLE":"NATIVE",
"DESCRIPTION":"Mobile Apps, Desktop, Smart Devices, etc."
},
"USERAGENT": {
"TITLE":"User Agent",
"DESCRIPTION":"Single Page Applications (SPA) und grundsätzlich alle im Browser aufgeführten JS Frameworks"
}
},
"AUTHMETHOD": {
"CODE": {
"TITLE":"Code",
"DESCRIPTION":"Tausche den Authorization Code gegen Tokens ein"
},
"PKCE": {
"TITLE":"PKCE",
"DESCRIPTION":"Nutze einen Zufalls Hash Wert anstelle des Client Secret für mehr Sicherheit"
},
"POST": {
"TITLE":"POST",
"DESCRIPTION":"Sende client_id und client_secret im (HTML) Formular"
},
"PK_JWT": {
"TITLE":"Private Key JWT",
"DESCRIPTION":"Nutze einen Private Key um deine Application zu authentifizieren"
},
"IMPLICIT": {
"TITLE":"Implicit",
"DESCRIPTION":"Erhalte die Token direkt vom authorize Endpoint"
},
"CUSTOM": {
"TITLE":"Custom",
"DESCRIPTION":"Deine Konfiguration entspricht keiner anderen Option."
}
}
}
},
"TOAST": {
"REACTIVATED":"Anwendung reaktiviert.",
"DEACTIVATED":"Anwendung deaktiviert.",
"OIDCUPDATED":"OIDC-Konfiguration geändert.",
"OIDCCLIENTSECRETREGENERATED":"OIDC-Client Secret generiert."
"OIDCCLIENTSECRETREGENERATED":"OIDC-Client Secret generiert.",
"DELETED":"App gelöscht."
}
},
"GENDERS": {

View File

@ -1,5 +1,29 @@
{
"APP_NAME": "ZITADEL",
"ONBOARDING": {
"HEADER":"First Steps",
"TITLE":"Learn how to use ZITADEL",
"LOGINDESC":"You need to log in to control your ZITADEL settings.",
"LOGIN":"Login",
"DESCRIPTION":"We at ZITADEL care a lot about security and performance. Carry out the following steps and adapt ZITADEL optimally to your needs.",
"STEPS_TITLE":"Complete the following steps in the order you want:",
"STEPS": {
"1": {
"TITLE":"Create a project",
"DESC":"Create your first project and define access rights for any employees."
},
"2": {
"TITLE":"Create Application",
"DESC":"Create an application within your project and define its properties."
},
"3": {
"TITLE":"Improve security",
"DESC":"Extend the access policies and thereby increase the security of your users."
}
},
"START":"Start",
"DOCS":"Docs"
},
"HOME": {
"TITLE": "ZITADEL",
"SECURITYANDPRIVACY": "Data Protection and Personalisation",
@ -32,9 +56,15 @@
"WELCOME":"Welcome",
"WELCOMESENTENCE":"Here you can find recommended actions based on your last acquired permissions. Note that you may have to select your organisation in the header above.",
"DISCLAIMER":"You can only see settings of your current organisation specified in the header. ZITADEL treats your data confidentially and securely.",
"DISCLAIMERLINK":"Further information"
"DISCLAIMERLINK":"Further information",
"QUICKSTARTS": {
"LABEL":"First Steps",
"TITLE":"Quickstarts",
"DESCRIPTION":"Get started with ZITADEL quickly."
}
},
"MENU": {
"DASHBOARD":"Overview",
"PERSONAL_INFO": "Personal Information",
"DOCUMENTATION":"Documentation",
"IAMPOLICIES":"IAM",
@ -54,6 +84,7 @@
"SHOWORGS":"Show All Organisations",
"GRANTSECTION":"Authorization Section",
"GRANTS":"Authorizations",
"TOC":"Privacy Policy and TOC",
"TOOLTIP": {
"PERSONAL":"Show your Personal Account, your IDPs, Login methods, Factors and Authorisations",
"IAMPOLICIES":"Manage ZITADELs global Access policies und elect ZITADEL Managers",
@ -930,12 +961,34 @@
"1": "Active",
"2": "Inactive"
}
},
"DIALOG": {
"DELETE": {
"TITLE": "Delete App",
"DESCRIPTION":"Do you really want to delete this application?"
}
},
"NEXTSTEPS": {
"TITLE":"Next Steps",
"0": {
"TITLE":"Add roles",
"DESC":"Enter your project roles"
},
"1": {
"TITLE":"Add users",
"DESC":"Add new users of your organization"
},
"2": {
"TITLE":"Help & Support",
"DESC":"Read our documentation on creating applications or contact our support"
}
}
},
"NAME": "Name",
"TYPE":"Application Type",
"GRANT":"Grant Types",
"OIDC": {
"CURRENT":"Current Config",
"TOKENSECTIONTITLE":"AuthToken Options",
"REDIRECTSECTIONTITLE":"Redirect Settings",
"PROSWITCH":"I'm a pro. Skip this wizard.",
@ -991,13 +1044,58 @@
"IDTOKENROLEASSERTION_DESCRIPTION":"If selected, the roles of the authenticated user are added to the ID token.",
"IDTOKENUSERINFOASSERTION":"User Info inside ID Token",
"IDTOKENUSERINFOASSERTION_DESCRIPTION":"Enables clients to retrieve profile, email, phone and address claims from ID token.",
"CLOCKSKEW":"Enables clients to handle clock skew of OP and client. The duration (0-5s) will be added to exp claim and subtracted from iats, auth_time and nbf."
"CLOCKSKEW":"Enables clients to handle clock skew of OP and client. The duration (0-5s) will be added to exp claim and subtracted from iats, auth_time and nbf.",
"RECOMMENDED":"recommended",
"NOTRECOMMENDED":"not recommended",
"SELECTION":{
"APPTYPE": {
"WEB": {
"TITLE":"Web",
"DESCRIPTION":"Regular Web applications like .net, PHP, Node.js, Java, etc."
},
"NATIVE": {
"TITLE":"NATIVE",
"DESCRIPTION":"Mobile Apps, Desktop, Smart Devices, etc."
},
"USERAGENT": {
"TITLE":"User Agent",
"DESCRIPTION":"Single Page Applications (SPA) and in general all JS frameworks executed in browsers"
}
},
"AUTHMETHOD": {
"CODE": {
"TITLE":"Code",
"DESCRIPTION":"Exchange the authorization code for the tokens"
},
"PKCE": {
"TITLE":"PKCE",
"DESCRIPTION":"Use a random hash instead of a static client secret for more security"
},
"POST": {
"TITLE":"POST",
"DESCRIPTION":"Send client_id and client_secret as part of the form"
},
"PK_JWT": {
"TITLE":"Private Key JWT",
"DESCRIPTION":"Use a private key to authorize your application"
},
"IMPLICIT": {
"TITLE":"Implicit",
"DESCRIPTION":"Get the tokens directly from the authorization endpoint"
},
"CUSTOM": {
"TITLE":"Custom",
"DESCRIPTION":"Your setting doesn't correspond to any other option."
}
}
}
},
"TOAST": {
"REACTIVATED":"Application reactivated.",
"DEACTIVATED":"Application deactivated.",
"OIDCUPDATED":"OIDC configuration updated.",
"OIDCCLIENTSECRETREGENERATED":"OIDC client secret generated."
"OIDCCLIENTSECRETREGENERATED":"OIDC client secret generated.",
"DELETED":"App deleted."
}
},
"GENDERS": {

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 467 468" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,0,-492)">
<g id="zitadel-logo-solo-lightdesign" transform="matrix(0.564847,0,0,0.659318,-1282.85,492.925)">
<rect x="2271.15" y="0" width="826.773" height="708.241" style="fill:none;"/>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5923.46,-2258.26)">
<path d="M1493.5,1056.38L1493.5,1037L1496.5,1037L1496.5,1061.62L1426.02,1020.38L1496.5,979.392L1496.5,1004L1493.5,1004L1493.5,984.608L1431.98,1020.39L1493.5,1056.38Z" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(31.0036,0,0,15.0393,-397275,-666.457)">
<g transform="matrix(-0.0429306,-0.282967,0.160219,-0.0758207,12884.5,137.392)">
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear1);"/>
</g>
<g transform="matrix(0.160219,0.0758207,-0.0429306,0.282967,12878.9,10.8747)">
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear2);"/>
</g>
<g transform="matrix(-0.117289,0.207146,-0.117289,-0.207146,12943.8,65.7)">
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear3);"/>
</g>
<g transform="matrix(-0.160219,-0.0758207,0.0429306,-0.282967,12917.4,132.195)">
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear4);"/>
</g>
<g transform="matrix(-0.117289,0.207146,0.117289,0.207146,12897.8,5.87512)">
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear5);"/>
</g>
<g transform="matrix(-0.0429306,-0.282967,-0.160219,0.0758207,12936.8,97.6441)">
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear6);"/>
</g>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5928.43,-2257.12)">
<circle cx="1496" cy="1004" r="7" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5884.5,-2116.69)">
<circle cx="1496" cy="1004" r="7" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5855.22,-2023.06)">
<circle cx="1496" cy="1004" r="7" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-6234.47,-2112.14)">
<circle cx="1496" cy="1004" r="7" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5957.71,-2350.75)">
<circle cx="1496" cy="1004" r="7" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5477.99,-831.33)">
<path d="M1499.26,757.787C1499.26,757.787 1497.37,756.489 1497,755.2C1496.71,754.182 1496.57,750.662 1496.54,750C1496.41,747.303 1499.21,745.644 1499.21,745.644L1490.01,745.835C1490.01,745.835 1493.15,745.713 1493.46,750C1493.51,750.661 1493.23,753.476 1493,755.2C1492.91,756.447 1491.2,757.668 1491.2,757.668L1499.26,757.787Z" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
<path d="M1495,760L1495,744" style="fill:none;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
<path d="M1498.27,757.077C1498.27,757.077 1496.71,756.46 1496.65,754.8C1496.65,753.658 1496.64,753.281 1496.65,752.016C1496.62,751.334 1496.59,750.608 1496.65,749.949C1496.78,746.836 1498.5,746.156 1498.5,746.156L1491.46,745.931C1491.46,745.931 1493.37,746.719 1493.65,749.83C1493.71,750.489 1493.69,751.528 1493.65,752.209C1493.64,753.331 1493.64,753.413 1493.65,754.518C1493.68,756.334 1492.58,756.827 1492.58,756.827L1498.27,757.077Z" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
<path d="M1500.86,762.056C1500.86,762.056 1499.86,760.4 1503.09,757.456C1504.91,755.797 1507.33,754.151 1509.98,752.255C1514.82,748.79 1520.68,744.94 1526.52,741.049C1531.45,737.766 1536.38,734.479 1540.82,731.68C1544.52,729.349 1547.85,727.296 1550.54,725.8C1551.07,725.506 1551.6,725.329 1552.05,725.029C1554.73,723.257 1556.85,724.968 1556.85,724.968L1552.23,716.282C1552.23,716.282 1551.99,719.454 1550,720.997C1549.57,721.333 1549.15,721.741 1548.67,722.12C1546.2,724.053 1542.99,726.344 1539.39,728.867C1535.06,731.898 1530.13,735.166 1525.19,738.438C1519.35,742.314 1513.52,746.234 1508.49,749.329C1505.74,751.023 1503.28,752.577 1501.13,753.598C1497.99,755.086 1495.28,753.617 1495.28,753.617L1500.86,762.056Z" style="fill:rgb(35,35,35);"/>
</g>
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
</g>
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
<path d="M1496.1,754.362C1496.1,754.362 1497.2,755.607 1501.13,753.598C1503.25,752.509 1505.74,751.023 1508.49,749.329C1513.52,746.234 1519.35,742.314 1525.19,738.438C1530.13,735.166 1534.94,731.832 1539.27,728.802C1542.87,726.279 1549.36,722.059 1549.81,721.75C1552.75,719.73 1552.18,718.196 1552.18,718.196L1555.28,724.152C1555.28,724.152 1553.77,722.905 1551.37,724.681C1550.93,725.006 1544.52,729.349 1540.82,731.68C1536.38,734.479 1531.45,737.766 1526.52,741.049C1520.68,744.94 1514.82,748.79 1509.98,752.255C1507.33,754.151 1504.89,755.771 1503.09,757.456C1499.47,760.841 1501.26,763.283 1501.26,763.283L1496.1,754.362Z" style="fill:rgb(35,35,35);"/>
</g>
</g>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,155.247,-155.247,-41.5984,201.516,76.8392)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(155.247,-41.5984,41.5984,155.247,110.08,195.509)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,-113.649,113.649,-113.649,258.31,215.618)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear4" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-155.247,41.5984,-41.5984,-155.247,220.914,144.546)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear5" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,113.649,113.649,113.649,206.837,124.661)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear6" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,-155.247,-155.247,41.5984,152.054,262.8)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 467 467" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g id="zitadel-logo-solo-darkdesign" transform="matrix(0.564847,0,0,0.659318,-1282.85,0)">
<rect x="2271.15" y="0" width="826.773" height="708.241" style="fill:none;"/>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5923.46,-2258.26)">
<path d="M1493.5,1056.38L1493.5,1037L1496.5,1037L1496.5,1061.62L1426.02,1020.38L1496.5,979.392L1496.5,1004L1493.5,1004L1493.5,984.608L1431.98,1020.39L1493.5,1056.38Z" style="fill:white;"/>
</g>
<g transform="matrix(31.0036,0,0,15.0393,-397275,-666.457)">
<g transform="matrix(-0.0429306,-0.282967,0.160219,-0.0758207,12884.5,137.392)">
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear1);"/>
</g>
<g transform="matrix(0.160219,0.0758207,-0.0429306,0.282967,12878.9,10.8747)">
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear2);"/>
</g>
<g transform="matrix(-0.117289,0.207146,-0.117289,-0.207146,12943.8,65.7)">
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear3);"/>
</g>
<g transform="matrix(-0.160219,-0.0758207,0.0429306,-0.282967,12917.4,132.195)">
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear4);"/>
</g>
<g transform="matrix(-0.117289,0.207146,0.117289,0.207146,12897.8,5.87512)">
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear5);"/>
</g>
<g transform="matrix(-0.0429306,-0.282967,-0.160219,0.0758207,12936.8,97.6441)">
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear6);"/>
</g>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5928.43,-2257.12)">
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5884.5,-2116.69)">
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5855.22,-2023.06)">
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-6234.47,-2112.14)">
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5957.71,-2350.75)">
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5477.99,-831.33)">
<path d="M1499.26,757.787C1499.26,757.787 1497.37,756.489 1497,755.2C1496.71,754.182 1496.57,750.662 1496.54,750C1496.41,747.303 1499.21,745.644 1499.21,745.644L1490.01,745.835C1490.01,745.835 1493.15,745.713 1493.46,750C1493.51,750.661 1493.23,753.476 1493,755.2C1492.91,756.447 1491.2,757.668 1491.2,757.668L1499.26,757.787Z" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
<path d="M1495,760L1495,744" style="fill:none;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
<path d="M1498.27,757.077C1498.27,757.077 1496.71,756.46 1496.65,754.8C1496.65,753.658 1496.64,753.281 1496.65,752.016C1496.62,751.334 1496.59,750.608 1496.65,749.949C1496.78,746.836 1498.5,746.156 1498.5,746.156L1491.46,745.931C1491.46,745.931 1493.37,746.719 1493.65,749.83C1493.71,750.489 1493.69,751.528 1493.65,752.209C1493.64,753.331 1493.64,753.413 1493.65,754.518C1493.68,756.334 1492.58,756.827 1492.58,756.827L1498.27,757.077Z" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
</g>
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
<path d="M1500.86,762.056C1500.86,762.056 1499.86,760.4 1503.09,757.456C1504.91,755.797 1507.33,754.151 1509.98,752.255C1514.82,748.79 1520.68,744.94 1526.52,741.049C1531.45,737.766 1536.38,734.479 1540.82,731.68C1544.52,729.349 1547.85,727.296 1550.54,725.8C1551.07,725.506 1551.6,725.329 1552.05,725.029C1554.73,723.257 1556.85,724.968 1556.85,724.968L1552.23,716.282C1552.23,716.282 1551.99,719.454 1550,720.997C1549.57,721.333 1549.15,721.741 1548.67,722.12C1546.2,724.053 1542.99,726.344 1539.39,728.867C1535.06,731.898 1530.13,735.166 1525.19,738.438C1519.35,742.314 1513.52,746.234 1508.49,749.329C1505.74,751.023 1503.28,752.577 1501.13,753.598C1497.99,755.086 1495.28,753.617 1495.28,753.617L1500.86,762.056Z" style="fill:white;"/>
</g>
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
</g>
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
<path d="M1496.1,754.362C1496.1,754.362 1497.2,755.607 1501.13,753.598C1503.25,752.509 1505.74,751.023 1508.49,749.329C1513.52,746.234 1519.35,742.314 1525.19,738.438C1530.13,735.166 1534.94,731.832 1539.27,728.802C1542.87,726.279 1549.36,722.059 1549.81,721.75C1552.75,719.73 1552.18,718.196 1552.18,718.196L1555.28,724.152C1555.28,724.152 1553.77,722.905 1551.37,724.681C1550.93,725.006 1544.52,729.349 1540.82,731.68C1536.38,734.479 1531.45,737.766 1526.52,741.049C1520.68,744.94 1514.82,748.79 1509.98,752.255C1507.33,754.151 1504.89,755.771 1503.09,757.456C1499.47,760.841 1501.26,763.283 1501.26,763.283L1496.1,754.362Z" style="fill:white;"/>
</g>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,155.247,-155.247,-41.5984,201.516,76.8392)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(155.247,-41.5984,41.5984,155.247,110.08,195.509)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,-113.649,113.649,-113.649,258.31,215.618)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear4" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-155.247,41.5984,-41.5984,-155.247,220.914,144.546)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear5" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,113.649,113.649,113.649,206.837,124.661)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear6" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,-155.247,-155.247,41.5984,152.054,262.8)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -5,24 +5,29 @@
@import './styles/link.scss';
@import './styles/sidenav-list';
@import 'src/app/modules/avatar/avatar.component';
@import 'src/app/modules/app-radio/app-type-radio/app-type-radio.component';
@import 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
@import 'src/app/modules/changes/changes.component';
@import 'src/app/modules/info-section/info-section.component';
@import 'src/app/modules/detail-layout/detail-layout.component';
@import 'src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component';
@import 'src/app/modules/app-card/app-card.component';
@import 'src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-card';
@import 'src/app/pages/users/user-detail/memberships/memberships.component';
@import 'src/app/app.component.scss';
@import 'src/app/modules/form-field/form-field.component.scss';
@import 'src/app/modules/label/label.component.scss';
@import 'src/app/modules/meta-layout/meta.scss';
@import 'src/app/modules/onboarding/onboarding.component.scss';
@mixin component-themes($theme) {
@include avatar-theme($theme);
@include app-type-radio-theme($theme);
@include app-auth-method-radio-theme($theme);
@include card-theme($theme);
@include table-theme($theme);
@include detail-layout-theme($theme);
@include sidenav-list-theme($theme);
@include application-grid-theme($theme);
@include app-card-theme($theme);
@include membership-theme($theme);
@include changes-theme($theme);
@include theme-card($theme);
@ -34,4 +39,5 @@
@include link-theme($theme);
@include meta-theme($theme);
@include info-section-theme($theme);
@include onboarding-theme($theme);
}

View File

@ -219,18 +219,21 @@ $custom-typography:
box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
background-color: #2d2e30;
border-radius: 8px;
transition: all .3s cubic-bezier(.645, .045, .355, 1) !important;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: #2d2e30;
transition: all .3s cubic-bezier(.645, .045, .355, 1) !important;
}
::-webkit-scrollbar-thumb {
background-color: #737c8870;
border-radius: 8px;
cursor: pointer;
transition: all .3s cubic-bezier(.645, .045, .355, 1) !important;
}
.root-header {

View File

@ -16,18 +16,23 @@
box-shadow: inset 1px 0 if($is-dark-theme, #303131, #e3e8ee);
}
.sidenav {
box-shadow: inset -1px 0 if($is-dark-theme, #303131, #e3e8ee);
transition: all .3s cubic-bezier(.645, .045, .355, 1) !important;
}
.nav-item {
color: mat-color($foreground, text) !important;
&:hover {
background-color: $sec-dark;
background-color: if($is-dark-theme, $sec-dark, rgb(84 105 212 / 6%));
border-top-right-radius: 1.5rem;
border-bottom-right-radius: 1.5rem;
}
&.active {
color: $primary-color !important;
background-color: rgba($color: $primary-color, $alpha: .1) !important;
background-color: if($is-dark-theme, rgba($color: $primary-color, $alpha: .1), rgb(84 105 212 / 6%)) !important;
}
.c_label {
@ -54,7 +59,16 @@
.root-header {
box-shadow: inset 0 -1px #e3e8ee;
background-color: $primary-dark !important;
transition: background-color .3s cubic-bezier(.645, .045, .355, 1);
transition: all .3s cubic-bezier(.645, .045, .355, 1);
.slash {
color: if($is-dark-theme, #525454, #d1d5d9);
}
.org-button {
border: 1px solid if($is-dark-theme, #303131, #e3e8ee);
transition: all .3s cubic-bezier(.645, .045, .355, 1) !important;
}
}
.admin-line {
@ -63,7 +77,7 @@
align-items: center;
bottom: 0;
left: 0;
right: calc(100vw - 300px);
right: calc(100vw - 280px);
background-color: $primary-color;
color: white;
z-index: 1;

View File

@ -64,7 +64,8 @@
}
}
.mat-checkbox {
td .mat-checkbox,
th .mat-checkbox {
margin-left: 1rem;
}

6
go.mod
View File

@ -16,7 +16,7 @@ require (
github.com/allegro/bigcache v1.2.1
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc
github.com/caos/logging v0.0.2
github.com/caos/oidc v0.13.2
github.com/caos/oidc v0.14.0
github.com/caos/orbos v1.5.14-0.20210205131708-6dc812182dc0
github.com/cockroachdb/cockroach-go/v2 v2.1.0
github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43
@ -56,7 +56,7 @@ require (
github.com/rs/cors v1.7.0
github.com/sony/sonyflake v1.0.0
github.com/spf13/cobra v0.0.7
github.com/stretchr/testify v1.6.1
github.com/stretchr/testify v1.7.0
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
github.com/ttacon/libphonenumber v1.1.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.13.0
@ -69,7 +69,7 @@ require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 // indirect
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
golang.org/x/text v0.3.4
golang.org/x/text v0.3.5
golang.org/x/tools v0.0.0-20201103235415-b653051172e4
google.golang.org/api v0.34.0
google.golang.org/appengine v1.6.7 // indirect

53
go.sum
View File

@ -108,6 +108,7 @@ github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKS
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@ -116,6 +117,7 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@ -124,6 +126,7 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.31.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJyXg=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@ -137,12 +140,8 @@ github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a/go.mod h1:9LKiDE2ChuG
github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo=
github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0=
github.com/caos/oidc v0.6.2/go.mod h1:ozoi3b+aY33gzdvjz4w90VZShIHGsmDa0goruuV0arQ=
github.com/caos/oidc v0.13.2 h1:52oP3KB1UrZuwraBTLuwM9ItRIhJQMYOm1J5uQ0sYXw=
github.com/caos/oidc v0.13.2/go.mod h1:dLvfYUiAt9ORfl77L/KkcWuR/N0ll8Ry1nD2ERsamDY=
github.com/caos/orbos v1.5.14-0.20210128140136-842933949472 h1:iti4tAKxBknjJkQcDKWaxlj9Jbng5kz5TpQzzyda49o=
github.com/caos/orbos v1.5.14-0.20210128140136-842933949472/go.mod h1:ZLxNgPuYIlSvr80trezGGUIXng9gY2hHEdky/m0B/P0=
github.com/caos/orbos v1.5.14-0.20210202122121-ad32524ffc73 h1:usYmCT11HvwxBCk1+DSCmEU6CVYhzY8jHaQHSJMrxlg=
github.com/caos/orbos v1.5.14-0.20210202122121-ad32524ffc73/go.mod h1:ZLxNgPuYIlSvr80trezGGUIXng9gY2hHEdky/m0B/P0=
github.com/caos/oidc v0.14.0 h1:l7mTqYDpqNRZF9Vwzq5KAQd1wQCThdceL5HpsEMGoao=
github.com/caos/oidc v0.14.0/go.mod h1:CPsubVrA110OyLnCKwVZjTdsAVwq67DTbYIvux7UgbY=
github.com/caos/orbos v1.5.14-0.20210205131708-6dc812182dc0 h1:N+KYBwuQO3QPr/nTUaNwjAetjp3NU4MP8Nv9Iue53UE=
github.com/caos/orbos v1.5.14-0.20210205131708-6dc812182dc0/go.mod h1:ZLxNgPuYIlSvr80trezGGUIXng9gY2hHEdky/m0B/P0=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
@ -154,9 +153,11 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
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 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
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 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
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=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@ -186,13 +187,17 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@ -212,6 +217,7 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@ -224,23 +230,28 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ=
github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@ -298,6 +309,7 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -308,6 +320,7 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
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 h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
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=
@ -367,8 +380,10 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -383,6 +398,8 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
@ -390,6 +407,7 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3 h1:eHv/jVY/JNop1xg2J9cBb4EzyMpWZoNCP1BslSAIkOI=
github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3/go.mod h1:h/KNeRx7oYU4SpA4SoY7W2/NxDKEEVuwA6j9A27L4OI=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@ -442,7 +460,9 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
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=
@ -455,6 +475,7 @@ github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 h1:KUDFlmBg2buRWNzIcwLlKvfcnujcHQRQ1As1LoaCLAM=
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
@ -510,6 +531,7 @@ github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBef
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
@ -523,6 +545,7 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
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=
@ -553,8 +576,11 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1/go.mod h1:f0X1c0za3TbET/rl5ThtCSel0+G3/yZ8iuU9BxnyVK0=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -602,6 +628,7 @@ github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@ -644,6 +671,7 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nicksnyder/go-i18n/v2 v2.1.1 h1:ATCOanRDlrfKVB4WHAdJnLEqZtDmKYsweqsOUYflnBU=
github.com/nicksnyder/go-i18n/v2 v2.1.1/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
@ -653,9 +681,11 @@ github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FW
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -792,6 +822,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -908,6 +940,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -1053,6 +1086,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1154,6 +1189,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -1231,9 +1267,11 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
@ -1246,9 +1284,11 @@ gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
@ -1301,6 +1341,7 @@ k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUc
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kubectl v0.18.3/go.mod h1:k/EpvXBDgEsHBzWr0A44l9+ArvYi3txBBnzXBjQasUQ=
k8s.io/metrics v0.18.3/go.mod h1:TkuJE3ezDZ1ym8pYkZoEzJB7HDiFE7qxl+EmExEBoPA=

View File

@ -37,6 +37,27 @@ type Grant struct {
Roles []string
}
type Memberships []*Membership
type Membership struct {
MemberType MemberType
AggregateID string
//ObjectID differs from aggregate id if obejct is sub of an aggregate
ObjectID string
Roles []string
}
type MemberType int32
const (
MemberTypeUnspecified MemberType = iota
MemberTypeOrganisation
MemberTypeProject
MemberTypeProjectGrant
MemberTypeIam
)
func VerifyTokenAndCreateCtxData(ctx context.Context, token, orgID string, t *TokenVerifier, method string) (_ CtxData, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()

View File

@ -2,7 +2,6 @@ package authz
import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
@ -16,41 +15,43 @@ func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPer
}
ctx = context.WithValue(ctx, dataKey, ctxData)
grant, err := t.ResolveGrant(ctx)
memberships, err := t.SearchMyMemberships(ctx)
if err != nil {
return nil, nil, err
}
if grant == nil {
if len(memberships) == 0 {
return requestedPermissions, nil, nil
}
requestedPermissions, allPermissions = mapGrantToPermissions(requiredPerm, grant, authConfig)
requestedPermissions, allPermissions = mapMembershipsToPermissions(requiredPerm, memberships, authConfig)
return requestedPermissions, allPermissions, nil
}
func mapGrantToPermissions(requiredPerm string, grant *Grant, authConfig Config) (requestPermissions, allPermissions []string) {
func mapMembershipsToPermissions(requiredPerm string, memberships []*Membership, authConfig Config) (requestPermissions, allPermissions []string) {
requestPermissions = make([]string, 0)
allPermissions = make([]string, 0)
for _, role := range grant.Roles {
requestPermissions, allPermissions = mapRoleToPerm(requiredPerm, role, authConfig, requestPermissions, allPermissions)
for _, membership := range memberships {
requestPermissions, allPermissions = mapMembershipToPerm(requiredPerm, membership, authConfig, requestPermissions, allPermissions)
}
return requestPermissions, allPermissions
}
func mapRoleToPerm(requiredPerm, actualRole string, authConfig Config, requestPermissions, allPermissions []string) ([]string, []string) {
roleName, roleContextID := SplitPermission(actualRole)
perms := authConfig.getPermissionsFromRole(roleName)
func mapMembershipToPerm(requiredPerm string, membership *Membership, authConfig Config, requestPermissions, allPermissions []string) ([]string, []string) {
roleNames, roleContextID := roleWithContext(membership)
for _, roleName := range roleNames {
perms := authConfig.getPermissionsFromRole(roleName)
for _, p := range perms {
permWithCtx := addRoleContextIDToPerm(p, roleContextID)
if !ExistsPerm(allPermissions, permWithCtx) {
allPermissions = append(allPermissions, permWithCtx)
}
for _, p := range perms {
permWithCtx := addRoleContextIDToPerm(p, roleContextID)
if !ExistsPerm(allPermissions, permWithCtx) {
allPermissions = append(allPermissions, permWithCtx)
}
p, _ = SplitPermission(p)
if p == requiredPerm {
if !ExistsPerm(requestPermissions, permWithCtx) {
requestPermissions = append(requestPermissions, permWithCtx)
p, _ = SplitPermission(p)
if p == requiredPerm {
if !ExistsPerm(requestPermissions, permWithCtx) {
requestPermissions = append(requestPermissions, permWithCtx)
}
}
}
}
@ -72,3 +73,10 @@ func ExistsPerm(existingPermissions []string, perm string) bool {
}
return false
}
func roleWithContext(membership *Membership) (roles []string, ctxID string) {
if membership.MemberType == MemberTypeProject || membership.MemberType == MemberTypeProjectGrant {
return membership.Roles, membership.ObjectID
}
return membership.Roles, ""
}

View File

@ -12,15 +12,14 @@ func getTestCtx(userID, orgID string) context.Context {
}
type testVerifier struct {
grant *Grant
memberships []*Membership
}
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, string, error) {
return "userID", "agentID", "de", "orgID", nil
}
func (v *testVerifier) ResolveGrants(ctx context.Context) (*Grant, error) {
return v.grant, nil
func (v *testVerifier) SearchMyMemberships(ctx context.Context) ([]*Membership, error) {
return v.memberships, nil
}
func (v *testVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
@ -65,8 +64,10 @@ func Test_GetUserMethodPermissions(t *testing.T) {
name: "Empty Context",
args: args{
ctxData: CtxData{},
verifier: Start(&testVerifier{grant: &Grant{
Roles: []string{"ORG_OWNER"},
verifier: Start(&testVerifier{memberships: []*Membership{
{
Roles: []string{"ORG_OWNER"},
},
}}),
requiredPerm: "project.read",
authConfig: Config{
@ -90,7 +91,7 @@ func Test_GetUserMethodPermissions(t *testing.T) {
name: "No Grants",
args: args{
ctxData: CtxData{},
verifier: Start(&testVerifier{grant: &Grant{}}),
verifier: Start(&testVerifier{memberships: []*Membership{}}),
requiredPerm: "project.read",
authConfig: Config{
RolePermissionMappings: []RoleMapping{
@ -111,8 +112,13 @@ func Test_GetUserMethodPermissions(t *testing.T) {
name: "Get Permissions",
args: args{
ctxData: CtxData{UserID: "userID", OrgID: "orgID"},
verifier: Start(&testVerifier{grant: &Grant{
Roles: []string{"IAM_OWNER"},
verifier: Start(&testVerifier{memberships: []*Membership{
{
AggregateID: "IAM",
ObjectID: "IAM",
MemberType: MemberTypeIam,
Roles: []string{"IAM_OWNER"},
},
}}),
requiredPerm: "project.read",
authConfig: Config{
@ -150,10 +156,10 @@ func Test_GetUserMethodPermissions(t *testing.T) {
}
}
func Test_MapGrantsToPermissions(t *testing.T) {
func Test_MapMembershipToPermissions(t *testing.T) {
type args struct {
requiredPerm string
grant *Grant
membership []*Membership
authConfig Config
}
tests := []struct {
@ -166,7 +172,14 @@ func Test_MapGrantsToPermissions(t *testing.T) {
name: "One Role existing perm",
args: args{
requiredPerm: "project.read",
grant: &Grant{Roles: []string{"ORG_OWNER"}},
membership: []*Membership{
{
AggregateID: "1",
ObjectID: "1",
MemberType: MemberTypeOrganisation,
Roles: []string{"ORG_OWNER"},
},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -187,7 +200,14 @@ func Test_MapGrantsToPermissions(t *testing.T) {
name: "One Role not existing perm",
args: args{
requiredPerm: "project.write",
grant: &Grant{Roles: []string{"ORG_OWNER"}},
membership: []*Membership{
{
AggregateID: "1",
ObjectID: "1",
MemberType: MemberTypeOrganisation,
Roles: []string{"ORG_OWNER"},
},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -208,7 +228,20 @@ func Test_MapGrantsToPermissions(t *testing.T) {
name: "Multiple Roles one existing",
args: args{
requiredPerm: "project.read",
grant: &Grant{Roles: []string{"ORG_OWNER", "IAM_OWNER"}},
membership: []*Membership{
{
AggregateID: "1",
ObjectID: "1",
MemberType: MemberTypeOrganisation,
Roles: []string{"ORG_OWNER"},
},
{
AggregateID: "IAM",
ObjectID: "IAM",
MemberType: MemberTypeIam,
Roles: []string{"IAM_OWNER"},
},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -229,7 +262,20 @@ func Test_MapGrantsToPermissions(t *testing.T) {
name: "Multiple Roles, global and specific",
args: args{
requiredPerm: "project.read",
grant: &Grant{Roles: []string{"ORG_OWNER", "PROJECT_OWNER:1"}},
membership: []*Membership{
{
AggregateID: "2",
ObjectID: "2",
MemberType: MemberTypeOrganisation,
Roles: []string{"ORG_OWNER"},
},
{
AggregateID: "1",
ObjectID: "1",
MemberType: MemberTypeProject,
Roles: []string{"PROJECT_OWNER"},
},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -249,7 +295,7 @@ func Test_MapGrantsToPermissions(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
requestPerms, allPerms := mapGrantToPermissions(tt.args.requiredPerm, tt.args.grant, tt.args.authConfig)
requestPerms, allPerms := mapMembershipsToPermissions(tt.args.requiredPerm, tt.args.membership, tt.args.authConfig)
if !equalStringArray(requestPerms, tt.requestPerms) {
t.Errorf("got wrong requestPerms, expecting: %v, actual: %v ", tt.requestPerms, requestPerms)
}
@ -260,10 +306,10 @@ func Test_MapGrantsToPermissions(t *testing.T) {
}
}
func Test_MapRoleToPerm(t *testing.T) {
func Test_MapMembershipToPerm(t *testing.T) {
type args struct {
requiredPerm string
actualRole string
membership *Membership
authConfig Config
requestPerms []string
allPerms []string
@ -278,7 +324,12 @@ func Test_MapRoleToPerm(t *testing.T) {
name: "first perm without context id",
args: args{
requiredPerm: "project.read",
actualRole: "ORG_OWNER",
membership: &Membership{
AggregateID: "Org",
ObjectID: "Org",
MemberType: MemberTypeOrganisation,
Roles: []string{"ORG_OWNER"},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -301,7 +352,12 @@ func Test_MapRoleToPerm(t *testing.T) {
name: "existing perm without context id",
args: args{
requiredPerm: "project.read",
actualRole: "ORG_OWNER",
membership: &Membership{
AggregateID: "Org",
ObjectID: "Org",
MemberType: MemberTypeOrganisation,
Roles: []string{"ORG_OWNER"},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -324,7 +380,12 @@ func Test_MapRoleToPerm(t *testing.T) {
name: "first perm with context id",
args: args{
requiredPerm: "project.read",
actualRole: "PROJECT_OWNER:1",
membership: &Membership{
AggregateID: "1",
ObjectID: "1",
MemberType: MemberTypeProject,
Roles: []string{"PROJECT_OWNER"},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -347,7 +408,12 @@ func Test_MapRoleToPerm(t *testing.T) {
name: "perm with context id, existing global",
args: args{
requiredPerm: "project.read",
actualRole: "PROJECT_OWNER:1",
membership: &Membership{
AggregateID: "1",
ObjectID: "1",
MemberType: MemberTypeProject,
Roles: []string{"PROJECT_OWNER"},
},
authConfig: Config{
RolePermissionMappings: []RoleMapping{
{
@ -369,7 +435,7 @@ func Test_MapRoleToPerm(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
requestPerms, allPerms := mapRoleToPerm(tt.args.requiredPerm, tt.args.actualRole, tt.args.authConfig, tt.args.requestPerms, tt.args.allPerms)
requestPerms, allPerms := mapMembershipToPerm(tt.args.requiredPerm, tt.args.membership, tt.args.authConfig, tt.args.requestPerms, tt.args.allPerms)
if !equalStringArray(requestPerms, tt.requestPerms) {
t.Errorf("got wrong requestPerms, expecting: %v, actual: %v ", tt.requestPerms, requestPerms)
}

View File

@ -22,7 +22,7 @@ type TokenVerifier struct {
type authZRepo interface {
VerifyAccessToken(ctx context.Context, token, clientID string) (userID, agentID, prefLang, resourceOwner string, err error)
VerifierClientID(ctx context.Context, name string) (clientID string, err error)
ResolveGrants(ctx context.Context) (grant *Grant, err error)
SearchMyMemberships(ctx context.Context) ([]*Membership, error)
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
ExistsOrg(ctx context.Context, orgID string) error
}
@ -86,11 +86,10 @@ func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (
v.clients.Store(prefix, c)
return c.id, nil
}
func (v *TokenVerifier) ResolveGrant(ctx context.Context) (_ *Grant, err error) {
func (v *TokenVerifier) SearchMyMemberships(ctx context.Context) (_ []*Membership, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
return v.authZRepo.ResolveGrants(ctx)
return v.authZRepo.SearchMyMemberships(ctx)
}
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (_ string, _ []string, err error) {

View File

@ -43,7 +43,7 @@ func Test_VerifyAccessToken(t *testing.T) {
ctx: context.Background(),
token: "Bearer AUTH",
verifier: &TokenVerifier{
authZRepo: &testVerifier{grant: &Grant{}},
authZRepo: &testVerifier{memberships: []*Membership{}},
clients: func() sync.Map {
m := sync.Map{}
m.Store("service", &client{name: "name"})

View File

@ -229,3 +229,13 @@ func (s *Server) GetMyUserChanges(ctx context.Context, request *auth.ChangesRequ
}
return userChangesToResponse(changes, request.GetSequenceOffset(), request.GetLimit()), nil
}
func (s *Server) SearchMyUserMemberships(ctx context.Context, in *auth.UserMembershipSearchRequest) (*auth.UserMembershipSearchResponse, error) {
request := userMembershipSearchRequestsToModel(in)
request.AppendUserIDQuery(authz.GetCtxData(ctx).UserID)
response, err := s.repo.SearchMyUserMemberships(ctx, request)
if err != nil {
return nil, err
}
return userMembershipSearchResponseFromModel(response), nil
}

View File

@ -3,7 +3,6 @@ package auth
import (
"context"
"encoding/json"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"golang.org/x/text/language"
@ -462,3 +461,93 @@ func ctxToObjectRoot(ctx context.Context) models.ObjectRoot {
ResourceOwner: ctxData.ResourceOwner,
}
}
func userMembershipSearchResponseFromModel(response *usr_model.UserMembershipSearchResponse) *auth.UserMembershipSearchResponse {
timestamp, err := ptypes.TimestampProto(response.Timestamp)
logging.Log("GRPC-Hs8jd").OnError(err).Debug("unable to parse timestamp")
return &auth.UserMembershipSearchResponse{
Offset: response.Offset,
Limit: response.Limit,
TotalResult: response.TotalResult,
Result: userMembershipViewsFromModel(response.Result),
ProcessedSequence: response.Sequence,
ViewTimestamp: timestamp,
}
}
func userMembershipViewsFromModel(memberships []*usr_model.UserMembershipView) []*auth.UserMembershipView {
converted := make([]*auth.UserMembershipView, len(memberships))
for i, membership := range memberships {
converted[i] = userMembershipViewFromModel(membership)
}
return converted
}
func userMembershipViewFromModel(membership *usr_model.UserMembershipView) *auth.UserMembershipView {
creationDate, err := ptypes.TimestampProto(membership.CreationDate)
logging.Log("GRPC-Msnu8").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(membership.ChangeDate)
logging.Log("GRPC-Slco9").OnError(err).Debug("unable to parse timestamp")
return &auth.UserMembershipView{
UserId: membership.UserID,
AggregateId: membership.AggregateID,
ObjectId: membership.ObjectID,
MemberType: memberTypeFromModel(membership.MemberType),
DisplayName: membership.DisplayName,
Roles: membership.Roles,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: membership.Sequence,
ResourceOwner: membership.ResourceOwner,
}
}
func userMembershipSearchRequestsToModel(request *auth.UserMembershipSearchRequest) *usr_model.UserMembershipSearchRequest {
return &usr_model.UserMembershipSearchRequest{
Offset: request.Offset,
Limit: request.Limit,
Queries: userMembershipSearchQueriesToModel(request.Queries),
}
}
func userMembershipSearchQueriesToModel(queries []*auth.UserMembershipSearchQuery) []*usr_model.UserMembershipSearchQuery {
converted := make([]*usr_model.UserMembershipSearchQuery, len(queries))
for i, q := range queries {
converted[i] = userMembershipSearchQueryToModel(q)
}
return converted
}
func userMembershipSearchQueryToModel(query *auth.UserMembershipSearchQuery) *usr_model.UserMembershipSearchQuery {
return &usr_model.UserMembershipSearchQuery{
Key: userMembershipSearchKeyToModel(query.Key),
Method: searchMethodToModel(query.Method),
Value: query.Value,
}
}
func userMembershipSearchKeyToModel(key auth.UserMembershipSearchKey) usr_model.UserMembershipSearchKey {
switch key {
case auth.UserMembershipSearchKey_USERMEMBERSHIPSEARCHKEY_TYPE:
return usr_model.UserMembershipSearchKeyMemberType
case auth.UserMembershipSearchKey_USERMEMBERSHIPSEARCHKEY_OBJECT_ID:
return usr_model.UserMembershipSearchKeyObjectID
default:
return usr_model.UserMembershipSearchKeyUnspecified
}
}
func memberTypeFromModel(memberType usr_model.MemberType) auth.MemberType {
switch memberType {
case usr_model.MemberTypeOrganisation:
return auth.MemberType_MEMBERTYPE_ORGANISATION
case usr_model.MemberTypeProject:
return auth.MemberType_MEMBERTYPE_PROJECT
case usr_model.MemberTypeProjectGrant:
return auth.MemberType_MEMBERTYPE_PROJECT_GRANT
default:
return auth.MemberType_MEMBERTYPE_UNSPECIFIED
}
}

View File

@ -3,7 +3,7 @@ package auth
import (
"github.com/caos/logging"
usr_model "github.com/caos/zitadel/internal/user/model"
auth "github.com/caos/zitadel/pkg/grpc/auth"
"github.com/caos/zitadel/pkg/grpc/auth"
"github.com/golang/protobuf/ptypes"
)

View File

@ -2,9 +2,10 @@ package auth
import (
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/pkg/grpc/auth"
"github.com/golang/protobuf/ptypes"
)
func machineViewFromModel(machine *usr_model.MachineView) *auth.MachineView {
@ -16,36 +17,3 @@ func machineViewFromModel(machine *usr_model.MachineView) *auth.MachineView {
LastKeyAdded: lastKeyAdded,
}
}
func machineKeyViewsFromModel(keys ...*usr_model.MachineKeyView) []*auth.MachineKeyView {
keyViews := make([]*auth.MachineKeyView, len(keys))
for i, key := range keys {
keyViews[i] = machineKeyViewFromModel(key)
}
return keyViews
}
func machineKeyViewFromModel(key *usr_model.MachineKeyView) *auth.MachineKeyView {
creationDate, err := ptypes.TimestampProto(key.CreationDate)
logging.Log("MANAG-gluk7").OnError(err).Debug("unable to parse timestamp")
expirationDate, err := ptypes.TimestampProto(key.CreationDate)
logging.Log("MANAG-gluk7").OnError(err).Debug("unable to parse timestamp")
return &auth.MachineKeyView{
Id: key.ID,
CreationDate: creationDate,
ExpirationDate: expirationDate,
Sequence: key.Sequence,
Type: machineKeyTypeFromModel(key.Type),
}
}
func machineKeyTypeFromModel(typ usr_model.MachineKeyType) auth.MachineKeyType {
switch typ {
case usr_model.MachineKeyTypeJSON:
return auth.MachineKeyType_MACHINEKEY_JSON
default:
return auth.MachineKeyType_MACHINEKEY_UNSPECIFIED
}
}

View File

@ -32,6 +32,13 @@ func (s *Server) CreateOIDCApplication(ctx context.Context, in *management.OIDCA
}
return oidcAppFromDomain(app), nil
}
func (s *Server) CreateAPIApplication(ctx context.Context, in *management.APIApplicationCreate) (*management.Application, error) {
app, err := s.project.AddApplication(ctx, apiAppCreateToModel(in))
if err != nil {
return nil, err
}
return appFromModel(app), nil
}
func (s *Server) UpdateApplication(ctx context.Context, in *management.ApplicationUpdate) (*management.Application, error) {
app, err := s.command.ChangeApplication(ctx, in.ProjectId, appUpdateToDomain(in), authz.GetCtxData(ctx).OrgID)
if err != nil {
@ -61,6 +68,14 @@ func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *management
return oidcConfigFromDomain(config), nil
}
func (s *Server) UpdateApplicationAPIConfig(ctx context.Context, in *management.APIConfigUpdate) (*management.APIConfig, error) {
config, err := s.project.ChangeAPIConfig(ctx, apiConfigUpdateToModel(in))
if err != nil {
return nil, err
}
return apiConfigFromModel(config), nil
}
func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *management.ApplicationID) (*management.ClientSecret, error) {
config, err := s.command.ChangeOIDCApplicationSecret(ctx, in.ProjectId, in.Id, authz.GetCtxData(ctx).ResourceOwner)
if err != nil {
@ -69,6 +84,14 @@ func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *management.
return &management.ClientSecret{ClientSecret: config.ClientSecretString}, nil
}
func (s *Server) RegenerateAPIClientSecret(ctx context.Context, in *management.ApplicationID) (*management.ClientSecret, error) {
config, err := s.project.ChangeAPIConfigSecret(ctx, in.ProjectId, in.Id)
if err != nil {
return nil, err
}
return &management.ClientSecret{ClientSecret: config.ClientSecretString}, nil
}
func (s *Server) ApplicationChanges(ctx context.Context, changesRequest *management.ChangeRequest) (*management.Changes, error) {
response, err := s.project.ApplicationChanges(ctx, changesRequest.Id, changesRequest.SecId, changesRequest.SequenceOffset, changesRequest.Limit, changesRequest.Asc)
if err != nil {
@ -76,3 +99,32 @@ func (s *Server) ApplicationChanges(ctx context.Context, changesRequest *managem
}
return appChangesToResponse(response, changesRequest.GetSequenceOffset(), changesRequest.GetLimit()), nil
}
func (s *Server) SearchClientKeys(ctx context.Context, req *management.ClientKeySearchRequest) (*management.ClientKeySearchResponse, error) {
result, err := s.project.SearchClientKeys(ctx, clientKeySearchRequestToModel(req))
if err != nil {
return nil, err
}
return clientKeySearchResponseFromModel(result), nil
}
func (s *Server) GetClientKey(ctx context.Context, req *management.ClientKeyIDRequest) (*management.ClientKeyView, error) {
key, err := s.project.GetClientKey(ctx, req.ProjectId, req.ApplicationId, req.KeyId)
if err != nil {
return nil, err
}
return clientKeyViewFromModel(key), nil
}
func (s *Server) AddClientKey(ctx context.Context, req *management.AddClientKeyRequest) (*management.AddClientKeyResponse, error) {
key, err := s.project.AddClientKey(ctx, addClientKeyToModel(req))
if err != nil {
return nil, err
}
return addClientKeyFromModel(key), nil
}
func (s *Server) DeleteClientKey(ctx context.Context, req *management.ClientKeyIDRequest) (*empty.Empty, error) {
err := s.project.RemoveClientKey(ctx, req.ProjectId, req.ApplicationId, req.KeyId)
return &empty.Empty{}, err
}

View File

@ -2,18 +2,20 @@ package management
import (
"encoding/json"
"github.com/caos/zitadel/internal/v2/domain"
"google.golang.org/protobuf/types/known/timestamppb"
"time"
"github.com/caos/logging"
"github.com/golang/protobuf/ptypes"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/caos/zitadel/internal/eventstore/models"
key_model "github.com/caos/zitadel/internal/key/model"
"github.com/caos/zitadel/internal/model"
proj_model "github.com/caos/zitadel/internal/project/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/pkg/grpc/management"
"github.com/caos/zitadel/pkg/grpc/message"
)
@ -25,6 +27,28 @@ func appFromDomain(app domain.Application) *management.Application {
Name: app.GetApplicationName(),
}
}
func appFromModel(app *proj_model.Application) *management.Application {
changeDate, err := ptypes.TimestampProto(app.ChangeDate)
logging.Log("GRPC-di7rw").OnError(err).Debug("unable to parse timestamp")
return &management.Application{
Id: app.AppID,
State: appStateFromModel(app.State),
ChangeDate: changeDate,
Name: app.Name,
Sequence: app.Sequence,
AppConfig: appConfigFromModel(app),
}
}
func appConfigFromModel(app *proj_model.Application) management.AppConfig {
if app.Type == proj_model.AppTypeAPI {
return &management.Application_ApiConfig{
ApiConfig: apiConfigFromModel(app.APIConfig),
}
}
return nil
}
func oidcAppFromDomain(app *domain.OIDCApp) *management.Application {
return &management.Application{
@ -41,6 +65,7 @@ func oidcAppConfigFromDomain(app *domain.OIDCApp) management.AppConfig {
return &management.Application_OidcConfig{
OidcConfig: oidcConfigFromDomain(app),
}
return nil
}
func oidcConfigFromDomain(config *domain.OIDCApp) *management.OIDCConfig {
@ -65,6 +90,14 @@ func oidcConfigFromDomain(config *domain.OIDCApp) *management.OIDCConfig {
}
}
func apiConfigFromModel(config *proj_model.APIConfig) *management.APIConfig {
return &management.APIConfig{
ClientId: config.ClientID,
ClientSecret: config.ClientSecretString,
AuthMethodType: apiAuthMethodTypeFromModel(config.AuthMethodType),
}
}
func oidcConfigFromApplicationViewModel(app *proj_model.ApplicationView) *management.OIDCConfig {
return &management.OIDCConfig{
RedirectUris: app.OIDCRedirectUris,
@ -74,11 +107,11 @@ func oidcConfigFromApplicationViewModel(app *proj_model.ApplicationView) *manage
ClientId: app.OIDCClientID,
AuthMethodType: oidcAuthMethodTypeFromModel(app.OIDCAuthMethodType),
PostLogoutRedirectUris: app.OIDCPostLogoutRedirectUris,
Version: oidcVersionFromModel(app.OIDCVersion),
Version: oidcVersionFromDomain(domain.OIDCVersion(app.OIDCVersion)),
NoneCompliant: app.NoneCompliant,
ComplianceProblems: complianceProblemsToLocalizedMessages(app.ComplianceProblems),
DevMode: app.DevMode,
AccessTokenType: oidcTokenTypeFromModel(app.AccessTokenType),
AccessTokenType: oidcTokenTypeFromDomain(domain.OIDCTokenType(app.AccessTokenType)),
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
IdTokenRoleAssertion: app.IDTokenRoleAssertion,
IdTokenUserinfoAssertion: app.IDTokenUserinfoAssertion,
@ -124,6 +157,29 @@ func appUpdateToDomain(app *management.ApplicationUpdate) domain.Application {
}
}
func apiAppCreateToModel(app *management.APIApplicationCreate) *proj_model.Application {
return &proj_model.Application{
ObjectRoot: models.ObjectRoot{
AggregateID: app.ProjectId,
},
Name: app.Name,
Type: proj_model.AppTypeAPI,
APIConfig: &proj_model.APIConfig{
AuthMethodType: apiAuthMethodTypeToModel(app.AuthMethodType),
},
}
}
func appUpdateToModel(app *management.ApplicationUpdate) *proj_model.Application {
return &proj_model.Application{
ObjectRoot: models.ObjectRoot{
AggregateID: app.ProjectId,
},
AppID: app.Id,
Name: app.Name,
}
}
func oidcConfigUpdateToDomain(app *management.OIDCConfigUpdate) *domain.OIDCApp {
return &domain.OIDCApp{
ObjectRoot: models.ObjectRoot{
@ -145,6 +201,16 @@ func oidcConfigUpdateToDomain(app *management.OIDCConfigUpdate) *domain.OIDCApp
}
}
func apiConfigUpdateToModel(app *management.APIConfigUpdate) *proj_model.APIConfig {
return &proj_model.APIConfig{
ObjectRoot: models.ObjectRoot{
AggregateID: app.ProjectId,
},
AppID: app.ApplicationId,
AuthMethodType: apiAuthMethodTypeToModel(app.AuthMethodType),
}
}
func applicationSearchRequestsToModel(request *management.ApplicationSearchRequest) *proj_model.ApplicationSearchRequest {
return &proj_model.ApplicationSearchRequest{
Offset: request.Offset,
@ -404,6 +470,8 @@ func oidcAuthMethodTypeToDomain(authType management.OIDCAuthMethodType) domain.O
return domain.OIDCAuthMethodTypePost
case management.OIDCAuthMethodType_OIDCAUTHMETHODTYPE_NONE:
return domain.OIDCAuthMethodTypeNone
case management.OIDCAuthMethodType_OIDCAUTHMETHODTYPE_PRIVATE_KEY_JWT:
return domain.OIDCAuthMethodTypePrivateKeyJWT
default:
return domain.OIDCAuthMethodTypeBasic
}
@ -422,6 +490,17 @@ func oidcAuthMethodTypeFromDomain(authType domain.OIDCAuthMethodType) management
}
}
func apiAuthMethodTypeToModel(authType management.APIAuthMethodType) proj_model.APIAuthMethodType {
switch authType {
case management.APIAuthMethodType_APIAUTHMETHODTYPE_BASIC:
return proj_model.APIAuthMethodTypeBasic
case management.APIAuthMethodType_APIAUTHMETHODTYPE_PRIVATE_KEY_JWT:
return proj_model.APIAuthMethodTypePrivateKeyJWT
default:
return proj_model.APIAuthMethodTypeBasic
}
}
func oidcAuthMethodTypeFromModel(authType proj_model.OIDCAuthMethodType) management.OIDCAuthMethodType {
switch authType {
case proj_model.OIDCAuthMethodTypeBasic:
@ -430,6 +509,8 @@ func oidcAuthMethodTypeFromModel(authType proj_model.OIDCAuthMethodType) managem
return management.OIDCAuthMethodType_OIDCAUTHMETHODTYPE_POST
case proj_model.OIDCAuthMethodTypeNone:
return management.OIDCAuthMethodType_OIDCAUTHMETHODTYPE_NONE
case proj_model.OIDCAuthMethodTypePrivateKeyJWT:
return management.OIDCAuthMethodType_OIDCAUTHMETHODTYPE_PRIVATE_KEY_JWT
default:
return management.OIDCAuthMethodType_OIDCAUTHMETHODTYPE_BASIC
}
@ -457,14 +538,14 @@ func oidcTokenTypeFromDomain(tokenType domain.OIDCTokenType) management.OIDCToke
}
}
func oidcTokenTypeFromModel(tokenType proj_model.OIDCTokenType) management.OIDCTokenType {
switch tokenType {
case proj_model.OIDCTokenTypeBearer:
return management.OIDCTokenType_OIDCTokenType_Bearer
case proj_model.OIDCTokenTypeJWT:
return management.OIDCTokenType_OIDCTokenType_JWT
func apiAuthMethodTypeFromModel(authType proj_model.APIAuthMethodType) management.APIAuthMethodType {
switch authType {
case proj_model.APIAuthMethodTypeBasic:
return management.APIAuthMethodType_APIAUTHMETHODTYPE_BASIC
case proj_model.APIAuthMethodTypePrivateKeyJWT:
return management.APIAuthMethodType_APIAUTHMETHODTYPE_PRIVATE_KEY_JWT
default:
return management.OIDCTokenType_OIDCTokenType_Bearer
return management.APIAuthMethodType_APIAUTHMETHODTYPE_BASIC
}
}
@ -477,15 +558,6 @@ func oidcVersionFromDomain(version domain.OIDCVersion) management.OIDCVersion {
}
}
func oidcVersionFromModel(version proj_model.OIDCVersion) management.OIDCVersion {
switch version {
case proj_model.OIDCVersionV1:
return management.OIDCVersion_OIDCV1_0
default:
return management.OIDCVersion_OIDCV1_0
}
}
func appChangesToResponse(response *proj_model.ApplicationChanges, offset uint64, limit uint64) (_ *management.Changes) {
return &management.Changes{
Limit: limit,
@ -515,3 +587,126 @@ func appChangesToMgtAPI(changes *proj_model.ApplicationChanges) (_ []*management
return result
}
func clientKeyViewsFromModel(keys ...*key_model.AuthNKeyView) []*management.ClientKeyView {
keyViews := make([]*management.ClientKeyView, len(keys))
for i, key := range keys {
keyViews[i] = clientKeyViewFromModel(key)
}
return keyViews
}
func clientKeyViewFromModel(key *key_model.AuthNKeyView) *management.ClientKeyView {
creationDate, err := ptypes.TimestampProto(key.CreationDate)
logging.Log("MANAG-DAs2t").OnError(err).Debug("unable to parse timestamp")
expirationDate, err := ptypes.TimestampProto(key.ExpirationDate)
logging.Log("MANAG-BDgh4").OnError(err).Debug("unable to parse timestamp")
return &management.ClientKeyView{
Id: key.ID,
CreationDate: creationDate,
ExpirationDate: expirationDate,
Sequence: key.Sequence,
Type: authNKeyTypeFromModel(key.Type),
}
}
func addClientKeyToModel(key *management.AddClientKeyRequest) *proj_model.ClientKey {
expirationDate := time.Time{}
if key.ExpirationDate != nil {
var err error
expirationDate, err = ptypes.Timestamp(key.ExpirationDate)
logging.Log("MANAG-Dgt42").OnError(err).Debug("unable to parse expiration date")
}
return &proj_model.ClientKey{
ExpirationDate: expirationDate,
Type: authNKeyTypeToModel(key.Type),
ApplicationID: key.ApplicationId,
ObjectRoot: models.ObjectRoot{AggregateID: key.ProjectId},
}
}
func addClientKeyFromModel(key *proj_model.ClientKey) *management.AddClientKeyResponse {
creationDate, err := ptypes.TimestampProto(key.CreationDate)
logging.Log("MANAG-FBzz4").OnError(err).Debug("unable to parse cretaion date")
expirationDate, err := ptypes.TimestampProto(key.ExpirationDate)
logging.Log("MANAG-sag21").OnError(err).Debug("unable to parse cretaion date")
detail, err := json.Marshal(struct {
Type string `json:"type"`
KeyID string `json:"keyId"`
Key string `json:"key"`
AppID string `json:"appId"`
ClientID string `json:"clientID"`
}{
Type: "application",
KeyID: key.KeyID,
Key: string(key.PrivateKey),
AppID: key.ApplicationID,
ClientID: key.ClientID,
})
logging.Log("MANAG-adt42").OnError(err).Warn("unable to marshall key")
return &management.AddClientKeyResponse{
Id: key.KeyID,
CreationDate: creationDate,
ExpirationDate: expirationDate,
Sequence: key.Sequence,
KeyDetails: detail,
Type: authNKeyTypeFromModel(key.Type),
}
}
func authNKeyTypeToModel(typ management.AuthNKeyType) key_model.AuthNKeyType {
switch typ {
case management.AuthNKeyType_AUTHNKEY_JSON:
return key_model.AuthNKeyTypeJSON
default:
return key_model.AuthNKeyTypeNONE
}
}
func authNKeyTypeFromModel(typ key_model.AuthNKeyType) management.AuthNKeyType {
switch typ {
case key_model.AuthNKeyTypeJSON:
return management.AuthNKeyType_AUTHNKEY_JSON
default:
return management.AuthNKeyType_AUTHNKEY_UNSPECIFIED
}
}
func clientKeySearchRequestToModel(req *management.ClientKeySearchRequest) *key_model.AuthNKeySearchRequest {
return &key_model.AuthNKeySearchRequest{
Offset: req.Offset,
Limit: req.Limit,
Asc: req.Asc,
Queries: []*key_model.AuthNKeySearchQuery{
{
Key: key_model.AuthNKeyObjectType,
Method: model.SearchMethodEquals,
Value: key_model.AuthNKeyObjectTypeApplication,
}, {
Key: key_model.AuthNKeyObjectID,
Method: model.SearchMethodEquals,
Value: req.ApplicationId,
},
},
}
}
func clientKeySearchResponseFromModel(req *key_model.AuthNKeySearchResponse) *management.ClientKeySearchResponse {
viewTimestamp, err := ptypes.TimestampProto(req.Timestamp)
logging.Log("MANAG-Sk9ds").OnError(err).Debug("unable to parse cretaion date")
return &management.ClientKeySearchResponse{
Offset: req.Offset,
Limit: req.Limit,
TotalResult: req.TotalResult,
ProcessedSequence: req.Sequence,
ViewTimestamp: viewTimestamp,
Result: clientKeyViewsFromModel(req.Result...),
}
}

View File

@ -12,6 +12,7 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/caos/zitadel/internal/eventstore/models"
key_model "github.com/caos/zitadel/internal/key/model"
"github.com/caos/zitadel/internal/model"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/pkg/grpc/management"
@ -52,7 +53,7 @@ func machineViewFromModel(machine *usr_model.MachineView) *management.MachineVie
}
}
func machineKeyViewsFromModel(keys ...*usr_model.MachineKeyView) []*management.MachineKeyView {
func authnKeyViewsFromModel(keys ...*key_model.AuthNKeyView) []*management.MachineKeyView {
keyViews := make([]*management.MachineKeyView, len(keys))
for i, key := range keys {
keyViews[i] = machineKeyViewFromModel(key)
@ -60,7 +61,7 @@ func machineKeyViewsFromModel(keys ...*usr_model.MachineKeyView) []*management.M
return keyViews
}
func machineKeyViewFromModel(key *usr_model.MachineKeyView) *management.MachineKeyView {
func machineKeyViewFromModel(key *key_model.AuthNKeyView) *management.MachineKeyView {
creationDate, err := ptypes.TimestampProto(key.CreationDate)
logging.Log("MANAG-gluk7").OnError(err).Debug("unable to parse timestamp")
@ -133,23 +134,27 @@ func machineKeyTypeFromDomain(typ domain.MachineKeyType) management.MachineKeyTy
}
}
func machineKeyTypeFromModel(typ usr_model.MachineKeyType) management.MachineKeyType {
func machineKeyTypeFromModel(typ key_model.AuthNKeyType) management.MachineKeyType {
switch typ {
case usr_model.MachineKeyTypeJSON:
case key_model.AuthNKeyTypeJSON:
return management.MachineKeyType_MACHINEKEY_JSON
default:
return management.MachineKeyType_MACHINEKEY_UNSPECIFIED
}
}
func machineKeySearchRequestToModel(req *management.MachineKeySearchRequest) *usr_model.MachineKeySearchRequest {
return &usr_model.MachineKeySearchRequest{
func machineKeySearchRequestToModel(req *management.MachineKeySearchRequest) *key_model.AuthNKeySearchRequest {
return &key_model.AuthNKeySearchRequest{
Offset: req.Offset,
Limit: req.Limit,
Asc: req.Asc,
Queries: []*usr_model.MachineKeySearchQuery{
Queries: []*key_model.AuthNKeySearchQuery{
{
Key: usr_model.MachineKeyKeyUserID,
Key: key_model.AuthNKeyObjectType,
Method: model.SearchMethodEquals,
Value: key_model.AuthNKeyObjectTypeUser,
}, {
Key: key_model.AuthNKeyObjectID,
Method: model.SearchMethodEquals,
Value: req.UserId,
},
@ -157,7 +162,7 @@ func machineKeySearchRequestToModel(req *management.MachineKeySearchRequest) *us
}
}
func machineKeySearchResponseFromModel(req *usr_model.MachineKeySearchResponse) *management.MachineKeySearchResponse {
func machineKeySearchResponseFromModel(req *key_model.AuthNKeySearchResponse) *management.MachineKeySearchResponse {
viewTimestamp, err := ptypes.TimestampProto(req.Timestamp)
logging.Log("MANAG-Sk9ds").OnError(err).Debug("unable to parse cretaion date")
@ -167,6 +172,6 @@ func machineKeySearchResponseFromModel(req *usr_model.MachineKeySearchResponse)
TotalResult: req.TotalResult,
ProcessedSequence: req.Sequence,
ViewTimestamp: viewTimestamp,
Result: machineKeyViewsFromModel(req.Result...),
Result: authnKeyViewsFromModel(req.Result...),
}
}

View File

@ -24,9 +24,10 @@ type verifierMock struct{}
func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, string, string, error) {
return "", "", "", "", nil
}
func (v *verifierMock) ResolveGrants(ctx context.Context) (*authz.Grant, error) {
func (v *verifierMock) SearchMyMemberships(ctx context.Context) ([]*authz.Membership, error) {
return nil, nil
}
func (v *verifierMock) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
return "", nil, nil
}

View File

@ -12,6 +12,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/auth_request/model"
authreq_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
proj_model "github.com/caos/zitadel/internal/project/model"
@ -55,13 +56,17 @@ func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (_ op.Cl
}
func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (_ *jose.JSONWebKey, err error) {
return o.GetKeyByIDAndIssuer(ctx, keyID, userID)
}
func (o *OPStorage) GetKeyByIDAndIssuer(ctx context.Context, keyID, issuer string) (_ *jose.JSONWebKey, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
key, err := o.repo.MachineKeyByID(ctx, keyID)
if err != nil {
return nil, err
}
if key.UserID != userID {
if key.AuthIdentifier != issuer {
return nil, errors.ThrowPermissionDenied(nil, "OIDC-24jm3", "key from different user")
}
publicKey, err := crypto.BytesToPublicKey(key.PublicKey)
@ -75,6 +80,29 @@ func (o *OPStorage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID strin
}, nil
}
func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string, scopes oidc.Scopes) (oidc.Scopes, error) {
user, err := o.repo.UserByID(ctx, subject)
if err != nil {
return nil, err
}
for i := len(scopes) - 1; i >= 0; i-- {
scope := scopes[i]
if strings.HasPrefix(scope, authreq_model.OrgDomainPrimaryScope) {
var orgID string
org, err := o.repo.OrgByPrimaryDomain(strings.TrimPrefix(scope, authreq_model.OrgDomainPrimaryScope))
if err == nil {
orgID = org.ID
}
if orgID != user.ResourceOwner {
scopes[i] = scopes[len(scopes)-1]
scopes[len(scopes)-1] = ""
scopes = scopes[:len(scopes)-1]
}
}
}
return scopes, nil
}
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
@ -85,33 +113,32 @@ func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secr
return o.repo.AuthorizeOIDCApplication(ctx, id, secret)
}
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, subject, origin string) (_ oidc.UserInfo, err error) {
func (o *OPStorage) SetUserinfoFromToken(ctx context.Context, userInfo oidc.UserInfoSetter, tokenID, subject, origin string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
token, err := o.repo.TokenByID(ctx, subject, tokenID)
if err != nil {
return nil, errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
return errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
}
if token.ApplicationID != "" {
app, err := o.repo.ApplicationByClientID(ctx, token.ApplicationID)
if err != nil {
return nil, err
return err
}
if origin != "" && !http.IsOriginAllowed(app.OriginAllowList, origin) {
return nil, errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
return errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
}
}
return o.GetUserinfoFromScopes(ctx, token.UserID, token.ApplicationID, token.Scopes)
return o.SetUserinfoFromScopes(ctx, userInfo, token.UserID, token.ApplicationID, token.Scopes)
}
func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID, applicationID string, scopes []string) (_ oidc.UserInfo, err error) {
func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo oidc.UserInfoSetter, userID, applicationID string, scopes []string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
user, err := o.repo.UserByID(ctx, userID)
if err != nil {
return nil, err
return err
}
userInfo := oidc.NewUserInfo()
roles := make([]string, 0)
for _, scope := range scopes {
switch scope {
@ -160,17 +187,40 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID, applicati
}
if len(roles) == 0 || applicationID == "" {
return userInfo, nil
return nil
}
projectRoles, err := o.assertRoles(ctx, userID, applicationID, roles)
if err != nil {
return nil, err
return err
}
if len(projectRoles) > 0 {
userInfo.AppendClaims(ClaimProjectRoles, projectRoles)
}
return userInfo, nil
return nil
}
func (o *OPStorage) SetIntrospectionFromToken(ctx context.Context, introspection oidc.IntrospectionResponse, tokenID, subject, clientID string) error {
token, err := o.repo.TokenByID(ctx, subject, tokenID)
if err != nil {
return errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
}
app, err := o.repo.ApplicationByClientID(ctx, clientID)
if err != nil {
return errors.ThrowPermissionDenied(nil, "OIDC-Adfg5", "client not found")
}
for _, aud := range token.Audience {
if aud == clientID || aud == app.ProjectID {
err := o.SetUserinfoFromScopes(ctx, introspection, token.UserID, clientID, token.Scopes)
if err != nil {
return err
}
introspection.SetScopes(token.Scopes)
introspection.SetClientID(token.ApplicationID)
return nil
}
}
return errors.ThrowPermissionDenied(nil, "OIDC-sdg3G", "token is not valid for this client")
}
func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, clientID string, scopes []string) (claims map[string]interface{}, err error) {

View File

@ -1,13 +1,13 @@
package oidc
import (
authreq_model "github.com/caos/zitadel/internal/auth_request/model"
"strings"
"time"
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/pkg/op"
authreq_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/project/model"
)
@ -37,7 +37,7 @@ func (c *Client) ApplicationType() op.ApplicationType {
return op.ApplicationType(c.OIDCApplicationType)
}
func (c *Client) AuthMethod() op.AuthMethod {
func (c *Client) AuthMethod() oidc.AuthMethod {
return authMethodToOIDC(c.OIDCAuthMethodType)
}
@ -129,16 +129,18 @@ func accessTokenTypeToOIDC(tokenType model.OIDCTokenType) op.AccessTokenType {
}
}
func authMethodToOIDC(authType model.OIDCAuthMethodType) op.AuthMethod {
func authMethodToOIDC(authType model.OIDCAuthMethodType) oidc.AuthMethod {
switch authType {
case model.OIDCAuthMethodTypeBasic:
return op.AuthMethodBasic
return oidc.AuthMethodBasic
case model.OIDCAuthMethodTypePost:
return op.AuthMethodPost
return oidc.AuthMethodPost
case model.OIDCAuthMethodTypeNone:
return op.AuthMethodNone
return oidc.AuthMethodNone
case model.OIDCAuthMethodTypePrivateKeyJWT:
return oidc.AuthMethodPrivateKeyJWT
default:
return op.AuthMethodBasic
return oidc.AuthMethodBasic
}
}

View File

@ -2,9 +2,6 @@ package oidc
import (
"context"
"github.com/caos/zitadel/internal/telemetry/metrics"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/query"
"time"
"github.com/caos/logging"
@ -15,7 +12,10 @@ import (
"github.com/caos/zitadel/internal/auth/repository"
"github.com/caos/zitadel/internal/config/types"
"github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/telemetry/metrics"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/query"
)
type OPHandlerConfig struct {
@ -34,11 +34,12 @@ type StorageConfig struct {
}
type EndpointConfig struct {
Auth *Endpoint
Token *Endpoint
Userinfo *Endpoint
EndSession *Endpoint
Keys *Endpoint
Auth *Endpoint
Token *Endpoint
Introspection *Endpoint
Userinfo *Endpoint
EndSession *Endpoint
Keys *Endpoint
}
type Endpoint struct {
@ -74,6 +75,7 @@ func NewProvider(ctx context.Context, config OPHandlerConfig, command *command.C
),
op.WithCustomAuthEndpoint(op.NewEndpointWithURL(config.Endpoints.Auth.Path, config.Endpoints.Auth.URL)),
op.WithCustomTokenEndpoint(op.NewEndpointWithURL(config.Endpoints.Token.Path, config.Endpoints.Token.URL)),
op.WithCustomIntrospectionEndpoint(op.NewEndpointWithURL(config.Endpoints.Introspection.Path, config.Endpoints.Introspection.URL)),
op.WithCustomUserinfoEndpoint(op.NewEndpointWithURL(config.Endpoints.Userinfo.Path, config.Endpoints.Userinfo.URL)),
op.WithCustomEndSessionEndpoint(op.NewEndpointWithURL(config.Endpoints.EndSession.Path, config.Endpoints.EndSession.URL)),
op.WithCustomKeysEndpoint(op.NewEndpointWithURL(config.Endpoints.Keys.Path, config.Endpoints.Keys.URL)),

View File

@ -4,6 +4,7 @@ import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
@ -52,6 +53,14 @@ func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.Or
return result, nil
}
func (repo *OrgRepository) OrgByPrimaryDomain(primaryDomain string) (*org_model.OrgView, error) {
org, err := repo.View.OrgByPrimaryDomain(primaryDomain)
if err != nil {
return nil, err
}
return model.OrgToModel(org), nil
}
func (repo *OrgRepository) GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
if err != nil {

View File

@ -2,20 +2,23 @@ package eventstore
import (
"context"
"time"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
"github.com/caos/zitadel/internal/errors"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/user/repository/view/model"
"time"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
)
type TokenRepo struct {
UserEvents *user_event.UserEventstore
View *view.View
UserEvents *user_event.UserEventstore
ProjectEvents *proj_event.ProjectEventstore
View *view.View
}
func (repo *TokenRepo) IsTokenValid(ctx context.Context, userID, tokenID string) (bool, error) {

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