From f8616265be183520c5a6318cad614ee64a53d456 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 20 Oct 2020 11:37:17 +0200 Subject: [PATCH] fix(console): login policy, idp type filter (#875) * cleanup login policy * detail layout * disable if no custom * fix login policy filter * add styletype to idp * stylelint * lint --- console/src/app/app.component.scss | 2 +- .../detail-layout.component.html | 24 ++-- .../detail-layout.component.scss | 2 +- .../idp-table/idp-table.component.scss | 3 +- .../src/app/modules/idp/idp.component.html | 14 ++- console/src/app/modules/idp/idp.component.ts | 119 ++++++++++-------- .../add-idp-dialog.component.html | 2 +- .../add-idp-dialog.component.ts | 4 +- .../login-policy/login-policy.component.html | 71 ++++++----- .../login-policy/login-policy.component.scss | 48 +++---- .../login-policy/login-policy.component.ts | 2 + console/src/assets/i18n/de.json | 13 +- console/src/assets/i18n/en.json | 11 +- 13 files changed, 184 insertions(+), 131 deletions(-) diff --git a/console/src/app/app.component.scss b/console/src/app/app.component.scss index 34c84ede69..739ffcf6cb 100644 --- a/console/src/app/app.component.scss +++ b/console/src/app/app.component.scss @@ -168,7 +168,7 @@ .router { height: 100%; - overflow: auto; + overflow-y: auto; } } diff --git a/console/src/app/modules/detail-layout/detail-layout.component.html b/console/src/app/modules/detail-layout/detail-layout.component.html index 4e00b046b2..784bbcb764 100644 --- a/console/src/app/modules/detail-layout/detail-layout.component.html +++ b/console/src/app/modules/detail-layout/detail-layout.component.html @@ -1,14 +1,16 @@ -
- -
-
-

{{ title }}

-

{{ description }}

- +
+
+ +
+
+

{{ title }}

+

{{ description }}

+ +
\ No newline at end of file diff --git a/console/src/app/modules/detail-layout/detail-layout.component.scss b/console/src/app/modules/detail-layout/detail-layout.component.scss index bf909abc65..e7b80e7cc2 100644 --- a/console/src/app/modules/detail-layout/detail-layout.component.scss +++ b/console/src/app/modules/detail-layout/detail-layout.component.scss @@ -10,6 +10,7 @@ $lighter-color: rgba(mat-color($primary, 300), .5); .detail-container { + width: 100%; display: flex; padding-bottom: 3rem; padding-top: 3rem; @@ -29,7 +30,6 @@ .detail-right { flex: 1; - position: relative; padding-left: 1rem; @media only screen and (max-width: 500px) { diff --git a/console/src/app/modules/idp-table/idp-table.component.scss b/console/src/app/modules/idp-table/idp-table.component.scss index 3dee4b8a1b..bab489b897 100644 --- a/console/src/app/modules/idp-table/idp-table.component.scss +++ b/console/src/app/modules/idp-table/idp-table.component.scss @@ -1,11 +1,10 @@ .table-wrapper { overflow: auto; + width: 100%; .table, .paginator { - width: 100%; - td, th { padding: 0 1rem; diff --git a/console/src/app/modules/idp/idp.component.html b/console/src/app/modules/idp/idp.component.html index 56c1329b32..d97d7db75b 100644 --- a/console/src/app/modules/idp/idp.component.html +++ b/console/src/app/modules/idp/idp.component.html @@ -63,7 +63,7 @@ {{ 'IDP.IDPDISPLAYNAMMAPPING' | translate }} - {{ 'IDP.MAPPINTFIELD.'+field | translate }} + {{ 'IDP.MAPPINGFIELD.'+field | translate }} @@ -71,7 +71,15 @@ {{ 'IDP.USERNAMEMAPPING' | translate }} - {{ 'IDP.MAPPINTFIELD.'+field | translate }} + {{ 'IDP.MAPPINGFIELD.'+field | translate }} + + + + + {{ 'IDP.STYLE' | translate }} + + + {{ 'IDP.STYLEFIELD.'+field | translate }} @@ -88,4 +96,4 @@
- + \ No newline at end of file diff --git a/console/src/app/modules/idp/idp.component.ts b/console/src/app/modules/idp/idp.component.ts index 21cd6053b3..e6bd1bd72a 100644 --- a/console/src/app/modules/idp/idp.component.ts +++ b/console/src/app/modules/idp/idp.component.ts @@ -1,20 +1,22 @@ import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes'; import { Location } from '@angular/common'; -import {Component, Injector, Input, OnDestroy, OnInit, Type} from '@angular/core'; +import { Component, Injector, OnDestroy, OnInit, Type } from '@angular/core'; import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms'; import { MatChipInputEvent } from '@angular/material/chips'; import { ActivatedRoute, Params } from '@angular/router'; import { Subscription } from 'rxjs'; import { switchMap, take } from 'rxjs/operators'; import { - OIDCMappingField as authMappingFields, - OidcIdpConfigUpdate as AdminOidcIdpConfigUpdate, - IdpUpdate as AdminIdpConfigUpdate, + IdpStylingType as adminIdpStylingType, + IdpUpdate as AdminIdpConfigUpdate, + OidcIdpConfigUpdate as AdminOidcIdpConfigUpdate, + OIDCMappingField as adminMappingFields, } from 'src/app/proto/generated/admin_pb'; import { - OIDCMappingField as mgmtMappingFields, - OidcIdpConfigUpdate as MgmtOidcIdpConfigUpdate, - IdpUpdate as MgmtIdpConfigUpdate, + IdpStylingType as mgmtIdpStylingType, + IdpUpdate as MgmtIdpConfigUpdate, + OidcIdpConfigUpdate as MgmtOidcIdpConfigUpdate, + OIDCMappingField as mgmtMappingFields, } from 'src/app/proto/generated/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { ManagementService } from 'src/app/services/mgmt.service'; @@ -28,7 +30,9 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e styleUrls: ['./idp.component.scss'], }) export class IdpComponent implements OnInit, OnDestroy { - public mappingFields: mgmtMappingFields[] | authMappingFields[] = []; + public mappingFields: mgmtMappingFields[] | adminMappingFields[] = []; + public styleFields: mgmtIdpStylingType[] | adminIdpStylingType[] = []; + public showIdSecretSection: boolean = false; public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT; private service!: ManagementService | AdminService; @@ -41,7 +45,6 @@ export class IdpComponent implements OnInit, OnDestroy { public oidcConfigForm!: FormGroup; constructor( - // private router: Router, private toast: ToastService, private injector: Injector, private route: ActivatedRoute, @@ -50,15 +53,16 @@ export class IdpComponent implements OnInit, OnDestroy { this.idpForm = new FormGroup({ id: new FormControl({ disabled: true, value: '' }, [Validators.required]), name: new FormControl('', [Validators.required]), + stylingType: new FormControl('', [Validators.required]), }); this.oidcConfigForm = new FormGroup({ - clientId: new FormControl('', [Validators.required]), - clientSecret: new FormControl(''), - issuer: new FormControl('', [Validators.required]), - scopesList: new FormControl([], []), - idpDisplayNameMapping: new FormControl(0), - usernameMapping: new FormControl(0), + clientId: new FormControl('', [Validators.required]), + clientSecret: new FormControl(''), + issuer: new FormControl('', [Validators.required]), + scopesList: new FormControl([], []), + idpDisplayNameMapping: new FormControl(0), + usernameMapping: new FormControl(0), }); this.route.data.pipe(switchMap(data => { @@ -68,14 +72,20 @@ export class IdpComponent implements OnInit, OnDestroy { case PolicyComponentServiceType.MGMT: this.service = this.injector.get(ManagementService as Type); this.mappingFields = [ - mgmtMappingFields.OIDCMAPPINGFIELD_PREFERRED_USERNAME, - mgmtMappingFields.OIDCMAPPINGFIELD_EMAIL]; + mgmtMappingFields.OIDCMAPPINGFIELD_PREFERRED_USERNAME, + mgmtMappingFields.OIDCMAPPINGFIELD_EMAIL]; + this.styleFields = [ + mgmtIdpStylingType.IDPSTYLINGTYPE_UNSPECIFIED, + mgmtIdpStylingType.IDPSTYLINGTYPE_GOOGLE]; break; case PolicyComponentServiceType.ADMIN: this.service = this.injector.get(AdminService as Type); this.mappingFields = [ - authMappingFields.OIDCMAPPINGFIELD_PREFERRED_USERNAME, - authMappingFields.OIDCMAPPINGFIELD_EMAIL]; + adminMappingFields.OIDCMAPPINGFIELD_PREFERRED_USERNAME, + adminMappingFields.OIDCMAPPINGFIELD_EMAIL]; + this.styleFields = [ + adminIdpStylingType.IDPSTYLINGTYPE_UNSPECIFIED, + adminIdpStylingType.IDPSTYLINGTYPE_GOOGLE]; break; } @@ -84,11 +94,11 @@ export class IdpComponent implements OnInit, OnDestroy { const { id } = params; if (id) { this.service.IdpByID(id).then(idp => { - const idpObject = idp.toObject(); - this.idpForm.patchValue(idpObject); - if (idpObject.oidcConfig) { - this.oidcConfigForm.patchValue(idpObject.oidcConfig); - } + const idpObject = idp.toObject(); + this.idpForm.patchValue(idpObject); + if (idpObject.oidcConfig) { + this.oidcConfigForm.patchValue(idpObject.oidcConfig); + } }); } }); @@ -120,9 +130,10 @@ export class IdpComponent implements OnInit, OnDestroy { req.setId(this.id?.value); req.setName(this.name?.value); + req.setStylingType(this.stylingType?.value); this.service.UpdateIdp(req).then((idp) => { - this.toast.showInfo('IDP.TOAST.SAVED', true); + this.toast.showInfo('IDP.TOAST.SAVED', true); // this.router.navigate(['idp', ]); }).catch(error => { this.toast.showError(error); @@ -130,31 +141,31 @@ export class IdpComponent implements OnInit, OnDestroy { } public updateOidcConfig(): void { - let req: AdminOidcIdpConfigUpdate | MgmtOidcIdpConfigUpdate; + let req: AdminOidcIdpConfigUpdate | MgmtOidcIdpConfigUpdate; - switch (this.serviceType) { - case PolicyComponentServiceType.MGMT: - req = new MgmtOidcIdpConfigUpdate(); - break; - case PolicyComponentServiceType.ADMIN: - req = new AdminOidcIdpConfigUpdate(); - break; - } + switch (this.serviceType) { + case PolicyComponentServiceType.MGMT: + req = new MgmtOidcIdpConfigUpdate(); + break; + case PolicyComponentServiceType.ADMIN: + req = new AdminOidcIdpConfigUpdate(); + break; + } - req.setIdpId(this.id?.value); - req.setClientId(this.clientId?.value); - req.setClientSecret(this.clientSecret?.value); - req.setIssuer(this.issuer?.value); - req.setScopesList(this.scopesList?.value); - req.setUsernameMapping(this.usernameMapping?.value); - req.setIdpDisplayNameMapping(this.idpDisplayNameMapping?.value); + req.setIdpId(this.id?.value); + req.setClientId(this.clientId?.value); + req.setClientSecret(this.clientSecret?.value); + req.setIssuer(this.issuer?.value); + req.setScopesList(this.scopesList?.value); + req.setUsernameMapping(this.usernameMapping?.value); + req.setIdpDisplayNameMapping(this.idpDisplayNameMapping?.value); - this.service.UpdateOidcIdpConfig(req).then((oidcConfig) => { - this.toast.showInfo('IDP.TOAST.SAVED', true); - // this.router.navigate(['idp', ]); - }).catch(error => { - this.toast.showError(error); - }); + this.service.UpdateOidcIdpConfig(req).then((oidcConfig) => { + this.toast.showInfo('IDP.TOAST.SAVED', true); + // this.router.navigate(['idp', ]); + }).catch(error => { + this.toast.showError(error); + }); } public close(): void { @@ -188,12 +199,10 @@ export class IdpComponent implements OnInit, OnDestroy { public get backroutes(): string[] { switch (this.serviceType) { case PolicyComponentServiceType.MGMT: - return ['/org', 'policy', 'login']; + return ['/org', 'policy', 'login']; case PolicyComponentServiceType.ADMIN: - return ['/iam', 'policy', 'login']; - break; + return ['/iam', 'policy', 'login']; } - return []; } public get id(): AbstractControl | null { @@ -204,6 +213,10 @@ export class IdpComponent implements OnInit, OnDestroy { return this.idpForm.get('name'); } + public get stylingType(): AbstractControl | null { + return this.idpForm.get('stylingType'); + } + public get clientId(): AbstractControl | null { return this.oidcConfigForm.get('clientId'); } @@ -221,10 +234,10 @@ export class IdpComponent implements OnInit, OnDestroy { } public get idpDisplayNameMapping(): AbstractControl | null { - return this.oidcConfigForm.get('idpDisplayNameMapping'); + return this.oidcConfigForm.get('idpDisplayNameMapping'); } public get usernameMapping(): AbstractControl | null { - return this.oidcConfigForm.get('usernameMapping'); + return this.oidcConfigForm.get('usernameMapping'); } } diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html index 719b94e646..0e500ef85b 100644 --- a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html +++ b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.html @@ -6,7 +6,7 @@
{{ 'IDP.TYPE' | translate }} - + {{ 'IDP.TYPES.'+type | translate}} diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts index 107a69d908..c0dafc96a1 100644 --- a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts +++ b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts @@ -61,7 +61,9 @@ export class AddIdpDialogComponent { query.setKey(IdpSearchKey.IDPSEARCHKEY_PROVIDER_TYPE); query.setMethod(SearchMethod.SEARCHMETHOD_EQUALS); query.setValue(this.idpType.toString()); - this.mgmtService.SearchIdps().then(idps => { + console.log(this.idpType); + console.log(query.toObject()); + this.mgmtService.SearchIdps(undefined, undefined, [query]).then(idps => { this.availableIdps = idps.toObject().resultList; }); } else if (this.serviceType === PolicyComponentServiceType.ADMIN) { diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.html b/console/src/app/modules/policies/login-policy/login-policy.component.html index cd48c2ffcf..a0465fcc0b 100644 --- a/console/src/app/modules/policies/login-policy/login-policy.component.html +++ b/console/src/app/modules/policies/login-policy/login-policy.component.html @@ -1,69 +1,76 @@ -

{{'ORG.POLICY.DEFAULTLABEL' | translate}}

- - - + + + + + + + + +
- {{'ORG.POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}} - - + {{'ORG.POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}} +

{{'ORG.POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}

- {{'ORG.POLICY.DATA.ALLOWREGISTER' | translate}} - - + + {{'ORG.POLICY.DATA.ALLOWREGISTER' | translate}} +

{{'ORG.POLICY.DATA.ALLOWREGISTER_DESC' | translate}}

- {{'ORG.POLICY.DATA.ALLOWEXTERNALIDP' | translate}} - - + {{'ORG.POLICY.DATA.ALLOWEXTERNALIDP' | translate}} +

{{'ORG.POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}}

{{'LOGINPOLICY.IDPS' | translate}}

-
- - remove_circle - {{idp.name}} +
+ + {{idp.name}} {{ 'IDP.TYPE' | translate }}: {{ 'IDP.TYPES.'+idp.type | translate }} {{ 'IDP.ID' | translate }}: {{idp.idpConfigId}}
-
+
add
-
- -
- + - - - - +

{{ 'IDP.LIST.TITLE' | translate }}

+

{{ 'IDP.LIST.DESCRIPTION' | translate }}

+ +
\ No newline at end of file diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.scss b/console/src/app/modules/policies/login-policy/login-policy.component.scss index 6834fca26e..ccfc996243 100644 --- a/console/src/app/modules/policies/login-policy/login-policy.component.scss +++ b/console/src/app/modules/policies/login-policy/login-policy.component.scss @@ -9,35 +9,24 @@ .content { padding-top: 1rem; - display: flex; - flex-direction: column; - width: 100%; .row { - display: flex; - align-items: center; - padding: .3rem 0; - - .left-desc { - font-size: .9rem; + .toggle { + margin: .3rem 0; } - .fill-space { - flex: 1; + p { + margin-top: .5rem; + font-size: 14px; + color: var(--grey); } } } -.btn-container { - display: flex; - justify-content: flex-end; - width: 100%; - - button { - margin-top: 3rem; - display: block; - padding: .5rem 4rem; - } +.save-button { + margin-top: 3rem; + display: block; + padding: .5rem 4rem; } .idp-table-card { @@ -63,6 +52,12 @@ border-radius: .5rem; cursor: pointer; position: relative; + min-height: 70px; + min-width: 150px; + + .name { + font-weight: 700; + } span { padding: 2px; @@ -70,6 +65,7 @@ .meta { font-size: 12px; + color: var(--grey); } .rm { @@ -78,10 +74,16 @@ left: 0; transform: translateX(-50%) translateY(-50%); cursor: pointer; + + &[disabled] { + display: none; + } } - &:hover { - background-color: #ffffff10; + &:not(.disabled) { + &:hover { + background-color: #ffffff10; + } } img { diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.ts b/console/src/app/modules/policies/login-policy/login-policy.component.ts index e6353eaf19..3feddb8d93 100644 --- a/console/src/app/modules/policies/login-policy/login-policy.component.ts +++ b/console/src/app/modules/policies/login-policy/login-policy.component.ts @@ -38,6 +38,7 @@ export class LoginPolicyComponent implements OnDestroy { public idps: MgmtIdpProviderView.AsObject[] | AdminIdpProviderView.AsObject[] = []; public loading: boolean = false; + public disabled: boolean = true; constructor( private route: ActivatedRoute, private toast: ToastService, @@ -66,6 +67,7 @@ export class LoginPolicyComponent implements OnDestroy { if (data) { this.loginData = data.toObject(); this.loading = false; + this.disabled = ((this.loginData as LoginPolicyView.AsObject)?.pb_default) ?? false; } }); this.getIdps().then(idps => { diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 0e9aca93d8..75fa5fd8d5 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -469,9 +469,13 @@ "USERLOGINMUSTBEDOMAIN":"Benutzer-Login muss eine Domain sein", "ALLOWUSERNAMEPASSWORD":"Benutzername Password erlaubt", "ALLOWEXTERNALIDP":"Externer IDP erlaubt", - "ALLOWREGISTER":"Registrieren erlaubt" + "ALLOWREGISTER":"Registrieren erlaubt", + "ALLOWUSERNAMEPASSWORD_DESC":"Der konventionelle Login mit Benutzername und Passwort wird erlaubt.", + "ALLOWEXTERNALIDP_DESC":"Der Login wird für die darunter liegenden Identity Provider erlaubt.", + "ALLOWREGISTER_DESC":"Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers." }, "RESET":"Richtlinie zurücksetzen", + "CREATECUSTOM":"Benutzerdefinierte Richtlinie erstellen", "TOAST":{ "SET":"Richtline erfolgreich gesetzt!", "RESETSUCCESS":"Richtline zurückgesetzt!" @@ -709,10 +713,15 @@ "1":"aktiv", "2":"inaktiv" }, - "MAPPINTFIELD": { + "MAPPINGFIELD": { "1": "Preferred Username", "2": "Email" }, + "STYLE":"Style", + "STYLEFIELD": { + "0": "kein Styling", + "1": "Google" + }, "TYPE":"Typ", "ID": "ID", "NAME":"Name", diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index 224cd0f22b..1899c2e163 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -469,9 +469,13 @@ "USERLOGINMUSTBEDOMAIN":"User Login must be Domain", "ALLOWUSERNAMEPASSWORD":"Username Password allowed", "ALLOWEXTERNALIDP":"External IDP allowed", - "ALLOWREGISTER":"Register allowed" + "ALLOWREGISTER":"Register allowed", + "ALLOWUSERNAMEPASSWORD_DESC":"The conventional login with user name and password is allowed.", + "ALLOWEXTERNALIDP_DESC":"The login is allowed for the underlying identity providers", + "ALLOWREGISTER_DESC":"If the option is selected, an additional step for registering a user appears in the login." }, "RESET":"Reset Policy", + "CREATECUSTOM":"Create Custom Policy", "TOAST":{ "SET":"Policy set successfully!", "RESETSUCCESS":"Policy reset successfully!" @@ -713,6 +717,11 @@ "1": "Preferred Username", "2": "Email" }, + "STYLE":"Style", + "STYLEFIELD": { + "0": "No Styling", + "1": "Google" + }, "TYPE":"Type", "ID": "ID", "NAME":"Name",