diff --git a/console/package-lock.json b/console/package-lock.json
index 2a0298bb9c..09332abba8 100644
--- a/console/package-lock.json
+++ b/console/package-lock.json
@@ -8,18 +8,18 @@
"name": "console",
"version": "0.0.0",
"dependencies": {
- "@angular/animations": "~12.2.7",
- "@angular/cdk": "~12.2.7",
- "@angular/common": "~12.2.7",
- "@angular/compiler": "~12.2.7",
- "@angular/core": "~12.2.7",
- "@angular/forms": "~12.2.7",
- "@angular/material": "^12.2.7",
- "@angular/material-moment-adapter": "^12.2.7",
- "@angular/platform-browser": "~12.2.7",
- "@angular/platform-browser-dynamic": "~12.2.7",
- "@angular/router": "~12.2.7",
- "@angular/service-worker": "~12.2.7",
+ "@angular/animations": "~12.2.8",
+ "@angular/cdk": "~12.2.8",
+ "@angular/common": "~12.2.8",
+ "@angular/compiler": "~12.2.8",
+ "@angular/core": "~12.2.8",
+ "@angular/forms": "~12.2.8",
+ "@angular/material": "^12.2.8",
+ "@angular/material-moment-adapter": "^12.2.8",
+ "@angular/platform-browser": "~12.2.8",
+ "@angular/platform-browser-dynamic": "~12.2.8",
+ "@angular/router": "~12.2.8",
+ "@angular/service-worker": "~12.2.8",
"@grpc/grpc-js": "^1.3.2",
"@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "^6.0.0",
@@ -31,7 +31,7 @@
"cors": "^2.8.5",
"file-saver": "^2.0.5",
"google-proto-files": "^2.4.0",
- "google-protobuf": "^3.17.2",
+ "google-protobuf": "^3.18.0",
"grpc-web": "^1.2.1",
"libphonenumber-js": "^1.9.34",
"moment": "^2.29.1",
@@ -46,13 +46,13 @@
"zone.js": "~0.11.4"
},
"devDependencies": {
- "@angular-devkit/build-angular": "~12.2.7",
- "@angular/cli": "~12.2.7",
- "@angular/compiler-cli": "~12.2.7",
- "@angular/language-service": "~12.2.7",
- "@types/jasmine": "~3.8.2",
+ "@angular-devkit/build-angular": "~12.2.8",
+ "@angular/cli": "~12.2.8",
+ "@angular/compiler-cli": "~12.2.8",
+ "@angular/language-service": "~12.2.8",
+ "@types/jasmine": "~3.9.1",
"@types/jasminewd2": "~2.0.10",
- "@types/node": "^16.7.6",
+ "@types/node": "^16.10.2",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.9.0",
"jasmine-spec-reporter": "~7.0.0",
@@ -60,12 +60,12 @@
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
- "karma-jasmine-html-reporter": "^1.5.0",
- "prettier": "^2.3.1",
+ "karma-jasmine-html-reporter": "^1.7.0",
+ "prettier": "^2.4.1",
"protractor": "~7.0.0",
"stylelint": "^13.10.0",
"stylelint-config-standard": "^22.0.0",
- "stylelint-scss": "^3.20.1",
+ "stylelint-scss": "^3.21.0",
"ts-node": "~10.2.1",
"tslint": "~6.1.3",
"typescript": "^4.2.4"
@@ -85,12 +85,12 @@
}
},
"node_modules/@angular-devkit/architect": {
- "version": "0.1202.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.7.tgz",
- "integrity": "sha512-zqqw3h8jMDYsRrXUNY1J8xtUl6wmBO++yTka+CoEIFetNdLdoWmb5VpaA81i0aSBhXBgnBUUFvqZGdiI7BbV8A==",
+ "version": "0.1202.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.8.tgz",
+ "integrity": "sha512-aPzwO3coRIuSjZa8FwFHy2y8OJarXG+afsqOk3muR6anvbdl+Av+m2RT8jjwj5J3D4N2eKZ7ob2q9HDUiHi4Pg==",
"dev": true,
"dependencies": {
- "@angular-devkit/core": "12.2.7",
+ "@angular-devkit/core": "12.2.8",
"rxjs": "6.6.7"
},
"engines": {
@@ -118,16 +118,16 @@
"dev": true
},
"node_modules/@angular-devkit/build-angular": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-12.2.7.tgz",
- "integrity": "sha512-ZgbdmPEiJ8ShKg6CwNEuot1xCHTC68WfTr1ClUhvMvK9nsBydPdeKAYiqEho8gP4PuC0v3Hssuokfkqdb3Ms/A==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-12.2.8.tgz",
+ "integrity": "sha512-nntuVk7K4DR0cdw1lAFLQKG6CFXQfnA2Ykk48gsMVAW2FHitrjiRfDuBKitx+D7f+cEXAFUO2wymrp9fIT2Z5w==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "1.0.1",
- "@angular-devkit/architect": "0.1202.7",
- "@angular-devkit/build-optimizer": "0.1202.7",
- "@angular-devkit/build-webpack": "0.1202.7",
- "@angular-devkit/core": "12.2.7",
+ "@angular-devkit/architect": "0.1202.8",
+ "@angular-devkit/build-optimizer": "0.1202.8",
+ "@angular-devkit/build-webpack": "0.1202.8",
+ "@angular-devkit/core": "12.2.8",
"@babel/core": "7.14.8",
"@babel/generator": "7.14.8",
"@babel/helper-annotate-as-pure": "7.14.5",
@@ -139,7 +139,7 @@
"@babel/template": "7.14.5",
"@discoveryjs/json-ext": "0.5.3",
"@jsdevtools/coverage-istanbul-loader": "3.0.5",
- "@ngtools/webpack": "12.2.7",
+ "@ngtools/webpack": "12.2.8",
"ansi-colors": "4.1.1",
"babel-loader": "8.2.2",
"browserslist": "^4.9.1",
@@ -255,9 +255,9 @@
"dev": true
},
"node_modules/@angular-devkit/build-optimizer": {
- "version": "0.1202.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.7.tgz",
- "integrity": "sha512-/VelwjOjQGZvXLwCuWVJ3MaTb1x0/UKYAqooEUW3yFkv6uXfpCCWywrIBZ3mYrU+m5ZeTjhDY4EFEd2WtBSroA==",
+ "version": "0.1202.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.8.tgz",
+ "integrity": "sha512-GyzlbIM5RX5RhnX3wW0YV7K9ctoJQv5O7L/VUuDFpK8yaJjqjC+sZT+rnu6oPGFbPnYMx/BkkxzU2D0z98T4Mg==",
"dev": true,
"dependencies": {
"source-map": "0.7.3",
@@ -282,12 +282,12 @@
}
},
"node_modules/@angular-devkit/build-webpack": {
- "version": "0.1202.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1202.7.tgz",
- "integrity": "sha512-DuWr6jEB/CBlmU1D+n0Jo6BMtYokbpBG0PZtnyzSvcwglIWIhxzFbCC7HTnlEzed+bmCSui7LtlGtkYcpFFsGw==",
+ "version": "0.1202.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1202.8.tgz",
+ "integrity": "sha512-ryzstLoMcJfICToZv/RwqeVNNZ3tn71+S1JxNled469gWnsZAvABfexe8BOaT0b0MTo8h49ULeK1DU8McLY78Q==",
"dev": true,
"dependencies": {
- "@angular-devkit/architect": "0.1202.7",
+ "@angular-devkit/architect": "0.1202.8",
"rxjs": "6.6.7"
},
"engines": {
@@ -319,9 +319,9 @@
"dev": true
},
"node_modules/@angular-devkit/core": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.7.tgz",
- "integrity": "sha512-WeLlDZaudpx10OGDPfVcWu/CaEWiWzAaLTUQz0Ww/yM+01FxR/P8yeH1sYAV1MS6d6KHvXGw7Lpf8PV7IA/zHA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.8.tgz",
+ "integrity": "sha512-N13N1Lm7qllBXSVZYz4Khw75rnQnS3lu5QiJqlsaNklWgVfVz8jt99AAeGGvNGSLEbmZjlr35YLxu8ugD267Ug==",
"dev": true,
"dependencies": {
"ajv": "8.6.2",
@@ -356,12 +356,12 @@
"dev": true
},
"node_modules/@angular-devkit/schematics": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.7.tgz",
- "integrity": "sha512-E0hCFyyfbixjerf0Okt4ynC6F1dsT2Wl7MwAePe+wzPTHCnKIRTa2PQTxJzdWeTlSkQMkSK6ft2iyWOD/FODng==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.8.tgz",
+ "integrity": "sha512-SPiMFoCi1TpFXY6h1xGCakgdwT25gGHdbis1MuHE5yMcPLvhl/yr7EQVY1GY00/iMrgeslTHg/UPp4D6xHyQxA==",
"dev": true,
"dependencies": {
- "@angular-devkit/core": "12.2.7",
+ "@angular-devkit/core": "12.2.8",
"ora": "5.4.1",
"rxjs": "6.6.7"
},
@@ -390,9 +390,9 @@
"dev": true
},
"node_modules/@angular/animations": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.7.tgz",
- "integrity": "sha512-ehlI4wnlHN213CiQNjYspoT9cEIrtOqVJfsPxUdzOCqCGBajVLxyqHb1skXtfOQXOIhznRS7P/d/4Ht7mWMizg==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.8.tgz",
+ "integrity": "sha512-uRK3EIIFMMIGBMIZscKt9p+H6lzuGXm+zokj5aZsB4Pu+rz8sc/Uxn26lTzq6o5GApiL4I75inK4Vs5f5RZKnA==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -400,13 +400,13 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/core": "12.2.7"
+ "@angular/core": "12.2.8"
}
},
"node_modules/@angular/cdk": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.7.tgz",
- "integrity": "sha512-OMPewaE1VxCSFkLDZQLFMkGQCQEvbizuVRzArZBB5xfxl98YMjntNQjlWH4rGbRhF+eZlpOrC+UAVnzTX2BzAw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.8.tgz",
+ "integrity": "sha512-M0Y61o0yEVLMg+DSNsaDgiOifAV6OdumTgt2/kNoSuauPRWS0bkZJE58k3LR+cPi1Cho3UXELMKMOXZN9AhofA==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -420,16 +420,16 @@
}
},
"node_modules/@angular/cli": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.7.tgz",
- "integrity": "sha512-FH34528+126Cxh/+1cBppBas8tExizKSJgbjpT3zgV6ijwHD7apT5zU9R1TyOhQPd6BhyaURo9Hnsjg49W4bRA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.8.tgz",
+ "integrity": "sha512-MkTVkQbI+58W1izHKpGdpj0YAFfQnf7oQIyMom13/8l83yuOJdNzFTG/Lt77hx19qaKemEdmqTqdEOOrzaqggw==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@angular-devkit/architect": "0.1202.7",
- "@angular-devkit/core": "12.2.7",
- "@angular-devkit/schematics": "12.2.7",
- "@schematics/angular": "12.2.7",
+ "@angular-devkit/architect": "0.1202.8",
+ "@angular-devkit/core": "12.2.8",
+ "@angular-devkit/schematics": "12.2.8",
+ "@schematics/angular": "12.2.8",
"@yarnpkg/lockfile": "1.1.0",
"ansi-colors": "4.1.1",
"debug": "4.3.2",
@@ -456,9 +456,9 @@
}
},
"node_modules/@angular/common": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.7.tgz",
- "integrity": "sha512-Gug5a59c4NwfmSvO9Ya7DoYjl6ndK7nDuBoPSpp6IHTlNE8FY/BOd29qEp/lYJ4cAWxVk14+lonUPs6C+Szekw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.8.tgz",
+ "integrity": "sha512-4nFlwC97wNEkB4vU2+xrbzpniuzmw8FG9zfqIeMFLLmceHLR7SQmxVKUrZylNXjT5TXXynpQzrpRAxQ1AEcTSA==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -466,14 +466,14 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/core": "12.2.7",
+ "@angular/core": "12.2.8",
"rxjs": "^6.5.3 || ^7.0.0"
}
},
"node_modules/@angular/compiler": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.7.tgz",
- "integrity": "sha512-9X7Vrfg6dWfYKPAJLQYR5W7N8WnESg8PG07gNzHZtavETPrDIoX+Av/kQcEdPu14zTZE5NWx5u5TUByFgouQiQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.8.tgz",
+ "integrity": "sha512-11AswnrVeipKibK0Ra4n3TjZfr6QYpiNGPvT6XQB9NLgSthAPTa9T1Bige2yQhgyWNaZsOPko/jhhNS8ufSZCg==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -482,9 +482,9 @@
}
},
"node_modules/@angular/compiler-cli": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.7.tgz",
- "integrity": "sha512-otsy3t3psrEWNbnjADaZVhBGBmBmBGxqknNoJ1+UeqSWf4z7su736jyzerxD684vmk08U6X2loxOuDr90idjPA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.8.tgz",
+ "integrity": "sha512-KFGYsDATUCEoY4KEVcpxyT5S0k2T14hIlmBxzmzRhsCVi2ZLti5E2tnqQi2klKCFxmsk7VYd3kqWRJWBZieQtA==",
"dev": true,
"dependencies": {
"@babel/core": "^7.8.6",
@@ -512,7 +512,7 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/compiler": "12.2.7",
+ "@angular/compiler": "12.2.8",
"typescript": ">=4.2.3 <4.4"
}
},
@@ -544,9 +544,9 @@
}
},
"node_modules/@angular/core": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.7.tgz",
- "integrity": "sha512-no4mQ4O1euNH6odho1H27dcUmYBaNuyYvpPvv0wbb1pMT3Mm2J/uueePx/fvwg3nQ+vnk/yL1VCCqR7Mt62nHA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.8.tgz",
+ "integrity": "sha512-ko7RJ8BImcMiI64Z8DM54ylkUwu2r/Mhf37BME0EEm+RIrH0KUVzrFOl2rMaxKBZUtY9qaxvVt43bZPrvN2acg==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -559,9 +559,9 @@
}
},
"node_modules/@angular/forms": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.7.tgz",
- "integrity": "sha512-TtXnwE/bouEtGddaaSGytwCoyRN8YPNN/yf81fFM9LOGef4ZpABMtuMnsZxlDS+91AGpVSzvR511O5DG1BXc4Q==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.8.tgz",
+ "integrity": "sha512-/4w+ggQdUg9Ab5s2yhd9A06uevRsyoZ28vGgLU861PZUe5hR4+Gv3XdIuyEBOFvifanWzuxR0xL3okVZAKCXyA==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -569,31 +569,31 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/common": "12.2.7",
- "@angular/core": "12.2.7",
- "@angular/platform-browser": "12.2.7",
+ "@angular/common": "12.2.8",
+ "@angular/core": "12.2.8",
+ "@angular/platform-browser": "12.2.8",
"rxjs": "^6.5.3 || ^7.0.0"
}
},
"node_modules/@angular/language-service": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-12.2.7.tgz",
- "integrity": "sha512-LCr4CUL1IFLfW9oHpv43/lhJ/kzCP4vhsGTmtOPup7Oc8/lVGUxvFrnIPx0o9qgSjT/ATbWr29+QY0bk02gsRQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-12.2.8.tgz",
+ "integrity": "sha512-/+GumfwB/j1ILrA5a8iv22FK+0M0GirnHjfOnqiRlcWPlmBkWSr+8RhjjT9TwcZsPS6QFxOBQUj1I5SDwG47Ug==",
"dev": true,
"engines": {
"node": "^12.14.1 || >=14.0.0"
}
},
"node_modules/@angular/material": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.2.7.tgz",
- "integrity": "sha512-uaenRwRywvn0hMvRIsSaFIgUSrfHHZMr/uAC3uDZh7zAVmsbAqgzyrNo7i4L5vZxQa3q1EXn1fFPPOTrPfqdJw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.2.8.tgz",
+ "integrity": "sha512-wRTaTZIGC9+2e8aft44V9Qqwp3PsR9AG0FeJ0spl8mdOlYEqMMyoRXjvMiWIjo2ywxHLoQgLXXsWn3ip2xnnVg==",
"dependencies": {
"tslib": "^2.2.0"
},
"peerDependencies": {
"@angular/animations": "^12.0.0 || ^13.0.0-0",
- "@angular/cdk": "12.2.7",
+ "@angular/cdk": "12.2.8",
"@angular/common": "^12.0.0 || ^13.0.0-0",
"@angular/core": "^12.0.0 || ^13.0.0-0",
"@angular/forms": "^12.0.0 || ^13.0.0-0",
@@ -601,22 +601,22 @@
}
},
"node_modules/@angular/material-moment-adapter": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-12.2.7.tgz",
- "integrity": "sha512-nwDTQLP5al5LJ+Sl4fJBnesfRjzaLe4ZJZOy+Yl5F+UU/JJSOZuYs38KqTYb89SJDnWnGsx6SFk9eqjQjGfpXQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-12.2.8.tgz",
+ "integrity": "sha512-uk81sYrY4TfX889ZXo7l7iV8Idxww+sTHzZueq8xC9UTG35FM0KLSvUa/EqwR31lau+6rbgKFCGurQVhBvHrQA==",
"dependencies": {
"tslib": "^2.2.0"
},
"peerDependencies": {
"@angular/core": "^12.0.0 || ^13.0.0-0",
- "@angular/material": "12.2.7",
+ "@angular/material": "12.2.8",
"moment": "^2.18.1"
}
},
"node_modules/@angular/platform-browser": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.7.tgz",
- "integrity": "sha512-mCQ5KqskMb98DLowyKfixH+ZpTjs5WuIZw9BqPc2knOlUxmfTuDRf5xDQn9Nur2ASF1wfJpaOogW685nB3ojnQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.8.tgz",
+ "integrity": "sha512-U79tj/fOIKYQbtrRhZm6IcHilUt3UEmloRh7hn2ozhYWOgJmTpygR6FIvvu1X7urAFoOMGY25UZjBNxbnabRNw==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -624,9 +624,9 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/animations": "12.2.7",
- "@angular/common": "12.2.7",
- "@angular/core": "12.2.7"
+ "@angular/animations": "12.2.8",
+ "@angular/common": "12.2.8",
+ "@angular/core": "12.2.8"
},
"peerDependenciesMeta": {
"@angular/animations": {
@@ -635,9 +635,9 @@
}
},
"node_modules/@angular/platform-browser-dynamic": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.7.tgz",
- "integrity": "sha512-KxIotZR/NaM4r6OyjVxpPIg2AOk2jXpZy77g868tzqt8GQVJ6NXHoNTIAfQhEelr6bSIELm+mTqhDbNNIrXEnQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.8.tgz",
+ "integrity": "sha512-kHU4mbbrc1TW5Fz9OHRN5IQcFsmEm3zR5g5V1QTFoLjj6jnRao2xd5KZ8Owt0vcf+Qr4/v4kQGh2pIFZJFMaxQ==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -645,16 +645,16 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/common": "12.2.7",
- "@angular/compiler": "12.2.7",
- "@angular/core": "12.2.7",
- "@angular/platform-browser": "12.2.7"
+ "@angular/common": "12.2.8",
+ "@angular/compiler": "12.2.8",
+ "@angular/core": "12.2.8",
+ "@angular/platform-browser": "12.2.8"
}
},
"node_modules/@angular/router": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.7.tgz",
- "integrity": "sha512-3RzeBXbV0B+sdSskRYV07KsCgcS8dMmce6oUQrDskEnAmakzFo+R6OVKBFhPtTrqUstHVUsXr2kcoaaPVLquYw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.8.tgz",
+ "integrity": "sha512-uYPT968IoGH01gUxHTG86hkFIS6G/sWr7QFXhuIzQHTnb+OeyaqWiw4iLc/QDAEPHJ7Wz6gNvCVHv9R2yod00g==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -662,16 +662,16 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/common": "12.2.7",
- "@angular/core": "12.2.7",
- "@angular/platform-browser": "12.2.7",
+ "@angular/common": "12.2.8",
+ "@angular/core": "12.2.8",
+ "@angular/platform-browser": "12.2.8",
"rxjs": "^6.5.3 || ^7.0.0"
}
},
"node_modules/@angular/service-worker": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-12.2.7.tgz",
- "integrity": "sha512-0Lz2y/1l2/mOmpuKVmzEFPOC+Gnj8LHJ6w/2DThXQdFxueYInBd+zF9i65TeVtytWe0ZtGEcLXX5GymaQhxsSg==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-12.2.8.tgz",
+ "integrity": "sha512-7/A6gSHrcUa7XHXp3WezUwqsMR4y8To1AvoZ7u0IGC/hbf9CpFk/RnMsItr8h4mxLQz7z214euEUAehYL9RunA==",
"dependencies": {
"tslib": "^2.2.0"
},
@@ -682,8 +682,8 @@
"node": "^12.14.1 || >=14.0.0"
},
"peerDependencies": {
- "@angular/common": "12.2.7",
- "@angular/core": "12.2.7"
+ "@angular/common": "12.2.8",
+ "@angular/core": "12.2.8"
}
},
"node_modules/@assemblyscript/loader": {
@@ -2411,9 +2411,9 @@
}
},
"node_modules/@ngtools/webpack": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.7.tgz",
- "integrity": "sha512-RX5UQA9Bwp/J5GPGtJiwEOQUdf/0UqdeIZtktOZJ4x3K676l//PCFxxxgGqi2qUR2eu/wLAyiDhvDwqDixsngQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.8.tgz",
+ "integrity": "sha512-utQrOXm4eS3BEQh2/y8zt5fVF9cuakfVQSPD/pWPKLqZsGc9wB3CHkrQED0EizsBfrsn5yLc3yPh3P8yGUmdRw==",
"dev": true,
"engines": {
"node": "^12.14.1 || >=14.0.0",
@@ -2629,13 +2629,13 @@
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
},
"node_modules/@schematics/angular": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.7.tgz",
- "integrity": "sha512-wGqp0jC545Fwf0ydBkeoJHx9snFW+uqn40WwVqs/27Nh4AEHB5uzwzLY7Ykae95Zn802a61KPqSNWpez2fWWGA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.8.tgz",
+ "integrity": "sha512-xkVcX6lTHC5JzDOjGdRAZutVVpxkRkT84vXtVlJwojyhNjAZg5dm/GC84+gVGfmVnO9vkUIYo/vGoN+/ydcSdA==",
"dev": true,
"dependencies": {
- "@angular-devkit/core": "12.2.7",
- "@angular-devkit/schematics": "12.2.7",
+ "@angular-devkit/core": "12.2.8",
+ "@angular-devkit/schematics": "12.2.8",
"jsonc-parser": "3.0.0"
},
"engines": {
@@ -2778,9 +2778,9 @@
"integrity": "sha512-MDpu7lit927cdLtBzTPUFjXGANFUnu5ThPqjygY8XmCyI/oDlIA0jAi4sffGOxYaLK2CCxAuU9wGxsgAQbA6FQ=="
},
"node_modules/@types/jasmine": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.8.2.tgz",
- "integrity": "sha512-u5h7dqzy2XpXTzhOzSNQUQpKGFvROF8ElNX9P/TJvsHnTg/JvsAseVsGWQAQQldqanYaM+5kwxW909BBFAUYsg==",
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.9.1.tgz",
+ "integrity": "sha512-PVpjh8S8lqKFKurWSKdFATlfBHGPzgy0PoDdzQ+rr78jTQ0aacyh9YndzZcAUPxhk4kRujItFFGQdUJ7flHumw==",
"dev": true
},
"node_modules/@types/jasminewd2": {
@@ -2825,9 +2825,9 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "16.7.6",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.6.tgz",
- "integrity": "sha512-VESVNFoa/ahYA62xnLBjo5ur6gPsgEE5cNRy8SrdnkZ2nwJSW0kJ4ufbFr2zuU9ALtHM8juY53VcRoTA7htXSg=="
+ "version": "16.10.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz",
+ "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ=="
},
"node_modules/@types/normalize-package-data": {
"version": "2.4.0",
@@ -7458,9 +7458,9 @@
}
},
"node_modules/google-protobuf": {
- "version": "3.17.3",
- "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.3.tgz",
- "integrity": "sha512-OVPzcSWIAJ+d5yiHyeaLrdufQtrvaBrF4JQg+z8ynTkbO3uFcujqXszTumqg1cGsAsjkWnI+M5B1xZ19yR4Wyg=="
+ "version": "3.18.0",
+ "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.18.0.tgz",
+ "integrity": "sha512-WlaQWRkUOo/lm9uTgNH6nk9IQt814RggWPzKBfnAVewOFzSzRUSmS1yUWRT6ixW1vS7er5p6tmLSmwzpPpmc8A=="
},
"node_modules/graceful-fs": {
"version": "4.2.6",
@@ -9341,12 +9341,12 @@
}
},
"node_modules/karma-jasmine-html-reporter": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.6.0.tgz",
- "integrity": "sha512-ELO9yf0cNqpzaNLsfFgXd/wxZVYkE2+ECUwhMHUD4PZ17kcsPsYsVyjquiRqyMn2jkd2sHt0IeMyAyq1MC23Fw==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz",
+ "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==",
"dev": true,
"peerDependencies": {
- "jasmine-core": ">=3.7.1",
+ "jasmine-core": ">=3.8",
"karma": ">=0.9",
"karma-jasmine": ">=1.1"
}
@@ -14174,9 +14174,9 @@
}
},
"node_modules/prettier": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz",
- "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
+ "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
@@ -16895,9 +16895,9 @@
}
},
"node_modules/stylelint-scss": {
- "version": "3.20.1",
- "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.20.1.tgz",
- "integrity": "sha512-OTd55O1TTAC5nGKkVmUDLpz53LlK39R3MImv1CfuvsK7/qugktqiZAeQLuuC4UBhzxCnsc7fp9u/gfRZwFAIkA==",
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.21.0.tgz",
+ "integrity": "sha512-CMI2wSHL+XVlNExpauy/+DbUcB/oUZLARDtMIXkpV/5yd8nthzylYd1cdHeDMJVBXeYHldsnebUX6MoV5zPW4A==",
"dev": true,
"dependencies": {
"lodash": "^4.17.15",
@@ -19718,12 +19718,12 @@
}
},
"@angular-devkit/architect": {
- "version": "0.1202.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.7.tgz",
- "integrity": "sha512-zqqw3h8jMDYsRrXUNY1J8xtUl6wmBO++yTka+CoEIFetNdLdoWmb5VpaA81i0aSBhXBgnBUUFvqZGdiI7BbV8A==",
+ "version": "0.1202.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.8.tgz",
+ "integrity": "sha512-aPzwO3coRIuSjZa8FwFHy2y8OJarXG+afsqOk3muR6anvbdl+Av+m2RT8jjwj5J3D4N2eKZ7ob2q9HDUiHi4Pg==",
"dev": true,
"requires": {
- "@angular-devkit/core": "12.2.7",
+ "@angular-devkit/core": "12.2.8",
"rxjs": "6.6.7"
},
"dependencies": {
@@ -19745,16 +19745,16 @@
}
},
"@angular-devkit/build-angular": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-12.2.7.tgz",
- "integrity": "sha512-ZgbdmPEiJ8ShKg6CwNEuot1xCHTC68WfTr1ClUhvMvK9nsBydPdeKAYiqEho8gP4PuC0v3Hssuokfkqdb3Ms/A==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-12.2.8.tgz",
+ "integrity": "sha512-nntuVk7K4DR0cdw1lAFLQKG6CFXQfnA2Ykk48gsMVAW2FHitrjiRfDuBKitx+D7f+cEXAFUO2wymrp9fIT2Z5w==",
"dev": true,
"requires": {
"@ampproject/remapping": "1.0.1",
- "@angular-devkit/architect": "0.1202.7",
- "@angular-devkit/build-optimizer": "0.1202.7",
- "@angular-devkit/build-webpack": "0.1202.7",
- "@angular-devkit/core": "12.2.7",
+ "@angular-devkit/architect": "0.1202.8",
+ "@angular-devkit/build-optimizer": "0.1202.8",
+ "@angular-devkit/build-webpack": "0.1202.8",
+ "@angular-devkit/core": "12.2.8",
"@babel/core": "7.14.8",
"@babel/generator": "7.14.8",
"@babel/helper-annotate-as-pure": "7.14.5",
@@ -19766,7 +19766,7 @@
"@babel/template": "7.14.5",
"@discoveryjs/json-ext": "0.5.3",
"@jsdevtools/coverage-istanbul-loader": "3.0.5",
- "@ngtools/webpack": "12.2.7",
+ "@ngtools/webpack": "12.2.8",
"ansi-colors": "4.1.1",
"babel-loader": "8.2.2",
"browserslist": "^4.9.1",
@@ -19842,9 +19842,9 @@
}
},
"@angular-devkit/build-optimizer": {
- "version": "0.1202.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.7.tgz",
- "integrity": "sha512-/VelwjOjQGZvXLwCuWVJ3MaTb1x0/UKYAqooEUW3yFkv6uXfpCCWywrIBZ3mYrU+m5ZeTjhDY4EFEd2WtBSroA==",
+ "version": "0.1202.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.8.tgz",
+ "integrity": "sha512-GyzlbIM5RX5RhnX3wW0YV7K9ctoJQv5O7L/VUuDFpK8yaJjqjC+sZT+rnu6oPGFbPnYMx/BkkxzU2D0z98T4Mg==",
"dev": true,
"requires": {
"source-map": "0.7.3",
@@ -19853,12 +19853,12 @@
}
},
"@angular-devkit/build-webpack": {
- "version": "0.1202.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1202.7.tgz",
- "integrity": "sha512-DuWr6jEB/CBlmU1D+n0Jo6BMtYokbpBG0PZtnyzSvcwglIWIhxzFbCC7HTnlEzed+bmCSui7LtlGtkYcpFFsGw==",
+ "version": "0.1202.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1202.8.tgz",
+ "integrity": "sha512-ryzstLoMcJfICToZv/RwqeVNNZ3tn71+S1JxNled469gWnsZAvABfexe8BOaT0b0MTo8h49ULeK1DU8McLY78Q==",
"dev": true,
"requires": {
- "@angular-devkit/architect": "0.1202.7",
+ "@angular-devkit/architect": "0.1202.8",
"rxjs": "6.6.7"
},
"dependencies": {
@@ -19880,9 +19880,9 @@
}
},
"@angular-devkit/core": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.7.tgz",
- "integrity": "sha512-WeLlDZaudpx10OGDPfVcWu/CaEWiWzAaLTUQz0Ww/yM+01FxR/P8yeH1sYAV1MS6d6KHvXGw7Lpf8PV7IA/zHA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.8.tgz",
+ "integrity": "sha512-N13N1Lm7qllBXSVZYz4Khw75rnQnS3lu5QiJqlsaNklWgVfVz8jt99AAeGGvNGSLEbmZjlr35YLxu8ugD267Ug==",
"dev": true,
"requires": {
"ajv": "8.6.2",
@@ -19911,12 +19911,12 @@
}
},
"@angular-devkit/schematics": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.7.tgz",
- "integrity": "sha512-E0hCFyyfbixjerf0Okt4ynC6F1dsT2Wl7MwAePe+wzPTHCnKIRTa2PQTxJzdWeTlSkQMkSK6ft2iyWOD/FODng==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.8.tgz",
+ "integrity": "sha512-SPiMFoCi1TpFXY6h1xGCakgdwT25gGHdbis1MuHE5yMcPLvhl/yr7EQVY1GY00/iMrgeslTHg/UPp4D6xHyQxA==",
"dev": true,
"requires": {
- "@angular-devkit/core": "12.2.7",
+ "@angular-devkit/core": "12.2.8",
"ora": "5.4.1",
"rxjs": "6.6.7"
},
@@ -19939,32 +19939,32 @@
}
},
"@angular/animations": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.7.tgz",
- "integrity": "sha512-ehlI4wnlHN213CiQNjYspoT9cEIrtOqVJfsPxUdzOCqCGBajVLxyqHb1skXtfOQXOIhznRS7P/d/4Ht7mWMizg==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.8.tgz",
+ "integrity": "sha512-uRK3EIIFMMIGBMIZscKt9p+H6lzuGXm+zokj5aZsB4Pu+rz8sc/Uxn26lTzq6o5GApiL4I75inK4Vs5f5RZKnA==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/cdk": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.7.tgz",
- "integrity": "sha512-OMPewaE1VxCSFkLDZQLFMkGQCQEvbizuVRzArZBB5xfxl98YMjntNQjlWH4rGbRhF+eZlpOrC+UAVnzTX2BzAw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.8.tgz",
+ "integrity": "sha512-M0Y61o0yEVLMg+DSNsaDgiOifAV6OdumTgt2/kNoSuauPRWS0bkZJE58k3LR+cPi1Cho3UXELMKMOXZN9AhofA==",
"requires": {
"parse5": "^5.0.0",
"tslib": "^2.2.0"
}
},
"@angular/cli": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.7.tgz",
- "integrity": "sha512-FH34528+126Cxh/+1cBppBas8tExizKSJgbjpT3zgV6ijwHD7apT5zU9R1TyOhQPd6BhyaURo9Hnsjg49W4bRA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.8.tgz",
+ "integrity": "sha512-MkTVkQbI+58W1izHKpGdpj0YAFfQnf7oQIyMom13/8l83yuOJdNzFTG/Lt77hx19qaKemEdmqTqdEOOrzaqggw==",
"dev": true,
"requires": {
- "@angular-devkit/architect": "0.1202.7",
- "@angular-devkit/core": "12.2.7",
- "@angular-devkit/schematics": "12.2.7",
- "@schematics/angular": "12.2.7",
+ "@angular-devkit/architect": "0.1202.8",
+ "@angular-devkit/core": "12.2.8",
+ "@angular-devkit/schematics": "12.2.8",
+ "@schematics/angular": "12.2.8",
"@yarnpkg/lockfile": "1.1.0",
"ansi-colors": "4.1.1",
"debug": "4.3.2",
@@ -19983,25 +19983,25 @@
}
},
"@angular/common": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.7.tgz",
- "integrity": "sha512-Gug5a59c4NwfmSvO9Ya7DoYjl6ndK7nDuBoPSpp6IHTlNE8FY/BOd29qEp/lYJ4cAWxVk14+lonUPs6C+Szekw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.8.tgz",
+ "integrity": "sha512-4nFlwC97wNEkB4vU2+xrbzpniuzmw8FG9zfqIeMFLLmceHLR7SQmxVKUrZylNXjT5TXXynpQzrpRAxQ1AEcTSA==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/compiler": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.7.tgz",
- "integrity": "sha512-9X7Vrfg6dWfYKPAJLQYR5W7N8WnESg8PG07gNzHZtavETPrDIoX+Av/kQcEdPu14zTZE5NWx5u5TUByFgouQiQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.8.tgz",
+ "integrity": "sha512-11AswnrVeipKibK0Ra4n3TjZfr6QYpiNGPvT6XQB9NLgSthAPTa9T1Bige2yQhgyWNaZsOPko/jhhNS8ufSZCg==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/compiler-cli": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.7.tgz",
- "integrity": "sha512-otsy3t3psrEWNbnjADaZVhBGBmBmBGxqknNoJ1+UeqSWf4z7su736jyzerxD684vmk08U6X2loxOuDr90idjPA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.8.tgz",
+ "integrity": "sha512-KFGYsDATUCEoY4KEVcpxyT5S0k2T14hIlmBxzmzRhsCVi2ZLti5E2tnqQi2klKCFxmsk7VYd3kqWRJWBZieQtA==",
"dev": true,
"requires": {
"@babel/core": "^7.8.6",
@@ -20044,71 +20044,71 @@
}
},
"@angular/core": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.7.tgz",
- "integrity": "sha512-no4mQ4O1euNH6odho1H27dcUmYBaNuyYvpPvv0wbb1pMT3Mm2J/uueePx/fvwg3nQ+vnk/yL1VCCqR7Mt62nHA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.8.tgz",
+ "integrity": "sha512-ko7RJ8BImcMiI64Z8DM54ylkUwu2r/Mhf37BME0EEm+RIrH0KUVzrFOl2rMaxKBZUtY9qaxvVt43bZPrvN2acg==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/forms": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.7.tgz",
- "integrity": "sha512-TtXnwE/bouEtGddaaSGytwCoyRN8YPNN/yf81fFM9LOGef4ZpABMtuMnsZxlDS+91AGpVSzvR511O5DG1BXc4Q==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.8.tgz",
+ "integrity": "sha512-/4w+ggQdUg9Ab5s2yhd9A06uevRsyoZ28vGgLU861PZUe5hR4+Gv3XdIuyEBOFvifanWzuxR0xL3okVZAKCXyA==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/language-service": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-12.2.7.tgz",
- "integrity": "sha512-LCr4CUL1IFLfW9oHpv43/lhJ/kzCP4vhsGTmtOPup7Oc8/lVGUxvFrnIPx0o9qgSjT/ATbWr29+QY0bk02gsRQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-12.2.8.tgz",
+ "integrity": "sha512-/+GumfwB/j1ILrA5a8iv22FK+0M0GirnHjfOnqiRlcWPlmBkWSr+8RhjjT9TwcZsPS6QFxOBQUj1I5SDwG47Ug==",
"dev": true
},
"@angular/material": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.2.7.tgz",
- "integrity": "sha512-uaenRwRywvn0hMvRIsSaFIgUSrfHHZMr/uAC3uDZh7zAVmsbAqgzyrNo7i4L5vZxQa3q1EXn1fFPPOTrPfqdJw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.2.8.tgz",
+ "integrity": "sha512-wRTaTZIGC9+2e8aft44V9Qqwp3PsR9AG0FeJ0spl8mdOlYEqMMyoRXjvMiWIjo2ywxHLoQgLXXsWn3ip2xnnVg==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/material-moment-adapter": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-12.2.7.tgz",
- "integrity": "sha512-nwDTQLP5al5LJ+Sl4fJBnesfRjzaLe4ZJZOy+Yl5F+UU/JJSOZuYs38KqTYb89SJDnWnGsx6SFk9eqjQjGfpXQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-12.2.8.tgz",
+ "integrity": "sha512-uk81sYrY4TfX889ZXo7l7iV8Idxww+sTHzZueq8xC9UTG35FM0KLSvUa/EqwR31lau+6rbgKFCGurQVhBvHrQA==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/platform-browser": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.7.tgz",
- "integrity": "sha512-mCQ5KqskMb98DLowyKfixH+ZpTjs5WuIZw9BqPc2knOlUxmfTuDRf5xDQn9Nur2ASF1wfJpaOogW685nB3ojnQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.8.tgz",
+ "integrity": "sha512-U79tj/fOIKYQbtrRhZm6IcHilUt3UEmloRh7hn2ozhYWOgJmTpygR6FIvvu1X7urAFoOMGY25UZjBNxbnabRNw==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/platform-browser-dynamic": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.7.tgz",
- "integrity": "sha512-KxIotZR/NaM4r6OyjVxpPIg2AOk2jXpZy77g868tzqt8GQVJ6NXHoNTIAfQhEelr6bSIELm+mTqhDbNNIrXEnQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.8.tgz",
+ "integrity": "sha512-kHU4mbbrc1TW5Fz9OHRN5IQcFsmEm3zR5g5V1QTFoLjj6jnRao2xd5KZ8Owt0vcf+Qr4/v4kQGh2pIFZJFMaxQ==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/router": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.7.tgz",
- "integrity": "sha512-3RzeBXbV0B+sdSskRYV07KsCgcS8dMmce6oUQrDskEnAmakzFo+R6OVKBFhPtTrqUstHVUsXr2kcoaaPVLquYw==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.8.tgz",
+ "integrity": "sha512-uYPT968IoGH01gUxHTG86hkFIS6G/sWr7QFXhuIzQHTnb+OeyaqWiw4iLc/QDAEPHJ7Wz6gNvCVHv9R2yod00g==",
"requires": {
"tslib": "^2.2.0"
}
},
"@angular/service-worker": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-12.2.7.tgz",
- "integrity": "sha512-0Lz2y/1l2/mOmpuKVmzEFPOC+Gnj8LHJ6w/2DThXQdFxueYInBd+zF9i65TeVtytWe0ZtGEcLXX5GymaQhxsSg==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-12.2.8.tgz",
+ "integrity": "sha512-7/A6gSHrcUa7XHXp3WezUwqsMR4y8To1AvoZ7u0IGC/hbf9CpFk/RnMsItr8h4mxLQz7z214euEUAehYL9RunA==",
"requires": {
"tslib": "^2.2.0"
}
@@ -21329,9 +21329,9 @@
}
},
"@ngtools/webpack": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.7.tgz",
- "integrity": "sha512-RX5UQA9Bwp/J5GPGtJiwEOQUdf/0UqdeIZtktOZJ4x3K676l//PCFxxxgGqi2qUR2eu/wLAyiDhvDwqDixsngQ==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.8.tgz",
+ "integrity": "sha512-utQrOXm4eS3BEQh2/y8zt5fVF9cuakfVQSPD/pWPKLqZsGc9wB3CHkrQED0EizsBfrsn5yLc3yPh3P8yGUmdRw==",
"dev": true,
"requires": {}
},
@@ -21507,13 +21507,13 @@
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
},
"@schematics/angular": {
- "version": "12.2.7",
- "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.7.tgz",
- "integrity": "sha512-wGqp0jC545Fwf0ydBkeoJHx9snFW+uqn40WwVqs/27Nh4AEHB5uzwzLY7Ykae95Zn802a61KPqSNWpez2fWWGA==",
+ "version": "12.2.8",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.8.tgz",
+ "integrity": "sha512-xkVcX6lTHC5JzDOjGdRAZutVVpxkRkT84vXtVlJwojyhNjAZg5dm/GC84+gVGfmVnO9vkUIYo/vGoN+/ydcSdA==",
"dev": true,
"requires": {
- "@angular-devkit/core": "12.2.7",
- "@angular-devkit/schematics": "12.2.7",
+ "@angular-devkit/core": "12.2.8",
+ "@angular-devkit/schematics": "12.2.8",
"jsonc-parser": "3.0.0"
}
},
@@ -21637,9 +21637,9 @@
"integrity": "sha512-MDpu7lit927cdLtBzTPUFjXGANFUnu5ThPqjygY8XmCyI/oDlIA0jAi4sffGOxYaLK2CCxAuU9wGxsgAQbA6FQ=="
},
"@types/jasmine": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.8.2.tgz",
- "integrity": "sha512-u5h7dqzy2XpXTzhOzSNQUQpKGFvROF8ElNX9P/TJvsHnTg/JvsAseVsGWQAQQldqanYaM+5kwxW909BBFAUYsg==",
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.9.1.tgz",
+ "integrity": "sha512-PVpjh8S8lqKFKurWSKdFATlfBHGPzgy0PoDdzQ+rr78jTQ0aacyh9YndzZcAUPxhk4kRujItFFGQdUJ7flHumw==",
"dev": true
},
"@types/jasminewd2": {
@@ -21684,9 +21684,9 @@
"dev": true
},
"@types/node": {
- "version": "16.7.6",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.6.tgz",
- "integrity": "sha512-VESVNFoa/ahYA62xnLBjo5ur6gPsgEE5cNRy8SrdnkZ2nwJSW0kJ4ufbFr2zuU9ALtHM8juY53VcRoTA7htXSg=="
+ "version": "16.10.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz",
+ "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ=="
},
"@types/normalize-package-data": {
"version": "2.4.0",
@@ -25371,9 +25371,9 @@
}
},
"google-protobuf": {
- "version": "3.17.3",
- "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.3.tgz",
- "integrity": "sha512-OVPzcSWIAJ+d5yiHyeaLrdufQtrvaBrF4JQg+z8ynTkbO3uFcujqXszTumqg1cGsAsjkWnI+M5B1xZ19yR4Wyg=="
+ "version": "3.18.0",
+ "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.18.0.tgz",
+ "integrity": "sha512-WlaQWRkUOo/lm9uTgNH6nk9IQt814RggWPzKBfnAVewOFzSzRUSmS1yUWRT6ixW1vS7er5p6tmLSmwzpPpmc8A=="
},
"graceful-fs": {
"version": "4.2.6",
@@ -26859,9 +26859,9 @@
}
},
"karma-jasmine-html-reporter": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.6.0.tgz",
- "integrity": "sha512-ELO9yf0cNqpzaNLsfFgXd/wxZVYkE2+ECUwhMHUD4PZ17kcsPsYsVyjquiRqyMn2jkd2sHt0IeMyAyq1MC23Fw==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz",
+ "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==",
"dev": true,
"requires": {}
},
@@ -30427,9 +30427,9 @@
}
},
"prettier": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz",
- "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
+ "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
"dev": true
},
"pretty-bytes": {
@@ -32716,9 +32716,9 @@
}
},
"stylelint-scss": {
- "version": "3.20.1",
- "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.20.1.tgz",
- "integrity": "sha512-OTd55O1TTAC5nGKkVmUDLpz53LlK39R3MImv1CfuvsK7/qugktqiZAeQLuuC4UBhzxCnsc7fp9u/gfRZwFAIkA==",
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.21.0.tgz",
+ "integrity": "sha512-CMI2wSHL+XVlNExpauy/+DbUcB/oUZLARDtMIXkpV/5yd8nthzylYd1cdHeDMJVBXeYHldsnebUX6MoV5zPW4A==",
"dev": true,
"requires": {
"lodash": "^4.17.15",
diff --git a/console/package.json b/console/package.json
index dbba66bf1e..c01316e45c 100644
--- a/console/package.json
+++ b/console/package.json
@@ -10,18 +10,18 @@
},
"private": true,
"dependencies": {
- "@angular/animations": "~12.2.7",
- "@angular/cdk": "~12.2.7",
- "@angular/common": "~12.2.7",
- "@angular/compiler": "~12.2.7",
- "@angular/core": "~12.2.7",
- "@angular/forms": "~12.2.7",
- "@angular/material": "^12.2.7",
- "@angular/material-moment-adapter": "^12.2.7",
- "@angular/platform-browser": "~12.2.7",
- "@angular/platform-browser-dynamic": "~12.2.7",
- "@angular/router": "~12.2.7",
- "@angular/service-worker": "~12.2.7",
+ "@angular/animations": "~12.2.8",
+ "@angular/cdk": "~12.2.8",
+ "@angular/common": "~12.2.8",
+ "@angular/compiler": "~12.2.8",
+ "@angular/core": "~12.2.8",
+ "@angular/forms": "~12.2.8",
+ "@angular/material": "^12.2.8",
+ "@angular/material-moment-adapter": "^12.2.8",
+ "@angular/platform-browser": "~12.2.8",
+ "@angular/platform-browser-dynamic": "~12.2.8",
+ "@angular/router": "~12.2.8",
+ "@angular/service-worker": "~12.2.8",
"@grpc/grpc-js": "^1.3.2",
"@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "^6.0.0",
@@ -33,7 +33,7 @@
"cors": "^2.8.5",
"file-saver": "^2.0.5",
"google-proto-files": "^2.4.0",
- "google-protobuf": "^3.17.2",
+ "google-protobuf": "^3.18.0",
"grpc-web": "^1.2.1",
"libphonenumber-js": "^1.9.34",
"moment": "^2.29.1",
@@ -48,13 +48,13 @@
"zone.js": "~0.11.4"
},
"devDependencies": {
- "@angular-devkit/build-angular": "~12.2.7",
- "@angular/cli": "~12.2.7",
- "@angular/compiler-cli": "~12.2.7",
- "@angular/language-service": "~12.2.7",
- "@types/jasmine": "~3.8.2",
+ "@angular-devkit/build-angular": "~12.2.8",
+ "@angular/cli": "~12.2.8",
+ "@angular/compiler-cli": "~12.2.8",
+ "@angular/language-service": "~12.2.8",
+ "@types/jasmine": "~3.9.1",
"@types/jasminewd2": "~2.0.10",
- "@types/node": "^16.7.6",
+ "@types/node": "^16.10.2",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.9.0",
"jasmine-spec-reporter": "~7.0.0",
@@ -62,12 +62,12 @@
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
- "karma-jasmine-html-reporter": "^1.5.0",
- "prettier": "^2.3.1",
+ "karma-jasmine-html-reporter": "^1.7.0",
+ "prettier": "^2.4.1",
"protractor": "~7.0.0",
"stylelint": "^13.10.0",
"stylelint-config-standard": "^22.0.0",
- "stylelint-scss": "^3.20.1",
+ "stylelint-scss": "^3.21.0",
"ts-node": "~10.2.1",
"tslint": "~6.1.3",
"typescript": "^4.2.4"
diff --git a/console/src/app/app-routing.module.ts b/console/src/app/app-routing.module.ts
index 0ed3ae8f64..98065c7290 100644
--- a/console/src/app/app-routing.module.ts
+++ b/console/src/app/app-routing.module.ts
@@ -26,7 +26,7 @@ const routes: Routes = [
.then(m => m.GrantedProjectsModule),
canActivate: [AuthGuard, RoleGuard],
data: {
- roles: ['project.read'],
+ roles: ['project.grant.read'],
},
},
{
diff --git a/console/src/app/app.component.ts b/console/src/app/app.component.ts
index bc6d37a535..0326ffdc5a 100644
--- a/console/src/app/app.component.ts
+++ b/console/src/app/app.component.ts
@@ -10,6 +10,7 @@ import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { LangChangeEvent, TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, from, Observable, of, Subject } from 'rxjs';
import { catchError, debounceTime, finalize, map, take, takeUntil } from 'rxjs/operators';
+
import { accountCard, adminLineAnimation, navAnimations, routeAnimations, toolbarAnimation } from './animations';
import { TextQueryMethod } from './proto/generated/zitadel/object_pb';
import { Org, OrgNameQuery, OrgQuery } from './proto/generated/zitadel/org_pb';
@@ -159,6 +160,16 @@ export class AppComponent implements OnDestroy {
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/counter.svg'),
);
+ this.matIconRegistry.addSvgIcon(
+ 'mdi_openid',
+ this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/openid.svg'),
+ );
+
+ this.matIconRegistry.addSvgIcon(
+ 'mdi_jwt',
+ this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/jwt.svg'),
+ );
+
this.matIconRegistry.addSvgIcon(
'mdi_symbol',
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/symbol.svg'),
diff --git a/console/src/app/modules/accounts-card/accounts-card.component.html b/console/src/app/modules/accounts-card/accounts-card.component.html
index f48d99343a..79cd242af7 100644
--- a/console/src/app/modules/accounts-card/accounts-card.component.html
+++ b/console/src/app/modules/accounts-card/accounts-card.component.html
@@ -1,42 +1,42 @@
-
-
+
+
-
{{user.human?.profile?.displayName ? user.human?.profile?.displayName : 'A'}}
-
{{user.human?.profile?.preferredLoginName}}
-
IAM USER
+
{{user.human?.profile?.displayName ? user.human?.profile?.displayName : 'A'}}
+
{{user?.preferredLoginName}}
+
IAM USER
-
{{'USER.EDITACCOUNT' | translate}}
-
-
{{'MENU.LOGOUT' | translate}}
+
{{'MENU.LOGOUT' | translate}}
\ No newline at end of file
diff --git a/console/src/app/modules/app-radio/app-type-radio/app-type-radio.component.html b/console/src/app/modules/app-radio/app-type-radio/app-type-radio.component.html
index 5999665d07..b78687189f 100644
--- a/console/src/app/modules/app-radio/app-type-radio/app-type-radio.component.html
+++ b/console/src/app/modules/app-radio/app-type-radio/app-type-radio.component.html
@@ -1,6 +1,6 @@
\ No newline at end of file
diff --git a/console/src/app/modules/idp-create/idp-create.component.scss b/console/src/app/modules/idp-create/idp-create.component.scss
index 97397c644b..0e04172e42 100644
--- a/console/src/app/modules/idp-create/idp-create.component.scss
+++ b/console/src/app/modules/idp-create/idp-create.component.scss
@@ -1,3 +1,7 @@
+.desc {
+ color: var(--grey);
+ font-size: 14px;
+}
.container {
padding: 4rem 4rem 2rem 4rem;
@@ -29,7 +33,6 @@
}
.auto-reg-info {
- margin: 0 .5rem 1rem .5rem;
display: block;
width: 100%;
@@ -38,7 +41,7 @@
}
}
-.content {
+.idp-content {
display: flex;
margin: 0 -.5rem;
flex-wrap: wrap;
@@ -51,7 +54,7 @@
}
.formfield {
- flex: 1 0 auto;
+ flex: 1;
margin: 0 .5rem;
@media only screen and (max-width: 450px) {
@@ -60,13 +63,17 @@
}
}
-.continue-button {
- margin-top: 3rem;
- display: block;
- padding: .5rem 4rem;
-
- @media only screen and (max-width: 450px) {
+.actions {
+ button[mat-stroked-button] {
+ float: left;
margin-top: 1rem;
- margin-bottom: 2rem;
+ border-radius: .5rem;
+ }
+
+ button[mat-raised-button] {
+ float: right;
+ margin-top: 1rem;
+ border-radius: .5rem;
+ min-width: 100px;
}
}
diff --git a/console/src/app/modules/idp-create/idp-create.component.ts b/console/src/app/modules/idp-create/idp-create.component.ts
index bffaa4d16b..07672ce961 100644
--- a/console/src/app/modules/idp-create/idp-create.component.ts
+++ b/console/src/app/modules/idp-create/idp-create.component.ts
@@ -6,14 +6,15 @@ import { MatChipInputEvent } from '@angular/material/chips';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
-import { AddOIDCIDPRequest } from 'src/app/proto/generated/zitadel/admin_pb';
+import { AddJWTIDPRequest, AddOIDCIDPRequest } from 'src/app/proto/generated/zitadel/admin_pb';
import { OIDCMappingField } from 'src/app/proto/generated/zitadel/idp_pb';
-import { AddOrgOIDCIDPRequest } from 'src/app/proto/generated/zitadel/management_pb';
+import { AddOrgJWTIDPRequest, AddOrgOIDCIDPRequest } from 'src/app/proto/generated/zitadel/management_pb';
import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
+import { JWT, OIDC, RadioItemIdpType } from './idptypes';
@Component({
selector: 'app-idp-create',
@@ -29,10 +30,23 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
private subscription?: Subscription;
public projectId: string = '';
- public formGroup!: FormGroup;
- public createSteps: number = 1;
+ public oidcFormGroup!: FormGroup;
+ public jwtFormGroup!: FormGroup;
+
+ public createSteps: number = 2;
public currentCreateStep: number = 1;
public loading: boolean = false;
+
+ public idpTypes: RadioItemIdpType[] = [
+ OIDC,
+ JWT,
+ ];
+
+ OIDC: any = OIDC;
+ JWT: any = JWT;
+
+ public idpType!: RadioItemIdpType;
+
constructor(
private router: Router,
private route: ActivatedRoute,
@@ -40,7 +54,7 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
private injector: Injector,
private _location: Location,
) {
- this.formGroup = new FormGroup({
+ this.oidcFormGroup = new FormGroup({
name: new FormControl('', [Validators.required]),
clientId: new FormControl('', [Validators.required]),
clientSecret: new FormControl('', [Validators.required]),
@@ -51,6 +65,16 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
autoRegister: new FormControl(false),
});
+ this.jwtFormGroup = new FormGroup({
+ jwtName: new FormControl('', [Validators.required]),
+ jwtHeaderName: new FormControl('', [Validators.required]),
+ jwtIssuer: new FormControl('', [Validators.required]),
+ jwtEndpoint: new FormControl('', [Validators.required]),
+ jwtKeysEndpoint: new FormControl('', [Validators.required]),
+ jwtStylingType: new FormControl(0),
+ jwtAutoRegister: new FormControl(false),
+ });
+
this.route.data.pipe(take(1)).subscribe(data => {
this.serviceType = data.serviceType;
switch (this.serviceType) {
@@ -82,7 +106,7 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
this.projectId = projectid;
}
- public addIdp(): void {
+ public addOIDCIdp(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new AddOrgOIDCIDPRequest();
@@ -133,6 +157,56 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
}
}
+ public addJWTIdp(): void {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ const req = new AddOrgJWTIDPRequest();
+
+ req.setName(this.jwtName?.value);
+ req.setHeaderName(this.jwtHeaderName?.value);
+ req.setIssuer(this.jwtIssuer?.value);
+ req.setJwtEndpoint(this.jwtEndpoint?.value);
+ req.setKeysEndpoint(this.jwtKeysEndpoint?.value);
+ req.setAutoRegister(this.jwtAutoRegister?.value);
+ req.setStylingType(this.jwtStylingType?.value);
+
+ this.loading = true;
+ (this.service as ManagementService).addOrgJWTIDP(req).then((idp) => {
+ setTimeout(() => {
+ this.loading = false;
+ this.router.navigate([
+ (this.serviceType === PolicyComponentServiceType.MGMT ? 'org' :
+ this.serviceType === PolicyComponentServiceType.ADMIN ? 'iam' : ''),
+ 'policy', 'login']);
+ }, 2000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ } else if (PolicyComponentServiceType.ADMIN) {
+ const req = new AddJWTIDPRequest();
+
+ req.setName(this.jwtName?.value);
+ req.setHeaderName(this.jwtHeaderName?.value);
+ req.setIssuer(this.jwtIssuer?.value);
+ req.setJwtEndpoint(this.jwtEndpoint?.value);
+ req.setKeysEndpoint(this.jwtKeysEndpoint?.value);
+ req.setAutoRegister(this.jwtAutoRegister?.value);
+ req.setStylingType(this.jwtStylingType?.value);
+
+ this.loading = true;
+ (this.service as AdminService).addJWTIDP(req).then((idp) => {
+ setTimeout(() => {
+ this.loading = false;
+ this.router.navigate([
+ (this.serviceType === PolicyComponentServiceType.MGMT ? 'org' :
+ this.serviceType === PolicyComponentServiceType.ADMIN ? 'iam' : ''),
+ 'policy', 'login']);
+ }, 2000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+ }
+
public close(): void {
this._location.back();
}
@@ -162,35 +236,62 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
}
public get name(): AbstractControl | null {
- return this.formGroup.get('name');
+ return this.oidcFormGroup.get('name');
}
public get clientId(): AbstractControl | null {
- return this.formGroup.get('clientId');
+ return this.oidcFormGroup.get('clientId');
}
public get clientSecret(): AbstractControl | null {
- return this.formGroup.get('clientSecret');
+ return this.oidcFormGroup.get('clientSecret');
}
public get issuer(): AbstractControl | null {
- return this.formGroup.get('issuer');
+ return this.oidcFormGroup.get('issuer');
}
public get scopesList(): AbstractControl | null {
- return this.formGroup.get('scopesList');
+ return this.oidcFormGroup.get('scopesList');
}
public get autoRegister(): AbstractControl | null {
- return this.formGroup.get('autoRegister');
+ return this.oidcFormGroup.get('autoRegister');
}
public get idpDisplayNameMapping(): AbstractControl | null {
- return this.formGroup.get('idpDisplayNameMapping');
+ return this.oidcFormGroup.get('idpDisplayNameMapping');
}
public get usernameMapping(): AbstractControl | null {
- return this.formGroup.get('usernameMapping');
+ return this.oidcFormGroup.get('usernameMapping');
}
+ public get jwtName(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtName');
+ }
+
+ public get jwtHeaderName(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtHeaderName');
+ }
+
+ public get jwtIssuer(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtIssuer');
+ }
+
+ public get jwtEndpoint(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtEndpoint');
+ }
+
+ public get jwtKeysEndpoint(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtKeysEndpoint');
+ }
+
+ public get jwtStylingType(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtStylingType');
+ }
+
+ public get jwtAutoRegister(): AbstractControl | null {
+ return this.jwtFormGroup.get('jwtAutoRegister');
+ }
}
diff --git a/console/src/app/modules/idp-create/idp-create.module.ts b/console/src/app/modules/idp-create/idp-create.module.ts
index e8ff5cdb82..315975a16e 100644
--- a/console/src/app/modules/idp-create/idp-create.module.ts
+++ b/console/src/app/modules/idp-create/idp-create.module.ts
@@ -14,9 +14,10 @@ import { InputModule } from 'src/app/modules/input/input.module';
import { InfoSectionModule } from '../info-section/info-section.module';
import { IdpCreateRoutingModule } from './idp-create-routing.module';
import { IdpCreateComponent } from './idp-create.component';
+import { IdpTypeRadioComponent } from './idp-type-radio/idp-type-radio.component';
@NgModule({
- declarations: [IdpCreateComponent],
+ declarations: [IdpCreateComponent, IdpTypeRadioComponent],
imports: [
IdpCreateRoutingModule,
CommonModule,
diff --git a/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.html b/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.html
new file mode 100644
index 0000000000..a6bd703eaa
--- /dev/null
+++ b/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.scss b/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.scss
new file mode 100644
index 0000000000..9d83d54601
--- /dev/null
+++ b/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.scss
@@ -0,0 +1,60 @@
+@use '~@angular/material' as mat;
+
+.idp-radio-button-wrapper {
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ margin: 0 -.5rem;
+ max-width: 500px;
+}
+
+@mixin idp-type-radio-theme($theme) {
+ $primary: map-get($theme, primary);
+ $primary-color: mat.get-color-from-palette($primary, 500);
+ $primary-color-light: mat.get-color-from-palette($primary, 300);
+ $primary-color-dark: mat.get-color-from-palette($primary, 700);
+ $primary-color-contrast: mat.get-color-from-palette($primary, default-contrast);
+ $is-dark-theme: map-get($theme, is-dark);
+ $back: map-get($theme, background);
+ $fg: map-get($theme, foreground);
+ $cardback: map-get($back, card);
+ $text: map-get($fg, text);
+
+ input[type="radio"].idp {
+ appearance: none;
+ opacity: 0;
+ display: none;
+ }
+
+ .cnsl-idp-type-radio-button {
+ margin: .5rem;
+ border-radius: .5rem;
+ display: flex;
+ flex-direction: column;
+ cursor: pointer;
+ position: relative;
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
+ background-color: $cardback;
+
+ .cnsl-idp-type-radio-header {
+ display: flex;
+ align-items: center;
+ padding: 0 1rem;
+
+ span {
+ margin: 1rem 0;
+ font-size: 1.1rem;
+ }
+
+ .fill-space {
+ flex: 1;
+ }
+ }
+ }
+
+ input.idp:checked + label {
+ border: 4px solid if($is-dark-theme, $primary-color-dark, $primary-color-light) !important;
+ background: $primary-color !important;
+ color: $primary-color-contrast !important;
+ }
+}
diff --git a/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.ts b/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.ts
new file mode 100644
index 0000000000..b876e37da6
--- /dev/null
+++ b/console/src/app/modules/idp-create/idp-type-radio/idp-type-radio.component.ts
@@ -0,0 +1,18 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+import { OIDC, RadioItemIdpType } from '../idptypes';
+
+@Component({
+ selector: 'cnsl-idp-type-radio',
+ templateUrl: './idp-type-radio.component.html',
+ styleUrls: ['./idp-type-radio.component.scss'],
+})
+export class IdpTypeRadioComponent {
+ @Input() selected: RadioItemIdpType = OIDC;
+ @Input() types!: RadioItemIdpType[];
+ @Output() selectedType: EventEmitter = new EventEmitter();
+
+ public emitChange(): void {
+ this.selectedType.emit(this.selected);
+ }
+}
diff --git a/console/src/app/modules/idp-create/idptypes.ts b/console/src/app/modules/idp-create/idptypes.ts
new file mode 100644
index 0000000000..2271cf8672
--- /dev/null
+++ b/console/src/app/modules/idp-create/idptypes.ts
@@ -0,0 +1,23 @@
+
+export enum IdpCreateType {
+ OIDC = 'OIDC',
+ JWT = 'JWT',
+}
+
+export interface RadioItemIdpType {
+ createType: IdpCreateType;
+ titleI18nKey: string;
+ mdi?: string;
+}
+
+export const OIDC = {
+ titleI18nKey: 'IDP.OIDC.TITLE',
+ mdi: 'mdi_openid',
+ createType: IdpCreateType.OIDC,
+};
+
+export const JWT = {
+ titleI18nKey: 'IDP.JWT.TITLE',
+ mdi: 'mdi_jwt',
+ createType: IdpCreateType.JWT,
+};
diff --git a/console/src/app/modules/idp-table/idp-table.component.html b/console/src/app/modules/idp-table/idp-table.component.html
index 7fb4e4341f..45fcaaf1a0 100644
--- a/console/src/app/modules/idp-table/idp-table.component.html
+++ b/console/src/app/modules/idp-table/idp-table.component.html
@@ -38,8 +38,14 @@
{{ 'IDP.NAME' | translate }}
- {{idp?.name}}
-
+
+
+ {{idp?.name}}
+
+
+
+
+
@@ -62,7 +68,7 @@
- {{ 'IDP.CREATIONDATE' | translate }}
+ {{ 'IDP.DATES' | translate }}
{{ 'IDP.CREATIONDATE' | translate }}:
@@ -76,7 +82,7 @@
- {{ 'IDP.TYPE' | translate }}
+ {{ 'IDP.OWNER' | translate }}
{{'IDP.OWNERTYPES.'+idp.owner | translate }}
@@ -88,7 +94,7 @@
[disabled]="serviceType==PolicyComponentServiceType.MGMT && idp?.providerType == IDPOwnerType.IDP_OWNER_TYPE_ORG"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.REMOVE' | translate}}"
(click)="removeIdp(idp)">
- remove_circle
+
diff --git a/console/src/app/modules/idp-table/idp-table.component.scss b/console/src/app/modules/idp-table/idp-table.component.scss
index 3673a1759c..ec7eb075a7 100644
--- a/console/src/app/modules/idp-table/idp-table.component.scss
+++ b/console/src/app/modules/idp-table/idp-table.component.scss
@@ -8,6 +8,8 @@
.table,
.paginator {
+ width: 100% !important;
+
td,
th {
padding: 0 1rem;
@@ -35,6 +37,15 @@ td {
object-fit: contain;
margin-top: .5rem;
}
+
+ .name-col {
+ display: flex;
+ flex-direction: column;
+
+ span {
+ margin-bottom: .5rem;
+ }
+ }
}
tr {
diff --git a/console/src/app/modules/idp-table/idp-table.component.ts b/console/src/app/modules/idp-table/idp-table.component.ts
index 62deba4286..7f044059e4 100644
--- a/console/src/app/modules/idp-table/idp-table.component.ts
+++ b/console/src/app/modules/idp-table/idp-table.component.ts
@@ -6,8 +6,8 @@ import { RouterLink } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { ListIDPsResponse } from 'src/app/proto/generated/zitadel/admin_pb';
-import { IDP, IDPOwnerType, IDPState, IDPStylingType } from 'src/app/proto/generated/zitadel/idp_pb';
-import { ListOrgIDPsResponse } from 'src/app/proto/generated/zitadel/management_pb';
+import { IDP, IDPOwnerType, IDPOwnerTypeQuery, IDPState, IDPStylingType } from 'src/app/proto/generated/zitadel/idp_pb';
+import { IDPQuery, ListOrgIDPsResponse } from 'src/app/proto/generated/zitadel/management_pb';
import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
@@ -17,187 +17,190 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
@Component({
- selector: 'app-idp-table',
- templateUrl: './idp-table.component.html',
- styleUrls: ['./idp-table.component.scss'],
+ selector: 'app-idp-table',
+ templateUrl: './idp-table.component.html',
+ styleUrls: ['./idp-table.component.scss'],
})
export class IdpTableComponent implements OnInit {
- @Input() public serviceType!: PolicyComponentServiceType;
- @Input() service!: AdminService | ManagementService;
- @Input() disabled: boolean = false;
- @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
- public dataSource: MatTableDataSource
- = new MatTableDataSource();
- public selection: SelectionModel
- = new SelectionModel(true, []);
- public idpResult!: ListIDPsResponse.AsObject | ListOrgIDPsResponse.AsObject;
- private loadingSubject: BehaviorSubject = new BehaviorSubject(false);
- public loading$: Observable = this.loadingSubject.asObservable();
- public PolicyComponentServiceType: any = PolicyComponentServiceType;
- public IDPOwnerType: any = IDPOwnerType;
- public IDPState: any = IDPState;
- public IDPSTYLINGTYPE: any = IDPStylingType;
- @Input() public displayedColumns: string[] = ['select', 'name', 'config', 'dates', 'state'];
+ @Input() public serviceType!: PolicyComponentServiceType;
+ @Input() service!: AdminService | ManagementService;
+ @Input() disabled: boolean = false;
+ @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
+ public dataSource: MatTableDataSource
+ = new MatTableDataSource();
+ public selection: SelectionModel
+ = new SelectionModel(true, []);
+ public idpResult!: ListIDPsResponse.AsObject | ListOrgIDPsResponse.AsObject;
+ private loadingSubject: BehaviorSubject = new BehaviorSubject(false);
+ public loading$: Observable = this.loadingSubject.asObservable();
+ public PolicyComponentServiceType: any = PolicyComponentServiceType;
+ public IDPOwnerType: any = IDPOwnerType;
+ public IDPState: any = IDPState;
+ public IDPSTYLINGTYPE: any = IDPStylingType;
+ @Input() public displayedColumns: string[] = ['select', 'name', 'dates', 'state'];
- @Output() public changedSelection: EventEmitter>
- = new EventEmitter();
+ @Output() public changedSelection: EventEmitter>
+ = new EventEmitter();
- constructor(public translate: TranslateService, private toast: ToastService, private dialog: MatDialog) {
- this.selection.changed.subscribe(() => {
- this.changedSelection.emit(this.selection.selected);
- });
+ constructor(public translate: TranslateService, private toast: ToastService, private dialog: MatDialog) {
+ this.selection.changed.subscribe(() => {
+ this.changedSelection.emit(this.selection.selected);
+ });
+ }
+
+ ngOnInit(): void {
+ this.getData(10, 0);
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ this.displayedColumns = ['select', 'name', 'dates', 'state', 'owner'];
}
- ngOnInit(): void {
- this.getData(10, 0);
+ if (!this.disabled) {
+ this.displayedColumns.push('actions');
+ }
+ }
+
+ public isAllSelected(): boolean {
+ const numSelected = this.selection.selected.length;
+ const numRows = this.dataSource.data.length;
+ return numSelected === numRows;
+ }
+
+ public masterToggle(): void {
+ this.isAllSelected() ?
+ this.selection.clear() :
+ this.dataSource.data.forEach(row => this.selection.select(row));
+ }
+
+
+ public changePage(event: PageEvent): void {
+ this.getData(event.pageSize, event.pageIndex * event.pageSize);
+ }
+
+ public deactivateSelectedIdps(): void {
+ const map: Promise[] = this.selection.selected.map(value => {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ return (this.service as ManagementService).deactivateOrgIDP(value.id);
+ } else {
+ return (this.service as AdminService).deactivateIDP(value.id);
+ }
+ });
+ Promise.all(map).then(() => {
+ this.selection.clear();
+ this.toast.showInfo('IDP.TOAST.SELECTEDDEACTIVATED', true);
+ this.refreshPage();
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+
+ public reactivateSelectedIdps(): void {
+ const map: Promise[] = this.selection.selected.map(value => {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ return (this.service as ManagementService).reactivateOrgIDP(value.id);
+ } else {
+ return (this.service as AdminService).reactivateIDP(value.id);
+ }
+ });
+ Promise.all(map).then(() => {
+ this.selection.clear();
+ this.toast.showInfo('IDP.TOAST.SELECTEDREACTIVATED', true);
+ this.refreshPage();
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+
+ public removeIdp(idp: IDP.AsObject): void {
+ const dialogRef = this.dialog.open(WarnDialogComponent, {
+ data: {
+ confirmKey: 'ACTIONS.DELETE',
+ cancelKey: 'ACTIONS.CANCEL',
+ titleKey: 'IDP.DELETE_TITLE',
+ descriptionKey: 'IDP.DELETE_DESCRIPTION',
+ },
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe(resp => {
+ if (resp) {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
- this.displayedColumns = ['select', 'name', 'config', 'dates', 'state', 'owner'];
- }
-
- if (!this.disabled) {
- this.displayedColumns.push('actions');
- }
- }
-
- public isAllSelected(): boolean {
- const numSelected = this.selection.selected.length;
- const numRows = this.dataSource.data.length;
- return numSelected === numRows;
- }
-
- public masterToggle(): void {
- this.isAllSelected() ?
- this.selection.clear() :
- this.dataSource.data.forEach(row => this.selection.select(row));
- }
-
-
- public changePage(event: PageEvent): void {
- this.getData(event.pageSize, event.pageIndex * event.pageSize);
- }
-
- public deactivateSelectedIdps(): void {
- const map: Promise[] = this.selection.selected.map(value => {
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- return (this.service as ManagementService).deactivateOrgIDP(value.id);
- } else {
- return (this.service as AdminService).deactivateIDP(value.id);
- }
- });
- Promise.all(map).then(() => {
- this.selection.clear();
- this.toast.showInfo('IDP.TOAST.SELECTEDDEACTIVATED', true);
- this.refreshPage();
- }).catch(error => {
+ (this.service as ManagementService).removeOrgIDP(idp.id).then(() => {
+ this.toast.showInfo('IDP.TOAST.DELETED', true);
+ setTimeout(() => {
+ this.refreshPage();
+ }, 1000);
+ }, error => {
this.toast.showError(error);
- });
- }
-
- public reactivateSelectedIdps(): void {
- const map: Promise[] = this.selection.selected.map(value => {
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- return (this.service as ManagementService).reactivateOrgIDP(value.id);
- } else {
- return (this.service as AdminService).reactivateIDP(value.id);
- }
- });
- Promise.all(map).then(() => {
- this.selection.clear();
- this.toast.showInfo('IDP.TOAST.SELECTEDREACTIVATED', true);
- this.refreshPage();
- }).catch(error => {
- this.toast.showError(error);
- });
- }
-
- public removeIdp(idp: IDP.AsObject): void {
- const dialogRef = this.dialog.open(WarnDialogComponent, {
- data: {
- confirmKey: 'ACTIONS.DELETE',
- cancelKey: 'ACTIONS.CANCEL',
- titleKey: 'IDP.DELETE_TITLE',
- descriptionKey: 'IDP.DELETE_DESCRIPTION',
- },
- width: '400px',
- });
-
- dialogRef.afterClosed().subscribe(resp => {
- if (resp) {
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- (this.service as ManagementService).removeOrgIDP(idp.id).then(() => {
- this.toast.showInfo('IDP.TOAST.DELETED', true);
- setTimeout(() => {
- this.refreshPage();
- }, 1000);
- }, error => {
- this.toast.showError(error);
- });
- } else {
- (this.service as AdminService).removeIDP(idp.id).then(() => {
- this.toast.showInfo('IDP.TOAST.DELETED', true);
- setTimeout(() => {
- this.refreshPage();
- }, 1000);
- }, error => {
- this.toast.showError(error);
- });
- }
- }
- });
- }
-
- private async getData(limit: number, offset: number): Promise {
- this.loadingSubject.next(true);
-
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- (this.service as ManagementService).listOrgIDPs(limit, offset).then(resp => {
- this.idpResult = resp;
- this.dataSource.data = resp.resultList;
- this.loadingSubject.next(false);
- }).catch(error => {
- this.toast.showError(error);
- this.loadingSubject.next(false);
- });
+ });
} else {
- (this.service as AdminService).listIDPs(limit, offset).then(resp => {
- this.idpResult = resp;
- this.dataSource.data = resp.resultList;
-
- this.loadingSubject.next(false);
- }).catch(error => {
- this.toast.showError(error);
- this.loadingSubject.next(false);
- });
+ (this.service as AdminService).removeIDP(idp.id).then(() => {
+ this.toast.showInfo('IDP.TOAST.DELETED', true);
+ setTimeout(() => {
+ this.refreshPage();
+ }, 1000);
+ }, error => {
+ this.toast.showError(error);
+ });
}
+ }
+ });
+ }
+ private async getData(limit: number, offset: number): Promise {
+ this.loadingSubject.next(true);
+
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ const query: IDPQuery = new IDPQuery();
+ const otQuery: IDPOwnerTypeQuery = new IDPOwnerTypeQuery();
+ otQuery.setOwnerType(IDPOwnerType.IDP_OWNER_TYPE_ORG);
+ query.setOwnerTypeQuery(otQuery);
+ (this.service as ManagementService).listOrgIDPs(limit, offset, [query]).then(resp => {
+ this.idpResult = resp;
+ this.dataSource.data = resp.resultList;
+ this.loadingSubject.next(false);
+ }).catch(error => {
+ this.toast.showError(error);
+ this.loadingSubject.next(false);
+ });
+ } else {
+ (this.service as AdminService).listIDPs(limit, offset).then(resp => {
+ this.idpResult = resp;
+ this.dataSource.data = resp.resultList;
+ this.loadingSubject.next(false);
+ }).catch(error => {
+ this.toast.showError(error);
+ this.loadingSubject.next(false);
+ });
}
- public refreshPage(): void {
- this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
- }
+ }
- public get createRouterLink(): RouterLink | any {
- if (this.service instanceof AdminService) {
- return ['/iam', 'idp', 'create'];
- } else if (this.service instanceof ManagementService) {
- return ['/org', 'idp', 'create'];
- }
- }
+ public refreshPage(): void {
+ this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
+ }
- public routerLinkForRow(row: IDP.AsObject): any {
- if (row.id) {
- switch (this.serviceType) {
- case PolicyComponentServiceType.MGMT:
- switch (row.owner) {
- case IDPOwnerType.IDP_OWNER_TYPE_SYSTEM:
- return ['/iam', 'idp', row.id];
- case IDPOwnerType.IDP_OWNER_TYPE_ORG:
- return ['/org', 'idp', row.id];
- }
- break;
- case PolicyComponentServiceType.ADMIN:
- return ['/iam', 'idp', row.id];
- }
- }
+ public get createRouterLink(): RouterLink | any {
+ if (this.service instanceof AdminService) {
+ return ['/iam', 'idp', 'create'];
+ } else if (this.service instanceof ManagementService) {
+ return ['/org', 'idp', 'create'];
}
+ }
+
+ public routerLinkForRow(row: IDP.AsObject): any {
+ if (row.id) {
+ switch (this.serviceType) {
+ case PolicyComponentServiceType.MGMT:
+ switch (row.owner) {
+ case IDPOwnerType.IDP_OWNER_TYPE_SYSTEM:
+ return ['/iam', 'idp', row.id];
+ case IDPOwnerType.IDP_OWNER_TYPE_ORG:
+ return ['/org', 'idp', row.id];
+ }
+ break;
+ case PolicyComponentServiceType.ADMIN:
+ return ['/iam', 'idp', row.id];
+ }
+ }
+ }
}
diff --git a/console/src/app/modules/idp/idp.component.html b/console/src/app/modules/idp/idp.component.html
index caaab96d86..27c7ea297e 100644
--- a/console/src/app/modules/idp/idp.component.html
+++ b/console/src/app/modules/idp/idp.component.html
@@ -1,13 +1,35 @@
-
+
+
+ {{'ACTIONS.ACTIONS' | translate}}
+ keyboard_arrow_down
+
+
+
+
+ {{'ACTIONS.DEACTIVATE' | translate}}
+
+
+ {{'ACTIONS.REACTIVATE' | translate}}
+
+
+ {{'IDP.DELETE_TITLE' | translate}}
+
+
+
+
-
+
+
+
-
-
- {{ 'IDP.ID' | translate }}
-
-
+
+
{{ 'IDP.NAME' | translate }}
@@ -40,77 +62,115 @@
-
- {{'IDP.DETAIL.OIDC.TITLE' | translate}}
- {{'IDP.DETAIL.OIDC.DESCRIPTION' | translate}}
+
+ {{'IDP.OIDC.TITLE' | translate}}
+ {{'IDP.OIDC.DESCRIPTION' | translate}}
-
-
-
\ No newline at end of file
diff --git a/console/src/app/modules/idp/idp.component.scss b/console/src/app/modules/idp/idp.component.scss
index c599d021e8..2f9aad3541 100644
--- a/console/src/app/modules/idp/idp.component.scss
+++ b/console/src/app/modules/idp/idp.component.scss
@@ -5,15 +5,20 @@
@media only screen and (max-width: 450px) {
padding: 4rem 1rem 2rem 1rem;
}
+
+ .idp-form {
+ border-top: 1px solid #ffffff20;
+ padding-top: 1rem;
+ }
}
-.content {
+.idp-content {
display: flex;
flex-direction: row;
margin: 0 -.5rem;
flex-wrap: wrap;
- .desc {
+ .idp-desc {
flex-basis: 100%;
margin: 0 .5rem;
margin-bottom: 1rem;
diff --git a/console/src/app/modules/idp/idp.component.ts b/console/src/app/modules/idp/idp.component.ts
index 17be806567..74301865d0 100644
--- a/console/src/app/modules/idp/idp.component.ts
+++ b/console/src/app/modules/idp/idp.component.ts
@@ -3,18 +3,28 @@ import { Location } from '@angular/common';
import { Component, Injector, OnDestroy, Type } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatChipInputEvent } from '@angular/material/chips';
-import { ActivatedRoute } from '@angular/router';
+import { MatDialog } from '@angular/material/dialog';
+import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { switchMap, take, takeUntil } from 'rxjs/operators';
-import { UpdateIDPOIDCConfigRequest, UpdateIDPRequest } from 'src/app/proto/generated/zitadel/admin_pb';
-import { IDPStylingType, OIDCMappingField } from 'src/app/proto/generated/zitadel/idp_pb';
-import { UpdateOrgIDPOIDCConfigRequest, UpdateOrgIDPRequest } from 'src/app/proto/generated/zitadel/management_pb';
+import {
+ UpdateIDPJWTConfigRequest,
+ UpdateIDPOIDCConfigRequest,
+ UpdateIDPRequest,
+} from 'src/app/proto/generated/zitadel/admin_pb';
+import { IDP, IDPState, IDPStylingType, OIDCMappingField } from 'src/app/proto/generated/zitadel/idp_pb';
+import {
+ UpdateOrgIDPJWTConfigRequest,
+ UpdateOrgIDPOIDCConfigRequest,
+ UpdateOrgIDPRequest,
+} from 'src/app/proto/generated/zitadel/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';
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
+import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
@Component({
selector: 'app-idp',
@@ -28,13 +38,18 @@ export class IdpComponent implements OnDestroy {
public showIdSecretSection: boolean = false;
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
private service!: ManagementService | AdminService;
+ public PolicyComponentServiceType: any = PolicyComponentServiceType;
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
+ public idp!: IDP.AsObject;
private destroy$: Subject = new Subject();
public projectId: string = '';
public idpForm!: FormGroup;
public oidcConfigForm!: FormGroup;
+ public jwtConfigForm!: FormGroup;
+
+ IDPState: any = IDPState;
public canWrite: Observable = this.authService.isAllowed([this.serviceType === PolicyComponentServiceType.ADMIN ?
'iam.idp.write' : this.serviceType === PolicyComponentServiceType.MGMT ?
@@ -44,8 +59,10 @@ export class IdpComponent implements OnDestroy {
private toast: ToastService,
private injector: Injector,
private route: ActivatedRoute,
+ private router: Router,
private _location: Location,
private authService: GrpcAuthService,
+ private dialog: MatDialog,
) {
this.idpForm = new FormGroup({
id: new FormControl({ disabled: true, value: '' }, [Validators.required]),
@@ -63,6 +80,13 @@ export class IdpComponent implements OnDestroy {
usernameMapping: new FormControl(0),
});
+ this.jwtConfigForm = new FormGroup({
+ jwtEndpoint: new FormControl('', [Validators.required]),
+ issuer: new FormControl('', [Validators.required]),
+ keysEndpoint: new FormControl('', [Validators.required]),
+ headerName: new FormControl('', [Validators.required]),
+ });
+
this.route.data.pipe(
takeUntil(this.destroy$),
switchMap(data => {
@@ -95,20 +119,26 @@ export class IdpComponent implements OnDestroy {
(this.service as ManagementService).getOrgIDPByID(id).then(resp => {
if (resp.idp) {
- const idpObject = resp.idp;
- this.idpForm.patchValue(idpObject);
- if (idpObject.oidcConfig) {
- this.oidcConfigForm.patchValue(idpObject.oidcConfig);
+ this.idp = resp.idp;
+ this.idpForm.patchValue(this.idp);
+ if (this.idp.oidcConfig) {
+ this.oidcConfigForm.patchValue(this.idp.oidcConfig);
+ } else if (this.idp.jwtConfig) {
+ this.jwtConfigForm.patchValue(this.idp.jwtConfig);
+ this.jwtIssuer?.setValue(this.idp.jwtConfig.issuer);
}
}
});
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
(this.service as AdminService).getIDPByID(id).then(resp => {
if (resp.idp) {
- const idpObject = resp.idp;
- this.idpForm.patchValue(idpObject);
- if (idpObject.oidcConfig) {
- this.oidcConfigForm.patchValue(idpObject.oidcConfig);
+ this.idp = resp.idp;
+ this.idpForm.patchValue(this.idp);
+ if (this.idp.oidcConfig) {
+ this.oidcConfigForm.patchValue(this.idp.oidcConfig);
+ } else if (this.idp.jwtConfig) {
+ this.jwtConfigForm.patchValue(this.idp.jwtConfig);
+ this.jwtIssuer?.setValue(this.idp.jwtConfig.issuer);
}
}
});
@@ -122,11 +152,9 @@ export class IdpComponent implements OnDestroy {
if (canWrite) {
this.idpForm.enable();
this.oidcConfigForm.enable();
- this.id?.disable();
} else {
this.idpForm.disable();
this.oidcConfigForm.disable();
- this.id?.disable();
}
});
}
@@ -136,32 +164,98 @@ export class IdpComponent implements OnDestroy {
this.destroy$.complete();
}
+ public deleteIdp(): void {
+ const dialogRef = this.dialog.open(WarnDialogComponent, {
+ data: {
+ confirmKey: 'ACTIONS.DELETE',
+ cancelKey: 'ACTIONS.CANCEL',
+ titleKey: 'IDP.DELETE_TITLE',
+ descriptionKey: 'IDP.DELETE_DESCRIPTION',
+ },
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe(resp => {
+ if (resp) {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ (this.service as ManagementService).removeOrgIDP(this.idp.id).then(() => {
+ this.toast.showInfo('IDP.TOAST.DELETED', true);
+ this.router.navigate(this.backroutes);
+ }).catch((error: any) => {
+ this.toast.showError(error);
+ });
+ } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
+ (this.service as AdminService).removeIDP(this.idp.id).then(() => {
+ this.toast.showInfo('IDP.TOAST.DELETED', true);
+ this.router.navigate(this.backroutes);
+ }).catch((error: any) => {
+ this.toast.showError(error);
+ });
+ }
+ }
+ });
+ }
+
+ public changeState(state: IDPState): void {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ if (state === IDPState.IDP_STATE_ACTIVE) {
+ (this.service as ManagementService).reactivateOrgIDP(this.idp.id).then(() => {
+ this.idp.state = state;
+ this.toast.showInfo('IDP.TOAST.REACTIVATED', true);
+ }).catch((error: any) => {
+ this.toast.showError(error);
+ });
+ } else if (state === IDPState.IDP_STATE_INACTIVE) {
+ (this.service as ManagementService).deactivateOrgIDP(this.idp.id).then(() => {
+ this.idp.state = state;
+ this.toast.showInfo('IDP.TOAST.DEACTIVATED', true);
+ }).catch((error: any) => {
+ this.toast.showError(error);
+ });
+ }
+ } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
+ if (state === IDPState.IDP_STATE_ACTIVE) {
+ (this.service as AdminService).reactivateIDP(this.idp.id).then(() => {
+ this.idp.state = state;
+ this.toast.showInfo('IDP.TOAST.REACTIVATED', true);
+ }).catch((error: any) => {
+ this.toast.showError(error);
+ });
+ } else if (state === IDPState.IDP_STATE_INACTIVE) {
+ (this.service as AdminService).deactivateIDP(this.idp.id).then(() => {
+ this.idp.state = state;
+ this.toast.showInfo('IDP.TOAST.DEACTIVATED', true);
+ }).catch((error: any) => {
+ this.toast.showError(error);
+ });
+ }
+ }
+ }
+
public updateIdp(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new UpdateOrgIDPRequest();
- req.setIdpId(this.id?.value);
+ req.setIdpId(this.idp.id);
req.setName(this.name?.value);
req.setStylingType(this.stylingType?.value);
req.setAutoRegister(this.autoRegister?.value);
(this.service as ManagementService).updateOrgIDP(req).then(() => {
this.toast.showInfo('IDP.TOAST.SAVED', true);
- // this.router.navigate(['idp', ]);
}).catch(error => {
this.toast.showError(error);
});
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
const req = new UpdateIDPRequest();
- req.setIdpId(this.id?.value);
+ req.setIdpId(this.idp.id);
req.setName(this.name?.value);
req.setStylingType(this.stylingType?.value);
req.setAutoRegister(this.autoRegister?.value);
(this.service as AdminService).updateIDP(req).then(() => {
this.toast.showInfo('IDP.TOAST.SAVED', true);
- // this.router.navigate(['idp', ]);
}).catch(error => {
this.toast.showError(error);
});
@@ -172,7 +266,7 @@ export class IdpComponent implements OnDestroy {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
const req = new UpdateOrgIDPOIDCConfigRequest();
- req.setIdpId(this.id?.value);
+ req.setIdpId(this.idp.id);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setIssuer(this.issuer?.value);
@@ -182,14 +276,13 @@ export class IdpComponent implements OnDestroy {
(this.service as ManagementService).updateOrgIDPOIDCConfig(req).then((oidcConfig) => {
this.toast.showInfo('IDP.TOAST.SAVED', true);
- // this.router.navigate(['idp', ]);
}).catch(error => {
this.toast.showError(error);
});
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
const req = new UpdateIDPOIDCConfigRequest();
- req.setIdpId(this.id?.value);
+ req.setIdpId(this.idp.id);
req.setClientId(this.clientId?.value);
req.setClientSecret(this.clientSecret?.value);
req.setIssuer(this.issuer?.value);
@@ -199,6 +292,39 @@ export class IdpComponent implements OnDestroy {
(this.service as AdminService).updateIDPOIDCConfig(req).then((oidcConfig) => {
this.toast.showInfo('IDP.TOAST.SAVED', true);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+ }
+
+ public updateJwtConfig(): void {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ const req = new UpdateOrgIDPJWTConfigRequest();
+
+ req.setIdpId(this.idp.id);
+ req.setIssuer(this.jwtIssuer?.value);
+ req.setHeaderName(this.headerName?.value);
+ req.setJwtEndpoint(this.jwtEndpoint?.value);
+ req.setKeysEndpoint(this.keyEndpoint?.value);
+
+ (this.service as ManagementService).updateOrgIDPJWTConfig(req).then((jwtConfig) => {
+ this.toast.showInfo('IDP.TOAST.SAVED', true);
+ // this.router.navigate(['idp', ]);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
+ const req = new UpdateIDPJWTConfigRequest();
+
+ req.setIdpId(this.idp.id);
+ req.setIssuer(this.jwtIssuer?.value);
+ req.setHeaderName(this.headerName?.value);
+ req.setJwtEndpoint(this.jwtEndpoint?.value);
+ req.setKeysEndpoint(this.keyEndpoint?.value);
+
+ (this.service as AdminService).updateIDPJWTConfig(req).then((jwtConfig) => {
+ this.toast.showInfo('IDP.TOAST.SAVED', true);
// this.router.navigate(['idp', ]);
}).catch(error => {
this.toast.showError(error);
@@ -243,10 +369,6 @@ export class IdpComponent implements OnDestroy {
}
}
- public get id(): AbstractControl | null {
- return this.idpForm.get('id');
- }
-
public get name(): AbstractControl | null {
return this.idpForm.get('name');
}
@@ -282,4 +404,21 @@ export class IdpComponent implements OnDestroy {
public get usernameMapping(): AbstractControl | null {
return this.oidcConfigForm.get('usernameMapping');
}
+
+
+ public get jwtIssuer(): AbstractControl | null {
+ return this.jwtConfigForm.get('issuer');
+ }
+
+ public get jwtEndpoint(): AbstractControl | null {
+ return this.jwtConfigForm.get('jwtEndpoint');
+ }
+
+ public get keyEndpoint(): AbstractControl | null {
+ return this.jwtConfigForm.get('keysEndpoint');
+ }
+
+ public get headerName(): AbstractControl | null {
+ return this.jwtConfigForm.get('headerName');
+ }
}
diff --git a/console/src/app/modules/idp/idp.module.ts b/console/src/app/modules/idp/idp.module.ts
index 0e51572aee..fde45c11e1 100644
--- a/console/src/app/modules/idp/idp.module.ts
+++ b/console/src/app/modules/idp/idp.module.ts
@@ -5,13 +5,16 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatIconModule } from '@angular/material/icon';
+import { MatMenuModule } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
import { InputModule } from 'src/app/modules/input/input.module';
+import { InfoRowModule } from '../info-row/info-row.module';
import { InfoSectionModule } from '../info-section/info-section.module';
+import { WarnDialogModule } from '../warn-dialog/warn-dialog.module';
import { IdpRoutingModule } from './idp-routing.module';
import { IdpComponent } from './idp.component';
@@ -24,12 +27,15 @@ import { IdpComponent } from './idp.component';
ReactiveFormsModule,
InputModule,
MatButtonModule,
+ WarnDialogModule,
MatIconModule,
InfoSectionModule,
+ MatMenuModule,
MatTooltipModule,
MatSelectModule,
TranslateModule,
MatCheckboxModule,
+ InfoRowModule,
MatChipsModule,
DetailLayoutModule,
],
diff --git a/console/src/app/modules/info-row/info-row.component.html b/console/src/app/modules/info-row/info-row.component.html
index 51ddb2f0c7..76c054d621 100644
--- a/console/src/app/modules/info-row/info-row.component.html
+++ b/console/src/app/modules/info-row/info-row.component.html
@@ -79,4 +79,34 @@
-
\ No newline at end of file
+
+
+
+
+
{{ 'IDP.ID' | translate }}
+
+
+ {{idp.id}}
+
+
+
+
+
+
{{ 'IDP.DETAIL.DATECREATED' | translate }}
+
{{idp?.details?.creationDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}
+
+
+
+
{{ 'IDP.DETAIL.DATECHANGED' | translate }}
+
{{idp?.details?.changeDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}
+
+
+
+
{{ 'IDP.STATE' | translate }}
+
{{'IDP.STATES.'+idp.state
+ | translate}}
+
+
diff --git a/console/src/app/modules/info-row/info-row.component.ts b/console/src/app/modules/info-row/info-row.component.ts
index 67e5051df4..474dc3afd3 100644
--- a/console/src/app/modules/info-row/info-row.component.ts
+++ b/console/src/app/modules/info-row/info-row.component.ts
@@ -1,6 +1,7 @@
import { HttpClient } from '@angular/common/http';
import { Component, Input, OnInit } from '@angular/core';
import { App, AppState } from 'src/app/proto/generated/zitadel/app_pb';
+import { IDP, IDPState } from 'src/app/proto/generated/zitadel/idp_pb';
import { User, UserState } from 'src/app/proto/generated/zitadel/user_pb';
@Component({
@@ -11,8 +12,11 @@ import { User, UserState } from 'src/app/proto/generated/zitadel/user_pb';
export class InfoRowComponent implements OnInit {
@Input() public user!: User.AsObject;
@Input() public app!: App.AsObject;
+ @Input() public idp!: IDP.AsObject;
+
public UserState: any = UserState;
public AppState: any = AppState;
+ public IDPState: any = IDPState;
public copied: string = '';
public environmentMap: { [key: string]: string; } = {};
diff --git a/console/src/app/modules/mfa-table/mfa-table.component.html b/console/src/app/modules/mfa-table/mfa-table.component.html
deleted file mode 100644
index f8ef5e1a3b..0000000000
--- a/console/src/app/modules/mfa-table/mfa-table.component.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
- remove_circle
-
- {{(componentType == LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.':
- LoginMethodComponentType.MultiFactor ? 'MFA.MULTIFACTORTYPES.': '')+mfa | translate}}
-
-
- add
-
-
\ No newline at end of file
diff --git a/console/src/app/modules/mfa-table/mfa-table.component.scss b/console/src/app/modules/mfa-table/mfa-table.component.scss
deleted file mode 100644
index dc481a67d7..0000000000
--- a/console/src/app/modules/mfa-table/mfa-table.component.scss
+++ /dev/null
@@ -1,62 +0,0 @@
-.t .sp_wrapper {
- display: block;
-}
-
-.mfa-list {
- display: flex;
- flex-wrap: wrap;
- margin: 0 -.5rem;
-
- .mfa {
- background-color: #6a506e;
- color: white;
- }
-
- .mfa,
- .new-mfa {
- border: 1px solid var(--grey);
- border-radius: .5rem;
- display: grid;
- align-items: center;
- justify-content: center;
- margin: .5rem;
- padding: 10px;
- position: relative;
- min-height: 70px;
- min-width: 150px;
-
- .rm {
- position: absolute;
- display: none;
- top: -2px;
- left: -2px;
- transform: translateX(-50%) translateY(-50%);
- cursor: pointer;
- color: var(--warn);
- transition: all .2s ease;
-
- &[disabled] {
- display: none;
- }
- }
-
- &:not(.disabled) {
- cursor: default;
-
- &:hover {
- .rm {
- display: block;
- }
- }
- }
-
- &.disabled {
- opacity: .5;
- cursor: not-allowed;
- }
- }
-
- .new-mfa:not(.disabled) {
- cursor: pointer;
- }
-}
diff --git a/console/src/app/modules/mfa-table/mfa-table.component.ts b/console/src/app/modules/mfa-table/mfa-table.component.ts
deleted file mode 100644
index 2b877b5976..0000000000
--- a/console/src/app/modules/mfa-table/mfa-table.component.ts
+++ /dev/null
@@ -1,224 +0,0 @@
-import { Component, Input, OnInit, ViewChild } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
-import { MatPaginator } from '@angular/material/paginator';
-import { TranslateService } from '@ngx-translate/core';
-import { BehaviorSubject, Observable } from 'rxjs';
-import {
- AddMultiFactorToLoginPolicyRequest as AdminAddMultiFactorToLoginPolicyRequest,
- AddSecondFactorToLoginPolicyRequest as AdminAddSecondFactorToLoginPolicyRequest,
- RemoveMultiFactorFromLoginPolicyRequest as AdminRemoveMultiFactorFromLoginPolicyRequest,
- RemoveSecondFactorFromLoginPolicyRequest as AdminRemoveSecondFactorFromLoginPolicyRequest,
-} from 'src/app/proto/generated/zitadel/admin_pb';
-import {
- AddMultiFactorToLoginPolicyRequest as MgmtAddMultiFactorToLoginPolicyRequest,
- AddSecondFactorToLoginPolicyRequest as MgmtAddSecondFactorToLoginPolicyRequest,
- RemoveMultiFactorFromLoginPolicyRequest as MgmtRemoveMultiFactorFromLoginPolicyRequest,
- RemoveSecondFactorFromLoginPolicyRequest as MgmtRemoveSecondFactorFromLoginPolicyRequest,
-} from 'src/app/proto/generated/zitadel/management_pb';
-import { MultiFactorType, SecondFactorType } from 'src/app/proto/generated/zitadel/policy_pb';
-import { AdminService } from 'src/app/services/admin.service';
-import { ManagementService } from 'src/app/services/mgmt.service';
-import { ToastService } from 'src/app/services/toast.service';
-
-import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
-import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
-import { DialogAddTypeComponent } from './dialog-add-type/dialog-add-type.component';
-
-export enum LoginMethodComponentType {
- MultiFactor = 1,
- SecondFactor = 2,
-}
-
-@Component({
- selector: 'app-mfa-table',
- templateUrl: './mfa-table.component.html',
- styleUrls: ['./mfa-table.component.scss'],
-})
-export class MfaTableComponent implements OnInit {
- public LoginMethodComponentType: any = LoginMethodComponentType;
- @Input() componentType!: LoginMethodComponentType;
- @Input() public serviceType!: PolicyComponentServiceType;
- @Input() service!: AdminService | ManagementService;
- @Input() disabled: boolean = false;
- @ViewChild(MatPaginator) public paginator!: MatPaginator;
- public mfas: Array = [];
-
- private loadingSubject: BehaviorSubject = new BehaviorSubject(false);
- public loading$: Observable = this.loadingSubject.asObservable();
-
- public PolicyComponentServiceType: any = PolicyComponentServiceType;
-
- constructor(public translate: TranslateService, private toast: ToastService, private dialog: MatDialog) { }
-
- public ngOnInit(): void {
- this.getData();
- }
-
- public removeMfa(type: MultiFactorType | SecondFactorType): void {
- const dialogRef = this.dialog.open(WarnDialogComponent, {
- data: {
- confirmKey: 'ACTIONS.DELETE',
- cancelKey: 'ACTIONS.CANCEL',
- titleKey: 'MFA.DELETE.TITLE',
- descriptionKey: 'MFA.DELETE.DESCRIPTION',
- },
- width: '400px',
- });
-
- dialogRef.afterClosed().subscribe(resp => {
- if (resp) {
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- const req = new MgmtRemoveMultiFactorFromLoginPolicyRequest();
- req.setType(type as MultiFactorType);
- (this.service as ManagementService).removeMultiFactorFromLoginPolicy(req).then(() => {
- this.toast.showInfo('MFA.TOAST.DELETED', true);
- this.refreshPageAfterTimout(2000);
- });
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- const req = new MgmtRemoveSecondFactorFromLoginPolicyRequest();
- req.setType(type as SecondFactorType);
- (this.service as ManagementService).removeSecondFactorFromLoginPolicy(req).then(() => {
- this.toast.showInfo('MFA.TOAST.DELETED', true);
- this.refreshPageAfterTimout(2000);
- });
- }
- } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- const req = new AdminRemoveMultiFactorFromLoginPolicyRequest();
- req.setType(type as MultiFactorType);
- (this.service as AdminService).removeMultiFactorFromLoginPolicy(req).then(() => {
- this.toast.showInfo('MFA.TOAST.DELETED', true);
- this.refreshPageAfterTimout(2000);
- });
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- const req = new AdminRemoveSecondFactorFromLoginPolicyRequest();
- req.setType(type as SecondFactorType);
- (this.service as AdminService).removeSecondFactorFromLoginPolicy(req).then(() => {
- this.toast.showInfo('MFA.TOAST.DELETED', true);
- this.refreshPageAfterTimout(2000);
- });
- }
- }
- }
- });
- }
-
- public addMfa(): void {
-
- let selection: any[] = [];
-
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- selection = [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION];
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- selection = [SecondFactorType.SECOND_FACTOR_TYPE_U2F, SecondFactorType.SECOND_FACTOR_TYPE_OTP];
- }
-
- this.mfas.forEach(mfa => {
- const index = selection.findIndex(sel => sel === mfa);
- if (index > -1) {
- selection.splice(index, 1);
- }
- });
-
- const dialogRef = this.dialog.open(DialogAddTypeComponent, {
- data: {
- title: 'MFA.CREATE.TITLE',
- desc: 'MFA.CREATE.DESCRIPTION',
- componentType: this.componentType,
- types: selection,
- },
- width: '400px',
- });
-
- dialogRef.afterClosed().subscribe((mfaType: MultiFactorType | SecondFactorType) => {
- if (mfaType) {
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- const req = new MgmtAddMultiFactorToLoginPolicyRequest();
- req.setType(mfaType as MultiFactorType);
- (this.service as ManagementService).addMultiFactorToLoginPolicy(req).then(() => {
- this.refreshPageAfterTimout(2000);
- }).catch(error => {
- this.toast.showError(error);
- });
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- const req = new MgmtAddSecondFactorToLoginPolicyRequest();
- req.setType(mfaType as SecondFactorType);
- (this.service as ManagementService).addSecondFactorToLoginPolicy(req).then(() => {
- this.refreshPageAfterTimout(2000);
- }).catch(error => {
- this.toast.showError(error);
- });
- }
- } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- const req = new AdminAddMultiFactorToLoginPolicyRequest();
- req.setType(mfaType as MultiFactorType);
- (this.service as AdminService).addMultiFactorToLoginPolicy(req).then(() => {
- this.refreshPageAfterTimout(2000);
- }).catch(error => {
- this.toast.showError(error);
- });
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- const req = new AdminAddSecondFactorToLoginPolicyRequest();
- req.setType(mfaType as SecondFactorType);
- (this.service as AdminService).addSecondFactorToLoginPolicy(req).then(() => {
- this.refreshPageAfterTimout(2000);
- }).catch(error => {
- this.toast.showError(error);
- });
- }
- }
- }
- });
- }
-
- private async getData(): Promise {
- this.loadingSubject.next(true);
-
- if (this.serviceType === PolicyComponentServiceType.MGMT) {
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- (this.service as ManagementService).listLoginPolicyMultiFactors().then(resp => {
- this.mfas = resp.resultList;
- this.loadingSubject.next(false);
- }).catch(error => {
- this.toast.showError(error);
- this.loadingSubject.next(false);
- });
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- (this.service as ManagementService).listLoginPolicySecondFactors().then(resp => {
- this.mfas = resp.resultList;
- this.loadingSubject.next(false);
- }).catch(error => {
- this.toast.showError(error);
- this.loadingSubject.next(false);
- });
- }
- } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
- if (this.componentType === LoginMethodComponentType.MultiFactor) {
- (this.service as AdminService).listLoginPolicyMultiFactors().then(resp => {
- this.mfas = resp.resultList;
- this.loadingSubject.next(false);
- }).catch(error => {
- this.toast.showError(error);
- this.loadingSubject.next(false);
- });
- } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
- (this.service as AdminService).listLoginPolicySecondFactors().then(resp => {
- this.mfas = resp.resultList;
- this.loadingSubject.next(false);
- }).catch(error => {
- this.toast.showError(error);
- this.loadingSubject.next(false);
- });
- }
- }
- }
-
- public refreshPageAfterTimout(to: number): void {
- setTimeout(() => {
- this.getData();
- }, to);
- }
-}
diff --git a/console/src/app/modules/mfa-table/mfa-table.module.ts b/console/src/app/modules/mfa-table/mfa-table.module.ts
deleted file mode 100644
index 7c4b890b4a..0000000000
--- a/console/src/app/modules/mfa-table/mfa-table.module.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { MatButtonModule } from '@angular/material/button';
-import { MatCheckboxModule } from '@angular/material/checkbox';
-import { MatIconModule } from '@angular/material/icon';
-import { MatPaginatorModule } from '@angular/material/paginator';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatTableModule } from '@angular/material/table';
-import { MatTooltipModule } from '@angular/material/tooltip';
-import { RouterModule } from '@angular/router';
-import { TranslateModule } from '@ngx-translate/core';
-import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
-import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
-import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
-import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
-import { TruncatePipeModule } from 'src/app/pipes/truncate-pipe/truncate-pipe.module';
-
-import { MfaTableComponent } from './mfa-table.component';
-import { DialogAddTypeComponent } from './dialog-add-type/dialog-add-type.component';
-import { InputModule } from '../input/input.module';
-import { MatSelectModule } from '@angular/material/select';
-import { MatRippleModule } from '@angular/material/core';
-
-@NgModule({
- declarations: [MfaTableComponent, DialogAddTypeComponent],
- imports: [
- CommonModule,
- FormsModule,
- ReactiveFormsModule,
- MatButtonModule,
- MatIconModule,
- InputModule,
- MatSelectModule,
- MatTooltipModule,
- TranslateModule,
- TimestampToDatePipeModule,
- HasRoleModule,
- MatProgressSpinnerModule,
- MatRippleModule,
- ],
- exports: [
- MfaTableComponent,
- ],
-})
-export class MfaTableModule { }
diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.module.ts b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.module.ts
deleted file mode 100644
index 8c125514c5..0000000000
--- a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.module.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { FormsModule } from '@angular/forms';
-import { MatButtonModule } from '@angular/material/button';
-import { MatDialogModule } from '@angular/material/dialog';
-import { MatSelectModule } from '@angular/material/select';
-import { TranslateModule } from '@ngx-translate/core';
-import { InputModule } from 'src/app/modules/input/input.module';
-
-import { AddIdpDialogComponent } from './add-idp-dialog.component';
-
-@NgModule({
- declarations: [AddIdpDialogComponent],
- imports: [
- CommonModule,
- MatDialogModule,
- MatButtonModule,
- TranslateModule,
- InputModule,
- MatSelectModule,
- FormsModule,
- ],
-})
-export class AddIdpDialogModule { }
diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html b/console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.html
similarity index 95%
rename from console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html
rename to console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.html
index 03cfaf280b..4d7b9f6429 100644
--- a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html
+++ b/console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.html
@@ -13,8 +13,6 @@
- {{'LOGINPOLICY.ADDIDP.SELECTIDPS' | translate}}
-
{{ 'LOGINPOLICY.ADDIDP.SELECTIDPS' | translate }}
diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.scss b/console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.scss
similarity index 100%
rename from console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.scss
rename to console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.scss
diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.spec.ts b/console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.spec.ts
similarity index 100%
rename from console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.spec.ts
rename to console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.spec.ts
diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts b/console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.ts
similarity index 97%
rename from console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts
rename to console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.ts
index 7b7843e8c8..65a82691e2 100644
--- a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts
+++ b/console/src/app/modules/policies/login-policy/login-policy-idps/add-idp-dialog/add-idp-dialog.component.ts
@@ -5,7 +5,7 @@ import { IDPQuery } from 'src/app/proto/generated/zitadel/management_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
-import { PolicyComponentServiceType } from '../../policy-component-types.enum';
+import { PolicyComponentServiceType } from '../../../policy-component-types.enum';
@Component({
selector: 'app-add-idp-dialog',
diff --git a/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.html b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.html
new file mode 100644
index 0000000000..c98839cd3a
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.html
@@ -0,0 +1,21 @@
+
+
+
+
+ {{idp.idpName}}
+ {{ 'IDP.TYPES.'+idp.idpType | translate }}
+
+
+
+
+ remove_circle
+
+
+
+ {{'IDP.ADD' | translate}}
+ add
+
+
\ No newline at end of file
diff --git a/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.scss b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.scss
new file mode 100644
index 0000000000..6bd2af4c1b
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.scss
@@ -0,0 +1,63 @@
+.idps {
+ display: flex;
+ flex-direction: column;
+
+ .idp {
+ display: flex;
+ align-items: center;
+ padding: 10px;
+ border-radius: .5rem;
+ position: relative;
+ margin-bottom: .5rem;
+ min-height: 40px;
+
+ img {
+ height: 30px;
+ width: 30px;
+ margin: .5rem;
+ border-radius: .5rem;
+ object-fit: contain;
+ }
+
+ div {
+ display: block;
+ margin-left: .5rem;
+
+ * {
+ display: block;
+ }
+ }
+
+ .meta-info {
+ font-size: 14px;
+ color: var(--grey);
+ }
+
+ .fill-space {
+ flex: 1;
+ }
+
+ .rm {
+ display: none;
+ transition: all .2s ease;
+ cursor: pointer;
+ }
+
+ &:hover {
+ .rm {
+ display: block;
+ }
+ }
+ }
+
+ .new-idp {
+ display: flex;
+ align-items: center;
+ align-self: flex-end;
+ margin-top: .5rem;
+
+ .icon {
+ margin-left: .5rem;
+ }
+ }
+}
diff --git a/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.spec.ts b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.spec.ts
new file mode 100644
index 0000000000..694a1cd15e
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginPolicyIdpsComponent } from './login-policy-idps.component';
+
+describe('LoginPolicyIdpsComponent', () => {
+ let component: LoginPolicyIdpsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [LoginPolicyIdpsComponent],
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LoginPolicyIdpsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.ts b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.ts
new file mode 100644
index 0000000000..312b87309b
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/login-policy-idps/login-policy-idps.component.ts
@@ -0,0 +1,108 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { IDP, IDPLoginPolicyLink, IDPOwnerType, IDPStylingType } from 'src/app/proto/generated/zitadel/idp_pb';
+import { AdminService } from 'src/app/services/admin.service';
+import { ManagementService } from 'src/app/services/mgmt.service';
+import { ToastService } from 'src/app/services/toast.service';
+
+import { PolicyComponentServiceType } from '../../policy-component-types.enum';
+import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
+
+@Component({
+ selector: 'cnsl-login-policy-idps',
+ templateUrl: './login-policy-idps.component.html',
+ styleUrls: ['./login-policy-idps.component.scss'],
+})
+export class LoginPolicyIdpsComponent implements OnInit {
+ @Input() public disabled: boolean = true;
+ @Input() public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
+ @Input() public service!: ManagementService | AdminService;
+ public loading: boolean = false;
+
+ public idps: IDPLoginPolicyLink.AsObject[] = [];
+
+ public IDPStylingType: any = IDPStylingType;
+
+ constructor(
+ private toast: ToastService,
+ private dialog: MatDialog,
+ ) { }
+
+ ngOnInit(): void {
+ this.getIdps().then(resp => {
+ this.idps = resp;
+ console.log(this.idps);
+ });
+ }
+
+ private async getIdps(): Promise {
+ switch (this.serviceType) {
+ case PolicyComponentServiceType.MGMT:
+ return (this.service as ManagementService).listLoginPolicyIDPs()
+ .then((resp) => {
+ return resp.resultList;
+ });
+ case PolicyComponentServiceType.ADMIN:
+ return (this.service as AdminService).listLoginPolicyIDPs()
+ .then((providers) => {
+ return providers.resultList;
+ });
+ }
+ }
+
+ private addIdp(idp: IDP.AsObject | IDP.AsObject, ownerType: IDPOwnerType): Promise {
+ switch (this.serviceType) {
+ case PolicyComponentServiceType.MGMT:
+ return (this.service as ManagementService).addIDPToLoginPolicy(idp.id, ownerType);
+ case PolicyComponentServiceType.ADMIN:
+ return (this.service as AdminService).addIDPToLoginPolicy(idp.id);
+ }
+ }
+
+ public openDialog(): void {
+ const dialogRef = this.dialog.open(AddIdpDialogComponent, {
+ data: {
+ serviceType: this.serviceType,
+ },
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe(resp => {
+ if (resp && resp.idp && resp.type) {
+ this.addIdp(resp.idp, resp.type).then(() => {
+ this.loading = true;
+ setTimeout(() => {
+ this.getIdps();
+ }, 1000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+ });
+ }
+
+ public removeIdp(idp: IDPLoginPolicyLink.AsObject): void {
+ switch (this.serviceType) {
+ case PolicyComponentServiceType.MGMT:
+ (this.service as ManagementService).removeIDPFromLoginPolicy(idp.idpId).then(() => {
+ const index = this.idps.findIndex(temp => temp === idp);
+ if (index > -1) {
+ this.idps.splice(index, 1);
+ }
+ }, error => {
+ this.toast.showError(error);
+ });
+ break;
+ case PolicyComponentServiceType.ADMIN:
+ (this.service as AdminService).removeIDPFromLoginPolicy(idp.idpId).then(() => {
+ const index = this.idps.findIndex(temp => temp === idp);
+ if (index > -1) {
+ this.idps.splice(index, 1);
+ }
+ }, error => {
+ this.toast.showError(error);
+ });
+ break;
+ }
+ }
+}
diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.html b/console/src/app/modules/policies/login-policy/login-policy.component.html
index b83f9e6e6b..4ec6f8b847 100644
--- a/console/src/app/modules/policies/login-policy/login-policy.component.html
+++ b/console/src/app/modules/policies/login-policy/login-policy.component.html
@@ -6,131 +6,35 @@
+
-
-
- {{'POLICY.RESET' | translate}}
-
-
+
+
+ {{'POLICY.RESET' | translate}}
+
+
-
-
- {{'POLICY.CREATECUSTOM' | translate}}
-
-
-
+
+
+ {{'POLICY.CREATECUSTOM' | translate}}
+
+
+
-
-
-
- {{'POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}}
-
-
-
-
+
-
-
- {{'POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}
-
-
-
-
-
- {{'POLICY.DATA.ALLOWREGISTER' | translate}}
-
-
-
-
-
-
-
-
- {{'POLICY.DATA.ALLOWREGISTER_DESC' | translate}}
-
-
-
-
-
- {{'POLICY.DATA.ALLOWEXTERNALIDP' | translate}}
-
-
-
-
-
-
-
-
- {{'POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}}
-
-
-
-
-
- {{'POLICY.DATA.FORCEMFA' | translate}}
-
-
-
-
-
-
-
-
- {{'POLICY.DATA.FORCEMFA_DESC' | translate}}
-
-
-
-
-
- {{'POLICY.DATA.HIDEPASSWORDRESET' | translate}}
-
-
-
-
+
+
+
+
+
-
-
- {{'POLICY.DATA.HIDEPASSWORDRESET_DESC' | translate}}
-
-
-
-
-
-
- {{'LOGINPOLICY.PASSWORDLESS' | translate}}
-
-
- {{'LOGINPOLICY.PASSWORDLESSTYPE.'+pt | translate}}
-
-
-
-
-
-
-
-
-
-
- {{ 'ACTIONS.SAVE' | translate }}
-
-
-
-
-
- {{ 'MFA.LIST.MULTIFACTORDESCRIPTION' | translate }}
-
+
@@ -139,62 +43,134 @@
[componentType]="LoginMethodComponentType.MultiFactor"
[disabled]="(([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) == false) || (serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false)">
+
-
- {{ 'MFA.LIST.SECONDFACTORDESCRIPTION' | translate }}
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
+
+ {{'POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}}
+
-
+
+
+
-
-
-
+
+
+ {{'POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}
+
+
+
+
+
+ {{'POLICY.DATA.ALLOWREGISTER' | translate}}
+
-
-
-
-
- remove_circle
-
-
-
-
- {{idp.idpName}}
- {{ 'IDP.TYPE' | translate }}: {{ 'IDP.TYPES.'+idp.idpType |
- translate
- }}
- {{ 'IDP.ID' | translate }}: {{idp.idpId}}
-
-
+
+
+
+
+
+
+ {{'POLICY.DATA.ALLOWREGISTER_DESC' | translate}}
+
+
+
+
+
+ {{'POLICY.DATA.ALLOWEXTERNALIDP' | translate}}
+
+
+
+
+
+
+
+
+ {{'POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}}
+
+
+
+
+
+ {{'POLICY.DATA.FORCEMFA' | translate}}
+
+
+
+
+
+
+
+
+ {{'POLICY.DATA.FORCEMFA_DESC' | translate}}
+
+
+
+
+
+ {{'POLICY.DATA.HIDEPASSWORDRESET' | translate}}
+
+
+
+
+
+
+
+
+ {{'POLICY.DATA.HIDEPASSWORDRESET_DESC' | translate}}
+
+
-
- add
-
-
+
+
+
+ {{'LOGINPOLICY.PASSWORDLESS' | translate}}
+
+
+ {{'LOGINPOLICY.PASSWORDLESSTYPE.'+pt | translate}}
+
+
+
+
+
+
+
+
+
+
+
+
{{ 'ACTIONS.SAVE' | translate }}
+
+
-
+
-
-
-
+
+
+
diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.scss b/console/src/app/modules/policies/login-policy/login-policy.component.scss
index 3105e4bf1a..c917b2bbc0 100644
--- a/console/src/app/modules/policies/login-policy/login-policy.component.scss
+++ b/console/src/app/modules/policies/login-policy/login-policy.component.scss
@@ -37,95 +37,6 @@
font-size: 14px;
}
-.idps {
- display: flex;
- margin: 0 -.5rem;
-
- .idp {
- background-color: #506e6e;
- color: white;
-
- .line {
- display: flex;
- align-items: center;
-
- img {
- height: 30px;
- width: 30px;
- margin-right: 1rem;
- border-radius: .5rem;
- object-fit: contain;
- }
-
- div {
- flex: 1;
- display: block;
-
- * {
- display: block;
- }
- }
- }
- }
-
- .idp,
- .new-idp {
- display: grid;
- align-items: center;
- justify-content: center;
- margin: .5rem;
- padding: 10px;
- border: 1px solid var(--grey);
- border-radius: .5rem;
- position: relative;
- min-height: 70px;
- min-width: 150px;
-
- .name {
- font-weight: 700;
- }
-
- span {
- padding: 2px;
- }
-
- .rm {
- color: var(--warn);
- position: absolute;
- display: none;
- top: -2px;
- transition: all .2s ease;
- left: -2px;
- transform: translateX(-50%) translateY(-50%);
- cursor: pointer;
-
- &[disabled] {
- display: none;
- }
- }
-
- &:not(.disabled) {
- cursor: default;
-
- &:hover {
- .rm {
- display: block;
- }
- }
- }
-
- img {
- height: 100%;
- width: 100%;
- object-fit: scale-down;
- }
- }
-
- .new-idp:not(.disabled) {
- cursor: pointer;
- }
-}
-
.divider {
width: 100%;
height: 1px;
diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.ts b/console/src/app/modules/policies/login-policy/login-policy.component.ts
index b054af484c..69d2c8e91f 100644
--- a/console/src/app/modules/policies/login-policy/login-policy.component.ts
+++ b/console/src/app/modules/policies/login-policy/login-policy.component.ts
@@ -1,15 +1,12 @@
import { Component, Injector, OnDestroy, Type } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { switchMap } from 'rxjs/operators';
-import { LoginMethodComponentType } from 'src/app/modules/mfa-table/mfa-table.component';
import {
GetLoginPolicyResponse as AdminGetLoginPolicyResponse,
UpdateLoginPolicyRequest,
UpdateLoginPolicyResponse,
} from 'src/app/proto/generated/zitadel/admin_pb';
-import { IDP, IDPLoginPolicyLink, IDPOwnerType, IDPStylingType } from 'src/app/proto/generated/zitadel/idp_pb';
import {
AddCustomLoginPolicyRequest,
GetLoginPolicyResponse as MgmtGetLoginPolicyResponse,
@@ -21,7 +18,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { GridPolicy, LOGIN_POLICY } from '../../policy-grid/policies';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
-import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
+import { LoginMethodComponentType } from './mfa-table/mfa-table.component';
@Component({
selector: 'app-login-policy',
@@ -37,17 +34,14 @@ export class LoginPolicyComponent implements OnDestroy {
public service!: ManagementService | AdminService;
public PolicyComponentServiceType: any = PolicyComponentServiceType;
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
- public idps: IDPLoginPolicyLink.AsObject[] = [];
public loading: boolean = false;
public disabled: boolean = true;
- public IDPStylingType: any = IDPStylingType;
public currentPolicy: GridPolicy = LOGIN_POLICY;
constructor(
private route: ActivatedRoute,
private toast: ToastService,
- private dialog: MatDialog,
private injector: Injector,
) {
this.sub = this.route.data.pipe(switchMap(data => {
@@ -83,9 +77,7 @@ export class LoginPolicyComponent implements OnDestroy {
this.disabled = this.isDefault;
}
});
- this.getIdps().then(resp => {
- this.idps = resp;
- });
+
}
public ngOnDestroy(): void {
@@ -102,21 +94,6 @@ export class LoginPolicyComponent implements OnDestroy {
}
}
- private async getIdps(): Promise
{
- switch (this.serviceType) {
- case PolicyComponentServiceType.MGMT:
- return (this.service as ManagementService).listLoginPolicyIDPs()
- .then((resp) => {
- return resp.resultList;
- });
- case PolicyComponentServiceType.ADMIN:
- return (this.service as AdminService).listLoginPolicyIDPs()
- .then((providers) => {
- return providers.resultList;
- });
- }
- }
-
private async updateData():
Promise {
switch (this.serviceType) {
@@ -172,62 +149,6 @@ export class LoginPolicyComponent implements OnDestroy {
}
}
- public openDialog(): void {
- const dialogRef = this.dialog.open(AddIdpDialogComponent, {
- data: {
- serviceType: this.serviceType,
- },
- width: '400px',
- });
-
- dialogRef.afterClosed().subscribe(resp => {
- if (resp && resp.idp && resp.type) {
- this.addIdp(resp.idp, resp.type).then(() => {
- this.loading = true;
- setTimeout(() => {
- this.fetchData();
- }, 2000);
- }).catch(error => {
- this.toast.showError(error);
- });
- }
- });
- }
-
- private addIdp(idp: IDP.AsObject | IDP.AsObject, ownerType: IDPOwnerType): Promise {
- switch (this.serviceType) {
- case PolicyComponentServiceType.MGMT:
- return (this.service as ManagementService).addIDPToLoginPolicy(idp.id, ownerType);
- case PolicyComponentServiceType.ADMIN:
- return (this.service as AdminService).addIDPToLoginPolicy(idp.id);
- }
- }
-
- public removeIdp(idp: IDPLoginPolicyLink.AsObject): void {
- switch (this.serviceType) {
- case PolicyComponentServiceType.MGMT:
- (this.service as ManagementService).removeIDPFromLoginPolicy(idp.idpId).then(() => {
- const index = this.idps.findIndex(temp => temp === idp);
- if (index > -1) {
- this.idps.splice(index, 1);
- }
- }, error => {
- this.toast.showError(error);
- });
- break;
- case PolicyComponentServiceType.ADMIN:
- (this.service as AdminService).removeIDPFromLoginPolicy(idp.idpId).then(() => {
- const index = this.idps.findIndex(temp => temp === idp);
- if (index > -1) {
- this.idps.splice(index, 1);
- }
- }, error => {
- this.toast.showError(error);
- });
- break;
- }
- }
-
public get isDefault(): boolean {
if (this.loginData && this.serviceType === PolicyComponentServiceType.MGMT) {
return (this.loginData as LoginPolicy.AsObject).isDefault;
diff --git a/console/src/app/modules/policies/login-policy/login-policy.module.ts b/console/src/app/modules/policies/login-policy/login-policy.module.ts
index 206820d454..f0d9a3a489 100644
--- a/console/src/app/modules/policies/login-policy/login-policy.module.ts
+++ b/console/src/app/modules/policies/login-policy/login-policy.module.ts
@@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatRippleModule } from '@angular/material/core';
+import { MatDialogModule } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
@@ -14,18 +15,26 @@ import { CardModule } from 'src/app/modules/card/card.module';
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
import { IdpTableModule } from 'src/app/modules/idp-table/idp-table.module';
import { InputModule } from 'src/app/modules/input/input.module';
-import { MfaTableModule } from 'src/app/modules/mfa-table/mfa-table.module';
import { HasFeaturePipeModule } from 'src/app/pipes/has-feature-pipe/has-feature-pipe.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { InfoSectionModule } from '../../info-section/info-section.module';
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
-import { AddIdpDialogModule } from './add-idp-dialog/add-idp-dialog.module';
+import { AddIdpDialogComponent } from './login-policy-idps/add-idp-dialog/add-idp-dialog.component';
+import { LoginPolicyIdpsComponent } from './login-policy-idps/login-policy-idps.component';
import { LoginPolicyRoutingModule } from './login-policy-routing.module';
import { LoginPolicyComponent } from './login-policy.component';
+import { DialogAddTypeComponent } from './mfa-table/dialog-add-type/dialog-add-type.component';
+import { MfaTableComponent } from './mfa-table/mfa-table.component';
@NgModule({
- declarations: [LoginPolicyComponent],
+ declarations: [
+ LoginPolicyComponent,
+ LoginPolicyIdpsComponent,
+ MfaTableComponent,
+ DialogAddTypeComponent,
+ AddIdpDialogComponent,
+ ],
imports: [
LoginPolicyRoutingModule,
CommonModule,
@@ -33,21 +42,20 @@ import { LoginPolicyComponent } from './login-policy.component';
FormsModule,
CardModule,
InputModule,
+ MatIconModule,
MatButtonModule,
HasFeaturePipeModule,
MatSlideToggleModule,
- MatIconModule,
HasRoleModule,
+ MatDialogModule,
HasRolePipeModule,
MatTooltipModule,
- TranslateModule,
DetailLayoutModule,
- AddIdpDialogModule,
IdpTableModule,
- MfaTableModule,
MatProgressSpinnerModule,
MatSelectModule,
MatRippleModule,
+ TranslateModule,
PolicyGridModule,
],
})
diff --git a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.html b/console/src/app/modules/policies/login-policy/mfa-table/dialog-add-type/dialog-add-type.component.html
similarity index 100%
rename from console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.html
rename to console/src/app/modules/policies/login-policy/mfa-table/dialog-add-type/dialog-add-type.component.html
diff --git a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.scss b/console/src/app/modules/policies/login-policy/mfa-table/dialog-add-type/dialog-add-type.component.scss
similarity index 100%
rename from console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.scss
rename to console/src/app/modules/policies/login-policy/mfa-table/dialog-add-type/dialog-add-type.component.scss
diff --git a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.ts b/console/src/app/modules/policies/login-policy/mfa-table/dialog-add-type/dialog-add-type.component.ts
similarity index 100%
rename from console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.ts
rename to console/src/app/modules/policies/login-policy/mfa-table/dialog-add-type/dialog-add-type.component.ts
diff --git a/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.html b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.html
new file mode 100644
index 0000000000..28b5e3cbf1
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ {{(componentType == LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.':
+ LoginMethodComponentType.MultiFactor ? 'MFA.MULTIFACTORTYPES.': '')+mfa | translate}}
+
+
+
+ remove_circle
+
+
+
+ {{'ACTIONS.ADD' | translate}}
+ add
+
+
\ No newline at end of file
diff --git a/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.scss b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.scss
new file mode 100644
index 0000000000..f43b5f0729
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.scss
@@ -0,0 +1,41 @@
+.mfa-list {
+ display: flex;
+ flex-direction: column;
+
+ .mfa {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 10px;
+ border-radius: .5rem;
+ margin-bottom: .5rem;
+ min-height: 40px;
+
+ .fill-space {
+ flex: 1;
+ }
+
+ .rm {
+ display: none;
+ transition: all .2s ease;
+ cursor: pointer;
+ }
+
+ &:hover {
+ .rm {
+ display: block;
+ }
+ }
+ }
+
+ .new-mfa {
+ display: flex;
+ align-items: center;
+ align-self: flex-end;
+ margin-top: .5rem;
+
+ .icon {
+ margin-left: .5rem;
+ }
+ }
+}
diff --git a/console/src/app/modules/mfa-table/mfa-table.component.spec.ts b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.spec.ts
similarity index 100%
rename from console/src/app/modules/mfa-table/mfa-table.component.spec.ts
rename to console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.spec.ts
diff --git a/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.ts b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.ts
new file mode 100644
index 0000000000..e54b372a75
--- /dev/null
+++ b/console/src/app/modules/policies/login-policy/mfa-table/mfa-table.component.ts
@@ -0,0 +1,224 @@
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { MatPaginator } from '@angular/material/paginator';
+import { TranslateService } from '@ngx-translate/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
+import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
+import {
+ AddMultiFactorToLoginPolicyRequest as AdminAddMultiFactorToLoginPolicyRequest,
+ AddSecondFactorToLoginPolicyRequest as AdminAddSecondFactorToLoginPolicyRequest,
+ RemoveMultiFactorFromLoginPolicyRequest as AdminRemoveMultiFactorFromLoginPolicyRequest,
+ RemoveSecondFactorFromLoginPolicyRequest as AdminRemoveSecondFactorFromLoginPolicyRequest,
+} from 'src/app/proto/generated/zitadel/admin_pb';
+import {
+ AddMultiFactorToLoginPolicyRequest as MgmtAddMultiFactorToLoginPolicyRequest,
+ AddSecondFactorToLoginPolicyRequest as MgmtAddSecondFactorToLoginPolicyRequest,
+ RemoveMultiFactorFromLoginPolicyRequest as MgmtRemoveMultiFactorFromLoginPolicyRequest,
+ RemoveSecondFactorFromLoginPolicyRequest as MgmtRemoveSecondFactorFromLoginPolicyRequest,
+} from 'src/app/proto/generated/zitadel/management_pb';
+import { MultiFactorType, SecondFactorType } from 'src/app/proto/generated/zitadel/policy_pb';
+import { AdminService } from 'src/app/services/admin.service';
+import { ManagementService } from 'src/app/services/mgmt.service';
+import { ToastService } from 'src/app/services/toast.service';
+
+import { DialogAddTypeComponent } from './dialog-add-type/dialog-add-type.component';
+
+export enum LoginMethodComponentType {
+ MultiFactor = 1,
+ SecondFactor = 2,
+}
+
+@Component({
+ selector: 'app-mfa-table',
+ templateUrl: './mfa-table.component.html',
+ styleUrls: ['./mfa-table.component.scss'],
+})
+export class MfaTableComponent implements OnInit {
+ public LoginMethodComponentType: any = LoginMethodComponentType;
+ @Input() componentType!: LoginMethodComponentType;
+ @Input() public serviceType!: PolicyComponentServiceType;
+ @Input() service!: AdminService | ManagementService;
+ @Input() disabled: boolean = false;
+ @ViewChild(MatPaginator) public paginator!: MatPaginator;
+ public mfas: Array = [];
+
+ private loadingSubject: BehaviorSubject = new BehaviorSubject(false);
+ public loading$: Observable = this.loadingSubject.asObservable();
+
+ public PolicyComponentServiceType: any = PolicyComponentServiceType;
+
+ constructor(public translate: TranslateService, private toast: ToastService, private dialog: MatDialog) { }
+
+ public ngOnInit(): void {
+ this.getData();
+ }
+
+ public removeMfa(type: MultiFactorType | SecondFactorType): void {
+ const dialogRef = this.dialog.open(WarnDialogComponent, {
+ data: {
+ confirmKey: 'ACTIONS.DELETE',
+ cancelKey: 'ACTIONS.CANCEL',
+ titleKey: 'MFA.DELETE.TITLE',
+ descriptionKey: 'MFA.DELETE.DESCRIPTION',
+ },
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe(resp => {
+ if (resp) {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ const req = new MgmtRemoveMultiFactorFromLoginPolicyRequest();
+ req.setType(type as MultiFactorType);
+ (this.service as ManagementService).removeMultiFactorFromLoginPolicy(req).then(() => {
+ this.toast.showInfo('MFA.TOAST.DELETED', true);
+ this.refreshPageAfterTimout(2000);
+ });
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ const req = new MgmtRemoveSecondFactorFromLoginPolicyRequest();
+ req.setType(type as SecondFactorType);
+ (this.service as ManagementService).removeSecondFactorFromLoginPolicy(req).then(() => {
+ this.toast.showInfo('MFA.TOAST.DELETED', true);
+ this.refreshPageAfterTimout(2000);
+ });
+ }
+ } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ const req = new AdminRemoveMultiFactorFromLoginPolicyRequest();
+ req.setType(type as MultiFactorType);
+ (this.service as AdminService).removeMultiFactorFromLoginPolicy(req).then(() => {
+ this.toast.showInfo('MFA.TOAST.DELETED', true);
+ this.refreshPageAfterTimout(2000);
+ });
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ const req = new AdminRemoveSecondFactorFromLoginPolicyRequest();
+ req.setType(type as SecondFactorType);
+ (this.service as AdminService).removeSecondFactorFromLoginPolicy(req).then(() => {
+ this.toast.showInfo('MFA.TOAST.DELETED', true);
+ this.refreshPageAfterTimout(2000);
+ });
+ }
+ }
+ }
+ });
+ }
+
+ public addMfa(): void {
+
+ let selection: any[] = [];
+
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ selection = [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION];
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ selection = [SecondFactorType.SECOND_FACTOR_TYPE_U2F, SecondFactorType.SECOND_FACTOR_TYPE_OTP];
+ }
+
+ this.mfas.forEach(mfa => {
+ const index = selection.findIndex(sel => sel === mfa);
+ if (index > -1) {
+ selection.splice(index, 1);
+ }
+ });
+
+ const dialogRef = this.dialog.open(DialogAddTypeComponent, {
+ data: {
+ title: 'MFA.CREATE.TITLE',
+ desc: 'MFA.CREATE.DESCRIPTION',
+ componentType: this.componentType,
+ types: selection,
+ },
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe((mfaType: MultiFactorType | SecondFactorType) => {
+ if (mfaType) {
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ const req = new MgmtAddMultiFactorToLoginPolicyRequest();
+ req.setType(mfaType as MultiFactorType);
+ (this.service as ManagementService).addMultiFactorToLoginPolicy(req).then(() => {
+ this.refreshPageAfterTimout(2000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ const req = new MgmtAddSecondFactorToLoginPolicyRequest();
+ req.setType(mfaType as SecondFactorType);
+ (this.service as ManagementService).addSecondFactorToLoginPolicy(req).then(() => {
+ this.refreshPageAfterTimout(2000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+ } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ const req = new AdminAddMultiFactorToLoginPolicyRequest();
+ req.setType(mfaType as MultiFactorType);
+ (this.service as AdminService).addMultiFactorToLoginPolicy(req).then(() => {
+ this.refreshPageAfterTimout(2000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ const req = new AdminAddSecondFactorToLoginPolicyRequest();
+ req.setType(mfaType as SecondFactorType);
+ (this.service as AdminService).addSecondFactorToLoginPolicy(req).then(() => {
+ this.refreshPageAfterTimout(2000);
+ }).catch(error => {
+ this.toast.showError(error);
+ });
+ }
+ }
+ }
+ });
+ }
+
+ private async getData(): Promise {
+ this.loadingSubject.next(true);
+
+ if (this.serviceType === PolicyComponentServiceType.MGMT) {
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ (this.service as ManagementService).listLoginPolicyMultiFactors().then(resp => {
+ this.mfas = resp.resultList;
+ this.loadingSubject.next(false);
+ }).catch(error => {
+ this.toast.showError(error);
+ this.loadingSubject.next(false);
+ });
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ (this.service as ManagementService).listLoginPolicySecondFactors().then(resp => {
+ this.mfas = resp.resultList;
+ this.loadingSubject.next(false);
+ }).catch(error => {
+ this.toast.showError(error);
+ this.loadingSubject.next(false);
+ });
+ }
+ } else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
+ if (this.componentType === LoginMethodComponentType.MultiFactor) {
+ (this.service as AdminService).listLoginPolicyMultiFactors().then(resp => {
+ this.mfas = resp.resultList;
+ this.loadingSubject.next(false);
+ }).catch(error => {
+ this.toast.showError(error);
+ this.loadingSubject.next(false);
+ });
+ } else if (this.componentType === LoginMethodComponentType.SecondFactor) {
+ (this.service as AdminService).listLoginPolicySecondFactors().then(resp => {
+ this.mfas = resp.resultList;
+ this.loadingSubject.next(false);
+ }).catch(error => {
+ this.toast.showError(error);
+ this.loadingSubject.next(false);
+ });
+ }
+ }
+ }
+
+ public refreshPageAfterTimout(to: number): void {
+ setTimeout(() => {
+ this.getData();
+ }, to);
+ }
+}
diff --git a/console/src/app/modules/user-grants/user-grants.component.html b/console/src/app/modules/user-grants/user-grants.component.html
index 71a5cade46..1f4617f250 100644
--- a/console/src/app/modules/user-grants/user-grants.component.html
+++ b/console/src/app/modules/user-grants/user-grants.component.html
@@ -1,180 +1,181 @@
-
-
-
+ [emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes" [timestamp]="dataSource?.viewTimestamp"
+ [dataSize]="dataSource?.totalResult" [selection]="selection">
+
+
+
-
-
-
-
- add {{ 'GRANTS.ADD_BTN' | translate }}
-
+
+
+
+
+ add {{ 'GRANTS.ADD_BTN' | translate }}
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ 'PROJECT.GRANT.USER' | translate }}
+
+
+
+ {{grant?.displayName}}
+
+
+
+
+ {{ 'PROJECT.GRANT.GRANTEDORGDOMAIN' | translate }}
+
+
+
+ {{grant.orgName}}
+
+
+
+ {{ 'PROJECT.GRANT.PROJECTNAME' | translate }}
+
+
+
+ {{grant.projectName}}
+
+
+
+ DATES
+
+
+ {{ 'PROJECT.GRANT.CREATIONDATE' | translate }}:
+ {{grant.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
+
+
+ {{ 'PROJECT.GRANT.CHANGEDATE' | translate }}
+ {{grant.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
+
+
+
+
+
+ {{'PROJECT.GRANT.CREATIONDATE' | translate}}
+
+ {{grant.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
+
+
+
+
+ {{ 'PROJECT.GRANT.CHANGEDATE' | translate }}
+
+ {{grant.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
+
+
+
+
+
+ {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}
+
+
+
+
+
+
+ {{ role }}
+
+
+
+
+ {{'ACTIONS.EDIT' | translate}}
+
+
+
+
+
+
+
+
+
+ {{role.key}}
+
+
+
+
+ close
+
-
- {{ 'PROJECT.GRANT.USER' | translate }}
-
-
-
- {{grant?.displayName}}
+
+
+
+
+ {{role}}
+
+
+
+
+ close
+
+
+
+
-
- {{ 'PROJECT.GRANT.GRANTEDORGDOMAIN' | translate }}
-
-
-
- {{grant.orgName}}
-
+
+
+
+
-
- {{ 'PROJECT.GRANT.PROJECTNAME' | translate }}
-
-
-
- {{grant.projectName}}
-
-
-
- DATES
-
-
- {{ 'PROJECT.GRANT.CREATIONDATE' | translate }}:
- {{grant.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
-
-
- {{ 'PROJECT.GRANT.CHANGEDATE' | translate }}
- {{grant.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
-
-
-
-
-
- {{'PROJECT.GRANT.CREATIONDATE' | translate}}
-
- {{grant.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
-
-
-
-
- {{ 'PROJECT.GRANT.CHANGEDATE' | translate }}
-
- {{grant.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
-
-
-
-
-
- {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}
-
-
-
-
-
-
- {{ role }}
-
-
-
-
- {{'ACTIONS.EDIT' | translate}}
-
-
-
-
-
-
-
-
-
- {{role.key}}
-
-
-
-
- close
-
-
-
-
-
-
-
- {{role}}
-
-
-
-
- close
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{'GRANTS.EMPTY' | translate}}
-
-
-
+
+
+ {{'GRANTS.EMPTY' | translate}}
+
+
+
-
- search
- search_off
-
+
+ search
+ search_off
+
\ No newline at end of file
diff --git a/console/src/app/modules/user-grants/user-grants.component.scss b/console/src/app/modules/user-grants/user-grants.component.scss
index 236e22c9c2..6de0262fef 100644
--- a/console/src/app/modules/user-grants/user-grants.component.scss
+++ b/console/src/app/modules/user-grants/user-grants.component.scss
@@ -21,6 +21,11 @@
}
}
+ .user {
+ text-decoration: none;
+ color: inherit;
+ }
+
th {
.search-button {
visibility: hidden;
diff --git a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts
index ec783e9316..e81b1b9d73 100644
--- a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts
+++ b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts
@@ -82,7 +82,7 @@ export class GrantedProjectGridComponent implements OnChanges {
private async getPrefixedItem(key: string): Promise {
const org = this.storage.getItem(StorageKey.organization, StorageLocation.session) as Org.AsObject;
- return localStorage.getItem(`${org.id}:${key}`);
+ return localStorage.getItem(`${org?.id}:${key}`);
}
private async setPrefixedItem(key: string, value: any): Promise {
diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html
index cc66d4c037..699b9d7e22 100644
--- a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html
+++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html
@@ -1,148 +1,153 @@
-
-
-
- arrow_back
-
-
{{ 'PROJECT.PAGES.TITLE' | translate }} {{project?.name}}
+
+
+
+ arrow_back
+
+
{{ 'PROJECT.PAGES.TITLE' | translate }} {{project?.name}}
-
+
-
-
- {{'ACTIONS.ACTIONS' | translate}}
- keyboard_arrow_down
-
-
-
- {{'ACTIONS.RENAME' | translate}}
-
+
+
+ {{'ACTIONS.ACTIONS' | translate}}
+ keyboard_arrow_down
+
+
+
+ {{'ACTIONS.RENAME' | translate}}
+
-
- {{'PROJECT.TABLE.DEACTIVATE' | translate}}
-
+
+ {{'PROJECT.TABLE.DEACTIVATE' | translate}}
+
-
- {{'PROJECT.TABLE.ACTIVATE' | translate}}
-
+
+ {{'PROJECT.TABLE.ACTIVATE' | translate}}
+
-
-
- {{'PROJECT.PAGES.DELETE' | translate}}
-
-
-
-
+
+
+ {{'PROJECT.PAGES.DELETE' | translate}}
+
+
+
+
-
-
{{ 'PROJECT.PAGES.DESCRIPTION' | translate }}
-
{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}
-
-
-
-
-
-
{{'PROJECT.PAGES.PRIVATELABEL.TITLE' | translate}}
-
- {{'PROJECT.PAGES.PRIVATELABEL.'+project.privateLabelingSetting+'.TITLE' | translate}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{'PROJECT.ROLE.OPTIONS' | translate}}
-
- {{'PROJECT.ROLE.ASSERTION' | translate}}
- {{'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate}}
-
- {{'PROJECT.ROLE.CHECK' | translate}}
- {{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}
-
- {{'PROJECT.HAS_PROJECT' | translate}}
- {{'PROJECT.HAS_PROJECT_DESCRIPTION' | translate}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
{{ 'PROJECT.PAGES.DESCRIPTION' | translate }}
+
{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
{{'PROJECT.PAGES.PRIVATELABEL.TITLE' | translate}}
+
+ {{'PROJECT.PAGES.PRIVATELABEL.'+project.privateLabelingSetting+'.TITLE' | translate}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{'PROJECT.ROLE.OPTIONS' | translate}}
+
+ {{'PROJECT.ROLE.ASSERTION' | translate}}
+ {{'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate}}
+
+ {{'PROJECT.ROLE.CHECK' | translate}}
+ {{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}
+
+ {{'PROJECT.HAS_PROJECT' | translate}}
+ {{'PROJECT.HAS_PROJECT_DESCRIPTION' | translate}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts
index 5c291bd225..41bfa06ba0 100644
--- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts
+++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts
@@ -106,7 +106,7 @@ export class OwnedProjectGridComponent implements OnChanges {
private async getPrefixedItem(key: string): Promise
{
const org = this.storage.getItem(StorageKey.organization, StorageLocation.session) as Org.AsObject;
- return localStorage.getItem(`${org.id}:${key}`);
+ return localStorage.getItem(`${org?.id}:${key}`);
}
private async setPrefixedItem(key: string, value: any): Promise {
diff --git a/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.component.html b/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.component.html
index eb101d1fbb..3a5ffd08ef 100644
--- a/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.component.html
+++ b/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.component.html
@@ -1,57 +1,64 @@
-
-
-
- {{'PROJECT.GRANT.DETAIL.PROJECTNAME' | translate}}
-
- {{grant?.projectName}}
-
-
- {{'PROJECT.GRANT.DETAIL.RESOURCEOWNER' | translate}}
-
- {{grant?.details?.resourceOwner}}
-
-
-
+ description="{{ 'PROJECT.GRANT.DETAIL.DESC' | translate }}">
+
+
+
+
{{'PROJECT.GRANT.DETAIL.PROJECTNAME' | translate}}
-
-
- {{'USER.PAGES.DEACTIVATE' | translate}}
- {{'USER.PAGES.REACTIVATE' | translate}}
-
+
{{grant?.projectName}}
+
+
+ {{'PROJECT.GRANT.DETAIL.RESOURCEOWNER' | translate}}
+
+ {{grant?.projectOwnerName}}
+
+
+ {{'PROJECT.GRANT.DETAIL.GRANTEDORG' | translate}}
+
+ {{grant?.grantedOrgName}}
+
-
- {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}
-
-
- {{role.key}}
-
-
-
+
-
+
+ {{'USER.PAGES.DEACTIVATE' |
+ translate}}
+ {{'USER.PAGES.REACTIVATE' |
+ translate}}
+
+
-
{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}
-
{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}
+
+ {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}
+
+
+ {{role.key}}
+
+
+
-
-
-
- {{'ACTIONS.SELECTIONDELETE' | translate}}
-
-
- add {{ 'ACTIONS.NEW' | translate }}
-
-
+
+
+
{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}
+
{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}
+
+
+
+
+ {{'ACTIONS.SELECTIONDELETE' | translate}}
+
+
+ add {{ 'ACTIONS.NEW' | translate }}
+
+
\ No newline at end of file
diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html
index e6468e50ed..8f8ea8175e 100644
--- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html
+++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html
@@ -1,135 +1,136 @@
+
{{error}}
+
-
-
-
- arrow_back
-
-
-
{{user.human ? user.human?.profile?.displayName : user.machine?.name}}
-
{{user?.preferredLoginName}}
-
-
-
-
-
- {{'ACTIONS.ACTIONS' | translate}}
- keyboard_arrow_down
-
-
- {{'USER.PAGES.UNLOCK' |
- translate}}
- {{'USER.PAGES.DEACTIVATE' |
- translate}}
- {{'USER.PAGES.REACTIVATE' | translate}}
-
- {{'USER.PAGES.DELETE' | translate}}
-
-
-
-
-
-
-
-
{{'USER.PAGES.LOCKEDDESCRIPTION' | translate}}
-
{{ 'USER.PAGES.NOUSER' | translate }}
-
-
-
-
-
-
-
-
-
-
-
- refresh
-
-
- {{
- 'USER.PASSWORD.RESENDNOTIFICATION' | translate }}
- {{'USER.RESENDINITIALEMAIL' |
- translate}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-