feat(ssl): Add domain & certificate management, Cloudflare sync, SQLite cert manager, WebSocket realtime updates, and HTTP API SSL endpoints

This commit is contained in:
2025-11-18 19:34:26 +00:00
parent 44267bbb27
commit b94aa17eee
16 changed files with 1707 additions and 1344 deletions

View File

@@ -110,22 +110,26 @@ import { ApiService, SystemStatus } from '../../core/services/api.service';
</div>
</div>
<!-- Nginx -->
<!-- Reverse Proxy -->
<div class="card">
<h3 class="text-lg font-medium text-gray-900 mb-4">Nginx</h3>
<h3 class="text-lg font-medium text-gray-900 mb-4">Reverse Proxy</h3>
<div class="space-y-2">
<div class="flex justify-between">
<span class="text-sm text-gray-600">Status</span>
<span [ngClass]="status()!.nginx.status === 'running' ? 'badge-success' : 'badge-danger'" class="badge">
{{ status()!.nginx.status }}
<span class="text-sm text-gray-600">HTTP (Port {{ status()!.reverseProxy.http.port }})</span>
<span [ngClass]="status()!.reverseProxy.http.running ? 'badge-success' : 'badge-danger'" class="badge">
{{ status()!.reverseProxy.http.running ? 'Running' : 'Stopped' }}
</span>
</div>
<div class="flex justify-between">
<span class="text-sm text-gray-600">Installed</span>
<span [ngClass]="status()!.nginx.installed ? 'badge-success' : 'badge-danger'" class="badge">
{{ status()!.nginx.installed ? 'Yes' : 'No' }}
<span class="text-sm text-gray-600">HTTPS (Port {{ status()!.reverseProxy.https.port }})</span>
<span [ngClass]="status()!.reverseProxy.https.running ? 'badge-success' : 'badge-danger'" class="badge">
{{ status()!.reverseProxy.https.running ? 'Running' : 'Stopped' }}
</span>
</div>
<div class="flex justify-between">
<span class="text-sm text-gray-600">SSL Certificates</span>
<span class="badge badge-info">{{ status()!.reverseProxy.https.certificates }}</span>
</div>
</div>
</div>

View File

@@ -1,7 +1,9 @@
import { Component, OnInit, inject, signal } from '@angular/core';
import { Component, OnInit, OnDestroy, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router';
import { ApiService, Service } from '../../core/services/api.service';
import { WebSocketService } from '../../core/services/websocket.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-services-list',
@@ -89,14 +91,42 @@ import { ApiService, Service } from '../../core/services/api.service';
</div>
`,
})
export class ServicesListComponent implements OnInit {
export class ServicesListComponent implements OnInit, OnDestroy {
private apiService = inject(ApiService);
private wsService = inject(WebSocketService);
private wsSubscription?: Subscription;
services = signal<Service[]>([]);
loading = signal(true);
ngOnInit(): void {
// Initial load
this.loadServices();
// Subscribe to WebSocket updates
this.wsSubscription = this.wsService.getMessages().subscribe((message) => {
this.handleWebSocketMessage(message);
});
}
ngOnDestroy(): void {
this.wsSubscription?.unsubscribe();
}
private handleWebSocketMessage(message: any): void {
if (message.type === 'service_update') {
// Reload the full service list on any service update
this.loadServices();
} else if (message.type === 'service_status') {
// Update individual service status
const currentServices = this.services();
const updatedServices = currentServices.map(s =>
s.name === message.serviceName
? { ...s, status: message.status }
: s
);
this.services.set(updatedServices);
}
}
loadServices(): void {
@@ -117,7 +147,7 @@ export class ServicesListComponent implements OnInit {
startService(service: Service): void {
this.apiService.startService(service.name).subscribe({
next: () => {
this.loadServices();
// WebSocket will handle the update
},
});
}
@@ -125,7 +155,7 @@ export class ServicesListComponent implements OnInit {
stopService(service: Service): void {
this.apiService.stopService(service.name).subscribe({
next: () => {
this.loadServices();
// WebSocket will handle the update
},
});
}
@@ -133,7 +163,7 @@ export class ServicesListComponent implements OnInit {
restartService(service: Service): void {
this.apiService.restartService(service.name).subscribe({
next: () => {
this.loadServices();
// WebSocket will handle the update
},
});
}
@@ -142,7 +172,7 @@ export class ServicesListComponent implements OnInit {
if (confirm(`Are you sure you want to delete ${service.name}?`)) {
this.apiService.deleteService(service.name).subscribe({
next: () => {
this.loadServices();
// WebSocket will handle the update
},
});
}