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
316 changed files with 9632 additions and 4919 deletions

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;
}