Security hardening and edge case fixes across frontend

Security Improvements:
- Add input sanitization utilities (XSS, SQL injection prevention)
- Add token validation with JWT structure verification
- Add secure form validators with pattern enforcement
- Implement proper token storage with encryption support

Service Hardening:
- Add timeout (30s) and retry logic (3 attempts) to all API calls
- Add UUID validation for all ID parameters
- Add null/undefined checks with defensive defaults
- Proper error propagation with typed error handling

Component Fixes:
- Fix memory leaks with takeUntilDestroyed pattern
- Remove mock data fallbacks in error handlers
- Add proper loading/error state management
- Add form field length limits and validation

Files affected: 51 (6000+ lines added for security)
This commit is contained in:
Mahi
2026-02-08 02:10:09 -04:00
parent 80566bf0a2
commit 2c10cd5662
51 changed files with 6094 additions and 656 deletions

View File

@@ -101,58 +101,90 @@
<div class="field-group">
<mat-form-field appearance="outline">
<mat-label>Business Name</mat-label>
<input matInput formControlName="businessName" placeholder="Enter your business name" />
<input matInput formControlName="businessName" placeholder="Enter your business name" [maxlength]="limits.NAME_MAX" />
<mat-icon matPrefix>business</mat-icon>
@if (metadataForm.controls.businessName.hasError('required')) {
<mat-error>Business name is required</mat-error>
}
@if (metadataForm.controls.businessName.hasError('minlength')) {
<mat-error>Minimum 3 characters required</mat-error>
<mat-error>Minimum {{ limits.NAME_MIN }} characters required</mat-error>
}
@if (metadataForm.controls.businessName.hasError('maxlength')) {
<mat-error>Maximum {{ limits.NAME_MAX }} characters allowed</mat-error>
}
@if (metadataForm.controls.businessName.hasError('dangerousContent')) {
<mat-error>Invalid characters detected</mat-error>
}
@if (metadataForm.controls.businessName.hasError('onlyWhitespace')) {
<mat-error>Cannot be only whitespace</mat-error>
}
<mat-hint align="end">{{ metadataForm.controls.businessName.value?.length || 0 }}/{{ limits.NAME_MAX }}</mat-hint>
</mat-form-field>
</div>
<div class="field-group">
<mat-form-field appearance="outline">
<mat-label>Business Address</mat-label>
<input matInput formControlName="businessAddress" placeholder="Full business address" />
<input matInput formControlName="businessAddress" placeholder="Full business address" [maxlength]="limits.ADDRESS_MAX" />
<mat-icon matPrefix>location_on</mat-icon>
@if (metadataForm.controls.businessAddress.hasError('required')) {
<mat-error>Business address is required</mat-error>
}
@if (metadataForm.controls.businessAddress.hasError('maxlength')) {
<mat-error>Maximum {{ limits.ADDRESS_MAX }} characters allowed</mat-error>
}
@if (metadataForm.controls.businessAddress.hasError('dangerousContent')) {
<mat-error>Invalid characters detected</mat-error>
}
<mat-hint align="end">{{ metadataForm.controls.businessAddress.value?.length || 0 }}/{{ limits.ADDRESS_MAX }}</mat-hint>
</mat-form-field>
</div>
<div class="field-group">
<mat-form-field appearance="outline">
<mat-label>Owner / Applicant Name</mat-label>
<input matInput formControlName="ownerName" placeholder="Full name of owner" />
<input matInput formControlName="ownerName" placeholder="Full name of owner" [maxlength]="limits.NAME_MAX" />
<mat-icon matPrefix>person</mat-icon>
@if (metadataForm.controls.ownerName.hasError('required')) {
<mat-error>Owner name is required</mat-error>
}
@if (metadataForm.controls.ownerName.hasError('minlength')) {
<mat-error>Minimum {{ limits.NAME_MIN }} characters required</mat-error>
}
@if (metadataForm.controls.ownerName.hasError('maxlength')) {
<mat-error>Maximum {{ limits.NAME_MAX }} characters allowed</mat-error>
}
@if (metadataForm.controls.ownerName.hasError('dangerousContent')) {
<mat-error>Invalid characters detected</mat-error>
}
</mat-form-field>
</div>
<div class="field-group">
<mat-form-field appearance="outline">
<mat-label>Contact Phone</mat-label>
<input matInput formControlName="ownerPhone" placeholder="+91 XXXXX XXXXX" type="tel" />
<input matInput formControlName="ownerPhone" placeholder="+91 XXXXX XXXXX" type="tel" [maxlength]="limits.PHONE_MAX" />
<mat-icon matPrefix>phone</mat-icon>
@if (metadataForm.controls.ownerPhone.hasError('required')) {
<mat-error>Phone number is required</mat-error>
}
@if (metadataForm.controls.ownerPhone.hasError('invalidPhone')) {
<mat-error>Enter a valid phone number (6-15 digits)</mat-error>
}
</mat-form-field>
</div>
<div class="field-group">
<mat-form-field appearance="outline">
<mat-label>Email Address</mat-label>
<input matInput formControlName="ownerEmail" placeholder="email@example.com" type="email" />
<input matInput formControlName="ownerEmail" placeholder="email@example.com" type="email" [maxlength]="limits.EMAIL_MAX" />
<mat-icon matPrefix>email</mat-icon>
@if (metadataForm.controls.ownerEmail.hasError('email')) {
<mat-error>Please enter a valid email address</mat-error>
}
@if (metadataForm.controls.ownerEmail.hasError('maxlength')) {
<mat-error>Email address is too long</mat-error>
}
</mat-form-field>
</div>
@@ -164,9 +196,16 @@
formControlName="description"
placeholder="Brief description of your business activities"
rows="4"
[maxlength]="limits.DESCRIPTION_MAX"
></textarea>
<mat-icon matPrefix>notes</mat-icon>
<mat-hint>Optional: Provide additional details about your business</mat-hint>
@if (metadataForm.controls.description.hasError('maxlength')) {
<mat-error>Maximum {{ limits.DESCRIPTION_MAX }} characters allowed</mat-error>
}
@if (metadataForm.controls.description.hasError('dangerousContent')) {
<mat-error>Invalid characters detected</mat-error>
}
<mat-hint>Optional: Provide additional details ({{ metadataForm.controls.description.value?.length || 0 }}/{{ limits.DESCRIPTION_MAX }})</mat-hint>
</mat-form-field>
</div>
</div>