- Added AuthRepository for user and settings management with CRUD operations. - Introduced CertificateRepository to handle domains, certificates, and requirements. - Created MetricsRepository for managing metrics and logs. - Developed PlatformRepository for platform services and resources management. - Established RegistryRepository for registry and token operations. - Implemented ServiceRepository for CRUD operations on services. - Defined types and interfaces in types.ts for database interactions.
382 lines
12 KiB
TypeScript
382 lines
12 KiB
TypeScript
/**
|
|
* Certificate Repository
|
|
* Handles CRUD operations for domains, certificates, cert_requirements, and legacy ssl_certificates
|
|
*/
|
|
|
|
import { BaseRepository } from '../base.repository.ts';
|
|
import type { TBindValue } from '../types.ts';
|
|
import type { IDomain, ICertificate, ICertRequirement, ISslCertificate } from '../../types.ts';
|
|
|
|
export class CertificateRepository extends BaseRepository {
|
|
// ============ Domains ============
|
|
|
|
createDomain(domain: Omit<IDomain, 'id'>): IDomain {
|
|
this.query(
|
|
`INSERT INTO domains (domain, dns_provider, cloudflare_zone_id, is_obsolete, default_wildcard, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
domain.domain,
|
|
domain.dnsProvider,
|
|
domain.cloudflareZoneId,
|
|
domain.isObsolete ? 1 : 0,
|
|
domain.defaultWildcard ? 1 : 0,
|
|
domain.createdAt,
|
|
domain.updatedAt,
|
|
]
|
|
);
|
|
|
|
return this.getDomainByName(domain.domain)!;
|
|
}
|
|
|
|
getDomainByName(domain: string): IDomain | null {
|
|
const rows = this.query('SELECT * FROM domains WHERE domain = ?', [domain]);
|
|
return rows.length > 0 ? this.rowToDomain(rows[0]) : null;
|
|
}
|
|
|
|
getDomainById(id: number): IDomain | null {
|
|
const rows = this.query('SELECT * FROM domains WHERE id = ?', [id]);
|
|
return rows.length > 0 ? this.rowToDomain(rows[0]) : null;
|
|
}
|
|
|
|
getAllDomains(): IDomain[] {
|
|
const rows = this.query('SELECT * FROM domains ORDER BY domain ASC');
|
|
return rows.map((row) => this.rowToDomain(row));
|
|
}
|
|
|
|
getDomainsByProvider(provider: 'cloudflare' | 'manual'): IDomain[] {
|
|
const rows = this.query('SELECT * FROM domains WHERE dns_provider = ? ORDER BY domain ASC', [provider]);
|
|
return rows.map((row) => this.rowToDomain(row));
|
|
}
|
|
|
|
updateDomain(id: number, updates: Partial<IDomain>): void {
|
|
const fields: string[] = [];
|
|
const values: TBindValue[] = [];
|
|
|
|
if (updates.domain !== undefined) {
|
|
fields.push('domain = ?');
|
|
values.push(updates.domain);
|
|
}
|
|
if (updates.dnsProvider !== undefined) {
|
|
fields.push('dns_provider = ?');
|
|
values.push(updates.dnsProvider);
|
|
}
|
|
if (updates.cloudflareZoneId !== undefined) {
|
|
fields.push('cloudflare_zone_id = ?');
|
|
values.push(updates.cloudflareZoneId);
|
|
}
|
|
if (updates.isObsolete !== undefined) {
|
|
fields.push('is_obsolete = ?');
|
|
values.push(updates.isObsolete ? 1 : 0);
|
|
}
|
|
if (updates.defaultWildcard !== undefined) {
|
|
fields.push('default_wildcard = ?');
|
|
values.push(updates.defaultWildcard ? 1 : 0);
|
|
}
|
|
|
|
fields.push('updated_at = ?');
|
|
values.push(Date.now());
|
|
values.push(id);
|
|
|
|
this.query(`UPDATE domains SET ${fields.join(', ')} WHERE id = ?`, values);
|
|
}
|
|
|
|
deleteDomain(id: number): void {
|
|
this.query('DELETE FROM domains WHERE id = ?', [id]);
|
|
}
|
|
|
|
private rowToDomain(row: any): IDomain {
|
|
return {
|
|
id: Number(row.id || row[0]),
|
|
domain: String(row.domain || row[1]),
|
|
dnsProvider: (row.dns_provider || row[2]) as IDomain['dnsProvider'],
|
|
cloudflareZoneId: row.cloudflare_zone_id || row[3] || undefined,
|
|
isObsolete: Boolean(row.is_obsolete || row[4]),
|
|
defaultWildcard: Boolean(row.default_wildcard || row[5]),
|
|
createdAt: Number(row.created_at || row[6]),
|
|
updatedAt: Number(row.updated_at || row[7]),
|
|
};
|
|
}
|
|
|
|
// ============ Certificates ============
|
|
|
|
createCertificate(cert: Omit<ICertificate, 'id'>): ICertificate {
|
|
this.query(
|
|
`INSERT INTO certificates (domain_id, cert_domain, is_wildcard, cert_pem, key_pem, fullchain_pem, expiry_date, issuer, is_valid, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
cert.domainId,
|
|
cert.certDomain,
|
|
cert.isWildcard ? 1 : 0,
|
|
cert.certPem,
|
|
cert.keyPem,
|
|
cert.fullchainPem,
|
|
cert.expiryDate,
|
|
cert.issuer,
|
|
cert.isValid ? 1 : 0,
|
|
cert.createdAt,
|
|
cert.updatedAt,
|
|
]
|
|
);
|
|
|
|
const rows = this.query('SELECT * FROM certificates WHERE id = last_insert_rowid()');
|
|
return this.rowToCertificate(rows[0]);
|
|
}
|
|
|
|
getCertificateById(id: number): ICertificate | null {
|
|
const rows = this.query('SELECT * FROM certificates WHERE id = ?', [id]);
|
|
return rows.length > 0 ? this.rowToCertificate(rows[0]) : null;
|
|
}
|
|
|
|
getCertificatesByDomain(domainId: number): ICertificate[] {
|
|
const rows = this.query('SELECT * FROM certificates WHERE domain_id = ? ORDER BY expiry_date DESC', [domainId]);
|
|
return rows.map((row) => this.rowToCertificate(row));
|
|
}
|
|
|
|
getAllCertificates(): ICertificate[] {
|
|
const rows = this.query('SELECT * FROM certificates ORDER BY expiry_date DESC');
|
|
return rows.map((row) => this.rowToCertificate(row));
|
|
}
|
|
|
|
updateCertificate(id: number, updates: Partial<ICertificate>): void {
|
|
const fields: string[] = [];
|
|
const values: TBindValue[] = [];
|
|
|
|
if (updates.certDomain !== undefined) {
|
|
fields.push('cert_domain = ?');
|
|
values.push(updates.certDomain);
|
|
}
|
|
if (updates.isWildcard !== undefined) {
|
|
fields.push('is_wildcard = ?');
|
|
values.push(updates.isWildcard ? 1 : 0);
|
|
}
|
|
if (updates.certPem !== undefined) {
|
|
fields.push('cert_pem = ?');
|
|
values.push(updates.certPem);
|
|
}
|
|
if (updates.keyPem !== undefined) {
|
|
fields.push('key_pem = ?');
|
|
values.push(updates.keyPem);
|
|
}
|
|
if (updates.fullchainPem !== undefined) {
|
|
fields.push('fullchain_pem = ?');
|
|
values.push(updates.fullchainPem);
|
|
}
|
|
if (updates.expiryDate !== undefined) {
|
|
fields.push('expiry_date = ?');
|
|
values.push(updates.expiryDate);
|
|
}
|
|
if (updates.issuer !== undefined) {
|
|
fields.push('issuer = ?');
|
|
values.push(updates.issuer);
|
|
}
|
|
if (updates.isValid !== undefined) {
|
|
fields.push('is_valid = ?');
|
|
values.push(updates.isValid ? 1 : 0);
|
|
}
|
|
|
|
fields.push('updated_at = ?');
|
|
values.push(Date.now());
|
|
values.push(id);
|
|
|
|
this.query(`UPDATE certificates SET ${fields.join(', ')} WHERE id = ?`, values);
|
|
}
|
|
|
|
deleteCertificate(id: number): void {
|
|
this.query('DELETE FROM certificates WHERE id = ?', [id]);
|
|
}
|
|
|
|
private rowToCertificate(row: any): ICertificate {
|
|
return {
|
|
id: Number(row.id || row[0]),
|
|
domainId: Number(row.domain_id || row[1]),
|
|
certDomain: String(row.cert_domain || row[2]),
|
|
isWildcard: Boolean(row.is_wildcard || row[3]),
|
|
certPem: String(row.cert_pem || row[4] || ''),
|
|
keyPem: String(row.key_pem || row[5] || ''),
|
|
fullchainPem: String(row.fullchain_pem || row[6] || ''),
|
|
expiryDate: Number(row.expiry_date || row[7]),
|
|
issuer: String(row.issuer || row[8]),
|
|
isValid: Boolean(row.is_valid || row[9]),
|
|
createdAt: Number(row.created_at || row[10]),
|
|
updatedAt: Number(row.updated_at || row[11]),
|
|
};
|
|
}
|
|
|
|
// ============ Certificate Requirements ============
|
|
|
|
createCertRequirement(req: Omit<ICertRequirement, 'id'>): ICertRequirement {
|
|
this.query(
|
|
`INSERT INTO cert_requirements (service_id, domain_id, subdomain, certificate_id, status, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
req.serviceId,
|
|
req.domainId,
|
|
req.subdomain,
|
|
req.certificateId,
|
|
req.status,
|
|
req.createdAt,
|
|
req.updatedAt,
|
|
]
|
|
);
|
|
|
|
const rows = this.query('SELECT * FROM cert_requirements WHERE id = last_insert_rowid()');
|
|
return this.rowToCertRequirement(rows[0]);
|
|
}
|
|
|
|
getCertRequirementById(id: number): ICertRequirement | null {
|
|
const rows = this.query('SELECT * FROM cert_requirements WHERE id = ?', [id]);
|
|
return rows.length > 0 ? this.rowToCertRequirement(rows[0]) : null;
|
|
}
|
|
|
|
getCertRequirementsByService(serviceId: number): ICertRequirement[] {
|
|
const rows = this.query('SELECT * FROM cert_requirements WHERE service_id = ?', [serviceId]);
|
|
return rows.map((row) => this.rowToCertRequirement(row));
|
|
}
|
|
|
|
getCertRequirementsByDomain(domainId: number): ICertRequirement[] {
|
|
const rows = this.query('SELECT * FROM cert_requirements WHERE domain_id = ?', [domainId]);
|
|
return rows.map((row) => this.rowToCertRequirement(row));
|
|
}
|
|
|
|
getAllCertRequirements(): ICertRequirement[] {
|
|
const rows = this.query('SELECT * FROM cert_requirements ORDER BY created_at DESC');
|
|
return rows.map((row) => this.rowToCertRequirement(row));
|
|
}
|
|
|
|
updateCertRequirement(id: number, updates: Partial<ICertRequirement>): void {
|
|
const fields: string[] = [];
|
|
const values: TBindValue[] = [];
|
|
|
|
if (updates.subdomain !== undefined) {
|
|
fields.push('subdomain = ?');
|
|
values.push(updates.subdomain);
|
|
}
|
|
if (updates.certificateId !== undefined) {
|
|
fields.push('certificate_id = ?');
|
|
values.push(updates.certificateId);
|
|
}
|
|
if (updates.status !== undefined) {
|
|
fields.push('status = ?');
|
|
values.push(updates.status);
|
|
}
|
|
|
|
fields.push('updated_at = ?');
|
|
values.push(Date.now());
|
|
values.push(id);
|
|
|
|
this.query(`UPDATE cert_requirements SET ${fields.join(', ')} WHERE id = ?`, values);
|
|
}
|
|
|
|
deleteCertRequirement(id: number): void {
|
|
this.query('DELETE FROM cert_requirements WHERE id = ?', [id]);
|
|
}
|
|
|
|
private rowToCertRequirement(row: any): ICertRequirement {
|
|
return {
|
|
id: Number(row.id || row[0]),
|
|
serviceId: Number(row.service_id || row[1]),
|
|
domainId: Number(row.domain_id || row[2]),
|
|
subdomain: String(row.subdomain || row[3]),
|
|
certificateId: row.certificate_id || row[4] || undefined,
|
|
status: String(row.status || row[5]) as ICertRequirement['status'],
|
|
createdAt: Number(row.created_at || row[6]),
|
|
updatedAt: Number(row.updated_at || row[7]),
|
|
};
|
|
}
|
|
|
|
// ============ SSL Certificates (Legacy API) ============
|
|
|
|
async createSSLCertificate(cert: Omit<ISslCertificate, 'id'>): Promise<ISslCertificate> {
|
|
// First, ensure domain exists in domains table
|
|
let domainRecord = this.getDomainByName(cert.domain);
|
|
if (!domainRecord) {
|
|
const now = Date.now();
|
|
domainRecord = this.createDomain({
|
|
domain: cert.domain,
|
|
dnsProvider: null,
|
|
isObsolete: false,
|
|
defaultWildcard: true,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
});
|
|
}
|
|
|
|
const now = Date.now();
|
|
this.query(
|
|
`INSERT INTO certificates (domain_id, cert_domain, is_wildcard, cert_pem, key_pem, fullchain_pem, expiry_date, issuer, is_valid, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
domainRecord.id,
|
|
cert.domain,
|
|
0,
|
|
cert.certPem,
|
|
cert.keyPem,
|
|
cert.fullchainPem,
|
|
cert.expiryDate,
|
|
cert.issuer,
|
|
1,
|
|
now,
|
|
now,
|
|
]
|
|
);
|
|
|
|
return this.getSSLCertificate(cert.domain)!;
|
|
}
|
|
|
|
getSSLCertificate(domain: string): ISslCertificate | null {
|
|
const rows = this.query('SELECT * FROM certificates WHERE cert_domain = ?', [domain]);
|
|
return rows.length > 0 ? this.rowToSSLCert(rows[0]) : null;
|
|
}
|
|
|
|
getAllSSLCertificates(): ISslCertificate[] {
|
|
const rows = this.query('SELECT * FROM certificates ORDER BY expiry_date ASC');
|
|
return rows.map((row) => this.rowToSSLCert(row));
|
|
}
|
|
|
|
updateSSLCertificate(domain: string, updates: Partial<ISslCertificate>): void {
|
|
const fields: string[] = [];
|
|
const values: TBindValue[] = [];
|
|
|
|
if (updates.certPem) {
|
|
fields.push('cert_pem = ?');
|
|
values.push(updates.certPem);
|
|
}
|
|
if (updates.keyPem) {
|
|
fields.push('key_pem = ?');
|
|
values.push(updates.keyPem);
|
|
}
|
|
if (updates.fullchainPem) {
|
|
fields.push('fullchain_pem = ?');
|
|
values.push(updates.fullchainPem);
|
|
}
|
|
if (updates.expiryDate) {
|
|
fields.push('expiry_date = ?');
|
|
values.push(updates.expiryDate);
|
|
}
|
|
|
|
fields.push('updated_at = ?');
|
|
values.push(Date.now());
|
|
values.push(domain);
|
|
|
|
this.query(`UPDATE certificates SET ${fields.join(', ')} WHERE cert_domain = ?`, values);
|
|
}
|
|
|
|
deleteSSLCertificate(domain: string): void {
|
|
this.query('DELETE FROM certificates WHERE cert_domain = ?', [domain]);
|
|
}
|
|
|
|
private rowToSSLCert(row: any): ISslCertificate {
|
|
return {
|
|
id: Number(row.id || row[0]),
|
|
domain: String(row.cert_domain || row[2] || ''),
|
|
certPem: String(row.cert_pem || row[4] || ''),
|
|
keyPem: String(row.key_pem || row[5] || ''),
|
|
fullchainPem: String(row.fullchain_pem || row[6] || ''),
|
|
expiryDate: Number(row.expiry_date || row[7]),
|
|
issuer: String(row.issuer || row[8]),
|
|
createdAt: Number(row.created_at || row[10]),
|
|
updatedAt: Number(row.updated_at || row[11]),
|
|
};
|
|
}
|
|
}
|