130 lines
3.9 KiB
TypeScript
130 lines
3.9 KiB
TypeScript
import * as q from 'q'
|
|
|
|
import * as plugins from './cert.plugins'
|
|
import * as paths from './cert.paths'
|
|
|
|
// import classes
|
|
import { Cert } from './cert.classes.cert'
|
|
import { Letsencrypt } from './cert.classes.letsencrypt'
|
|
import { CertRepo } from './cert.classes.certrepo'
|
|
|
|
export interface ICertificateFsConfig {
|
|
domainName: string
|
|
creationTime: number
|
|
expiryTime: number
|
|
}
|
|
|
|
export interface ICertificateConstructorOptions {
|
|
domainName: string,
|
|
certInstance: Cert
|
|
}
|
|
|
|
export type TCertificateStatus = 'unregistered' | 'valid' | 'expiring' | 'expired'
|
|
|
|
export class Certificate {
|
|
domainName: string
|
|
certInstance: Cert
|
|
domainData: plugins.smartstring.Domain
|
|
creationDate: Date = null
|
|
expiryDate: Date = null
|
|
publicKey: string = null
|
|
privKey: string = null
|
|
|
|
/**
|
|
* run when creating a new instance of Certificate
|
|
*/
|
|
constructor(optionsArg: ICertificateConstructorOptions) {
|
|
this.domainName = optionsArg.domainName
|
|
this.domainData = new plugins.smartstring.Domain(this.domainName)
|
|
this.certInstance = optionsArg.certInstance
|
|
}
|
|
|
|
/**
|
|
* the status of the Certificate
|
|
*/
|
|
get status(): TCertificateStatus {
|
|
let validTimeRemaining: number = 0
|
|
if (this.creationDate !== null && this.expiryDate !== null) {
|
|
validTimeRemaining = this.expiryDate.getTime() - Date.now()
|
|
}
|
|
let MonthMilliseconds = 2629746000
|
|
if (this.publicKey === null || this.privKey === null) {
|
|
return 'unregistered'
|
|
} else if (validTimeRemaining >= MonthMilliseconds) {
|
|
return 'valid'
|
|
} else if (validTimeRemaining < MonthMilliseconds && validTimeRemaining >= 0) {
|
|
return 'expiring'
|
|
} else {
|
|
return 'expired'
|
|
}
|
|
}
|
|
|
|
get sameZoneRequesting(): boolean {
|
|
return this.certInstance.domainStringRequestMap.checkMinimatch('*' + this.domainData.zoneName)
|
|
}
|
|
|
|
/**
|
|
* schedule a retry of certificate request
|
|
*/
|
|
scheduleRetry() {
|
|
let done = plugins.q.defer()
|
|
setTimeout(() => {
|
|
this.renew()
|
|
.then(done.resolve)
|
|
}, 60000)
|
|
return done.promise
|
|
}
|
|
|
|
/**
|
|
* renew certificate if needed
|
|
*/
|
|
renew(force: boolean = false) {
|
|
let done = q.defer()
|
|
if (this.status === 'valid') {
|
|
plugins.beautylog.log('Certificate still valid for more than 1 month, so it is not renewed now')
|
|
done.resolve()
|
|
} else if (this.status === 'expiring' || this.status === 'expired' || this.status === 'unregistered') {
|
|
plugins.beautylog.info('Certificate not valid currently, going to renew now!')
|
|
if (this.sameZoneRequesting) {
|
|
this.certInstance.domainStringRequestMap.registerUntilTrue(
|
|
() => {
|
|
return !this.sameZoneRequesting
|
|
},
|
|
() => {
|
|
this.renew().then(done.resolve)
|
|
}
|
|
)
|
|
} else {
|
|
this.certInstance.letsencrypt.registerDomain(this.domainName)
|
|
.then(() => {
|
|
return this.syncFs()
|
|
})
|
|
.then(() => {
|
|
done.resolve()
|
|
}).catch((err) => { console.log(err) })
|
|
}
|
|
} else {
|
|
throw Error(`weird status for certificate with domain name ${this.domainName}`)
|
|
}
|
|
done.resolve()
|
|
return done.promise
|
|
}
|
|
|
|
/**
|
|
* syncFs syncs the certificate with disk
|
|
*/
|
|
syncFs() {
|
|
let configJsonMemory: ICertificateFsConfig = {
|
|
domainName: this.domainName,
|
|
creationTime: this.creationDate.getTime(),
|
|
expiryTime: this.expiryDate.getTime()
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* deletes the certificate
|
|
*/
|
|
delete() { }
|
|
}
|