feat: Implement repositories for authentication, certificates, metrics, and platform services
- 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.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* SQLite-based Certificate Manager for SmartACME
|
||||
*
|
||||
* Implements ICertManager interface to store SSL certificates in SQLite database
|
||||
* and write PEM files to filesystem for use by the reverse proxy.
|
||||
* Implements ICertManager interface to store SSL certificates directly in SQLite database.
|
||||
* Certificate PEM content is stored in the database, not on the filesystem.
|
||||
*/
|
||||
|
||||
import * as plugins from '../plugins.ts';
|
||||
@@ -12,25 +12,16 @@ import { OneboxDatabase } from './database.ts';
|
||||
|
||||
export class SqliteCertManager implements plugins.smartacme.ICertManager {
|
||||
private database: OneboxDatabase;
|
||||
private certBasePath: string;
|
||||
|
||||
constructor(database: OneboxDatabase, certBasePath = './.nogit/ssl/live') {
|
||||
constructor(database: OneboxDatabase) {
|
||||
this.database = database;
|
||||
this.certBasePath = certBasePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the certificate manager
|
||||
*/
|
||||
async init(): Promise<void> {
|
||||
try {
|
||||
// Ensure certificate directory exists
|
||||
await Deno.mkdir(this.certBasePath, { recursive: true });
|
||||
logger.info(`Certificate manager initialized (path: ${this.certBasePath})`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to initialize certificate manager: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
logger.info('Certificate manager initialized (database storage)');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,7 +31,7 @@ export class SqliteCertManager implements plugins.smartacme.ICertManager {
|
||||
try {
|
||||
const dbCert = this.database.getSSLCertificate(domainName);
|
||||
|
||||
if (!dbCert) {
|
||||
if (!dbCert || !dbCert.keyPem || !dbCert.fullchainPem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -49,8 +40,8 @@ export class SqliteCertManager implements plugins.smartacme.ICertManager {
|
||||
id: dbCert.id?.toString() || domainName,
|
||||
domainName: dbCert.domain,
|
||||
created: dbCert.createdAt,
|
||||
privateKey: await this.readPemFile(dbCert.keyPath),
|
||||
publicKey: await this.readPemFile(dbCert.fullChainPath), // Full chain as public key
|
||||
privateKey: dbCert.keyPem,
|
||||
publicKey: dbCert.fullchainPem, // Full chain as public key
|
||||
csr: '', // CSR not stored separately
|
||||
validUntil: dbCert.expiryDate,
|
||||
});
|
||||
@@ -68,42 +59,28 @@ export class SqliteCertManager implements plugins.smartacme.ICertManager {
|
||||
async storeCertificate(cert: plugins.smartacme.Cert): Promise<void> {
|
||||
try {
|
||||
const domain = cert.domainName;
|
||||
const domainPath = `${this.certBasePath}/${domain}`;
|
||||
|
||||
// Create domain-specific directory
|
||||
await Deno.mkdir(domainPath, { recursive: true });
|
||||
|
||||
// Write PEM files
|
||||
const keyPath = `${domainPath}/privkey.pem`;
|
||||
const certPath = `${domainPath}/cert.pem`;
|
||||
const fullChainPath = `${domainPath}/fullchain.pem`;
|
||||
|
||||
await Deno.writeTextFile(keyPath, cert.privateKey);
|
||||
await Deno.writeTextFile(fullChainPath, cert.publicKey);
|
||||
|
||||
// Extract certificate from full chain (first certificate in the chain)
|
||||
const certOnly = this.extractCertFromChain(cert.publicKey);
|
||||
await Deno.writeTextFile(certPath, certOnly);
|
||||
const certPem = this.extractCertFromChain(cert.publicKey);
|
||||
|
||||
// Store/update in database
|
||||
// Store/update in database with PEM content
|
||||
const existing = this.database.getSSLCertificate(domain);
|
||||
|
||||
if (existing) {
|
||||
this.database.updateSSLCertificate(domain, {
|
||||
certPath,
|
||||
keyPath,
|
||||
fullChainPath,
|
||||
certPem: certPem,
|
||||
keyPem: cert.privateKey,
|
||||
fullchainPem: cert.publicKey,
|
||||
expiryDate: cert.validUntil,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
} else {
|
||||
await this.database.createSSLCertificate({
|
||||
domain,
|
||||
certPath,
|
||||
keyPath,
|
||||
fullChainPath,
|
||||
certPem: certPem,
|
||||
keyPem: cert.privateKey,
|
||||
fullchainPem: cert.publicKey,
|
||||
expiryDate: cert.validUntil,
|
||||
issuer: 'Let\'s Encrypt',
|
||||
issuer: "Let's Encrypt",
|
||||
createdAt: cert.created,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
@@ -124,17 +101,8 @@ export class SqliteCertManager implements plugins.smartacme.ICertManager {
|
||||
const dbCert = this.database.getSSLCertificate(domainName);
|
||||
|
||||
if (dbCert) {
|
||||
// Delete PEM files
|
||||
const domainPath = `${this.certBasePath}/${domainName}`;
|
||||
try {
|
||||
await Deno.remove(domainPath, { recursive: true });
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to delete PEM files for ${domainName}: ${getErrorMessage(error)}`);
|
||||
}
|
||||
|
||||
// Delete from database
|
||||
this.database.deleteSSLCertificate(domainName);
|
||||
|
||||
logger.info(`Certificate deleted for ${domainName}`);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -169,17 +137,6 @@ export class SqliteCertManager implements plugins.smartacme.ICertManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read PEM file from filesystem
|
||||
*/
|
||||
private async readPemFile(path: string): Promise<string> {
|
||||
try {
|
||||
return await Deno.readTextFile(path);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to read PEM file ${path}: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the first certificate from a PEM chain
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user