From 4ee1c4b08cedf7b80ed9b06cfab446fed298b65a Mon Sep 17 00:00:00 2001 From: Phil Kunz Date: Tue, 15 Jan 2019 23:39:31 +0100 Subject: [PATCH] fix(core): update --- package.json | 1 + ts/smartacme.classes.certmanager.ts | 23 ++++++--- ts/smartacme.classes.certremoteclient.ts | 27 ++++++---- ts/smartacme.classes.smartacme.ts | 63 +++++++++++++----------- ts/smartacme.plugins.ts | 3 +- 5 files changed, 69 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 1f705cc..7681d66 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@pushrocks/smartdelay": "^2.0.2", "@pushrocks/smartdns": "^3.0.8", "@pushrocks/smartexpress": "^3.0.4", + "@pushrocks/smartlog": "^2.0.9", "@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartrequest": "^1.1.14", "@pushrocks/smartstring": "^3.0.8", diff --git a/ts/smartacme.classes.certmanager.ts b/ts/smartacme.classes.certmanager.ts index 373e7c9..8026eea 100644 --- a/ts/smartacme.classes.certmanager.ts +++ b/ts/smartacme.classes.certmanager.ts @@ -56,10 +56,8 @@ export class CertManager { } /** - * stores the certificate with the - * @param publicKeyArg - * @param privateKeyArg - * @param csrArg + * stores the certificate + * @param optionsArg */ public async storeCertificate(optionsArg: interfaces.ICert) { const cert = new Cert(optionsArg); @@ -70,14 +68,25 @@ export class CertManager { } - public async getCertificateStatus(domainNameArg: string): Promise { - const isPending = this.pendingMap.checkString('domainNameArg'); + /** + * announce a certificate as being in the process of being retrieved + */ + public async announceCertificate (domainNameArg: string) { + this.pendingMap.addString(domainNameArg); + } + + /** + * gets the status of a certificate by certDomain name + * @param certDomainArg + */ + public async getCertificateStatus(certDomainArg: string): Promise { + const isPending = this.pendingMap.checkString(certDomainArg); if (isPending) { return 'pending'; } // otherwise lets continue - const existingCertificate = this.retrieveCertificate(domainNameArg); + const existingCertificate = this.retrieveCertificate(certDomainArg); if (existingCertificate) { return 'existing'; } diff --git a/ts/smartacme.classes.certremoteclient.ts b/ts/smartacme.classes.certremoteclient.ts index 8c339c9..085d744 100644 --- a/ts/smartacme.classes.certremoteclient.ts +++ b/ts/smartacme.classes.certremoteclient.ts @@ -1,34 +1,41 @@ import * as plugins from './smartacme.plugins'; import * as interfaces from './interfaces'; -import { ICertRemoteResponse } from './interfaces'; // tslint:disable-next-line: max-classes-per-file export class CertRemoteClient { private remoteUrl: string; private secret: string; + private logger: plugins.smartlog.Smartlog; constructor(optionsArg: { remoteUrl: string; secret: string; + logger?: plugins.smartlog.Smartlog; }) { this.remoteUrl = optionsArg.remoteUrl; this.secret = optionsArg.secret; + optionsArg.logger + ? (this.logger = optionsArg.logger) + : (this.logger = plugins.smartlog.defaultLogger); } /** - * - * @param domainNameArg + * + * @param domainNameArg */ - async getCertificateForDomain(domainNameArg: string): Promise { + public async getCertificateForDomain(domainNameArg: string): Promise { let certificate: interfaces.ICert; const doRequestCycle = async (): Promise => { - const response: ICertRemoteResponse = (await plugins.smartrequest.postJson(this.remoteUrl, { - requestBody: { - domainName: domainNameArg, - secret: this.secret + const response: interfaces.ICertRemoteResponse = (await plugins.smartrequest.postJson( + this.remoteUrl, + { + requestBody: { + domainName: domainNameArg, + secret: this.secret + } } - })).body; - switch(response.status) { + )).body; + switch (response.status as interfaces.TCertStatus) { case 'pending': await plugins.smartdelay.delayFor(5000); const finalResponse = await doRequestCycle(); diff --git a/ts/smartacme.classes.smartacme.ts b/ts/smartacme.classes.smartacme.ts index 53b0c62..792a143 100644 --- a/ts/smartacme.classes.smartacme.ts +++ b/ts/smartacme.classes.smartacme.ts @@ -21,7 +21,7 @@ export interface ISmartAcmeOptions { /** * class SmartAcme * can be used for setting up communication with an ACME authority - * + * * ```ts * const mySmartAcmeInstance = new SmartAcme({ * // see ISmartAcmeOptions for options @@ -49,7 +49,36 @@ export class SmartAcme { /** * the remote handler to hand the request and response to. */ - public certremoteHandler: (req: plugins.smartexpress.Request, res: plugins.smartexpress.Response) => Promise; + public certremoteHandler = async (req: plugins.smartexpress.Request, res: plugins.smartexpress.Response) => { + const requestBody: interfaces.ICertRemoteRequest = req.body; + const certDomain = this.certmatcher.getCertificateDomainNameByDomainName(requestBody.domainName); + let status: interfaces.TCertStatus = await this.certmanager.getCertificateStatus( + certDomain + ); + let response: interfaces.ICertRemoteResponse; + switch (status) { + case 'existing': + response = { + status, + certificate: await (await this.certmanager.retrieveCertificate( + certDomain + )).createSavableObject() + }; + break; + default: + if (status === "nonexisting") { + this.getCertificateForDomain(certDomain); + status = 'pending'; + } + response = { + status + }; + break; + } + res.status(200); + res.send(response); + res.end(); + } constructor(optionsArg: ISmartAcmeOptions) { this.options = optionsArg; @@ -76,36 +105,10 @@ export class SmartAcme { // CertMatcher this.certmatcher = new CertMatcher(); - // CertRemoteHandler - this.certremoteHandler = async (req, res) => { - const requestBody: interfaces.ICertRemoteRequest = req.body; - const status: interfaces.TCertStatus = await this.certmanager.getCertificateStatus(requestBody.domainName); - const existingCertificate = await this.certmanager.retrieveCertificate( - requestBody.domainName - ); - let response: interfaces.ICertRemoteResponse; - switch (status) { - case 'existing': - response = { - status, - certificate: await existingCertificate.createSavableObject() - }; - break; - default: - response = { - status - }; - break; - } - res.status(200); - res.send(response); - res.end(); - }; - // ACME Client this.client = new plugins.acme.Client({ directoryUrl: (() => { - if(this.options.environment === 'production') { + if (this.options.environment === 'production') { return plugins.acme.directory.letsencrypt.production; } else { return plugins.acme.directory.letsencrypt.staging; @@ -127,7 +130,7 @@ export class SmartAcme { public async getCertificateForDomain(domainArg: string): Promise { const certDomain = this.certmatcher.getCertificateDomainNameByDomainName(domainArg); - + await this.certmanager.announceCertificate(certDomain); const retrievedCertificate = await this.certmanager.retrieveCertificate(certDomain); if (retrievedCertificate) { diff --git a/ts/smartacme.plugins.ts b/ts/smartacme.plugins.ts index 7b5a00f..5e51bbd 100644 --- a/ts/smartacme.plugins.ts +++ b/ts/smartacme.plugins.ts @@ -4,13 +4,14 @@ import * as smartdata from '@pushrocks/smartdata'; import * as smartdelay from '@pushrocks/smartdelay'; import * as smartdns from '@pushrocks/smartdns'; import * as smartexpress from '@pushrocks/smartexpress'; +import * as smartlog from '@pushrocks/smartlog'; import * as smartpromise from '@pushrocks/smartpromise'; import * as smartrequest from '@pushrocks/smartrequest'; import * as smartunique from '@pushrocks/smartunique'; import * as smartstring from '@pushrocks/smartstring'; import * as smarttime from '@pushrocks/smarttime'; -export { lik, smartdata, smartdelay, smartdns, smartexpress, smartpromise, smartrequest, smartunique, smartstring, smarttime }; +export { lik, smartdata, smartdelay, smartdns, smartexpress, smartlog, smartpromise, smartrequest, smartunique, smartstring, smarttime }; // thirs party scope import * as acme from 'acme-client';