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:
@@ -1,4 +1,5 @@
|
||||
import { Component, OnInit, inject, signal } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, inject, signal, DestroyRef } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
@@ -128,12 +129,14 @@ import { WebhookLogEntryDto } from '../../../api/models';
|
||||
`,
|
||||
],
|
||||
})
|
||||
export class WebhookLogsComponent implements OnInit {
|
||||
export class WebhookLogsComponent implements OnInit, OnDestroy {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly router = inject(Router);
|
||||
private readonly webhookService = inject(WebhookService);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
readonly loading = signal(true);
|
||||
readonly hasError = signal(false);
|
||||
readonly logs = signal<WebhookLogEntryDto[]>([]);
|
||||
readonly totalItems = signal(0);
|
||||
readonly pageSize = signal(20);
|
||||
@@ -156,15 +159,19 @@ export class WebhookLogsComponent implements OnInit {
|
||||
if (!this.webhookId) return;
|
||||
|
||||
this.loading.set(true);
|
||||
this.hasError.set(false);
|
||||
|
||||
this.webhookService
|
||||
.getWebhookLogs(this.webhookId, this.pageIndex() + 1, this.pageSize())
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
this.logs.set(response.data);
|
||||
this.totalItems.set(response.total);
|
||||
this.logs.set(response?.data ?? []);
|
||||
this.totalItems.set(response?.total ?? 0);
|
||||
this.loading.set(false);
|
||||
},
|
||||
error: () => {
|
||||
this.hasError.set(true);
|
||||
this.loading.set(false);
|
||||
},
|
||||
});
|
||||
@@ -177,10 +184,19 @@ export class WebhookLogsComponent implements OnInit {
|
||||
}
|
||||
|
||||
formatEvent(event: string): string {
|
||||
return event.replace(/_/g, ' ').toLowerCase();
|
||||
return event?.replace(/_/g, ' ').toLowerCase() ?? '';
|
||||
}
|
||||
|
||||
isSuccess(statusCode: number): boolean {
|
||||
return statusCode >= 200 && statusCode < 300;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
// Cleanup handled by DestroyRef/takeUntilDestroyed
|
||||
}
|
||||
|
||||
/** Retry loading data - clears error state */
|
||||
retryLoad(): void {
|
||||
this.loadLogs();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user