diff --git a/projects/app-ziti-console/src/app/app-routing.module.ts b/projects/app-ziti-console/src/app/app-routing.module.ts index 4d489bb0..595b45e5 100644 --- a/projects/app-ziti-console/src/app/app-routing.module.ts +++ b/projects/app-ziti-console/src/app/app-routing.module.ts @@ -41,7 +41,9 @@ import { TerminatorsPageComponent, TerminatorFormComponent, JwtSignersPageComponent, - JwtSignerFormComponent + JwtSignerFormComponent, + AuthPoliciesPageComponent, + AuthPolicyFormComponent } from "ziti-console-lib"; import {environment} from "./environments/environment"; import {URLS} from "./app-urls.constants"; @@ -102,6 +104,20 @@ const routes: Routes = [ canDeactivate: [DeactivateGuardService], runGuardsAndResolvers: 'always', }, + { + path: 'auth-policies', + component: AuthPoliciesPageComponent, + canActivate: mapToCanActivate([AuthenticationGuard]), + canDeactivate: [DeactivateGuardService], + runGuardsAndResolvers: 'always', + }, + { + path: 'auth-policies/:id', + component: AuthPolicyFormComponent, + canActivate: mapToCanActivate([AuthenticationGuard]), + canDeactivate: [DeactivateGuardService], + runGuardsAndResolvers: 'always', + }, { path: 'services', component: ServicesPageComponent, diff --git a/projects/ziti-console-lib/src/lib/features/data-table/cells/table-cell-name/table-cell-name.component.ts b/projects/ziti-console-lib/src/lib/features/data-table/cells/table-cell-name/table-cell-name.component.ts index 80cda133..0d979077 100644 --- a/projects/ziti-console-lib/src/lib/features/data-table/cells/table-cell-name/table-cell-name.component.ts +++ b/projects/ziti-console-lib/src/lib/features/data-table/cells/table-cell-name/table-cell-name.component.ts @@ -4,7 +4,7 @@ import {MatDialog} from "@angular/material/dialog"; import {ICellRendererParams} from "ag-grid-community"; import {Router} from "@angular/router"; -import {isEmpty, get} from 'lodash'; +import {isEmpty, isFunction, get} from 'lodash'; @Component({ selector: 'lib-table-cell-name', @@ -32,9 +32,18 @@ export class TableCellNameComponent implements ICellRendererAngularComp { } linkClicked(event) { - this.router.navigateByUrl(`${this.cellParams.pathRoot}/${this.item.id}`); event.stopPropagation(); event.preventDefault(); + if (isFunction(this.cellParams?.cellNamePreCheck)) { + this.cellParams?.cellNamePreCheck(this.item).then((result) => { + if (!result) { + return; + } + this.router.navigateByUrl(`${this.cellParams.pathRoot}/${this.item.id}`); + }) + return; + } + this.router.navigateByUrl(`${this.cellParams.pathRoot}/${this.item.id}`); } get cellText() { diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.html b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.html new file mode 100644 index 00000000..e9473419 --- /dev/null +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.html @@ -0,0 +1,336 @@ +
+ +
+
+
+ + + + +
+
+
+
Cert
+
+
+
+ YES + NO +
+
+
+
+
+
+
+
Ext JWT
+
+
+
+ YES + NO +
+
+
+
+
+
+
+
UPDB
+
+
+
+ YES + NO +
+
+
+
+
+ +
+
+
+
Allow Expired Certificates
+
+
+
+ YES + NO +
+
+
+
+
+ +
+
+ Allowed JWT Signers +
+
+ +
+
+ +
+
+
+ Minimum Length +
+ +
+
+
+ Max Attempts +
+ +
+
+
+ Lockout Duration
(min)
+
+ +
+
+
+
+
+
+
Mixed Case
+
+
+
+ YES + NO +
+
+
+
+
+
+
+
Numeric
+
+
+
+ YES + NO +
+
+
+
+
+
+
+
Special
+
+
+
+ YES + NO +
+
+
+
+
+
+ +
+ + + +
+
+
+ +
+
+ TOTP MFA +
+
+
+
+
+
Require TOTP
+
+
+ YES + NO +
+
+
+
+
+
+
+ JWT Signer +
+
+ + + + + +
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+
+ diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.scss b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.scss new file mode 100644 index 00000000..e4f08a66 --- /dev/null +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.scss @@ -0,0 +1,187 @@ +.form-group-column { + &.three-fifths { + min-width: 500px; + } +} + +.jwt-signer-form-container { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + align-items: center; + gap: var(--gapXL); + + .select-file-button { + padding-left: var(--paddingMedium); + padding-right: var(--paddingMedium); + height: 25px; + width: fit-content; + white-space: nowrap; + display: flex; + align-items: center; + justify-content: center; + font-weight: 600; + font-size: 14px; + background: var(--primary); + border-style: solid; + border-width: 1px; + border-color: var(--stroke); + color: var(--white); + cursor: pointer; + border-radius: var(--inputBorderRadius); + gap: var(--marginMedium); + margin-top: -5px; + + &:hover { + filter: brightness(.8); + } + &:active { + filter: grayscale(1); + transform: translateY(1px); + } + + .spinner { + display: inline-block; + width: 8px; + height: 8px; + border-radius: 50%; + background: transparent; + border-top: 2px solid white; + border-right: 2px solid white; + border-bottom: 2px solid transparent; + border-left: 2px solid transparent; + -webkit-animation: loading 0.5s infinite linear; + animation: loading 0.5s infinite linear; + } + } + + .select-file-label-container { + gap: var(--marginMedium); + } + + .updb-input-options { + margin-top: var(--marginSmall); + background-color: var(--formGroup); + padding: var(--paddingMedium); + border-radius: var(--inputBorderRadius); + + .form-field-title { + color: var(--offWhite); + } + } +} + +::ng-deep .jwt-signer-form-container { + select, + input { + &:disabled { + opacity: 0.75 !important; + cursor: text; + background-color: var(--stroke) !important; + } + } +} + +::ng-deep .api-data-no-wrap{ + .jse-text-mode { + width: 100%; + .cm-editor { + width: 100%; + .cm-scroller { + width: 100%; + .cm-content { + width: 100%; + overflow: auto; + .ͼr { + white-space: nowrap; + } + } + } + } + } +} + +.radio-group-container { + display: flex; + gap: var(--marginLarge); + + &:focus { + .radio-button-container { + .radio-button-circle { + border-color: var(--primaryColor); + } + } + } + + .radio-button-container { + display: flex; + flex-direction: row; + align-items: center; + background-color: var(--formGroup); + border-radius: var(--inputBorderRadius); + width: 100%; + padding-left: var(--paddingMedium); + padding-right: var(--paddingMedium); + padding-top: var(--paddingLarge); + padding-bottom: var(--paddingLarge); + cursor: pointer; + gap: var(--marginMedium); + + .radio-button-circle { + display: flex; + width: 21px; + height: 21px; + border-radius: 21px; + border-width: 2px; + border-style: solid; + border-color: var(--offWhite); + align-items: center; + justify-content: center; + background-color: var(--offWhite); + + .radio-button-inner-circle { + display: none; + width: 15px; + height: 15px; + border-radius: 15px; + align-items: center; + justify-content: center; + background-color: var(--primaryColor); + } + } + + &.selected { + .radio-button-circle { + .radio-button-inner-circle { + display: flex; + } + } + } + + &:active { + .radio-button-circle { + .radio-button-inner-circle { + display: flex; + background-color: var(--menu); + } + } + } + + .radio-button-label { + color: var(--offWhite); + font-size: 14px; + font-weight: 600; + } + } +} + +.allowed-signers-container { + background-color: var(--formGroup); + padding: var(--paddingMedium); + border-radius: var(--inputBorderRadius); + + .form-field-title { + color: var(--offWhite); + } +} \ No newline at end of file diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.ts b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.ts new file mode 100644 index 00000000..9c365e31 --- /dev/null +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.component.ts @@ -0,0 +1,379 @@ +/* + Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { + Component, ElementRef, + EventEmitter, Inject, + Input, + OnDestroy, + OnInit, Output, + ViewChild, +} from '@angular/core'; +import {AuthPolicyFormService} from "./auth-policy-form.service"; +import {SchemaService} from "../../../services/schema.service"; +import {KEY_CODES, ProjectableForm} from "../projectable-form.class"; +import {GrowlerService} from "../../messaging/growler.service"; +import {ExtensionService, SHAREDZ_EXTENSION} from "../../extendable/extensions-noop.service"; + +import {cloneDeep, defer, delay, forOwn, keys, invert, isEmpty, isNil, unset, sortedUniq, debounce} from 'lodash'; +import {GrowlerModel} from "../../messaging/growler.model"; +import {SETTINGS_SERVICE, SettingsService} from "../../../services/settings.service"; +import {ZITI_DATA_SERVICE, ZitiDataService} from "../../../services/ziti-data.service"; +import {ActivatedRoute, Router} from "@angular/router"; +import {Location} from "@angular/common"; +import {ValidationService} from "../../../services/validation.service"; +import {AuthPolicy} from "../../../models/auth-policy"; + +@Component({ + selector: 'lib-configuration', + templateUrl: './auth-policy-form.component.html', + styleUrls: ['./auth-policy-form.component.scss'] +}) +export class AuthPolicyFormComponent extends ProjectableForm implements OnInit, OnDestroy { + + @Input() override formData: any = new AuthPolicy(); + @Input() override errors: any = {}; + @Output() close: EventEmitter = new EventEmitter(); + + allowedJwtSignerAttributes = []; + + formView = 'simple'; + options: any[] = []; + isEditing = !isEmpty(this.formData.id); + formDataInvalid = false; + editMode = false; + items: any = []; + settings: any = {}; + fileSelectOpening = false; + override entityType = 'auth-policies'; + override entityClass = AuthPolicy; + + jwtSignersFilterChangedDebounced = debounce(this.jwtSignerFilterChanged.bind(this), 200); + + @ViewChild('fileSelect') filterInput: ElementRef; + + constructor( + public svc: AuthPolicyFormService, + private schemaSvc: SchemaService, + growlerService: GrowlerService, + @Inject(SHAREDZ_EXTENSION) extService: ExtensionService, + @Inject(SETTINGS_SERVICE) public settingsService: SettingsService, + @Inject(ZITI_DATA_SERVICE) override zitiService: ZitiDataService, + protected override router: Router, + protected override route: ActivatedRoute, + location: Location, + private validationService: ValidationService + ) { + super(growlerService, extService, zitiService, router, route, location); + } + + override ngOnInit(): void { + super.ngOnInit(); + this.svc.getJwtSigners(); + this.svc.getJwtSignerNamedAttributes().then(() => { + this.initSelectedAttributes(); + }); + this.settingsService.settingsChange.subscribe((results:any) => { + this.settings = results; + }); + } + + protected override entityUpdated() { + super.entityUpdated(); + } + + ngOnDestroy(): void { + this.clearForm(); + } + + headerActionRequested(event) { + switch(event.name) { + case 'save': + this.save(event); + break; + case 'close': + this.returnToListPage(); + break; + case 'toggle-view': + this.formView = event.data; + break; + } + } + + override clear() { + this.formData.configTypeId = ''; + this.clearForm(); + } + + clearForm() { + this.items.forEach((item: any) => { + if (item?.component) item.component.destroy(); + }); + this.errors = {}; + this.items = []; + this.formData = new AuthPolicy(); + if (this.subscription) this.subscription.unsubscribe(); + } + + allowedJwtSignersChanged(event) { + this.formData.primary.extJwt.allowedSigners = this.getSelectedAttributes(this.allowedJwtSignerAttributes, this.svc.jwtSignerNamedAttributesMap); + } + + getSelectedAttributes(namedAttributes, namedAttributeMap) { + const prependedNamedAttributes = namedAttributes.map((attr) => { + return namedAttributeMap[attr]; + }); + return [...prependedNamedAttributes]; + } + + initSelectedAttributes() { + const jwtSignerNamedAttributesMap = invert(this.svc.jwtSignerNamedAttributesMap); + this.formData.primary?.extJwt?.allowedSigners?.forEach(attr => { + this.allowedJwtSignerAttributes.push(jwtSignerNamedAttributesMap[attr]); + }); + } + + async save(event?: any) { + if(!this.validate()) { + return; + } + const tagVals = this.getTagValues(); + if (!isEmpty(tagVals)) { + forOwn(tagVals, (value, key) => { + this.formData.tags[key] = value; + }); + } + const apiData = this.apiData; + apiData.id = this.formData.id; + this.isLoading = true; + this.svc.save(apiData).then((result) => { + if (this.isModal) { + this.closeModal(true, true); + return; + } + this.initData = this.formData; + this._dataChange = false; + this.returnToListPage(); + }).finally(() => { + this.isLoading = false; + }); + } + + validate() { + this.errors = {}; + const labels = []; + const growlers = []; + if (isEmpty(this.formData.name)) { + this.errors.name = true; + labels.push('Name'); + } + if (!isEmpty(this.errors)) { + let missingFields = labels.join(', '); + growlers.push(new GrowlerModel( + 'error', + 'Invalid', + `Missing Form Data`, + `Please enter a value for the highlighted fields: ${missingFields}`, + )); + } + if (!isEmpty(growlers)) { + growlers.forEach((growlerData) => { + this.growlerService.show(growlerData); + }); + return isEmpty(this.errors); + } + + growlers.forEach((growlerData) => { + this.growlerService.show(growlerData); + }); + return isEmpty(this.errors); + } + + get apiCallURL() { + return this.settings.selectedEdgeController + '/edge/management/v1/auth-policies' + (this.formData.id ? `/${this.formData.id}` : ''); + } + + get apiData(): any { + const data: any = { + name: this.formData.name || '', + primary: this.formData.primary || {}, + secondary: this.formData.secondary || {}, + tags: this.formData.tags || {} + }; + this._apiData = data; + return this._apiData; + } + + _apiData: any = {}; + set apiData(data) { + this._apiData = data; + } + + dataChanged(event) { + this._apiData = cloneDeep(this.apiData); + } + + toggleCertAllowed() { + this.formData.primary.cert.allowed = !this.formData.primary.cert.allowed; + if (!this.formData.primary.cert.allowed) { + this.formData.primary.cert.allowExpiredCerts = false; + } + } + + toggleExtJwtAllowed() { + this.formData.primary.extJwt.allowed = !this.formData.primary.extJwt.allowed; + } + + toggleUpdbAllowed() { + this.formData.primary.updb.allowed = !this.formData.primary.updb.allowed; + } + + toggleAllowExpiredCerts() { + this.formData.primary.cert.allowExpiredCerts = !this.formData.primary.cert.allowExpiredCerts; + } + + toggleUpdbMixed() { + this.formData.primary.updb.requireMixedCase = !this.formData.primary.updb.requireMixedCase; + } + + toggleUpdbNumeric() { + this.formData.primary.updb.requireNumericChar = !this.formData.primary.updb.requireNumericChar; + } + + toggleUpdbSpecial() { + this.formData.primary.updb.requireSpecialChar = !this.formData.primary.updb.requireSpecialChar; + } + + toggleRequireTotp() { + this.formData.secondary.requireTotp = !this.formData.secondary.requireTotp; + } + + openFileSelect(event: any) { + this.filterInput.nativeElement.click(); + this.fileSelectOpening = true; + delay(() => { + this.fileSelectOpening = false; + }, 1000); + } + + selectPemFile(event: any) { + console.log(event); + const file: File = event?.target?.files[0]; + + if (file) { + const fileReader = new FileReader(); + fileReader.onload = (fileLoadedEvent) => { + const textFromSelectedFile: any = fileLoadedEvent.target?.result; + if (!this.validationService.isValidPEM(textFromSelectedFile?.trim())) { + this.errors.certPem = true; + const growlerData = new GrowlerModel( + 'error', + 'Invalid', + `Cert PEM Invalid`, + `The file selected for the Cert PEM field is invalid. Please check your input and try again.`, + ); + this.growlerService.show(growlerData); + this.formData.certPem = 'Invalid PEM. Please select or enter a valid PEM certificate.'; + } else { + unset(this.errors, 'certPem'); + this.formData.certPem = textFromSelectedFile; + } + }; + fileReader.readAsText(file, "UTF-8"); + } + } + + apiActionRequested(action) { + switch (action.id) { + case 'cli': + this.copyCLICommand(); + break; + case 'curl': + this.copyCURLCommand(); + break; + } + } + + copyCLICommand() { + const command = `ziti edge ${this.formData.id ? 'update' : 'create'} auth-policy ${this.formData.id ? `'${this.formData.id}'` : ''} ${this.formData.id ? '--name' : ''} '${this.formData.name}' --primary-cert-allowed '${this.formData.primary.cert.allowed}' --primary-cert-expired-allowed '${this.formData.primary.cert.allowExpiredCerts}' --primary-ext-jwt-allowed '${this.formData.primary.extJwt.allowed}' --primary-ext-jwt-allowed-signers ${this.formData.primary.extJwt.allowedSigners.join(',') || ''} --primary-updb-allowed '${this.formData.primary.updb.allowed}' --primary-updb-lockout-min ${this.formData.primary.updb.lockoutDurationMinutes} --primary-updb-max-attempts ${this.formData.primary.updb.maxAttempts} --primary-updb-min-length ${this.formData.primary.updb.minPasswordLength} --primary-updb-req-mixed-case '${this.formData.primary.updb.requireMixedCase}' --primary-updb-req-numbers '${this.formData.primary.updb.requireNumberChar}' --primary-updb-req-special '${this.formData.primary.updb.requireSpecialChar}' --secondary-req-ext-jwt-signer '${this.formData.secondary.requireExtJwtSigner}' --secondary-req-totp '${this.formData.secondary.requireTotp}' --tags-json '${JSON.stringify(this.formData.tags)}'`; + + navigator.clipboard.writeText(command); + const growlerData = new GrowlerModel( + 'success', + 'Success', + `Text Copied`, + `CLI command copied to clipboard`, + ); + this.growlerService.show(growlerData); + } + + copyCURLCommand() { + const command = `curl '${this.apiCallURL}' \\ + ${this.formData.id ? '--request PATCH \\' : '\\'} + -H 'accept: application/json' \\ + -H 'content-type: application/json' \\ + -H 'zt-session: ${this.settings.session.id}' \\ + --data-raw '${JSON.stringify(this.apiData)}'`; + + navigator.clipboard.writeText(command); + const growlerData = new GrowlerModel( + 'success', + 'Success', + `Text Copied`, + `CURL command copied to clipboard`, + ); + this.growlerService.show(growlerData); + } + + scopesOnKeyup(event: any) { + const key = event.key?.toLowerCase(); + if (key === " " || key === 'enter') { + event.preventDefault(); + event.stopPropagation(); + const element = event.target as HTMLElement; + element.blur(); + element.focus(); + } + } + + jwtSignerFilterChanged(event) { + if (event?.keyCode === KEY_CODES.LEFT_ARROW || event?.keyCode === KEY_CODES.RIGHT_ARROW || event?.keyCode === KEY_CODES.UP_ARROW || event?.keyCode === KEY_CODES.DOWN_ARROW) { + return; + } + let filters = []; + if (event?.target?.value) { + filters.push({ + columnId: 'name', + value: event.target.value, + label: event.target.value, + filterName: 'Name', + type: 'TEXTINPUT', + }); + } + this.svc.getJwtSigners(filters,1); + } + + secondaryJwtSignerChanged(event) { + this.svc.filteredJwtSigners = this.svc.jwtSigners.filter((jwtSigner) => { + return jwtSigner.id === this.formData.secondary.requireExtJwtSigner; + }); + } + + clearJwtSignerFilter(event) { + const filters = []; + this.svc.getJwtSigners(filters,1); + } +} diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.service.ts b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.service.ts new file mode 100644 index 00000000..d95c7495 --- /dev/null +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/auth-policy/auth-policy-form.service.ts @@ -0,0 +1,132 @@ +import {Injectable, Inject} from '@angular/core'; +import {ZITI_DATA_SERVICE, ZitiDataService} from "../../../services/ziti-data.service"; +import {cloneDeep, defer, invert, isBoolean, isEmpty, isNil, keys} from "lodash"; +import {GrowlerModel} from "../../messaging/growler.model"; +import {GrowlerService} from "../../messaging/growler.service"; +import {ExtensionService, SHAREDZ_EXTENSION} from "../../extendable/extensions-noop.service"; +import {ValidationService} from "../../../services/validation.service"; +import {AuthPolicy} from "../../../models/auth-policy"; + +@Injectable({ + providedIn: 'root' +}) +export class AuthPolicyFormService { + + items: any[] = []; + errors: any[] = []; + saveDisabled = false; + + jwtSigners = []; + jwtSignerNamedAttributes = []; + jwtSignerNamedAttributesMap = {}; + jwtSignersLoading = false; + + selectedSecondaryJwtSigner; + filteredJwtSigners; + + paging = { + filter: "", + noSearch: true, + order: "asc", + page: 1, + searchOn: "name", + sort: "name", + total: 100 + } + + constructor( + @Inject(ZITI_DATA_SERVICE) private dataService: ZitiDataService, + @Inject(SHAREDZ_EXTENSION)private extService: ExtensionService, + private growlerService: GrowlerService, + private validationService: ValidationService + ) { + } + + public getJwtSignerNamedAttributes() { + return this.dataService.get('external-jwt-signers', {rawFilter: true, filter: '', sort: 'name', order: 'asc', total: -1, page: 1}, []).then((result) => { + const namedAttributes = result.data.map((identity) => { + this.jwtSignerNamedAttributesMap[identity.name] = identity.id; + return identity.name; + }); + this.jwtSignerNamedAttributes = namedAttributes; + return namedAttributes; + }); + } + + getJwtSigners(filters = [], page = 1) { + this.jwtSignersLoading = true; + const paging = cloneDeep(this.paging); + if (filters.length > 0) { + paging.noSearch = false; + } + return this.dataService.get('external-jwt-signers', paging, filters).then((result: any) => { + this.jwtSigners = result.data; + }).finally(() => { + this.jwtSignersLoading = false; + }); + } + + save(formData) { + const isUpdate = !isEmpty(formData.id); + const data: any = this.getAuthPolicyDataModel(formData, isUpdate); + let prom; + if (isUpdate) { + prom = this.dataService.put('auth-policies', data, formData.id, true); + } else { + prom = this.dataService.post('auth-policies', data, true); + } + + return prom.then(async (result: any) => { + const id = isUpdate ? formData.id : (result?.data?.id || result?.id); + let config = await this.dataService.getSubdata('auth-policies', id, '').then((svcData) => { + return svcData.data; + }); + return this.extService.formDataSaved(config).then((formSavedResult: any) => { + if (!formSavedResult) { + return config; + } + const growlerData = new GrowlerModel( + 'success', + 'Success', + `Auth Policy ${isUpdate ? 'Updated' : 'Created'}`, + `Successfully ${isUpdate ? 'updated' : 'created'} Auth Policy: ${formData.name}`, + ); + this.growlerService.show(growlerData); + return config; + }).catch((result) => { + return false; + }); + }).catch((resp) => { + let errorMessage; + if (resp?.error?.error?.cause?.message) { + errorMessage = resp?.error?.error?.cause?.message; + } else if (resp?.error?.error?.cause?.reason) { + errorMessage = resp?.error?.error?.cause?.reason; + }else if (resp?.error?.message) { + errorMessage = resp?.error?.message; + } else { + errorMessage = 'An unknown error occurred'; + } + const growlerData = new GrowlerModel( + 'error', + 'Error', + `Error Creating Auth Policy`, + errorMessage, + ); + this.growlerService.show(growlerData); + throw resp; + }) + } + + getAuthPolicyDataModel(formData, isUpdate) { + const saveModel = new AuthPolicy(); + const modelProperties = keys(saveModel); + modelProperties.forEach((prop) => { + switch(prop) { + default: + saveModel[prop] = formData[prop]; + } + }); + return saveModel; + } +} diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html index 730d8c10..10a72eae 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.html @@ -38,17 +38,6 @@ -
-
- Claims Property -
-
- -
Audience @@ -60,24 +49,44 @@
-
-
+
+
-
Use External ID
+ Claims Property
-
- YES - NO -
+ +
+
+
+
+
External ID
+
+
+
+
+
+
+
Use External ID
+
+
+ YES + NO +
+
+
@@ -97,7 +106,7 @@ matTooltipPosition="below" >
- +
diff --git a/projects/ziti-console-lib/src/lib/features/projectable-forms/service/service-form.component.html b/projects/ziti-console-lib/src/lib/features/projectable-forms/service/service-form.component.html index 61a4d001..24740e7d 100644 --- a/projects/ziti-console-lib/src/lib/features/projectable-forms/service/service-form.component.html +++ b/projects/ziti-console-lib/src/lib/features/projectable-forms/service/service-form.component.html @@ -75,7 +75,7 @@ [(ngModel)]="svc.selectedConfigId" > -
+