name="addresses"
id="addresses"
formControlName="addresses"
- placeholder="192.168.0.10, 192.168.1.0/8"
+ placeholder="e.g. 192.168.0.10, 192.168.1.0/8"
[invalid]="!item.controls['addresses'].valid && (item.controls['addresses'].dirty)">
</cds-text-label>
<ng-template #addressesError>
<span *ngIf="showError(index, 'addresses', formDir, 'required')"
i18n>This field is required.</span>
- <span *ngIf="showError(index, 'addresses', formDir, 'pattern')">
- <ng-container i18n>Must contain one or more comma-separated values</ng-container>
+ <span *ngIf="showError(index, 'addresses', formDir, 'invalidAddress')">
+ <ng-container i18n>Must contain one or more comma-separated valid addresses.</ng-container>
<br>
<ng-container i18n>For example:</ng-container> 192.168.0.10, 192.168.1.0/8
</span>
component.removeClient(0);
expect(component.form.getValue('clients')).toEqual([]);
});
+
+ describe(`test 'isValidClientAddress'`, () => {
+ it('should return false for empty value', () => {
+ expect(component.isValidClientAddress('')).toBeFalsy();
+ expect(component.isValidClientAddress(null)).toBeFalsy();
+ });
+
+ it('should return false for valid single IPv4 address', () => {
+ expect(component.isValidClientAddress('192.168.1.1')).toBeFalsy();
+ });
+
+ it('should return false for valid IPv6 address', () => {
+ expect(component.isValidClientAddress('2001:db8::1')).toBeFalsy();
+ });
+
+ it('should return false for valid FQDN', () => {
+ expect(component.isValidClientAddress('nfs.example.com')).toBeFalsy();
+ });
+
+ it('should return false for valid IP CIDR range', () => {
+ expect(component.isValidClientAddress('192.168.0.0/24')).toBeFalsy();
+ expect(component.isValidClientAddress('2001:db8::/64')).toBeFalsy();
+ });
+
+ it('should return false for multiple valid addresses separated by comma', () => {
+ const input = '192.168.1.1, 2001:db8::1, nfs.example.com, 10.0.0.0/8';
+ expect(component.isValidClientAddress(input)).toBeFalsy();
+ });
+
+ it('should return true for invalid single address', () => {
+ expect(component.isValidClientAddress('invalid-address')).toBeTruthy();
+ });
+
+ it('should return true for mixed valid and invalid addresses', () => {
+ const input = '192.168.1.1, invalid-address';
+ expect(component.isValidClientAddress(input)).toBeTruthy();
+ });
+
+ it('should return true for URLs with protocols', () => {
+ expect(component.isValidClientAddress('http://nfs.example.com')).toBeTruthy();
+ });
+ });
});
import { UntypedFormArray, UntypedFormControl, NgForm, Validators } from '@angular/forms';
import _ from 'lodash';
+import validator from 'validator';
import { NfsService } from '~/app/shared/api/nfs.service';
import { Icons } from '~/app/shared/enum/icons.enum';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
+import { CdValidators } from '~/app/shared/forms/cd-validators';
@Component({
selector: 'cd-nfs-form-client',
return $localize`-- Select what kind of user id squashing is performed --`;
}
+ isValidClientAddress(value: string): boolean {
+ if (_.isEmpty(value)) {
+ return false;
+ }
+
+ const addressList = value.includes(',')
+ ? value.split(',').map((addr) => addr.trim())
+ : [value.trim()];
+ const invalidAddresses = addressList.filter(
+ (address: string) =>
+ !validator.isFQDN(address, {
+ allow_underscores: true,
+ require_tld: true
+ }) &&
+ !validator.isIP(address) &&
+ !validator.isIPRange(address)
+ );
+
+ return invalidAddresses.length > 0;
+ }
+
addClient() {
this.clientsFormArray = this.form.get('clients') as UntypedFormArray;
- const REGEX_IP = `(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\.([0-9]{1,3})([/](\\d|[1-2]\\d|3[0-2]))?)`;
- const REGEX_LIST_IP = `${REGEX_IP}([ ,]{1,2}${REGEX_IP})*`;
const fg = new CdFormGroup({
addresses: new UntypedFormControl('', {
- validators: [Validators.required, Validators.pattern(REGEX_LIST_IP)]
+ validators: [
+ Validators.required,
+ CdValidators.custom('invalidAddress', this.isValidClientAddress)
+ ]
}),
access_type: new UntypedFormControl(''),
squash: new UntypedFormControl('')
return null;
}
- const urls = value.includes(',') ? value.split(',') : [value];
+ const urls = value.includes(',')
+ ? value.split(',').map((v: string) => v.trim())
+ : [value.trim()];
const invalidUrls = urls.filter(
(url: string) =>