72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import os from 'node:os'
|
|
import Site from '#models/site'
|
|
import AuditLog from '#models/audit_log'
|
|
import backupService from '#services/backup_service'
|
|
import dockerService from '#services/docker_service'
|
|
import metricsService from '#services/metrics_service'
|
|
|
|
const CERT_WARNING_DAYS = 14
|
|
|
|
export default class OverviewController {
|
|
async index() {
|
|
const now = Math.floor(Date.now() / 1000)
|
|
|
|
const [containers, sites, backups, recent, uptime] = await Promise.all([
|
|
dockerService.list().catch((error: Error) => error),
|
|
Site.query().where('active', true).orderBy('domain'),
|
|
backupService.list(),
|
|
AuditLog.query().orderBy('id', 'desc').limit(8),
|
|
metricsService.uptime(),
|
|
])
|
|
|
|
const docker =
|
|
containers instanceof Error
|
|
? { ok: false as const, error: containers.message }
|
|
: {
|
|
ok: true as const,
|
|
total: containers.length,
|
|
running: containers.filter((c) => c.state === 'running').length,
|
|
unhealthy: containers.filter((c) => c.health === 'unhealthy').map((c) => c.name),
|
|
stopped: containers.filter((c) => c.state !== 'running').map((c) => c.name),
|
|
}
|
|
|
|
return {
|
|
host: {
|
|
latest: metricsService.latest,
|
|
uptime,
|
|
cpus: os.cpus().length,
|
|
},
|
|
docker,
|
|
sites: {
|
|
total: sites.length,
|
|
up: sites.filter((site) => site.lastOk === true).length,
|
|
down: sites
|
|
.filter((site) => site.lastOk === false)
|
|
.map((site) => ({ id: site.id, domain: site.domain, error: site.lastError })),
|
|
certSoon: sites
|
|
.filter(
|
|
(site) => site.certExpiresAt && site.certExpiresAt - now < CERT_WARNING_DAYS * 86_400
|
|
)
|
|
.map((site) => ({
|
|
id: site.id,
|
|
domain: site.domain,
|
|
days: Math.floor((site.certExpiresAt! - now) / 86_400),
|
|
})),
|
|
},
|
|
backups: {
|
|
last: backups[0] ?? null,
|
|
count: backups.length,
|
|
schedule: backupService.schedule,
|
|
},
|
|
recent: recent.map((entry) => ({
|
|
id: entry.id,
|
|
action: entry.action,
|
|
target: entry.target,
|
|
status: entry.status,
|
|
username: entry.username,
|
|
createdAt: entry.createdAt.toISO(),
|
|
})),
|
|
}
|
|
}
|
|
}
|