Skip to content

Commit

Permalink
Merge pull request #61 from StatCan/59-add-custom-image-url-validation
Browse files Browse the repository at this point in the history
fix: add url validation for custom images
  • Loading branch information
wg102 authored May 21, 2021
2 parents 37c5e7c + 4e2554f commit 416bcb1
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ <h3>
</h3>
<p>
{{ "formImage.txtImage" | translate }}
<a href="https://statcan.github.io/daaas/en/1-Experiments/Selecting-an-Image/"
target="_blank" style="text-decoration: none">
<a
href="https://statcan.github.io/daaas/en/1-Experiments/Selecting-an-Image/"
target="_blank"
style="text-decoration: none"
>
{{ "formImage.txtImageLink" | translate }}
</a>
</p>
Expand Down Expand Up @@ -43,6 +46,6 @@ <h3>
formControlName="customImage"
#cstmimg
/>
<mat-error>{{ "formImage.errorImageRequired" | translate }}</mat-error>
<mat-error>{{ urlValidation() }}</mat-error>
</mat-form-field>
</div>
60 changes: 51 additions & 9 deletions frontend/src/app/resource-form/form-image/form-image.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Component, OnInit, Input } from "@angular/core";
import { FormGroup } from "@angular/forms";
import {Component, OnInit, Input} from "@angular/core";
import {FormGroup, ValidatorFn, AbstractControl} from "@angular/forms";
import {TranslateService} from "@ngx-translate/core";
import {Subscription} from "rxjs";

@Component({
selector: "app-form-image",
Expand All @@ -12,24 +14,64 @@ export class FormImageComponent implements OnInit {
@Input() readonly: boolean;
@Input() hideRegistry: boolean;
@Input() hideVersion: boolean;
subscriptions = new Subscription();

constructor() {}
constructor(private translate: TranslateService) {}

ngOnInit() {}
ngOnInit() {
//Add validator for custom image urls (no http[s]://)
this.parentForm.get("customImage").setValidators([this.urlValidator()]);

//disable custom image input when not being used, so errors are ignored
this.subscriptions.add(
this.parentForm
.get("customImageCheck")
.valueChanges.subscribe((b: boolean) => {
if (b) {
this.parentForm.controls.customImage.enable();
} else {
this.parentForm.controls.customImage.disable();
}
})
);
}

imageDisplayName(image: string): string {
const [name, version = null] = image.split(':');
let tokens = name.split('/')
const [name, version = null] = image.split(":");
let tokens = name.split("/");

if (this.hideRegistry && tokens.length > 1 && tokens[0].includes('.')) {
if (this.hideRegistry && tokens.length > 1 && tokens[0].includes(".")) {
tokens.shift();
}
let displayName = tokens.join('/');
let displayName = tokens.join("/");

if (!this.hideVersion && version !== null) {
displayName = `${displayName}:${version}`;
}

return displayName;
}

urlValidation(): void {
const url = this.parentForm.get("customImage");

if (url.hasError("invalidUrl")) {
let urlBeginning = "https://";
const schemeReg = /^http:\/\//i;

if (schemeReg.test(url.value)) {
urlBeginning = "http://";
}

return this.translate.instant("formImage.errorHttp", {
scheme: urlBeginning
});
}
}

private urlValidator(): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
const schemeReg = /^http[s]?:\/\//i;
return schemeReg.test(control.value) ? {invalidUrl: true} : null;
};
}
}
7 changes: 4 additions & 3 deletions frontend/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"formAdvancedOptions": {
"h3AdvancedSettings": "Advanced Settings",
"toggleSharedMemory": "Enable Shared Memory",
"lblSystemLanguage":"System language",
"lblSystemLanguage": "System language",
"lblEnglish": "English",
"lblFrench": "Français"
},
Expand Down Expand Up @@ -83,7 +83,8 @@
"plhImage": "Docker Image",
"lblCustomImage": "Custom Image",
"plhCustomImage": "Provide a custom Image",
"errorImageRequired": "Please provide and Image to use"
"errorImageRequired": "Please provide and Image to use",
"errorHttp": "{{scheme}} is not allowed in URLs"
},
"formName": {
"h3Name": "Name",
Expand Down Expand Up @@ -129,7 +130,7 @@
"lblName": "Name",
"errorNameRequired": "The volume name can't be empty",
"errorNamePattern": "The volume name can only contain lowercase alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character",
"errorMountedVolume":"The volume is already mounted to another notebook and cannot be currently selected",
"errorMountedVolume": "The volume is already mounted to another notebook and cannot be currently selected",
"lblSize": "Size",
"lblMode": "Mode",
"optReadWriteOnce": "ReadWriteOnce",
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"formAdvancedOptions": {
"h3AdvancedSettings": "Paramètres avancés",
"toggleSharedMemory": "Activer la mémoire partagée",
"lblSystemLanguage":"Langue du système",
"lblSystemLanguage": "Langue du système",
"lblEnglish": "English",
"lblFrench": "Français"
},
Expand All @@ -73,18 +73,18 @@
"lblGpuVendor": "Vendeur de GPU",
"errorGpuVendorRequired": "Vous devez spécifier le vendeur des GPUs assignés",
"specsWarningMessage": "La sélection de 1 GPU définira automatiquement 4 processeurs et 96Gi de la mémoire."

},
"formImage": {
"h3Image": "Image",
"txtImage": "Sélectionner les logiciels de base désirés sur votre serveur. Si vous choisissez une image personnallisée, elle doit être disponible dans le registre des conteneurs DAaaS.",
"txtImageLink": "Voici plus d'informations pour vous aider à sélectionner une image selon vos besoins.",
"txtImageLink": "Voici plus d'informations pour vous aider à sélectionner une image selon vos besoins.",
"ckbImage": "Image personnalisée",
"lblImage": "Image",
"plhImage": "Image Docker",
"lblCustomImage": "Image personnalisée",
"plhCustomImage": "Fournir une image personnalisée",
"errorImageRequired": "Veuillez fournir une image a utiliser"
"errorImageRequired": "Veuillez fournir une image a utiliser",
"errorHttp": "{{scheme}} n'est pas autorisé dans les URLs"
},
"formName": {
"h3Name": "Nom",
Expand Down Expand Up @@ -130,7 +130,7 @@
"lblName": "Nom",
"errorNameRequired": "Le nom du volume ne peut pas être vide",
"errorNamePattern": "Le nom du volume ne peut contenir que des caractères alphanumériques en minuscule, '-' ou '.', et doit commencer et se terminer par un caractères alphanumériques",
"errorMountedVolume":"Le volume est déjà monté sur un autre bloc-notes et ne peut être sélectionné actuellement",
"errorMountedVolume": "Le volume est déjà monté sur un autre bloc-notes et ne peut être sélectionné actuellement",
"lblSize": "Taille",
"lblMode": "Mode",
"optReadWriteOnce": "ReadWriteOnce",
Expand Down

0 comments on commit 416bcb1

Please sign in to comment.