2019-10-20 08:51:19 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var A = module.exports;
|
|
|
|
var U = require('./utils.js');
|
|
|
|
var E = require('./errors.js');
|
|
|
|
|
|
|
|
var pending = {};
|
|
|
|
|
2019-10-27 10:38:05 +00:00
|
|
|
A._getOrCreate = function(gnlck, mconf, db, acme, args) {
|
2019-10-31 11:49:37 +00:00
|
|
|
var email = args.subscriberEmail || mconf.subscriberEmail;
|
2019-10-20 08:51:19 +00:00
|
|
|
|
|
|
|
if (!email) {
|
|
|
|
throw E.NO_SUBSCRIBER('get account', args.subject);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO send welcome message with benefit info
|
|
|
|
return U._validMx(email)
|
|
|
|
.catch(function() {
|
|
|
|
throw E.NO_SUBSCRIBER('get account', args.subcriberEmail);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
if (pending[email]) {
|
|
|
|
return pending[email];
|
|
|
|
}
|
|
|
|
|
2019-10-27 10:38:05 +00:00
|
|
|
pending[email] = A._rawGetOrCreate(
|
|
|
|
gnlck,
|
|
|
|
mconf,
|
|
|
|
db,
|
|
|
|
acme,
|
|
|
|
args,
|
|
|
|
email
|
|
|
|
)
|
2019-10-20 08:51:19 +00:00
|
|
|
.catch(function(e) {
|
|
|
|
delete pending[email];
|
|
|
|
throw e;
|
|
|
|
})
|
|
|
|
.then(function(result) {
|
|
|
|
delete pending[email];
|
|
|
|
return result;
|
|
|
|
});
|
|
|
|
|
|
|
|
return pending[email];
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// What we really need out of this is the private key and the ACME "key" id
|
2019-10-27 10:38:05 +00:00
|
|
|
A._rawGetOrCreate = function(gnlck, mconf, db, acme, args, email) {
|
2019-10-20 08:51:19 +00:00
|
|
|
var p;
|
|
|
|
if (db.check) {
|
2019-10-27 10:38:05 +00:00
|
|
|
p = A._checkStore(gnlck, mconf, db, acme, args, email);
|
2019-10-20 08:51:19 +00:00
|
|
|
} else {
|
|
|
|
p = Promise.resolve(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.then(function(fullAccount) {
|
|
|
|
if (!fullAccount) {
|
2019-10-27 10:38:05 +00:00
|
|
|
return A._newAccount(gnlck, mconf, db, acme, args, email, null);
|
2019-10-20 08:51:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fullAccount.keypair && fullAccount.key && fullAccount.key.kid) {
|
|
|
|
return fullAccount;
|
|
|
|
}
|
|
|
|
|
2019-10-27 10:38:05 +00:00
|
|
|
return A._newAccount(gnlck, mconf, db, acme, args, email, fullAccount);
|
2019-10-20 08:51:19 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-10-27 10:38:05 +00:00
|
|
|
A._newAccount = function(gnlck, mconf, db, acme, args, email, fullAccount) {
|
2019-10-31 11:49:37 +00:00
|
|
|
var keyType = args.accountKeyType || mconf.accountKeyType;
|
2019-10-20 08:51:19 +00:00
|
|
|
var query = {
|
|
|
|
subject: args.subject,
|
|
|
|
email: email,
|
2019-10-27 10:38:05 +00:00
|
|
|
subscriberEmail: email,
|
|
|
|
customerEmail: args.customerEmail,
|
2019-10-29 18:47:15 +00:00
|
|
|
account: fullAccount || {},
|
|
|
|
directoryUrl:
|
|
|
|
args.directoryUrl ||
|
|
|
|
mconf.directoryUrl ||
|
|
|
|
gnlck._defaults.directoryUrl
|
2019-10-20 08:51:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return U._getOrCreateKeypair(db, args.subject, query, keyType).then(
|
|
|
|
function(kresult) {
|
|
|
|
var keypair = kresult.keypair;
|
|
|
|
var accReg = {
|
|
|
|
subscriberEmail: email,
|
|
|
|
agreeToTerms:
|
2019-10-27 10:38:05 +00:00
|
|
|
args.agreeToTerms ||
|
|
|
|
mconf.agreeToTerms ||
|
|
|
|
gnlck._defaults.agreeToTerms,
|
|
|
|
accountKey: keypair.privateKeyJwk || keypair.private,
|
2019-10-20 08:51:19 +00:00
|
|
|
debug: args.debug
|
|
|
|
};
|
|
|
|
return acme.accounts.create(accReg).then(function(receipt) {
|
|
|
|
var reg = {
|
|
|
|
keypair: keypair,
|
|
|
|
receipt: receipt,
|
|
|
|
// shudder... not actually a KeyID... but so it is called anyway...
|
|
|
|
kid:
|
|
|
|
receipt &&
|
|
|
|
receipt.key &&
|
|
|
|
(receipt.key.kid || receipt.kid),
|
2019-10-27 10:38:05 +00:00
|
|
|
email: args.email,
|
|
|
|
subscriberEmail: email,
|
|
|
|
customerEmail: args.customerEmail
|
2019-10-20 08:51:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
var keyP;
|
|
|
|
if (kresult.exists) {
|
|
|
|
keyP = Promise.resolve();
|
|
|
|
} else {
|
|
|
|
query.keypair = keypair;
|
|
|
|
query.receipt = receipt;
|
2019-10-27 10:38:05 +00:00
|
|
|
/*
|
|
|
|
query.server = gnlck._defaults.directoryUrl.replace(
|
|
|
|
/^https?:\/\//i,
|
|
|
|
''
|
|
|
|
);
|
|
|
|
*/
|
2019-10-20 08:51:19 +00:00
|
|
|
keyP = db.setKeypair(query, keypair);
|
|
|
|
}
|
|
|
|
|
|
|
|
return keyP
|
|
|
|
.then(function() {
|
|
|
|
if (!db.set) {
|
|
|
|
return Promise.resolve({
|
|
|
|
keypair: keypair
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return db.set(
|
|
|
|
{
|
|
|
|
// id to be set by Store
|
|
|
|
email: email,
|
2019-10-27 10:38:05 +00:00
|
|
|
subscriberEmail: email,
|
|
|
|
customerEmail: args.customerEmail,
|
|
|
|
agreeTos: true,
|
2019-10-29 18:47:15 +00:00
|
|
|
agreeToTerms: true,
|
|
|
|
directoryUrl:
|
|
|
|
args.directoryUrl ||
|
|
|
|
mconf.directoryUrl ||
|
|
|
|
gnlck._defaults.directoryUrl
|
2019-10-27 10:38:05 +00:00
|
|
|
/*
|
|
|
|
server: gnlck._defaults.directoryUrl.replace(
|
|
|
|
/^https?:\/\//i,
|
|
|
|
''
|
|
|
|
)
|
|
|
|
*/
|
2019-10-20 08:51:19 +00:00
|
|
|
},
|
|
|
|
reg
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.then(function(fullAccount) {
|
|
|
|
if (fullAccount && 'object' !== typeof fullAccount) {
|
|
|
|
throw new Error(
|
|
|
|
"accounts.set should either return 'null' or an object with an 'id' string"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fullAccount) {
|
|
|
|
fullAccount = {};
|
|
|
|
}
|
|
|
|
fullAccount.keypair = keypair;
|
|
|
|
if (!fullAccount.key) {
|
|
|
|
fullAccount.key = {};
|
|
|
|
}
|
|
|
|
fullAccount.key.kid = reg.kid;
|
|
|
|
|
|
|
|
return fullAccount;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-10-27 10:38:05 +00:00
|
|
|
A._checkStore = function(gnlck, mconf, db, acme, args, email) {
|
2019-10-20 08:51:19 +00:00
|
|
|
if ((args.domain || args.domains) && !args.subject) {
|
|
|
|
console.warn("use 'subject' instead of 'domain'");
|
|
|
|
args.subject = args.domain;
|
|
|
|
}
|
|
|
|
|
|
|
|
var account = args.account;
|
|
|
|
if (!account) {
|
|
|
|
account = {};
|
|
|
|
}
|
|
|
|
|
2019-10-27 10:38:05 +00:00
|
|
|
if (args.accountKey) {
|
2019-10-20 08:51:19 +00:00
|
|
|
console.warn(
|
2019-10-27 10:38:05 +00:00
|
|
|
'rather than passing accountKey, put it directly into your account key store'
|
2019-10-20 08:51:19 +00:00
|
|
|
);
|
|
|
|
// TODO we probably don't need this
|
2019-10-27 10:38:05 +00:00
|
|
|
return U._importKeypair(args.accountKey);
|
2019-10-20 08:51:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!db.check) {
|
|
|
|
return Promise.resolve(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
return db
|
|
|
|
.check({
|
|
|
|
//keypair: undefined,
|
|
|
|
//receipt: undefined,
|
|
|
|
email: email,
|
2019-10-27 10:38:05 +00:00
|
|
|
subscriberEmail: email,
|
|
|
|
customerEmail: args.customerEmail || mconf.customerEmail,
|
2019-10-29 18:47:15 +00:00
|
|
|
account: account,
|
|
|
|
directoryUrl:
|
|
|
|
args.directoryUrl ||
|
|
|
|
mconf.directoryUrl ||
|
|
|
|
gnlck._defaults.directoryUrl
|
2019-10-20 08:51:19 +00:00
|
|
|
})
|
|
|
|
.then(function(fullAccount) {
|
|
|
|
if (!fullAccount) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullAccount;
|
|
|
|
});
|
|
|
|
};
|