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)
73 lines
2.5 KiB
TypeScript
73 lines
2.5 KiB
TypeScript
import { Component, OnInit, signal } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { MatTableModule } from '@angular/material/table';
|
|
import { MatChipsModule } from '@angular/material/chips';
|
|
import { MatCardModule } from '@angular/material/card';
|
|
import { ApiService } from '../../../core/services/api.service';
|
|
import { NotificationService } from '../../../core/services/notification.service';
|
|
|
|
@Component({
|
|
selector: 'app-user-list',
|
|
standalone: true,
|
|
imports: [CommonModule, MatTableModule, MatChipsModule, MatCardModule],
|
|
template: `
|
|
<mat-card>
|
|
<mat-card-header>
|
|
<mat-card-title>All Users</mat-card-title>
|
|
</mat-card-header>
|
|
<mat-card-content>
|
|
<table mat-table [dataSource]="users" class="full-width">
|
|
<ng-container matColumnDef="name">
|
|
<th mat-header-cell *matHeaderCellDef>Name</th>
|
|
<td mat-cell *matCellDef="let user">{{ user.name }}</td>
|
|
</ng-container>
|
|
|
|
<ng-container matColumnDef="email">
|
|
<th mat-header-cell *matHeaderCellDef>Email</th>
|
|
<td mat-cell *matCellDef="let user">{{ user.email }}</td>
|
|
</ng-container>
|
|
|
|
<ng-container matColumnDef="role">
|
|
<th mat-header-cell *matHeaderCellDef>Role</th>
|
|
<td mat-cell *matCellDef="let user">
|
|
<mat-chip>{{ user.role }}</mat-chip>
|
|
</td>
|
|
</ng-container>
|
|
|
|
<ng-container matColumnDef="wallet">
|
|
<th mat-header-cell *matHeaderCellDef>Wallet</th>
|
|
<td mat-cell *matCellDef="let user"><code class="wallet-addr">{{ user.walletAddress }}</code></td>
|
|
</ng-container>
|
|
|
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
|
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
|
</table>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
`,
|
|
styles: [`
|
|
.full-width { width: 100%; }
|
|
.wallet-addr { font-size: 0.75rem; }
|
|
`]
|
|
})
|
|
export class UserListComponent implements OnInit {
|
|
users: any[] = [];
|
|
displayedColumns = ['name', 'email', 'role', 'wallet'];
|
|
readonly loading = signal(false);
|
|
|
|
constructor(private api: ApiService, private notification: NotificationService) {}
|
|
|
|
async ngOnInit() {
|
|
this.loading.set(true);
|
|
try {
|
|
this.users = await this.api.get<any[]>('/admin/users').toPromise() || [];
|
|
} catch (error) {
|
|
this.loading.set(false);
|
|
this.notification.error('Failed to load users. Please try again.');
|
|
console.error('Error:', error);
|
|
} finally {
|
|
this.loading.set(false);
|
|
}
|
|
}
|
|
}
|