greenlock-store-sequelize.js/greenlock-store-sequelize.js

196 lines
5.7 KiB
JavaScript

'use strict';
var mkdirp = require('@root/mkdirp');
module.exports.create = function (config={}) {
var store = {
options: {},
accounts: {},
certificates: {}
};
var Sequelize;
var sequelize = config.db;
var confDir = config.configDir || (require('os').homedir() + '/acme');
// The user can provide their own db, but if they don't, we'll use the
// baked-in db.
if (!sequelize) {
// If the user provides options for the baked-in db, we'll use them. If
// they don't, we'll use the baked-in db with its defaults.
Sequelize = require('sequelize');
if (config.storeDatabaseUrl) {
sequelize = new Sequelize(config.storeDatabaseUrl, { logging: false });
} else {
sequelize = new Promise(function (resolve, reject) {
confDir = confDir.replace(/~\//, require('os').homedir() + '/');
mkdirp(confDir, function (err) {
if (err) { reject(err); return; }
resolve(new Sequelize({ dialect: 'sqlite', storage: confDir + '/db.sqlite3', logging: false }));
});
});
}
}
// This library expects config.db to resolve the db object. We'll ensure
// that this is the case with the provided db, as it was with the baked-in
// db.
config.db = Promise.resolve(sequelize).then(function (sequelize) {
return require('./db')(sequelize);
});
store.certificates.check = function (opts) {
return config.db.then(function (db) {
return db.Certificate.findOne({
where: {
subject: opts.subject
},
attributes: {
exclude: ['createdAt','updatedAt']
},
include: {
model: db.Chain
}
});
}).then(function (record) {
if (record) {
var obj = record.get();
obj.Chain = obj.Chain.get();
obj.chain = obj.Chain.content;
delete obj.Chain;
obj.issuedAt = new Date(obj.issuedAt).getTime();
obj.expiresAt = new Date(obj.expiresAt).getTime();
obj.altnames = String(obj.altnames).split(',');
return obj;
}
var err = new Error('certificate record not found');
err.code = 'ENOENT';
throw err;
}).catch(function (err) {
if (err.code === 'ENOENT') {
return null;
}
throw err;
});
};
// optional, not implemented
store.accounts.check = function () {
return Promise.resolve(null);
};
store.accounts.checkKeypair = function (opts) {
return config.db.then(function (db) {
return db.Keypair.findOne({
where: {
// using xid because id is reserved by sequelize
xid: opts.account.id || opts.email || 'single-user'
}
});
}).then(function (record) {
if (record) {
return JSON.parse(record.get().content);
}
var err = new Error('keypair record not found');
err.code = 'ENOENT';
throw err;
}).catch(function (err) {
if (err.code === 'ENOENT') {
return null;
}
throw err;
});
};
store.accounts.setKeypair = function (opts) {
return config.db.then(function (db) {
return db.Keypair.findOrCreate({
where: {
// using xid because id is reserved by sequelize
xid: opts.account.id || opts.email || 'single-user'
}
});
}).then(function ([record,created]) {
record.content = JSON.stringify(opts.keypair);
return record.save();
});
};
// optional, not implemented
store.accounts.set = function (opts) {
return Promise.resolve(null);
};
store.certificates.checkKeypair = function (opts) {
return config.db.then(function (db) {
return db.Keypair.findOne({
where: {
// using xid because id is reserved by sequelize
xid: (opts.certificate && (opts.certificate.kid || opts.certificate.id)) || opts.subject
}
});
}).then(function (record) {
if (record) {
return JSON.parse(record.get().content);
}
var err = new Error('keypair record not found');
err.code = 'ENOENT';
throw err;
}).catch(function (err) {
if (err.code === 'ENOENT') {
return null;
}
throw err;
});
};
store.certificates.setKeypair = function (opts) {
return config.db.then(function (db) {
return db.Keypair.findOrCreate({
where: {
// using xid because id is reserved by sequelize
xid: (opts.certificate && (opts.certificate.kid || opts.certificate.id)) || opts.subject
}
});
}).then(function ([record,created]) {
// { privateKeyPem, privateKeyJWK }
record.content = JSON.stringify(opts.keypair);
return record.save();
});
};
store.certificates.set = function (opts) {
var chainDbId;
var chainShaId = require('./make-safe-sha-str')(opts.pems.chain);
return config.db.then(function (db) {
return db.Chain.findOrCreate({
where: {
xid: chainShaId
}
}).then(function ([chainRec,created]) {
chainDbId = chainRec.id;
chainRec.content = opts.pems.chain;
return chainRec.save();
}).then(function () {
var query = { where: {} };
if (opts.certificate.id) {
query.where.id = opts.certificate.id;
}
else {
query.where.subject = opts.subject;
}
return db.Certificate.findOrCreate(query);
}).then(function (records) {
var record = records[0];
record.cert = opts.pems.cert;
record.altnames = opts.pems.altnames.join(',');
record.issuedAt = new Date(opts.pems.issuedAt).toISOString();
record.expiresAt = new Date(opts.pems.expiresAt).toISOString();
record.setChain(chainDbId);
return record.save();
});
});
};
return store;
};