Update validation

This commit is contained in:
2025-08-26 20:23:26 -07:00
parent 1df4c054b1
commit 5b8ec7a27e
5 changed files with 80 additions and 28 deletions
@@ -22,7 +22,7 @@
<div class="center">
<div class="content-frame">
<label>Company Website URL</label>
<input class="input-field" name="url" [(ngModel)]="newListing.websiteURL" type="text" placeholder="https://mistox.com/" />
<input class="input-field" name="url" [(ngModel)]="newListing.websiteURL" type="text" (blur)="validateURL(newListing.websiteURL)" placeholder="https://mistox.com/" />
<button type="button" (click)="prevStep()">Back</button>
<button type="button" (click)="nextStep()">Next</button>
</div>
@@ -62,9 +62,12 @@ export class CompanyEditorComponent {
validateEmail(input: string){
let result = this.validator.validateEmail(input);
if (result[0]){
this.newListing.email = result[1];
}
validateURL(input: string){
let result = this.validator.validateURL(input);
this.newListing.websiteURL = result[1];
}
@HostListener('window:keydown', ['$event'])
@@ -146,6 +149,12 @@ export class CompanyEditorComponent {
return;
}
if (this.validator.validateURL(company.websiteURL)[0]){
this.ErrorMsg = "Website is invalid";
this.focusFrame(3, 1);
return;
}
if (this.isNullOrEmpty(company.logo)){
this.ErrorMsg = "Logo is blank";
this.focusFrame(2, 0);
@@ -5,7 +5,6 @@
</div>
<h1>Public: </h1><input [name]="'active' + resume.trackUUID" [(ngModel)]="resume.isActive" type="checkbox" />
<h1>Is Veteran: </h1><input [name]="'veteran' + resume.military?.trackUUID" type="checkbox" [checked]="resume.military !== null" (change)="onVeteranChange($event)" />
<button type="button" (click)="PrintResume()">Print</button>
</div>
<div class="paper">
@@ -140,7 +139,7 @@
<div class="resume-sub-section flex-two-row">
<div>
<input [name]="'certname' + cert.trackUUID" [(ngModel)]="cert.name" type="text" placeholder="Certification Name" />
<input [name]="'certverificationURL' + cert.trackUUID" [(ngModel)]="cert.verificationURL" type="text" placeholder="Verification URL" />
<input [name]="'certverificationURL' + cert.trackUUID" [(ngModel)]="cert.verificationURL" type="text" (blur)="validateCertURL(cert)" placeholder="Verification URL" />
</div>
<textarea [name]="'certdescription' + cert.trackUUID" [(ngModel)]="cert.description" placeholder="Description"></textarea>
</div>
@@ -156,7 +155,7 @@
<div class="resume-sub-section flex-two-row">
<div>
<input [name]="'projname' + proj.trackUUID" [(ngModel)]="proj.name" type="text" placeholder="Project Name" />
<input [name]="'projurl' + proj.trackUUID" [(ngModel)]="proj.url" type="text" placeholder="Reference URL" />
<input [name]="'projurl' + proj.trackUUID" [(ngModel)]="proj.url" type="text" (blur)="validateProjectURL(proj)" placeholder="Reference URL" />
</div>
<textarea [name]="'projdescription' + proj.trackUUID" [(ngModel)]="proj.description" placeholder="Description"></textarea>
</div>
@@ -90,32 +90,22 @@ export class ResumesEditorComponent {
validatePhone(input: string){
let result = this.validator.validatePhoneNumber(input);
if (result[0]){
this.resume.phoneNumber = result[1];
}
}
validateEmail(input: string){
let result = this.validator.validateEmail(input);
if (result[0]){
this.resume.email = result[1];
}
validateCertURL(input: ResumeCertification){
let result = this.validator.validateURL(input.verificationURL);
input.verificationURL = result[1];
}
PrintResume(){
const divToPrint = document.getElementsByClassName("paper")[0];
const printContents = divToPrint.innerHTML;
const originalContents = document.body.innerHTML; // Store original body content
// Temporarily replace the body content with the div's content
document.body.innerHTML = printContents;
// Trigger the print dialog
window.print();
// Restore the original body content
document.body.innerHTML = originalContents;
validateProjectURL(input: ResumeProject){
let result = this.validator.validateURL(input.url);
input.url = result[1];
}
addExperience(){
+56 -2
View File
@@ -25,11 +25,65 @@ export class Validation {
}
}
emailRegex: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
emailRegex: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
validateEmail(input: string): [boolean, string] {
const corrected = input.trim().toLowerCase();
const trimmed = input.trim();
const [local, domain] = trimmed.split('@');
const corrected = domain ? `${local}@${domain.toLowerCase()}` : trimmed;
// Extra checks to avoid invalid formats
if ( corrected.includes('..') || corrected.startsWith('.') || corrected.endsWith('.') ) {
return [false, corrected];
}
const success = this.emailRegex.test(corrected);
return [success, corrected];
}
validateURL(input: string): [boolean, string] {
const testUrl = /^https?:\/\//i.test(input) ? input : "http://" + input;
var urlToParse = new URL(testUrl);
try {
if (urlToParse.protocol !== 'http:' && urlToParse.protocol !== 'https:') {
return [false, urlToParse.href];
}
const hostname = urlToParse.hostname.toLowerCase();
if (hostname === 'localhost' || hostname.endsWith('.localhost')) {
return [false, urlToParse.href];
}
const privateIpRegex = /^(127\.|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)/;
if (privateIpRegex.test(hostname)) {
return [false, urlToParse.href];
}
if (hostname.includes(':')) {
if (this.isPrivateIPv6(hostname)) {
return [false, urlToParse.href];
}
}
return [true, urlToParse.href.substring(0, urlToParse.href.length - 1)];
} catch (e) {
return [false, urlToParse.href];
}
}
///////// HELPER FUNCTIONS /////////
isPrivateIPv6(ip: string): boolean {
try {
const normalized = ip.replace(/^\[|\]$/g, '').toLowerCase();
if (normalized === '::1') return true;
if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;
const first4 = normalized.slice(0, 4);
if (first4 >= 'fe80' && first4 <= 'febf') return true;
return false;
} catch {
return true;
}
}
}