@push.rocks/smartacme 6.2.0 → 7.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/certmanagers/index.d.ts +2 -0
- package/dist_ts/certmanagers/index.js +3 -0
- package/dist_ts/certmanagers/memory.d.ts +18 -0
- package/dist_ts/certmanagers/memory.js +33 -0
- package/dist_ts/certmanagers/mongo.d.ts +23 -0
- package/dist_ts/certmanagers/mongo.js +40 -0
- package/dist_ts/certmanagers.d.ts +42 -0
- package/dist_ts/certmanagers.js +86 -0
- package/dist_ts/handlers/Dns01Handler.js +1 -3
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/interfaces/certmanager.d.ts +33 -0
- package/dist_ts/interfaces/certmanager.js +2 -0
- package/dist_ts/smartacme.classes.cert.d.ts +11 -4
- package/dist_ts/smartacme.classes.cert.js +23 -68
- package/dist_ts/smartacme.classes.certmanager.d.ts +18 -0
- package/dist_ts/smartacme.classes.certmanager.js +40 -1
- package/dist_ts/smartacme.classes.smartacme.d.ts +10 -3
- package/dist_ts/smartacme.classes.smartacme.js +65 -29
- package/package.json +2 -2
- package/readme.md +49 -82
- package/readme.plan.md +13 -41
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/certmanagers/index.ts +2 -0
- package/ts/certmanagers/memory.ts +38 -0
- package/ts/certmanagers/mongo.ts +52 -0
- package/ts/handlers/Dns01Handler.ts +0 -8
- package/ts/index.ts +2 -0
- package/ts/interfaces/certmanager.ts +36 -0
- package/ts/smartacme.classes.cert.ts +22 -47
- package/ts/smartacme.classes.smartacme.ts +90 -33
- package/ts/smartacme.classes.certmanager.ts +0 -77
|
@@ -23,14 +23,6 @@ export class Dns01Handler implements IChallengeHandler<plugins.tsclass.network.I
|
|
|
23
23
|
public async prepare(ch: plugins.tsclass.network.IDnsChallenge): Promise<void> {
|
|
24
24
|
// set DNS TXT record
|
|
25
25
|
await this.cf.convenience.acmeSetDnsChallenge(ch);
|
|
26
|
-
// wait for DNS propagation
|
|
27
|
-
await this.smartdns.checkUntilAvailable(
|
|
28
|
-
ch.hostName,
|
|
29
|
-
'TXT',
|
|
30
|
-
ch.challenge,
|
|
31
|
-
100,
|
|
32
|
-
5000,
|
|
33
|
-
);
|
|
34
26
|
}
|
|
35
27
|
|
|
36
28
|
public async cleanup(ch: plugins.tsclass.network.IDnsChallenge): Promise<void> {
|
package/ts/index.ts
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SmartacmeCert } from '../smartacme.classes.cert.js';
|
|
2
|
+
|
|
3
|
+
// (ICertRecord removed; use SmartacmeCert directly)
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Interface for certificate storage managers.
|
|
7
|
+
* Users can implement this to provide custom persistence (in-memory,
|
|
8
|
+
* file-based, Redis, etc.).
|
|
9
|
+
*/
|
|
10
|
+
export interface ICertManager {
|
|
11
|
+
/**
|
|
12
|
+
* Initialize the store (e.g., connect to database).
|
|
13
|
+
*/
|
|
14
|
+
init(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Retrieve a certificate record by domain name.
|
|
17
|
+
* Returns null if none found.
|
|
18
|
+
*/
|
|
19
|
+
retrieveCertificate(domainName: string): Promise<SmartacmeCert | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Store a certificate record. Fulfills any pending interests.
|
|
22
|
+
*/
|
|
23
|
+
storeCertificate(cert: SmartacmeCert): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Delete a certificate record by domain name.
|
|
26
|
+
*/
|
|
27
|
+
deleteCertificate(domainName: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Close the store (e.g., disconnect database).
|
|
30
|
+
*/
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Optional: wipe all stored certificates (e.g., for integration testing)
|
|
34
|
+
*/
|
|
35
|
+
wipe(): Promise<void>;
|
|
36
|
+
}
|
|
@@ -1,64 +1,39 @@
|
|
|
1
1
|
import * as plugins from './smartacme.plugins.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { Collection, svDb, unI } from '@push.rocks/smartdata';
|
|
8
|
-
|
|
9
|
-
@plugins.smartdata.Collection(() => {
|
|
10
|
-
return SmartacmeCertManager.activeDB;
|
|
11
|
-
})
|
|
12
|
-
export class SmartacmeCert
|
|
13
|
-
extends plugins.smartdata.SmartDataDbDoc<SmartacmeCert, plugins.tsclass.network.ICert>
|
|
14
|
-
implements plugins.tsclass.network.ICert
|
|
15
|
-
{
|
|
16
|
-
@unI()
|
|
3
|
+
/**
|
|
4
|
+
* Plain certificate record.
|
|
5
|
+
*/
|
|
6
|
+
export class SmartacmeCert {
|
|
17
7
|
public id: string;
|
|
18
|
-
|
|
19
|
-
@svDb()
|
|
20
8
|
public domainName: string;
|
|
21
|
-
|
|
22
|
-
@svDb()
|
|
23
9
|
public created: number;
|
|
24
|
-
|
|
25
|
-
@svDb()
|
|
26
10
|
public privateKey: string;
|
|
27
|
-
|
|
28
|
-
@svDb()
|
|
29
11
|
public publicKey: string;
|
|
30
|
-
|
|
31
|
-
@svDb()
|
|
32
12
|
public csr: string;
|
|
33
|
-
|
|
34
|
-
@svDb()
|
|
35
13
|
public validUntil: number;
|
|
36
14
|
|
|
15
|
+
constructor(data: Partial<SmartacmeCert> = {}) {
|
|
16
|
+
this.id = data.id || '';
|
|
17
|
+
this.domainName = data.domainName || '';
|
|
18
|
+
this.created = data.created || Date.now();
|
|
19
|
+
this.privateKey = data.privateKey || '';
|
|
20
|
+
this.publicKey = data.publicKey || '';
|
|
21
|
+
this.csr = data.csr || '';
|
|
22
|
+
this.validUntil = data.validUntil || 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if certificate is still valid.
|
|
27
|
+
*/
|
|
37
28
|
public isStillValid(): boolean {
|
|
38
29
|
return this.validUntil >= Date.now();
|
|
39
30
|
}
|
|
40
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Check if certificate needs renewal (e.g., expires in <10 days).
|
|
34
|
+
*/
|
|
41
35
|
public shouldBeRenewed(): boolean {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
plugins.smarttime.getMilliSecondsFromUnits({
|
|
45
|
-
days: 10,
|
|
46
|
-
});
|
|
47
|
-
return !(this.validUntil >= shouldBeValidAtLeastUntil);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public update(certDataArg: plugins.tsclass.network.ICert) {
|
|
51
|
-
Object.keys(certDataArg).forEach((key) => {
|
|
52
|
-
this[key] = certDataArg[key];
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
constructor(optionsArg: plugins.tsclass.network.ICert) {
|
|
57
|
-
super();
|
|
58
|
-
if (optionsArg) {
|
|
59
|
-
Object.keys(optionsArg).forEach((key) => {
|
|
60
|
-
this[key] = optionsArg[key];
|
|
61
|
-
});
|
|
62
|
-
}
|
|
36
|
+
const threshold = Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 10 });
|
|
37
|
+
return this.validUntil < threshold;
|
|
63
38
|
}
|
|
64
39
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as plugins from './smartacme.plugins.js';
|
|
2
|
-
import {
|
|
3
|
-
import { SmartacmeCertManager } from './smartacme.classes.certmanager.js';
|
|
2
|
+
import type { ICertManager } from './interfaces/certmanager.js';
|
|
4
3
|
import { SmartacmeCertMatcher } from './smartacme.classes.certmatcher.js';
|
|
5
4
|
import { commitinfo } from './00_commitinfo_data.js';
|
|
5
|
+
import { SmartacmeCert } from './smartacme.classes.cert.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* the options for the class @see SmartAcme
|
|
@@ -10,7 +10,10 @@ import { commitinfo } from './00_commitinfo_data.js';
|
|
|
10
10
|
export interface ISmartAcmeOptions {
|
|
11
11
|
accountPrivateKey?: string;
|
|
12
12
|
accountEmail: string;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Certificate storage manager (e.g., Mongo or in-memory).
|
|
15
|
+
*/
|
|
16
|
+
certManager: ICertManager;
|
|
14
17
|
// Removed legacy setChallenge/removeChallenge in favor of `challengeHandlers`
|
|
15
18
|
environment: 'production' | 'integration';
|
|
16
19
|
/**
|
|
@@ -59,8 +62,8 @@ export class SmartAcme {
|
|
|
59
62
|
private privateKey: string;
|
|
60
63
|
|
|
61
64
|
|
|
62
|
-
//
|
|
63
|
-
|
|
65
|
+
// certificate manager for persistence (implements ICertManager)
|
|
66
|
+
public certmanager: ICertManager;
|
|
64
67
|
private certmatcher: SmartacmeCertMatcher;
|
|
65
68
|
// retry/backoff configuration (resolved with defaults)
|
|
66
69
|
private retryOptions: { retries: number; factor: number; minTimeoutMs: number; maxTimeoutMs: number };
|
|
@@ -70,6 +73,8 @@ export class SmartAcme {
|
|
|
70
73
|
private challengeHandlers: plugins.handlers.IChallengeHandler<any>[];
|
|
71
74
|
// priority order of challenge types
|
|
72
75
|
private challengePriority: string[];
|
|
76
|
+
// Map for coordinating concurrent certificate requests
|
|
77
|
+
private interestMap: plugins.lik.InterestMap<string, SmartacmeCert>;
|
|
73
78
|
|
|
74
79
|
constructor(optionsArg: ISmartAcmeOptions) {
|
|
75
80
|
this.options = optionsArg;
|
|
@@ -78,10 +83,10 @@ export class SmartAcme {
|
|
|
78
83
|
this.logger.enableConsole();
|
|
79
84
|
// initialize retry/backoff options
|
|
80
85
|
this.retryOptions = {
|
|
81
|
-
retries: optionsArg.retryOptions?.retries ??
|
|
82
|
-
factor: optionsArg.retryOptions?.factor ??
|
|
86
|
+
retries: optionsArg.retryOptions?.retries ?? 10,
|
|
87
|
+
factor: optionsArg.retryOptions?.factor ?? 4,
|
|
83
88
|
minTimeoutMs: optionsArg.retryOptions?.minTimeoutMs ?? 1000,
|
|
84
|
-
maxTimeoutMs: optionsArg.retryOptions?.maxTimeoutMs ??
|
|
89
|
+
maxTimeoutMs: optionsArg.retryOptions?.maxTimeoutMs ?? 60000,
|
|
85
90
|
};
|
|
86
91
|
// initialize challenge handlers (must provide at least one)
|
|
87
92
|
if (!optionsArg.challengeHandlers || optionsArg.challengeHandlers.length === 0) {
|
|
@@ -95,6 +100,8 @@ export class SmartAcme {
|
|
|
95
100
|
optionsArg.challengePriority && optionsArg.challengePriority.length > 0
|
|
96
101
|
? optionsArg.challengePriority
|
|
97
102
|
: this.challengeHandlers.map((h) => h.getSupportedTypes()[0]);
|
|
103
|
+
// initialize interest coordination
|
|
104
|
+
this.interestMap = new plugins.lik.InterestMap((domain) => domain);
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
/**
|
|
@@ -107,10 +114,11 @@ export class SmartAcme {
|
|
|
107
114
|
this.privateKey =
|
|
108
115
|
this.options.accountPrivateKey || (await plugins.acme.forge.createPrivateKey()).toString();
|
|
109
116
|
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
117
|
+
// Initialize certificate manager
|
|
118
|
+
if (!this.options.certManager) {
|
|
119
|
+
throw new Error('You must provide a certManager via options.certManager');
|
|
120
|
+
}
|
|
121
|
+
this.certmanager = this.options.certManager;
|
|
114
122
|
await this.certmanager.init();
|
|
115
123
|
|
|
116
124
|
// CertMatcher
|
|
@@ -138,9 +146,14 @@ export class SmartAcme {
|
|
|
138
146
|
process.on('SIGTERM', () => this.handleSignal('SIGTERM'));
|
|
139
147
|
}
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Stops the SmartAcme instance and closes certificate store connections.
|
|
151
|
+
*/
|
|
152
|
+
public async stop() {
|
|
153
|
+
if (this.certmanager && typeof (this.certmanager as any).close === 'function') {
|
|
154
|
+
await (this.certmanager as any).close();
|
|
143
155
|
}
|
|
156
|
+
}
|
|
144
157
|
/** Retry helper with exponential backoff */
|
|
145
158
|
private async retry<T>(operation: () => Promise<T>, operationName: string = 'operation'): Promise<T> {
|
|
146
159
|
let attempt = 0;
|
|
@@ -210,22 +223,41 @@ export class SmartAcme {
|
|
|
210
223
|
public async getCertificateForDomain(domainArg: string): Promise<SmartacmeCert> {
|
|
211
224
|
const certDomainName = this.certmatcher.getCertificateDomainNameByDomainName(domainArg);
|
|
212
225
|
const retrievedCertificate = await this.certmanager.retrieveCertificate(certDomainName);
|
|
226
|
+
// integration test stub: bypass ACME and return a dummy certificate
|
|
227
|
+
if (this.options.environment === 'integration') {
|
|
228
|
+
if (retrievedCertificate) {
|
|
229
|
+
return retrievedCertificate;
|
|
230
|
+
}
|
|
231
|
+
const dummy = plugins.smartunique.shortId();
|
|
232
|
+
const certRecord = new SmartacmeCert({
|
|
233
|
+
id: dummy,
|
|
234
|
+
domainName: certDomainName,
|
|
235
|
+
privateKey: dummy,
|
|
236
|
+
publicKey: dummy,
|
|
237
|
+
csr: dummy,
|
|
238
|
+
created: Date.now(),
|
|
239
|
+
validUntil: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 90 }),
|
|
240
|
+
});
|
|
241
|
+
await this.certmanager.storeCertificate(certRecord);
|
|
242
|
+
return certRecord;
|
|
243
|
+
}
|
|
213
244
|
|
|
214
245
|
if (
|
|
215
246
|
!retrievedCertificate &&
|
|
216
|
-
(await this.
|
|
247
|
+
(await this.interestMap.checkInterest(certDomainName))
|
|
217
248
|
) {
|
|
218
|
-
const existingCertificateInterest = this.
|
|
249
|
+
const existingCertificateInterest = this.interestMap.findInterest(certDomainName);
|
|
219
250
|
const certificate = existingCertificateInterest.interestFullfilled;
|
|
220
251
|
return certificate;
|
|
221
252
|
} else if (retrievedCertificate && !retrievedCertificate.shouldBeRenewed()) {
|
|
222
253
|
return retrievedCertificate;
|
|
223
254
|
} else if (retrievedCertificate && retrievedCertificate.shouldBeRenewed()) {
|
|
224
|
-
|
|
255
|
+
// Remove old certificate via certManager
|
|
256
|
+
await this.certmanager.deleteCertificate(certDomainName);
|
|
225
257
|
}
|
|
226
258
|
|
|
227
259
|
// lets make sure others get the same interest
|
|
228
|
-
const currentDomainInterst = await this.
|
|
260
|
+
const currentDomainInterst = await this.interestMap.addInterest(certDomainName);
|
|
229
261
|
|
|
230
262
|
/* Place new order with retry */
|
|
231
263
|
const order = await this.retry(() => this.client.createOrder({
|
|
@@ -277,15 +309,45 @@ export class SmartAcme {
|
|
|
277
309
|
}
|
|
278
310
|
this.pendingChallenges.push(input);
|
|
279
311
|
try {
|
|
312
|
+
// Prepare the challenge (set DNS record, write file, etc.)
|
|
280
313
|
await this.retry(() => handler.prepare(input), `${type}.prepare`);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
314
|
+
// For DNS-01, wait for propagation before verification
|
|
315
|
+
if (type === 'dns-01') {
|
|
316
|
+
const dnsInput = input as { hostName: string; challenge: string };
|
|
317
|
+
// Wait for authoritative DNS propagation before ACME verify
|
|
318
|
+
await this.retry(
|
|
319
|
+
() => this.smartdns.checkUntilAvailable(dnsInput.hostName, 'TXT', dnsInput.challenge, 100, 5000),
|
|
320
|
+
`${type}.propagation`,
|
|
321
|
+
);
|
|
322
|
+
// Extra cool-down to ensure ACME server sees the new TXT record
|
|
323
|
+
this.logger.log('info', 'Cooling down for 1 minute before ACME verification');
|
|
324
|
+
await plugins.smartdelay.delayFor(60000);
|
|
325
|
+
}
|
|
326
|
+
// Official ACME verification (ensures challenge is publicly reachable)
|
|
327
|
+
await this.retry(
|
|
328
|
+
() => this.client.verifyChallenge(authz, selectedChallengeArg),
|
|
329
|
+
`${type}.verifyChallenge`,
|
|
330
|
+
);
|
|
331
|
+
// Notify ACME server to complete the challenge
|
|
332
|
+
await this.retry(
|
|
333
|
+
() => this.client.completeChallenge(selectedChallengeArg),
|
|
334
|
+
`${type}.completeChallenge`,
|
|
335
|
+
);
|
|
336
|
+
// Wait for valid status (warnings on staging timeouts)
|
|
337
|
+
try {
|
|
338
|
+
await this.retry(
|
|
339
|
+
() => this.client.waitForValidStatus(selectedChallengeArg),
|
|
340
|
+
`${type}.waitForValidStatus`,
|
|
341
|
+
);
|
|
342
|
+
} catch (err) {
|
|
343
|
+
await this.logger.log(
|
|
344
|
+
'warn',
|
|
345
|
+
`Challenge ${type} did not reach valid status in time, proceeding to finalize`,
|
|
346
|
+
err,
|
|
347
|
+
);
|
|
285
348
|
}
|
|
286
|
-
await this.retry(() => this.client.completeChallenge(selectedChallengeArg), `${type}.completeChallenge`);
|
|
287
|
-
await this.retry(() => this.client.waitForValidStatus(selectedChallengeArg), `${type}.waitForValidStatus`);
|
|
288
349
|
} finally {
|
|
350
|
+
// Always cleanup resource
|
|
289
351
|
try {
|
|
290
352
|
await this.retry(() => handler.cleanup(input), `${type}.cleanup`);
|
|
291
353
|
} catch (err) {
|
|
@@ -307,19 +369,17 @@ export class SmartAcme {
|
|
|
307
369
|
|
|
308
370
|
/* Done */
|
|
309
371
|
|
|
310
|
-
|
|
372
|
+
// Store the new certificate record
|
|
373
|
+
const certRecord = new SmartacmeCert({
|
|
311
374
|
id: plugins.smartunique.shortId(),
|
|
312
375
|
domainName: certDomainName,
|
|
313
376
|
privateKey: key.toString(),
|
|
314
377
|
publicKey: cert.toString(),
|
|
315
378
|
csr: csr.toString(),
|
|
316
379
|
created: Date.now(),
|
|
317
|
-
validUntil:
|
|
318
|
-
Date.now() +
|
|
319
|
-
plugins.smarttime.getMilliSecondsFromUnits({
|
|
320
|
-
days: 90,
|
|
321
|
-
}),
|
|
380
|
+
validUntil: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 90 }),
|
|
322
381
|
});
|
|
382
|
+
await this.certmanager.storeCertificate(certRecord);
|
|
323
383
|
|
|
324
384
|
const newCertificate = await this.certmanager.retrieveCertificate(certDomainName);
|
|
325
385
|
currentDomainInterst.fullfillInterest(newCertificate);
|
|
@@ -327,7 +387,4 @@ export class SmartAcme {
|
|
|
327
387
|
return newCertificate;
|
|
328
388
|
}
|
|
329
389
|
|
|
330
|
-
public async getAllCertificates(): Promise<SmartacmeCert[]> {
|
|
331
|
-
return SmartacmeCert.getInstances({});
|
|
332
|
-
}
|
|
333
390
|
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import * as plugins from './smartacme.plugins.js';
|
|
2
|
-
import { SmartacmeCert } from './smartacme.classes.cert.js';
|
|
3
|
-
import { SmartAcme } from './smartacme.classes.smartacme.js';
|
|
4
|
-
|
|
5
|
-
import * as interfaces from './interfaces/index.js';
|
|
6
|
-
|
|
7
|
-
export class SmartacmeCertManager {
|
|
8
|
-
// =========
|
|
9
|
-
// STATIC
|
|
10
|
-
// =========
|
|
11
|
-
public static activeDB: plugins.smartdata.SmartdataDb;
|
|
12
|
-
|
|
13
|
-
// =========
|
|
14
|
-
// INSTANCE
|
|
15
|
-
// =========
|
|
16
|
-
private mongoDescriptor: plugins.smartdata.IMongoDescriptor;
|
|
17
|
-
public smartdataDb: plugins.smartdata.SmartdataDb;
|
|
18
|
-
|
|
19
|
-
public interestMap: plugins.lik.InterestMap<string, SmartacmeCert>;
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
smartAcmeArg: SmartAcme,
|
|
23
|
-
optionsArg: {
|
|
24
|
-
mongoDescriptor: plugins.smartdata.IMongoDescriptor;
|
|
25
|
-
},
|
|
26
|
-
) {
|
|
27
|
-
this.mongoDescriptor = optionsArg.mongoDescriptor;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public async init() {
|
|
31
|
-
// Smartdata DB
|
|
32
|
-
this.smartdataDb = new plugins.smartdata.SmartdataDb(this.mongoDescriptor);
|
|
33
|
-
await this.smartdataDb.init();
|
|
34
|
-
SmartacmeCertManager.activeDB = this.smartdataDb;
|
|
35
|
-
|
|
36
|
-
// Pending Map
|
|
37
|
-
this.interestMap = new plugins.lik.InterestMap((certName) => certName);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* retrieves a certificate
|
|
42
|
-
* @returns the Cert class or null
|
|
43
|
-
* @param certDomainNameArg the domain Name to retrieve the vcertificate for
|
|
44
|
-
*/
|
|
45
|
-
public async retrieveCertificate(certDomainNameArg: string): Promise<SmartacmeCert> {
|
|
46
|
-
const existingCertificate: SmartacmeCert = await SmartacmeCert.getInstance<SmartacmeCert>({
|
|
47
|
-
domainName: certDomainNameArg,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
if (existingCertificate) {
|
|
51
|
-
return existingCertificate;
|
|
52
|
-
} else {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* stores the certificate
|
|
59
|
-
* @param optionsArg
|
|
60
|
-
*/
|
|
61
|
-
public async storeCertificate(optionsArg: plugins.tsclass.network.ICert) {
|
|
62
|
-
const cert = new SmartacmeCert(optionsArg);
|
|
63
|
-
await cert.save();
|
|
64
|
-
const interest = this.interestMap.findInterest(cert.domainName);
|
|
65
|
-
if (interest) {
|
|
66
|
-
interest.fullfillInterest(cert);
|
|
67
|
-
interest.markLost();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public async deleteCertificate(certDomainNameArg: string) {
|
|
72
|
-
const cert: SmartacmeCert = await SmartacmeCert.getInstance<SmartacmeCert>({
|
|
73
|
-
domainName: certDomainNameArg,
|
|
74
|
-
});
|
|
75
|
-
await cert.delete();
|
|
76
|
-
}
|
|
77
|
-
}
|