fix(cnsl): some saml provider issues (#7220)

Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
Miguel Cabrerizo 2024-01-15 16:10:45 +01:00 committed by GitHub
parent c7e45f7f49
commit fc34896092
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 23 deletions

View File

@ -83,3 +83,23 @@ function i18nErr(err: ValidationErrors | null | undefined, i18nKey: string, para
};
}
}
const isFieldEmpty = (fieldName: string, g: AbstractControl) => {
const field = g.get(fieldName)?.value;
if (typeof field === 'number') {
return field && field >= 0 ? true : false;
}
if (typeof field === 'string') {
return field && field.length > 0 ? true : false;
}
return false;
};
// Reference: https://stackoverflow.com/a/56057955
export function atLeastOneIsFilled(...fields: string[]): ValidationErrors | null {
return (g: AbstractControl): ValidationErrors | null => {
return fields.some((fieldName) => isFieldEmpty(fieldName, g))
? null
: ({ atLeastOne: 'At least one field has to be provided.' } as ValidationErrors);
};
}

View File

@ -21,7 +21,12 @@
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.SAML.METADATAXML' | translate }}</cnsl-label>
<input cnslInput formControlName="metadataXml" />
<textarea
cnslInput
formControlName="metadataXml"
placeholder="base64 encoded metadata xml"
class="metadata-xml"
></textarea>
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.SAML.METADATAURL' | translate }}</cnsl-label>
@ -29,7 +34,7 @@
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.SAML.BINDING' | translate }}</cnsl-label>
<mat-select formControlName="binding">
<mat-select formControlName="binding" [compareWith]="compareBinding">
<mat-option *ngFor="let binding of bindingValues" [value]="binding">{{ binding }}</mat-option>
</mat-select>
</cnsl-form-field>

View File

@ -0,0 +1,3 @@
.metadata-xml {
min-height: 200px;
}

View File

@ -1,6 +1,6 @@
import { Component, Injector, Type } from '@angular/core';
import { Location } from '@angular/common';
import { Options, Provider } from '../../../proto/generated/zitadel/idp_pb';
import { Options, Provider, SAMLBinding } from '../../../proto/generated/zitadel/idp_pb';
import { AbstractControl, FormGroup, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
import { ManagementService } from '../../../services/mgmt.service';
@ -10,7 +10,7 @@ import { GrpcAuthService } from '../../../services/grpc-auth.service';
import { take } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from '../../../services/breadcrumb.service';
import { requiredValidator } from '../../form-field/validators/validators';
import { atLeastOneIsFilled, requiredValidator } from '../../form-field/validators/validators';
import {
AddSAMLProviderRequest as AdminAddSAMLProviderRequest,
GetProviderByIDRequest as AdminGetProviderByIDRequest,
@ -21,7 +21,6 @@ import {
GetProviderByIDRequest as MgmtGetProviderByIDRequest,
UpdateSAMLProviderRequest as MgmtUpdateSAMLProviderRequest,
} from 'src/app/proto/generated/zitadel/management_pb';
import * as zitadel_idp_pb from '../../../proto/generated/zitadel/idp_pb';
@Component({
selector: 'cnsl-provider-saml-sp',
@ -38,7 +37,7 @@ export class ProviderSamlSpComponent {
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
private service!: ManagementService | AdminService;
bindingValues: string[] = Object.keys(zitadel_idp_pb.SAMLBinding);
bindingValues: string[] = Object.keys(SAMLBinding);
constructor(
private _location: Location,
@ -54,13 +53,16 @@ export class ProviderSamlSpComponent {
}
private _initializeForm(): void {
this.form = new UntypedFormGroup({
this.form = new UntypedFormGroup(
{
name: new UntypedFormControl('', [requiredValidator]),
metadataXml: new UntypedFormControl('', [requiredValidator]),
metadataUrl: new UntypedFormControl('', [requiredValidator]),
metadataXml: new UntypedFormControl('', []),
metadataUrl: new UntypedFormControl('', []),
binding: new UntypedFormControl(this.bindingValues[0], [requiredValidator]),
withSignedRequest: new UntypedFormControl(true, [requiredValidator]),
});
},
atLeastOneIsFilled('metadataXml', 'metadataUrl'),
);
}
private _checkFormPermissions(): void {
@ -121,18 +123,23 @@ export class ProviderSamlSpComponent {
this.serviceType === PolicyComponentServiceType.MGMT
? new MgmtUpdateSAMLProviderRequest()
: new AdminUpdateSAMLProviderRequest();
req.setId(this.provider.id);
req.setName(this.name?.value);
req.setMetadataUrl(this.metadataUrl?.value);
if (this.metadataXml?.value) {
req.setMetadataXml(this.metadataXml?.value);
} else {
req.setMetadataUrl(this.metadataUrl?.value);
}
req.setWithSignedRequest(this.withSignedRequest?.value);
// @ts-ignore
req.setBinding(zitadel_idp_pb.SAMLBinding[`${this.biding?.value}`]);
req.setBinding(SAMLBinding[this.binding?.value]);
req.setProviderOptions(this.options);
this.loading = true;
this.service
.updateSAMLProvider(req)
.then((idp) => {
.then(() => {
setTimeout(() => {
this.loading = false;
this.close();
@ -151,16 +158,19 @@ export class ProviderSamlSpComponent {
? new MgmtAddSAMLProviderRequest()
: new AdminAddSAMLProviderRequest();
req.setName(this.name?.value);
req.setMetadataUrl(this.metadataUrl?.value);
if (this.metadataXml?.value) {
req.setMetadataXml(this.metadataXml?.value);
} else {
req.setMetadataUrl(this.metadataUrl?.value);
}
req.setProviderOptions(this.options);
// @ts-ignore
req.setBinding(zitadel_idp_pb.SAMLBinding[`${this.biding?.value}`]);
req.setBinding(SAMLBinding[this.binding?.value]);
req.setWithSignedRequest(this.withSignedRequest?.value);
this.loading = true;
this.service
.addSAMLProvider(req)
.then((idp) => {
.then(() => {
setTimeout(() => {
this.loading = false;
this.close();
@ -187,9 +197,9 @@ export class ProviderSamlSpComponent {
.then((resp) => {
this.provider = resp.idp;
this.loading = false;
this.name?.setValue(this.provider?.name);
if (this.provider?.config?.saml) {
this.form.patchValue(this.provider.config.saml);
this.name?.setValue(this.provider.name);
}
})
.catch((error) => {
@ -202,6 +212,13 @@ export class ProviderSamlSpComponent {
this._location.back();
}
compareBinding(value: string, index: number) {
if (value) {
return value === Object.keys(SAMLBinding)[index];
}
return false;
}
private get name(): AbstractControl | null {
return this.form.get('name');
}
@ -214,7 +231,7 @@ export class ProviderSamlSpComponent {
return this.form.get('metadataUrl');
}
private get biding(): AbstractControl | null {
private get binding(): AbstractControl | null {
return this.form.get('binding');
}