From 542271b46707a860aaffb65fdaba9377d0c882cf Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 28 Mar 2023 09:38:17 +0200 Subject: [PATCH] feat(console): Active Directory / LDAP, cleanup idp component routing (#5506) feat(console): LDAP --- .../idp-table/idp-table.component.html | 8 + .../modules/idp-table/idp-table.component.ts | 2 + .../idp-settings/idp-settings.component.html | 18 ++ .../message-texts.component.html | 2 +- .../message-texts.component.scss | 2 +- .../ldap-attributes.component.html | 54 ++++ .../ldap-attributes.component.scss | 6 + .../ldap-attributes.component.spec.ts | 22 ++ .../ldap-attributes.component.ts | 64 +++++ .../provider-azure-ad-routing.module.ts | 18 -- .../provider-azure-ad.component.html | 8 +- .../provider-azure-ad.component.ts | 22 +- .../provider-azure-ad.module.ts | 43 --- .../provider-github-es-routing.module.ts | 17 -- .../provider-github-es.component.html | 8 +- .../provider-github-es.component.ts | 19 ++ .../provider-github-es.module.ts | 43 --- .../provider-github-routing.module.ts | 18 -- .../provider-github.component.html | 8 +- .../provider-github.component.ts | 19 ++ .../provider-github/provider-github.module.ts | 43 --- ...vider-gitlab-self-hosted-routing.module.ts | 17 -- ...provider-gitlab-self-hosted.component.html | 8 +- .../provider-gitlab-self-hosted.component.ts | 19 ++ .../provider-gitlab-self-hosted.module.ts | 43 --- .../provider-gitlab-routing.module.ts | 17 -- .../provider-gitlab.component.html | 8 +- .../provider-gitlab.component.ts | 19 ++ .../provider-gitlab/provider-gitlab.module.ts | 43 --- .../provider-google-routing.module.ts | 18 -- .../provider-google.component.html | 8 +- .../provider-google.component.ts | 19 ++ .../provider-google/provider-google.module.ts | 43 --- .../provider-jwt-routing.module.ts | 17 -- .../provider-jwt/provider-jwt.component.html | 8 +- .../provider-jwt/provider-jwt.component.ts | 19 ++ .../provider-jwt/provider-jwt.module.ts | 43 --- .../provider-ldap.component.html | 125 +++++++++ .../provider-ldap.component.spec.ts | 24 ++ .../provider-ldap/provider-ldap.component.ts | 264 ++++++++++++++++++ .../provider-oauth-routing.module.ts | 18 -- .../provider-oauth.component.html | 8 +- .../provider-oauth.component.ts | 22 +- .../provider-oauth/provider-oauth.module.ts | 43 --- .../provider-oidc-routing.module.ts | 18 -- .../provider-oidc.component.html | 10 +- .../provider-oidc/provider-oidc.component.ts | 16 +- .../provider-oidc/provider-oidc.module.ts | 43 --- .../providers/providers-routing.module.ts | 52 ++++ .../app/modules/providers/providers.module.ts | 68 +++++ .../src/app/modules/providers/providers.scss | 22 +- .../string-list/string-list.component.html | 30 ++ .../string-list/string-list.component.scss | 60 ++++ .../string-list/string-list.component.spec.ts | 24 ++ .../string-list/string-list.component.ts | 100 +++++++ .../modules/string-list/string-list.module.ts | 25 ++ .../pages/instance/instance-routing.module.ts | 124 +------- .../src/app/pages/orgs/org-routing.module.ts | 124 +------- .../apps/app-create/app-create.component.html | 24 +- .../apps/app-create/app-create.component.ts | 16 ++ .../apps/app-detail/app-detail.component.html | 12 +- .../apps/app-detail/app-detail.component.scss | 6 - .../redirect-uris.component.html | 12 +- .../redirect-uris/redirect-uris.component.ts | 81 ++++-- console/src/app/services/admin.service.ts | 12 + console/src/app/services/mgmt.service.ts | 12 + console/src/assets/i18n/de.json | 31 ++ console/src/assets/i18n/en.json | 31 ++ console/src/assets/i18n/fr.json | 31 ++ console/src/assets/i18n/it.json | 31 ++ console/src/assets/i18n/ja.json | 31 ++ console/src/assets/i18n/pl.json | 31 ++ console/src/assets/i18n/zh.json | 31 ++ console/src/component-themes.scss | 2 + 74 files changed, 1542 insertions(+), 865 deletions(-) create mode 100644 console/src/app/modules/providers/ldap-attributes/ldap-attributes.component.html create mode 100644 console/src/app/modules/providers/ldap-attributes/ldap-attributes.component.scss create mode 100644 console/src/app/modules/providers/ldap-attributes/ldap-attributes.component.spec.ts create mode 100644 console/src/app/modules/providers/ldap-attributes/ldap-attributes.component.ts delete mode 100644 console/src/app/modules/providers/provider-azure-ad/provider-azure-ad-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.module.ts delete mode 100644 console/src/app/modules/providers/provider-github-es/provider-github-es-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-github-es/provider-github-es.module.ts delete mode 100644 console/src/app/modules/providers/provider-github/provider-github-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-github/provider-github.module.ts delete mode 100644 console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module.ts delete mode 100644 console/src/app/modules/providers/provider-gitlab/provider-gitlab-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-gitlab/provider-gitlab.module.ts delete mode 100644 console/src/app/modules/providers/provider-google/provider-google-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-google/provider-google.module.ts delete mode 100644 console/src/app/modules/providers/provider-jwt/provider-jwt-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-jwt/provider-jwt.module.ts create mode 100644 console/src/app/modules/providers/provider-ldap/provider-ldap.component.html create mode 100644 console/src/app/modules/providers/provider-ldap/provider-ldap.component.spec.ts create mode 100644 console/src/app/modules/providers/provider-ldap/provider-ldap.component.ts delete mode 100644 console/src/app/modules/providers/provider-oauth/provider-oauth-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-oauth/provider-oauth.module.ts delete mode 100644 console/src/app/modules/providers/provider-oidc/provider-oidc-routing.module.ts delete mode 100644 console/src/app/modules/providers/provider-oidc/provider-oidc.module.ts create mode 100644 console/src/app/modules/providers/providers-routing.module.ts create mode 100644 console/src/app/modules/providers/providers.module.ts create mode 100644 console/src/app/modules/string-list/string-list.component.html create mode 100644 console/src/app/modules/string-list/string-list.component.scss create mode 100644 console/src/app/modules/string-list/string-list.component.spec.ts create mode 100644 console/src/app/modules/string-list/string-list.component.ts create mode 100644 console/src/app/modules/string-list/string-list.module.ts 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 bcbf18e491..1110232853 100644 --- a/console/src/app/modules/idp-table/idp-table.component.html +++ b/console/src/app/modules/idp-table/idp-table.component.html @@ -76,6 +76,10 @@ GitHub Enterprise Server +
+ + Active Directory / LDAP +
coming soon
@@ -162,6 +166,10 @@ diff --git a/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.ts b/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.ts index e572f4e48f..df188d9cd2 100644 --- a/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.ts +++ b/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.ts @@ -3,7 +3,7 @@ import { Location } from '@angular/common'; import { Component, Injector, Type } from '@angular/core'; import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { take } from 'rxjs'; import { AddAzureADProviderRequest as AdminAddAzureADProviderRequest, @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -50,7 +51,7 @@ export class ProviderAzureADComponent { ]; constructor( - private router: Router, + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -67,6 +68,23 @@ export class ProviderAzureADComponent { emailVerified: new FormControl(false), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.module.ts b/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.module.ts deleted file mode 100644 index 9b6b875b0d..0000000000 --- a/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderAzureADRoutingModule } from './provider-azure-ad-routing.module'; -import { ProviderAzureADComponent } from './provider-azure-ad.component'; - -@NgModule({ - declarations: [ProviderAzureADComponent], - imports: [ - ProviderAzureADRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderAzureADModule {} diff --git a/console/src/app/modules/providers/provider-github-es/provider-github-es-routing.module.ts b/console/src/app/modules/providers/provider-github-es/provider-github-es-routing.module.ts deleted file mode 100644 index 66e95eb17c..0000000000 --- a/console/src/app/modules/providers/provider-github-es/provider-github-es-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { ProviderGithubESComponent } from './provider-github-es.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderGithubESComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderGithubESRoutingModule {} diff --git a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html index 014a3f9a52..f0c439d298 100644 --- a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html +++ b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html @@ -97,7 +97,13 @@
- diff --git a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts index 1e26d5e28f..3264f0b297 100644 --- a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts +++ b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -44,6 +45,7 @@ export class ProviderGithubESComponent { public provider?: Provider.AsObject; constructor( + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -60,6 +62,23 @@ export class ProviderGithubESComponent { scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-github-es/provider-github-es.module.ts b/console/src/app/modules/providers/provider-github-es/provider-github-es.module.ts deleted file mode 100644 index b334a531f4..0000000000 --- a/console/src/app/modules/providers/provider-github-es/provider-github-es.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderGithubESRoutingModule } from './provider-github-es-routing.module'; -import { ProviderGithubESComponent } from './provider-github-es.component'; - -@NgModule({ - declarations: [ProviderGithubESComponent], - imports: [ - ProviderGithubESRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderGithubESModule {} diff --git a/console/src/app/modules/providers/provider-github/provider-github-routing.module.ts b/console/src/app/modules/providers/provider-github/provider-github-routing.module.ts deleted file mode 100644 index d5014162d2..0000000000 --- a/console/src/app/modules/providers/provider-github/provider-github-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ProviderGithubComponent } from './provider-github.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderGithubComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderGithubRoutingModule {} diff --git a/console/src/app/modules/providers/provider-github/provider-github.component.html b/console/src/app/modules/providers/provider-github/provider-github.component.html index f2248b7400..8b40a2070e 100644 --- a/console/src/app/modules/providers/provider-github/provider-github.component.html +++ b/console/src/app/modules/providers/provider-github/provider-github.component.html @@ -84,7 +84,13 @@
- diff --git a/console/src/app/modules/providers/provider-github/provider-github.component.ts b/console/src/app/modules/providers/provider-github/provider-github.component.ts index 28f4757f49..975b255d1c 100644 --- a/console/src/app/modules/providers/provider-github/provider-github.component.ts +++ b/console/src/app/modules/providers/provider-github/provider-github.component.ts @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -45,6 +46,7 @@ export class ProviderGithubComponent { public updateClientSecret: boolean = false; constructor( + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -58,6 +60,23 @@ export class ProviderGithubComponent { scopesList: new FormControl(['openid', 'profile', 'email'], []), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-github/provider-github.module.ts b/console/src/app/modules/providers/provider-github/provider-github.module.ts deleted file mode 100644 index 8a617b0692..0000000000 --- a/console/src/app/modules/providers/provider-github/provider-github.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderGithubRoutingModule } from './provider-github-routing.module'; -import { ProviderGithubComponent } from './provider-github.component'; - -@NgModule({ - declarations: [ProviderGithubComponent], - imports: [ - ProviderGithubRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderGithubModule {} diff --git a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted-routing.module.ts b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted-routing.module.ts deleted file mode 100644 index bc8f9c753b..0000000000 --- a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { ProviderGitlabSelfHostedComponent } from './provider-gitlab-self-hosted.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderGitlabSelfHostedComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderGitlabSelfHostedRoutingModule {} diff --git a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html index a4346256a8..194e9dbede 100644 --- a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html +++ b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html @@ -87,7 +87,13 @@
- diff --git a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.ts b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.ts index 1b5ea437be..72610d03ae 100644 --- a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.ts +++ b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.ts @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -45,6 +46,7 @@ export class ProviderGitlabSelfHostedComponent { public updateClientSecret: boolean = false; constructor( + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -59,6 +61,23 @@ export class ProviderGitlabSelfHostedComponent { scopesList: new FormControl(['openid', 'profile', 'email'], []), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module.ts b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module.ts deleted file mode 100644 index f516dddfe8..0000000000 --- a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderGitlabSelfHostedRoutingModule } from './provider-gitlab-self-hosted-routing.module'; -import { ProviderGitlabSelfHostedComponent } from './provider-gitlab-self-hosted.component'; - -@NgModule({ - declarations: [ProviderGitlabSelfHostedComponent], - imports: [ - ProviderGitlabSelfHostedRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderGitlabSelfHostedModule {} diff --git a/console/src/app/modules/providers/provider-gitlab/provider-gitlab-routing.module.ts b/console/src/app/modules/providers/provider-gitlab/provider-gitlab-routing.module.ts deleted file mode 100644 index ccc9aa76d4..0000000000 --- a/console/src/app/modules/providers/provider-gitlab/provider-gitlab-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { ProviderGitlabComponent } from './provider-gitlab.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderGitlabComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderGitlabRoutingModule {} diff --git a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html index 6d8802a6a9..0ef22147de 100644 --- a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html +++ b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html @@ -83,7 +83,13 @@
- diff --git a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.ts b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.ts index 295c77acde..dd3c2976ef 100644 --- a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.ts +++ b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.ts @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -45,6 +46,7 @@ export class ProviderGitlabComponent { public updateClientSecret: boolean = false; constructor( + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -58,6 +60,23 @@ export class ProviderGitlabComponent { scopesList: new FormControl(['openid', 'profile', 'email'], []), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.module.ts b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.module.ts deleted file mode 100644 index 328f231366..0000000000 --- a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderGitlabRoutingModule } from './provider-gitlab-routing.module'; -import { ProviderGitlabComponent } from './provider-gitlab.component'; - -@NgModule({ - declarations: [ProviderGitlabComponent], - imports: [ - ProviderGitlabRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderGitlabModule {} diff --git a/console/src/app/modules/providers/provider-google/provider-google-routing.module.ts b/console/src/app/modules/providers/provider-google/provider-google-routing.module.ts deleted file mode 100644 index aa03e3bb98..0000000000 --- a/console/src/app/modules/providers/provider-google/provider-google-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ProviderGoogleComponent } from './provider-google.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderGoogleComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderGoogleRoutingModule {} diff --git a/console/src/app/modules/providers/provider-google/provider-google.component.html b/console/src/app/modules/providers/provider-google/provider-google.component.html index 32643471a8..912d4fd8b5 100644 --- a/console/src/app/modules/providers/provider-google/provider-google.component.html +++ b/console/src/app/modules/providers/provider-google/provider-google.component.html @@ -83,7 +83,13 @@
- diff --git a/console/src/app/modules/providers/provider-google/provider-google.component.ts b/console/src/app/modules/providers/provider-google/provider-google.component.ts index 3515c0553e..e606e26553 100644 --- a/console/src/app/modules/providers/provider-google/provider-google.component.ts +++ b/console/src/app/modules/providers/provider-google/provider-google.component.ts @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -45,6 +46,7 @@ export class ProviderGoogleComponent { public updateClientSecret: boolean = false; constructor( + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -58,6 +60,23 @@ export class ProviderGoogleComponent { scopesList: new FormControl(['openid', 'profile', 'email'], []), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-google/provider-google.module.ts b/console/src/app/modules/providers/provider-google/provider-google.module.ts deleted file mode 100644 index e0af1a8030..0000000000 --- a/console/src/app/modules/providers/provider-google/provider-google.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderGoogleRoutingModule } from './provider-google-routing.module'; -import { ProviderGoogleComponent } from './provider-google.component'; - -@NgModule({ - declarations: [ProviderGoogleComponent], - imports: [ - ProviderGoogleRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderGoogleModule {} diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt-routing.module.ts b/console/src/app/modules/providers/provider-jwt/provider-jwt-routing.module.ts deleted file mode 100644 index 35f580044b..0000000000 --- a/console/src/app/modules/providers/provider-jwt/provider-jwt-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { ProviderJWTComponent } from './provider-jwt.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderJWTComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderJWTCreateRoutingModule {} diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html index 853bb3e800..151599c0f2 100644 --- a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html +++ b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html @@ -50,7 +50,13 @@
- diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts index cf82a3289f..ed77f4460c 100644 --- a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts +++ b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts @@ -17,6 +17,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -42,6 +43,7 @@ export class ProviderJWTComponent { public provider?: Provider.AsObject; constructor( + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -87,6 +89,23 @@ export class ProviderJWTComponent { jwtEndpoint: new UntypedFormControl('', [requiredValidator]), keysEndpoint: new UntypedFormControl('', [requiredValidator]), }); + + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); } private getData(id: string): void { diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt.module.ts b/console/src/app/modules/providers/provider-jwt/provider-jwt.module.ts deleted file mode 100644 index 2231cf807a..0000000000 --- a/console/src/app/modules/providers/provider-jwt/provider-jwt.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderJWTCreateRoutingModule } from './provider-jwt-routing.module'; -import { ProviderJWTComponent } from './provider-jwt.component'; - -@NgModule({ - declarations: [ProviderJWTComponent], - imports: [ - ProviderJWTCreateRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderJWTModule {} diff --git a/console/src/app/modules/providers/provider-ldap/provider-ldap.component.html b/console/src/app/modules/providers/provider-ldap/provider-ldap.component.html new file mode 100644 index 0000000000..ee49949346 --- /dev/null +++ b/console/src/app/modules/providers/provider-ldap/provider-ldap.component.html @@ -0,0 +1,125 @@ + +
+
+ +

{{ 'IDP.CREATE.LDAP.TITLE' | translate }}

+ +
+ +

+ {{ !provider ? ('IDP.CREATE.LDAP.DESCRIPTION' | translate) : ('IDP.DETAIL.DESCRIPTION' | translate) }} +

+ +
+
+ + {{ 'IDP.NAME' | translate }} + + + +

{{ 'IDP.LDAPCONNECTION' | translate }}

+ + + + + {{ 'IDP.BASEDN' | translate }} + + + +
+ + {{ 'IDP.BINDDN' | translate }} + + + + {{ + 'IDP.UPDATEBINDPASSWORD' | translate + }} + + {{ 'IDP.BINDPASSWORD' | translate }} + + +
+ +

{{ 'IDP.LDAPUSERBINDING' | translate }}

+ + + {{ 'IDP.USERBASE' | translate }} + + + + + + + +
+

{{ 'IDP.LDAPATTRIBUTES' | translate }}

+ + + + {{ + 'IDP.REQUIRED' | translate + }} +
+
+ +
+ +
+

{{ 'IDP.OPTIONAL' | translate }}

+ +
+
+ {{ 'IDP.STARTTLS' | translate }} + + + {{ 'IDP.TIMEOUT' | translate }} + + + + +
+
+ +
+ +
+
+
+
diff --git a/console/src/app/modules/providers/provider-ldap/provider-ldap.component.spec.ts b/console/src/app/modules/providers/provider-ldap/provider-ldap.component.spec.ts new file mode 100644 index 0000000000..ac5c30e675 --- /dev/null +++ b/console/src/app/modules/providers/provider-ldap/provider-ldap.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { ProviderLDAPComponent } from './provider-ldap.component'; + +describe('ProviderLDAPComponent', () => { + let component: ProviderLDAPComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ProviderLDAPComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProviderLDAPComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/console/src/app/modules/providers/provider-ldap/provider-ldap.component.ts b/console/src/app/modules/providers/provider-ldap/provider-ldap.component.ts new file mode 100644 index 0000000000..98df95ad99 --- /dev/null +++ b/console/src/app/modules/providers/provider-ldap/provider-ldap.component.ts @@ -0,0 +1,264 @@ +import { Location } from '@angular/common'; +import { Component, Injector, Type } from '@angular/core'; +import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; +import { Duration } from 'google-protobuf/google/protobuf/duration_pb'; +import { take } from 'rxjs'; +import { + AddLDAPProviderRequest as AdminAddLDAPProviderRequest, + GetProviderByIDRequest as AdminGetProviderByIDRequest, + UpdateLDAPProviderRequest as AdminUpdateLDAPProviderRequest, +} from 'src/app/proto/generated/zitadel/admin_pb'; +import { LDAPAttributes, Options, Provider } from 'src/app/proto/generated/zitadel/idp_pb'; +import { + AddLDAPProviderRequest as MgmtAddLDAPProviderRequest, + GetProviderByIDRequest as MgmtGetProviderByIDRequest, + UpdateLDAPProviderRequest as MgmtUpdateLDAPProviderRequest, +} from 'src/app/proto/generated/zitadel/management_pb'; +import { AdminService } from 'src/app/services/admin.service'; +import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; + +import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum'; + +@Component({ + selector: 'cnsl-provider-ldap', + templateUrl: './provider-ldap.component.html', +}) +export class ProviderLDAPComponent { + public updateBindPassword: boolean = false; + public showAttributes: boolean = false; + public showOptional: boolean = false; + public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true); + public attributes: LDAPAttributes = new LDAPAttributes(); + public id: string | null = ''; + public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT; + private service!: ManagementService | AdminService; + + public form!: FormGroup; + + public loading: boolean = false; + + public provider?: Provider.AsObject; + + constructor( + private authService: GrpcAuthService, + private route: ActivatedRoute, + private toast: ToastService, + private injector: Injector, + private _location: Location, + private breadcrumbService: BreadcrumbService, + ) { + this.form = new FormGroup({ + name: new FormControl('', [requiredValidator]), + serversList: new FormControl('', [requiredValidator]), + baseDn: new FormControl('', [requiredValidator]), + bindDn: new FormControl('', [requiredValidator]), + bindPassword: new FormControl('', [requiredValidator]), + userBase: new FormControl('', [requiredValidator]), + userFiltersList: new FormControl('', [requiredValidator]), + userObjectClassesList: new FormControl('', [requiredValidator]), + timeout: new FormControl(0), + startTls: new FormControl(false), + }); + + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + + this.route.data.pipe(take(1)).subscribe((data) => { + this.serviceType = data.serviceType; + + switch (this.serviceType) { + case PolicyComponentServiceType.MGMT: + this.service = this.injector.get(ManagementService as Type); + + const bread: Breadcrumb = { + type: BreadcrumbType.ORG, + routerLink: ['/org'], + }; + + this.breadcrumbService.setBreadcrumb([bread]); + break; + case PolicyComponentServiceType.ADMIN: + this.service = this.injector.get(AdminService as Type); + + const iamBread = new Breadcrumb({ + type: BreadcrumbType.ORG, + name: 'Instance', + routerLink: ['/instance'], + }); + this.breadcrumbService.setBreadcrumb([iamBread]); + break; + } + + this.id = this.route.snapshot.paramMap.get('id'); + if (this.id) { + this.getData(this.id); + this.bindPassword?.setValidators([]); + } + }); + } + + private getData(id: string): void { + const req = + this.serviceType === PolicyComponentServiceType.ADMIN + ? new AdminGetProviderByIDRequest() + : new MgmtGetProviderByIDRequest(); + req.setId(id); + this.service + .getProviderByID(req) + .then((resp) => { + this.provider = resp.idp; + this.loading = false; + if (this.provider?.config?.ldap) { + this.form.patchValue(this.provider.config.ldap); + this.name?.setValue(this.provider.name); + this.timeout?.setValue(this.provider.config.ldap.timeout?.seconds); + } + }) + .catch((error) => { + this.toast.showError(error); + this.loading = false; + }); + } + + public submitForm(): void { + this.provider ? this.updateLDAPProvider() : this.addLDAPProvider(); + } + + public addLDAPProvider(): void { + const req = + this.serviceType === PolicyComponentServiceType.MGMT + ? new MgmtAddLDAPProviderRequest() + : new AdminAddLDAPProviderRequest(); + + req.setName(this.name?.value); + req.setProviderOptions(this.options); + req.setAttributes(this.attributes); + + req.setBaseDn(this.baseDn?.value); + req.setBindDn(this.bindDn?.value); + req.setBindPassword(this.bindPassword?.value); + req.setServersList(this.serversList?.value); // list + req.setStartTls(this.startTls?.value); + req.setTimeout(new Duration().setSeconds(this.timeout?.value ?? 0)); + req.setUserBase(this.userBase?.value); + req.setUserFiltersList(this.userFiltersList?.value); // list + req.setUserObjectClassesList(this.userObjectClassesList?.value); // list + + this.loading = true; + (this.service as ManagementService) + .addLDAPProvider(req) + .then((idp) => { + setTimeout(() => { + this.loading = false; + this.close(); + }, 2000); + }) + .catch((error) => { + this.toast.showError(error); + this.loading = false; + }); + } + + public updateLDAPProvider(): void { + if (this.provider) { + const req = + this.serviceType === PolicyComponentServiceType.MGMT + ? new MgmtUpdateLDAPProviderRequest() + : new AdminUpdateLDAPProviderRequest(); + req.setId(this.provider.id); + req.setName(this.name?.value); + req.setProviderOptions(this.options); + + req.setAttributes(this.attributes); + + req.setBaseDn(this.baseDn?.value); + req.setBindDn(this.bindDn?.value); + if (this.updateBindPassword) { + req.setBindPassword(this.bindPassword?.value); + } + req.setServersList(this.serversList?.value); + req.setStartTls(this.startTls?.value); + req.setTimeout(new Duration().setSeconds(this.timeout?.value ?? 0)); + req.setUserBase(this.userBase?.value); + req.setUserFiltersList(this.userFiltersList?.value); + req.setUserObjectClassesList(this.userObjectClassesList?.value); + + this.loading = true; + (this.service as ManagementService) + .updateLDAPProvider(req) + .then((idp) => { + setTimeout(() => { + this.loading = false; + this.close(); + }, 2000); + }) + .catch((error) => { + this.toast.showError(error); + this.loading = false; + }); + } + } + + public close(): void { + this._location.back(); + } + + public get name(): AbstractControl | null { + return this.form.get('name'); + } + + public get baseDn(): AbstractControl | null { + return this.form.get('baseDn'); + } + + public get bindDn(): AbstractControl | null { + return this.form.get('bindDn'); + } + + public get bindPassword(): AbstractControl | null { + return this.form.get('bindPassword'); + } + + public get serversList(): AbstractControl | null { + return this.form.get('serversList'); + } + + public get startTls(): AbstractControl | null { + return this.form.get('startTls'); + } + + public get timeout(): AbstractControl | null { + return this.form.get('timeout'); + } + + public get userBase(): AbstractControl | null { + return this.form.get('userBase'); + } + + public get userFiltersList(): AbstractControl | null { + return this.form.get('userFiltersList'); + } + + public get userObjectClassesList(): AbstractControl | null { + return this.form.get('userObjectClassesList'); + } +} diff --git a/console/src/app/modules/providers/provider-oauth/provider-oauth-routing.module.ts b/console/src/app/modules/providers/provider-oauth/provider-oauth-routing.module.ts deleted file mode 100644 index 326108faff..0000000000 --- a/console/src/app/modules/providers/provider-oauth/provider-oauth-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ProviderOAuthComponent } from './provider-oauth.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderOAuthComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderOAuthRoutingModule {} diff --git a/console/src/app/modules/providers/provider-oauth/provider-oauth.component.html b/console/src/app/modules/providers/provider-oauth/provider-oauth.component.html index c18544ae0d..b88aece27d 100644 --- a/console/src/app/modules/providers/provider-oauth/provider-oauth.component.html +++ b/console/src/app/modules/providers/provider-oauth/provider-oauth.component.html @@ -101,7 +101,13 @@
- diff --git a/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts b/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts index 598b84573a..e789e89eb4 100644 --- a/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts +++ b/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts @@ -3,7 +3,7 @@ import { Location } from '@angular/common'; import { Component, Injector, Type } from '@angular/core'; import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { take } from 'rxjs'; import { AddGenericOAuthProviderRequest as AdminAddGenericOAuthProviderRequest, @@ -18,6 +18,7 @@ import { } from 'src/app/proto/generated/zitadel/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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 { requiredValidator } from '../../form-field/validators/validators'; @@ -44,7 +45,7 @@ export class ProviderOAuthComponent { public provider?: Provider.AsObject; constructor( - private router: Router, + private authService: GrpcAuthService, private route: ActivatedRoute, private toast: ToastService, private injector: Injector, @@ -62,6 +63,23 @@ export class ProviderOAuthComponent { scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []), }); + this.authService + .isAllowed( + this.serviceType === PolicyComponentServiceType.ADMIN + ? ['iam.idp.write'] + : this.serviceType === PolicyComponentServiceType.MGMT + ? ['org.idp.write'] + : [], + ) + .pipe(take(1)) + .subscribe((allowed) => { + if (allowed) { + this.form.enable(); + } else { + this.form.disable(); + } + }); + this.route.data.pipe(take(1)).subscribe((data) => { this.serviceType = data.serviceType; diff --git a/console/src/app/modules/providers/provider-oauth/provider-oauth.module.ts b/console/src/app/modules/providers/provider-oauth/provider-oauth.module.ts deleted file mode 100644 index 0cbe334707..0000000000 --- a/console/src/app/modules/providers/provider-oauth/provider-oauth.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderOAuthRoutingModule } from './provider-oauth-routing.module'; -import { ProviderOAuthComponent } from './provider-oauth.component'; - -@NgModule({ - declarations: [ProviderOAuthComponent], - imports: [ - ProviderOAuthRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderOAuthModule {} diff --git a/console/src/app/modules/providers/provider-oidc/provider-oidc-routing.module.ts b/console/src/app/modules/providers/provider-oidc/provider-oidc-routing.module.ts deleted file mode 100644 index c42248bd33..0000000000 --- a/console/src/app/modules/providers/provider-oidc/provider-oidc-routing.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { ProviderOIDCComponent } from './provider-oidc.component'; - -const routes: Routes = [ - { - path: '', - component: ProviderOIDCComponent, - data: { animation: 'DetailPage' }, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class ProviderOIDCRoutingModule {} diff --git a/console/src/app/modules/providers/provider-oidc/provider-oidc.component.html b/console/src/app/modules/providers/provider-oidc/provider-oidc.component.html index 49805f4405..a33b4aa3d9 100644 --- a/console/src/app/modules/providers/provider-oidc/provider-oidc.component.html +++ b/console/src/app/modules/providers/provider-oidc/provider-oidc.component.html @@ -11,7 +11,7 @@

{{ 'IDP.CREATE.OIDC.DESCRIPTION' | translate }}

-
+
{{ 'IDP.NAME' | translate }} @@ -86,7 +86,13 @@
- diff --git a/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts b/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts index edfeaf3639..6302df15c6 100644 --- a/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts +++ b/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts @@ -37,7 +37,7 @@ export class ProviderOIDCComponent { public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT; private service!: ManagementService | AdminService; public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE]; - public oidcFormGroup!: UntypedFormGroup; + public form!: UntypedFormGroup; public loading: boolean = false; @@ -50,7 +50,7 @@ export class ProviderOIDCComponent { private _location: Location, breadcrumbService: BreadcrumbService, ) { - this.oidcFormGroup = new UntypedFormGroup({ + this.form = new UntypedFormGroup({ name: new UntypedFormControl('', [requiredValidator]), clientId: new UntypedFormControl('', [requiredValidator]), clientSecret: new UntypedFormControl('', [requiredValidator]), @@ -105,7 +105,7 @@ export class ProviderOIDCComponent { this.provider = resp.idp; this.loading = false; if (this.provider?.config?.oidc) { - this.oidcFormGroup.patchValue(this.provider.config.oidc); + this.form.patchValue(this.provider.config.oidc); this.name?.setValue(this.provider.name); } }) @@ -204,22 +204,22 @@ export class ProviderOIDCComponent { } public get name(): AbstractControl | null { - return this.oidcFormGroup.get('name'); + return this.form.get('name'); } public get clientId(): AbstractControl | null { - return this.oidcFormGroup.get('clientId'); + return this.form.get('clientId'); } public get clientSecret(): AbstractControl | null { - return this.oidcFormGroup.get('clientSecret'); + return this.form.get('clientSecret'); } public get issuer(): AbstractControl | null { - return this.oidcFormGroup.get('issuer'); + return this.form.get('issuer'); } public get scopesList(): AbstractControl | null { - return this.oidcFormGroup.get('scopesList'); + return this.form.get('scopesList'); } } diff --git a/console/src/app/modules/providers/provider-oidc/provider-oidc.module.ts b/console/src/app/modules/providers/provider-oidc/provider-oidc.module.ts deleted file mode 100644 index 3f55a8a132..0000000000 --- a/console/src/app/modules/providers/provider-oidc/provider-oidc.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatIconModule } from '@angular/material/icon'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; -import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; -import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; -import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; -import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; -import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; -import { TranslateModule } from '@ngx-translate/core'; -import { InputModule } from 'src/app/modules/input/input.module'; - -import { CardModule } from '../../card/card.module'; -import { CreateLayoutModule } from '../../create-layout/create-layout.module'; -import { InfoSectionModule } from '../../info-section/info-section.module'; -import { ProviderOptionsModule } from '../../provider-options/provider-options.module'; -import { ProviderOIDCRoutingModule } from './provider-oidc-routing.module'; -import { ProviderOIDCComponent } from './provider-oidc.component'; - -@NgModule({ - declarations: [ProviderOIDCComponent], - imports: [ - ProviderOIDCRoutingModule, - CommonModule, - FormsModule, - ReactiveFormsModule, - CreateLayoutModule, - InfoSectionModule, - InputModule, - MatButtonModule, - MatSelectModule, - MatIconModule, - MatChipsModule, - CardModule, - MatCheckboxModule, - MatTooltipModule, - TranslateModule, - ProviderOptionsModule, - MatLegacyProgressSpinnerModule, - ], -}) -export default class ProviderOIDCModule {} diff --git a/console/src/app/modules/providers/providers-routing.module.ts b/console/src/app/modules/providers/providers-routing.module.ts new file mode 100644 index 0000000000..91301cf3b5 --- /dev/null +++ b/console/src/app/modules/providers/providers-routing.module.ts @@ -0,0 +1,52 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { ProviderType } from 'src/app/proto/generated/zitadel/idp_pb'; +import { ProviderAzureADComponent } from './provider-azure-ad/provider-azure-ad.component'; +import { ProviderGithubESComponent } from './provider-github-es/provider-github-es.component'; +import { ProviderGithubComponent } from './provider-github/provider-github.component'; +import { ProviderGitlabSelfHostedComponent } from './provider-gitlab-self-hosted/provider-gitlab-self-hosted.component'; +import { ProviderGitlabComponent } from './provider-gitlab/provider-gitlab.component'; +import { ProviderGoogleComponent } from './provider-google/provider-google.component'; +import { ProviderJWTComponent } from './provider-jwt/provider-jwt.component'; +import { ProviderLDAPComponent } from './provider-ldap/provider-ldap.component'; +import { ProviderOAuthComponent } from './provider-oauth/provider-oauth.component'; +import { ProviderOIDCComponent } from './provider-oidc/provider-oidc.component'; + +const typeMap = { + [ProviderType.PROVIDER_TYPE_AZURE_AD]: { path: 'azure', component: ProviderAzureADComponent }, + [ProviderType.PROVIDER_TYPE_GITHUB]: { path: 'github', component: ProviderGithubComponent }, + [ProviderType.PROVIDER_TYPE_GITHUB_ES]: { path: 'github-es', component: ProviderGithubESComponent }, + [ProviderType.PROVIDER_TYPE_GITLAB]: { path: 'gitlab', component: ProviderGitlabComponent }, + [ProviderType.PROVIDER_TYPE_GITLAB_SELF_HOSTED]: { + path: 'gitlab-self-hosted', + component: ProviderGitlabSelfHostedComponent, + }, + [ProviderType.PROVIDER_TYPE_GOOGLE]: { path: 'google', component: ProviderGoogleComponent }, + [ProviderType.PROVIDER_TYPE_JWT]: { path: 'jwt', component: ProviderJWTComponent }, + [ProviderType.PROVIDER_TYPE_OAUTH]: { path: 'oauth', component: ProviderOAuthComponent }, + [ProviderType.PROVIDER_TYPE_OIDC]: { path: 'oidc', component: ProviderOIDCComponent }, + [ProviderType.PROVIDER_TYPE_LDAP]: { path: 'ldap', component: ProviderLDAPComponent }, +}; + +const routes: Routes = Object.entries(typeMap).map(([key, value]) => { + return { + path: value.path, + children: [ + { + path: 'create', + component: value.component, + }, + { + path: ':id', + component: value.component, + }, + ], + }; +}); + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class ProvidersRoutingModule {} diff --git a/console/src/app/modules/providers/providers.module.ts b/console/src/app/modules/providers/providers.module.ts new file mode 100644 index 0000000000..b002ba41a0 --- /dev/null +++ b/console/src/app/modules/providers/providers.module.ts @@ -0,0 +1,68 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatIconModule } from '@angular/material/icon'; +import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; +import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; +import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; +import { MatLegacyProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; +import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; +import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; +import { TranslateModule } from '@ngx-translate/core'; +import { InputModule } from 'src/app/modules/input/input.module'; + +import { CardModule } from '../card/card.module'; +import { CreateLayoutModule } from '../create-layout/create-layout.module'; +import { InfoSectionModule } from '../info-section/info-section.module'; +import { ProviderOptionsModule } from '../provider-options/provider-options.module'; +import { StringListModule } from '../string-list/string-list.module'; +import { LDAPAttributesComponent } from './ldap-attributes/ldap-attributes.component'; +import { ProviderAzureADComponent } from './provider-azure-ad/provider-azure-ad.component'; +import { ProviderGithubESComponent } from './provider-github-es/provider-github-es.component'; +import { ProviderGithubComponent } from './provider-github/provider-github.component'; +import { ProviderGitlabSelfHostedComponent } from './provider-gitlab-self-hosted/provider-gitlab-self-hosted.component'; +import { ProviderGitlabComponent } from './provider-gitlab/provider-gitlab.component'; +import { ProviderGoogleComponent } from './provider-google/provider-google.component'; +import { ProviderJWTComponent } from './provider-jwt/provider-jwt.component'; +import { ProviderLDAPComponent } from './provider-ldap/provider-ldap.component'; +import { ProviderOAuthComponent } from './provider-oauth/provider-oauth.component'; +import { ProviderOIDCComponent } from './provider-oidc/provider-oidc.component'; +import { ProvidersRoutingModule } from './providers-routing.module'; + +@NgModule({ + declarations: [ + ProviderGoogleComponent, + ProviderGithubComponent, + ProviderGithubESComponent, + ProviderAzureADComponent, + LDAPAttributesComponent, + ProviderGitlabSelfHostedComponent, + ProviderGitlabComponent, + ProviderGithubESComponent, + ProviderJWTComponent, + ProviderOIDCComponent, + ProviderOAuthComponent, + ProviderLDAPComponent, + ], + imports: [ + ProvidersRoutingModule, + CommonModule, + FormsModule, + ReactiveFormsModule, + CreateLayoutModule, + StringListModule, + InfoSectionModule, + InputModule, + MatButtonModule, + MatSelectModule, + MatIconModule, + MatChipsModule, + CardModule, + MatCheckboxModule, + MatTooltipModule, + TranslateModule, + ProviderOptionsModule, + MatLegacyProgressSpinnerModule, + ], +}) +export default class ProvidersModule {} diff --git a/console/src/app/modules/providers/providers.scss b/console/src/app/modules/providers/providers.scss index a506e4bbf4..cb3ccaddf7 100644 --- a/console/src/app/modules/providers/providers.scss +++ b/console/src/app/modules/providers/providers.scss @@ -25,6 +25,12 @@ } } + .idp-icon { + font-size: 36px; + margin-right: 1rem; + flex-shrink: 0; + } + h1 { margin: 0 1rem 0 0; } @@ -54,6 +60,20 @@ } .identity-provider-content { + display: flex; + flex-direction: column; + + .subheader { + margin: 2rem 0 0.5rem 0; + } + + .identity-provider-2-col { + max-width: 400px; + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 1rem; + } + .desc { margin-bottom: 1rem; } @@ -93,7 +113,7 @@ align-items: center; h2 { - margin-right: 0.25rem; + margin: 1rem 0.25rem 1rem 0; } } } diff --git a/console/src/app/modules/string-list/string-list.component.html b/console/src/app/modules/string-list/string-list.component.html new file mode 100644 index 0000000000..936bc9159f --- /dev/null +++ b/console/src/app/modules/string-list/string-list.component.html @@ -0,0 +1,30 @@ + + + {{ title }} + + + + + +
+
+ {{ str }} + + +
+
diff --git a/console/src/app/modules/string-list/string-list.component.scss b/console/src/app/modules/string-list/string-list.component.scss new file mode 100644 index 0000000000..2d1779eb72 --- /dev/null +++ b/console/src/app/modules/string-list/string-list.component.scss @@ -0,0 +1,60 @@ +@use '@angular/material' as mat; + +@mixin string-list-theme($theme) { + $foreground: map-get($theme, foreground); + $background: map-get($theme, background); + $is-dark-theme: map-get($theme, is-dark); + $warn: map-get($theme, warn); + $warn-color: map-get($warn, 500); + $button-text-color: map-get($foreground, text); + $button-disabled-text-color: map-get($foreground, disabled-button); + $divider-color: map-get($foreground, dividers); + $secondary-text: map-get($foreground, secondary-text); + + .string-list { + width: 100%; + max-width: 400px; + + .value-line { + display: flex; + align-items: center; + margin: 0.5rem 0; + padding: 0 0 0 0.75rem; + border-radius: 4px; + background: map-get($background, infosection); + + .fill-space { + flex: 1; + } + + .icon-button { + height: 30px; + line-height: 30px; + + .icon { + font-size: 1rem; + margin-bottom: 3px; + } + + &:not(:hover) { + color: $secondary-text; + } + } + } + } +} + +.string-list-form { + display: flex; + align-items: flex-end; + min-width: 320px; + + .formfield { + width: 500px; + } + + button { + margin-bottom: 0.9rem; + margin-right: -0.5rem; + } +} diff --git a/console/src/app/modules/string-list/string-list.component.spec.ts b/console/src/app/modules/string-list/string-list.component.spec.ts new file mode 100644 index 0000000000..d316e51447 --- /dev/null +++ b/console/src/app/modules/string-list/string-list.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StringListComponent } from './string-list.component'; + +describe('StringListComponent', () => { + let component: StringListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [StringListComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StringListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/console/src/app/modules/string-list/string-list.component.ts b/console/src/app/modules/string-list/string-list.component.ts new file mode 100644 index 0000000000..3afa966aa1 --- /dev/null +++ b/console/src/app/modules/string-list/string-list.component.ts @@ -0,0 +1,100 @@ +import { Component, forwardRef, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { Observable, Subject, takeUntil } from 'rxjs'; +import { requiredValidator } from '../form-field/validators/validators'; + +@Component({ + selector: 'cnsl-string-list', + templateUrl: './string-list.component.html', + styleUrls: ['./string-list.component.scss'], + encapsulation: ViewEncapsulation.None, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => StringListComponent), + multi: true, + }, + ], +}) +export class StringListComponent implements ControlValueAccessor, OnInit, OnDestroy { + @Input() title: string = ''; + @Input() required: boolean = false; + @Input() public getValues: Observable = new Observable(); // adds formfieldinput to array on emission + + @Input() public control: FormControl = new FormControl({ value: '', disabled: true }); + private destroy$: Subject = new Subject(); + @ViewChild('redInput') input!: any; + private val: string[] = []; + + ngOnInit(): void { + this.getValues.pipe(takeUntil(this.destroy$)).subscribe(() => { + this.add(this.input.nativeElement); + }); + + this.required ? this.control.setValidators([requiredValidator]) : this.control.setValidators([]); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + onChange: any = () => {}; + onTouch: any = () => {}; + + set value(val: string[]) { + if (val !== undefined && this.val !== val) { + this.val = val; + this.onChange(val); + this.onTouch(val); + } + } + + get value() { + return this.val; + } + + writeValue(value: string[]) { + this.value = value; + } + + registerOnChange(fn: any) { + this.onChange = fn; + } + + registerOnTouched(fn: any) { + this.onTouch = fn; + } + + public setDisabledState(isDisabled: boolean): void { + if (isDisabled) { + this.control.disable(); + } else { + this.control.enable(); + } + } + + public add(input: any): void { + if (this.control.valid) { + const trimmed = input.value.trim(); + if (trimmed) { + this.val ? this.val.push(input.value) : (this.val = [input.value]); + this.onChange(this.val); + this.onTouch(this.val); + } + if (input) { + input.value = ''; + } + } + } + + public remove(str: string): void { + const index = this.value.indexOf(str); + + if (index >= 0) { + this.value.splice(index, 1); + this.onChange(this.value); + this.onTouch(this.value); + } + } +} diff --git a/console/src/app/modules/string-list/string-list.module.ts b/console/src/app/modules/string-list/string-list.module.ts new file mode 100644 index 0000000000..fe72b2adaa --- /dev/null +++ b/console/src/app/modules/string-list/string-list.module.ts @@ -0,0 +1,25 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatIconModule } from '@angular/material/icon'; +import { MatLegacyButtonModule } from '@angular/material/legacy-button'; +import { MatLegacyTooltipModule } from '@angular/material/legacy-tooltip'; +import { TranslateModule } from '@ngx-translate/core'; +import { InputModule } from '../input/input.module'; +import { StringListComponent } from './string-list.component'; + +@NgModule({ + declarations: [StringListComponent], + imports: [ + CommonModule, + InputModule, + FormsModule, + ReactiveFormsModule, + TranslateModule, + MatIconModule, + MatLegacyTooltipModule, + MatLegacyButtonModule, + ], + exports: [StringListComponent], +}) +export class StringListModule {} diff --git a/console/src/app/pages/instance/instance-routing.module.ts b/console/src/app/pages/instance/instance-routing.module.ts index 273858d5f5..c88cbafaf7 100644 --- a/console/src/app/pages/instance/instance-routing.module.ts +++ b/console/src/app/pages/instance/instance-routing.module.ts @@ -26,131 +26,11 @@ const routes: Routes = [ { path: 'provider', canActivate: [AuthGuard, RoleGuard], + loadChildren: () => import('src/app/modules/providers/providers.module'), data: { - roles: ['iam.idp.write'], + roles: ['iam.idp.read'], serviceType: PolicyComponentServiceType.ADMIN, }, - children: [ - { - path: 'azure-ad', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'), - }, - ], - }, - { - path: 'oidc', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-oidc/provider-oidc.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-oidc/provider-oidc.module'), - }, - ], - }, - { - path: 'oauth', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'), - }, - ], - }, - { - path: 'github-es', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-github-es/provider-github-es.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-github-es/provider-github-es.module'), - }, - ], - }, - { - path: 'jwt', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-jwt/provider-jwt.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-jwt/provider-jwt.module'), - }, - ], - }, - { - path: 'google', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-google/provider-google.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-google/provider-google.module'), - }, - ], - }, - { - path: 'gitlab', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-gitlab/provider-gitlab.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-gitlab/provider-gitlab.module'), - }, - ], - }, - { - path: 'gitlab-self-hosted', - children: [ - { - path: 'create', - loadChildren: () => - import('src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module'), - }, - { - path: ':id', - loadChildren: () => - import('src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module'), - }, - ], - }, - { - path: 'github', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'), - }, - ], - }, - ], }, ]; diff --git a/console/src/app/pages/orgs/org-routing.module.ts b/console/src/app/pages/orgs/org-routing.module.ts index 89241b30b9..0f79b185e7 100644 --- a/console/src/app/pages/orgs/org-routing.module.ts +++ b/console/src/app/pages/orgs/org-routing.module.ts @@ -14,131 +14,11 @@ const routes: Routes = [ { path: 'provider', canActivate: [AuthGuard, RoleGuard], + loadChildren: () => import('src/app/modules/providers/providers.module'), data: { - roles: ['org.idp.write'], + roles: ['org.idp.read'], serviceType: PolicyComponentServiceType.MGMT, }, - children: [ - { - path: 'oauth', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-oauth/provider-oauth.module'), - }, - ], - }, - { - path: 'oidc', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-oidc/provider-oidc.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-oidc/provider-oidc.module'), - }, - ], - }, - { - path: 'github-es', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-github-es/provider-github-es.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-github-es/provider-github-es.module'), - }, - ], - }, - { - path: 'jwt', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-jwt/provider-jwt.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-jwt/provider-jwt.module'), - }, - ], - }, - { - path: 'google', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-google/provider-google.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-google/provider-google.module'), - }, - ], - }, - { - path: 'gitlab', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-gitlab/provider-gitlab.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-gitlab/provider-gitlab.module'), - }, - ], - }, - { - path: 'gitlab-self-hosted', - children: [ - { - path: 'create', - loadChildren: () => - import('src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module'), - }, - { - path: ':id', - loadChildren: () => - import('src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.module'), - }, - ], - }, - { - path: 'github', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-github/provider-github.module'), - }, - ], - }, - { - path: 'azure-ad', - children: [ - { - path: 'create', - loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'), - }, - { - path: ':id', - loadChildren: () => import('src/app/modules/providers/provider-azure-ad/provider-azure-ad.module'), - }, - ], - }, - ], }, { path: '', diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.html b/console/src/app/pages/projects/apps/app-create/app-create.component.html index a31a937ddc..e078c5a67e 100644 --- a/console/src/app/pages/projects/apps/app-create/app-create.component.html +++ b/console/src/app/pages/projects/apps/app-create/app-create.component.html @@ -110,10 +110,9 @@ @@ -431,20 +429,18 @@
this.getData(params)); diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html index 68f1508aa2..bc18c9bcfc 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html @@ -334,11 +334,9 @@ @@ -347,11 +345,9 @@ diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss b/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss index 93c2523962..32bb796a9f 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss @@ -268,12 +268,6 @@ margin-bottom: 1.5rem; } -.error { - font-size: 13px; - color: var(--warn); - margin: 0 0.5rem 1.5rem 0.5rem; -} - .btn-container { display: flex; justify-content: flex-end; diff --git a/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.html b/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.html index 56903473f5..970dbe3a0f 100644 --- a/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.html +++ b/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.html @@ -8,14 +8,14 @@ matTooltip="{{ 'ACTIONS.ADD' | translate }}" type="submit" mat-icon-button - [disabled]="redirectControl.invalid || !canWrite" + [disabled]="redirectControl.invalid || redirectControl.disabled" > add
-
+
-
diff --git a/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.ts b/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.ts index 229a5ee1c1..94cd8093b7 100644 --- a/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.ts +++ b/console/src/app/pages/projects/apps/redirect-uris/redirect-uris.component.ts @@ -1,44 +1,83 @@ -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; -import { UntypedFormControl } from '@angular/forms'; -import { Observable, Subscription } from 'rxjs'; +import { Component, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { Observable, Subject, takeUntil } from 'rxjs'; @Component({ selector: 'cnsl-redirect-uris', templateUrl: './redirect-uris.component.html', styleUrls: ['./redirect-uris.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RedirectUrisComponent), + multi: true, + }, + ], }) -export class RedirectUrisComponent implements OnInit, OnDestroy { +export class RedirectUrisComponent implements ControlValueAccessor, OnInit, OnDestroy { @Input() title: string = ''; @Input() devMode: boolean = false; - @Input() canWrite: boolean = false; @Input() isNative!: boolean; - @Input() public urisList: string[] = []; - @Input() public redirectControl: UntypedFormControl = new UntypedFormControl({ value: '', disabled: true }); - @Output() public changedUris: EventEmitter = new EventEmitter(); - @Input() public getValues: Observable = new Observable(); + @Input() public getValues: Observable = new Observable(); // adds formfieldinput to array on emission + public redirectControl: FormControl = new FormControl({ value: '', disabled: true }); + private destroy$: Subject = new Subject(); @ViewChild('redInput') input!: any; - private sub: Subscription = new Subscription(); - constructor() {} ngOnInit(): void { - if (this.canWrite) { - this.redirectControl.enable(); - } - - this.sub = this.getValues.subscribe(() => { + this.getValues.pipe(takeUntil(this.destroy$)).subscribe(() => { this.add(this.input.nativeElement); }); } ngOnDestroy(): void { - this.sub.unsubscribe(); + this.destroy$.next(); + this.destroy$.complete(); + } + + onChange: any = () => {}; + onTouch: any = () => {}; + + private val: string[] = []; + + set value(val: string[]) { + if (val !== undefined && this.val !== val) { + this.val = val; + this.onChange(val); + this.onTouch(val); + } + } + + get value() { + return this.val; + } + + writeValue(value: string[]) { + this.value = value; + } + + registerOnChange(fn: any) { + this.onChange = fn; + } + + registerOnTouched(fn: any) { + this.onTouch = fn; + } + + public setDisabledState(isDisabled: boolean): void { + if (isDisabled) { + this.redirectControl.disable(); + } else { + this.redirectControl.enable(); + } } public add(input: any): void { if (this.redirectControl.valid) { if (input.value !== '' && input.value !== ' ' && input.value !== '/') { - this.urisList.push(input.value); + this.val.push(input.value); + this.onChange(this.val); + this.onTouch(this.val); } if (input) { input.value = ''; @@ -47,10 +86,12 @@ export class RedirectUrisComponent implements OnInit, OnDestroy { } public remove(redirect: any): void { - const index = this.urisList.indexOf(redirect); + const index = this.value.indexOf(redirect); if (index >= 0) { - this.urisList.splice(index, 1); + this.value.splice(index, 1); + this.onChange(this.value); + this.onTouch(this.value); } } } diff --git a/console/src/app/services/admin.service.ts b/console/src/app/services/admin.service.ts index e7e97f0b9a..25b3620efb 100644 --- a/console/src/app/services/admin.service.ts +++ b/console/src/app/services/admin.service.ts @@ -30,6 +30,8 @@ import { AddIDPToLoginPolicyResponse, AddJWTProviderRequest, AddJWTProviderResponse, + AddLDAPProviderRequest, + AddLDAPProviderResponse, AddMultiFactorToLoginPolicyRequest, AddMultiFactorToLoginPolicyResponse, AddNotificationPolicyRequest, @@ -226,6 +228,8 @@ import { UpdateJWTProviderResponse, UpdateLabelPolicyRequest, UpdateLabelPolicyResponse, + UpdateLDAPProviderRequest, + UpdateLDAPProviderResponse, UpdateLockoutPolicyRequest, UpdateLockoutPolicyResponse, UpdateLoginPolicyRequest, @@ -926,6 +930,14 @@ export class AdminService { return this.grpcService.admin.updateGoogleProvider(req, null).then((resp) => resp.toObject()); } + public addLDAPProvider(req: AddLDAPProviderRequest): Promise { + return this.grpcService.admin.addLDAPProvider(req, null).then((resp) => resp.toObject()); + } + + public updateLDAPProvider(req: UpdateLDAPProviderRequest): Promise { + return this.grpcService.admin.updateLDAPProvider(req, null).then((resp) => resp.toObject()); + } + public addGitLabProvider(req: AddGitLabProviderRequest): Promise { return this.grpcService.admin.addGitLabProvider(req, null).then((resp) => resp.toObject()); } diff --git a/console/src/app/services/mgmt.service.ts b/console/src/app/services/mgmt.service.ts index 93a8036f8d..37f5f14984 100644 --- a/console/src/app/services/mgmt.service.ts +++ b/console/src/app/services/mgmt.service.ts @@ -51,6 +51,8 @@ import { AddIDPToLoginPolicyResponse, AddJWTProviderRequest, AddJWTProviderResponse, + AddLDAPProviderRequest, + AddLDAPProviderResponse, AddMachineKeyRequest, AddMachineKeyResponse, AddMachineUserRequest, @@ -461,6 +463,8 @@ import { UpdateHumanProfileResponse, UpdateJWTProviderRequest, UpdateJWTProviderResponse, + UpdateLDAPProviderRequest, + UpdateLDAPProviderResponse, UpdateMachineRequest, UpdateMachineResponse, UpdateOIDCAppConfigRequest, @@ -885,6 +889,14 @@ export class ManagementService { return this.grpcService.mgmt.updateGoogleProvider(req, null).then((resp) => resp.toObject()); } + public addLDAPProvider(req: AddLDAPProviderRequest): Promise { + return this.grpcService.mgmt.addLDAPProvider(req, null).then((resp) => resp.toObject()); + } + + public updateLDAPProvider(req: UpdateLDAPProviderRequest): Promise { + return this.grpcService.mgmt.updateLDAPProvider(req, null).then((resp) => resp.toObject()); + } + public addGitLabProvider(req: AddGitLabProviderRequest): Promise { return this.grpcService.mgmt.addGitLabProvider(req, null).then((resp) => resp.toObject()); } diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index c00cfe6cec..4b48c22db7 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -1648,6 +1648,10 @@ "AZUREAD": { "TITLE": "Microsoft Provider", "DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren Microsoft-Identitätsprovider ein." + }, + "LDAP": { + "TITLE": "Active Directory / LDAP", + "DESCRIPTION": "Geben Sie die erforderlichen Daten für Ihren LDAP Provider ein." } }, "DETAIL": { @@ -1690,6 +1694,8 @@ "EMAILVERIFIED": "Email verifiziert", "NAMEHINT": "Wenn angegeben, wir er im Login interface angezeigt.", "OPTIONAL": "optional", + "LDAPATTRIBUTES": "LDAP Attribute", + "UPDATEBINDPASSWORD": "Bind Password updaten", "UPDATECLIENTSECRET": "Client Secret updaten", "ADD": "Identity Provider hinzufügen", "TYPE": "Typ", @@ -1711,6 +1717,31 @@ "SCOPESLIST": "Scopes List", "CLIENTID": "Client ID", "CLIENTSECRET": "Client Secret", + "LDAPCONNECTION": "Verbindung", + "LDAPUSERBINDING": "User binding", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in Sekunden", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "erfolderlich", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "IDP Anzeigename Mapping", "USERNAMEMAPPING": "Username Mapping", "DATES": "Datum", diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index 2a6cd36f0b..8c24142f44 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -1653,6 +1653,10 @@ "AZUREAD": { "TITLE": "Microsoft Provider", "DESCRIPTION": "Enter the credentials for your Microsoft Identity Provider" + }, + "LDAP": { + "TITLE": "Active Directory / LDAP", + "DESCRIPTION": "Enter the credentials for your LDAP Provider" } }, "DETAIL": { @@ -1690,6 +1694,8 @@ "EMAILVERIFIED": "Email verified", "NAMEHINT": "If specified it will be shown in the login interface.", "OPTIONAL": "optional", + "LDAPATTRIBUTES": "LDAP Attributes", + "UPDATEBINDPASSWORD": "update Bind Password", "UPDATECLIENTSECRET": "update client secret", "ADD": "Add Identity Provider", "TYPE": "Type", @@ -1711,6 +1717,31 @@ "SCOPESLIST": "Scopes List", "CLIENTID": "Client ID", "CLIENTSECRET": "Client Secret", + "LDAPCONNECTION": "Connection", + "LDAPUSERBINDING": "User binding", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in seconds", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "required", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "IDP Display Name Mapping", "USERNAMEMAPPING": "Username Mapping", "DATES": "Dates", diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json index 715388d9d1..06f9a9b5e4 100644 --- a/console/src/assets/i18n/fr.json +++ b/console/src/assets/i18n/fr.json @@ -1652,6 +1652,10 @@ "AZUREAD": { "TITLE": "Fournisseur Microsoft", "DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité Microsoft" + }, + "LDAP": { + "TITLE": "Active Directory / LDAP", + "DESCRIPTION": "Saisissez les informations d'identification de votre fournisseur d'identité LDAP" } }, "DETAIL": { @@ -1694,6 +1698,8 @@ "EMAILVERIFIED": "Courriel vérifié", "NAMEHINT": "Si elle est spécifiée, elle sera affichée dans l'interface de connexion.", "OPTIONAL": "optionnel", + "LDAPATTRIBUTES": "Attributs LDAP", + "UPDATEBINDPASSWORD": "mettre à jour le mot de bind password", "UPDATECLIENTSECRET": "mise à jour du secret client", "ADD": "Ajouter un fournisseur d'identité", "TYPE": "Type", @@ -1715,6 +1721,31 @@ "SCOPESLIST": "Liste des champs d'application", "CLIENTID": "ID du client", "CLIENTSECRET": "Secret du client", + "LDAPCONNECTION": "Connexion", + "LDAPUSERBINDING": "Enchères utilisateur", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in seconds", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "requis", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "Mappage de IDP nom d'affichage", "USERNAMEMAPPING": "Mappage des noms d'utilisateur", "DATES": "Dates", diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json index 32037f67ab..ac7ed3323a 100644 --- a/console/src/assets/i18n/it.json +++ b/console/src/assets/i18n/it.json @@ -1653,6 +1653,10 @@ "AZUREAD": { "TITLE": "Microsoft Provider", "DESCRIPTION": "Inserisci i dati necessari per il tuo Microsoft provider." + }, + "LDAP": { + "TITLE": "Active Directory / LDAP", + "DESCRIPTION": "Inserisci i dati necessari per il tuo provider LDAP." } }, "DETAIL": { @@ -1695,6 +1699,8 @@ "EMAILVERIFIED": "Email verificata", "NAMEHINT": "Se specificato, verrà mostrato nell'interfaccia di accesso.", "OPTIONAL": "opzionale", + "LDAPATTRIBUTES": "Attributi LDAP", + "UPDATEBINDPASSWORD": "aggiorna Bind Password", "UPDATECLIENTSECRET": "Aggiorna secret", "ADD": "Aggiungi Identity Provider", "TYPE": "Tipo", @@ -1716,6 +1722,31 @@ "SCOPESLIST": "Scope list", "CLIENTID": "Client ID", "CLIENTSECRET": "Client Secret", + "LDAPCONNECTION": "Connessione", + "LDAPUSERBINDING": "User binding", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in seconds", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "necessario", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "Mapping del nome di visualizzazione IDP", "USERNAMEMAPPING": "Mapping del nome utente", "DATES": "Date", diff --git a/console/src/assets/i18n/ja.json b/console/src/assets/i18n/ja.json index f2dcc078aa..bab05f88ad 100644 --- a/console/src/assets/i18n/ja.json +++ b/console/src/assets/i18n/ja.json @@ -1653,6 +1653,10 @@ "AZUREAD": { "TITLE": "Microsoftプロバイダー", "DESCRIPTION": "Microsoftプロバイダーのクレデンシャルを入力してください。" + }, + "LDAP": { + "TITLE": "LDAPプロバイダー", + "DESCRIPTION": "LDAPプロバイダーのクレデンシャルを入力してください。" } }, "DETAIL": { @@ -1690,6 +1694,8 @@ "EMAILVERIFIED": "検証済みメールアドレス", "NAMEHINT": "指定されている場合、ログイン画面に表示されます。", "OPTIONAL": "オプション", + "LDAPATTRIBUTES": "LDAP 属性", + "UPDATEBINDPASSWORD": "バインドパスワードの更新", "UPDATECLIENTSECRET": "クライアントシークレットを更新する", "ADD": "IDプロバイダーを追加する", "TYPE": "タイプ", @@ -1711,6 +1717,31 @@ "SCOPESLIST": "スコープリスト", "CLIENTID": "クライアントID", "CLIENTSECRET": "クライアントシークレット", + "LDAPCONNECTION": "繋がり", + "LDAPUSERBINDING": "ユーザーバインディング", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in seconds", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "必要", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "IDP表示名マッピング", "USERNAMEMAPPING": "ユーザー名マッピング", "DATES": "日付", diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json index 4ee5bfe39a..e77e3cc92a 100644 --- a/console/src/assets/i18n/pl.json +++ b/console/src/assets/i18n/pl.json @@ -1652,6 +1652,10 @@ "AZUREAD": { "TITLE": "Microsoft Provider", "DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości Microsoft" + }, + "LDAP": { + "TITLE": "LDAP Provider", + "DESCRIPTION": "Wprowadź dane dla swojego dostawcy tożsamości LDAP" } }, "DETAIL": { @@ -1694,6 +1698,8 @@ "EMAILVERIFIED": "Email zweryfikowany", "NAMEHINT": "Jeśli zostanie podany, będzie widoczny w interfejsie logowania.", "OPTIONAL": "opcjonalnie", + "LDAPATTRIBUTES": "LDAP Atrybuty", + "UPDATEBINDPASSWORD": "aktualizacja bind password", "UPDATECLIENTSECRET": "aktualizacja tajemnicy klienta", "ADD": "Dodaj dostawcę tożsamości", "TYPE": "Typ", @@ -1715,6 +1721,31 @@ "SCOPESLIST": "Lista zakresów", "CLIENTID": "Identyfikator klienta", "CLIENTSECRET": "Tajne klienta", + "LDAPCONNECTION": "Połączenie", + "LDAPUSERBINDING": "Wiązanie użytkownika", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in seconds", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "wymagany", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "Mapowanie wyświetlanej nazwy IDP", "USERNAMEMAPPING": "Mapowanie nazwy użytkownika", "DATES": "Daty", diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json index 68adfa84aa..bd989f7cca 100644 --- a/console/src/assets/i18n/zh.json +++ b/console/src/assets/i18n/zh.json @@ -1651,6 +1651,10 @@ "AZUREAD": { "TITLE": "Microsoft 身份提供者", "DESCRIPTION": "输入您的 Microsoft 身份提供商的凭据" + }, + "LDAP": { + "TITLE": "LDAP 身份提供者", + "DESCRIPTION": "输入您的 LDAP 身份提供商的凭据" } }, "DETAIL": { @@ -1693,6 +1697,8 @@ "EMAILVERIFIED": "电子邮件已验证", "NAMEHINT": "如果指定,它将显示在登录界面。", "OPTIONAL": "可选", + "LDAPATTRIBUTES": "LDAP 属性", + "UPDATEBINDPASSWORD": "更新绑定密码", "UPDATECLIENTSECRET": "更新客户秘密", "ADD": "添加身份提供者", "TYPE": "类型", @@ -1714,6 +1720,31 @@ "SCOPESLIST": "Scopes List", "CLIENTID": "Client ID", "CLIENTSECRET": "Client Secret", + "LDAPCONNECTION": "联系", + "LDAPUSERBINDING": "用户绑定", + "BASEDN": "BaseDn", + "BINDDN": "BindDn", + "BINDPASSWORD": "Bind Password", + "SERVERS": "Servers", + "STARTTLS": "Start TLS", + "TIMEOUT": "Timeout in seconds", + "USERBASE": "Userbase", + "USERFILTERS": "User filters", + "USEROBJECTCLASSES": "User Object Classes", + "REQUIRED": "必需的", + "LDAPIDATTRIBUTE": "ID attribute", + "AVATARURLATTRIBUTE": "Avatar Url attribute", + "DISPLAYNAMEATTRIBUTE": "Displayname attribute", + "EMAILATTRIBUTEATTRIBUTE": "Email attribute", + "EMAILVERIFIEDATTRIBUTE": "Email verified attribute", + "FIRSTNAMEATTRIBUTE": "Firstname attribute", + "LASTNAMEATTRIBUTE": "Lastname attribute", + "NICKNAMEATTRIBUTE": "Nickname attribute", + "PHONEATTRIBUTE": "Phone attribute", + "PHONEVERIFIEDATTRIBUTE": "Phone verified attribute", + "PREFERREDLANGUAGEATTRIBUTE": "Preferred language attribute", + "PREFERREDUSERNAMEATTRIBUTE": "Preferred username attribute", + "PROFILEATTRIBUTE": "Profile attribute", "IDPDISPLAYNAMMAPPING": "IDP 展示名称映射", "USERNAMEMAPPING": "用户名映射", "DATES": "日期", diff --git a/console/src/component-themes.scss b/console/src/component-themes.scss index 74927a0a18..88b4201422 100644 --- a/console/src/component-themes.scss +++ b/console/src/component-themes.scss @@ -42,6 +42,7 @@ @import 'src/app/modules/refresh-table/refresh-table.component.scss'; @import 'src/app/modules/form-field/field/form-field.component.scss'; @import 'src/app/modules/label/label.component.scss'; +@import 'src/app/modules/string-list/string-list.component.scss'; @import 'src/app/modules/meta-layout/meta.scss'; @import 'src/app/pages/projects/owned-projects/project-grant-detail/project-grant-illustration/project-grant-illustration.component'; @import 'src/app/modules/accounts-card/accounts-card.component.scss'; @@ -99,6 +100,7 @@ @include input-theme($theme); @include cnsl-form-field-theme($theme); @include contributors-theme($theme); + @include string-list-theme($theme); @include shortcut-theme($theme); @include message-texts-theme($theme); @include app-detail-theme($theme);