Merge pull request #2123 from mozilla/train-143-clear-recovery-code, r=@philbooth, @rfk

feat(recovery): Clear recovery keys when resetting account
This commit is contained in:
Vijay Budhram 2019-08-09 08:28:52 -04:00 коммит произвёл GitHub
Родитель 44763c4e97 f1f93cc195
Коммит b4b754b40c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 102 добавлений и 28 удалений

Просмотреть файл

@ -4210,6 +4210,22 @@ module.exports = function(config, DB) {
}
);
});
it('should remove recovery key when account password is reset', () => {
const options = {
id: account.uid,
recoveryKeyId: data.recoveryKeyId,
};
return db
.resetAccount(account.uid, account)
.then(() => db.getRecoveryKey(options))
.then(
() => assert.fail('should have deleted recovery key'),
err => {
assert.equal(err.errno, 116, 'correct errno, not found');
}
);
});
});
describe('account subscriptions', () => {

Просмотреть файл

@ -959,6 +959,7 @@ module.exports = function(log, error) {
deleteByUid(uid, passwordChangeTokens);
deleteByUid(uid, passwordForgotTokens);
deleteByUid(uid, unverifiedTokens);
deleteByUid(uid, recoveryKeys);
account.verifyHash = data.verifyHash;
account.authSalt = data.authSalt;
@ -1133,14 +1134,14 @@ module.exports = function(log, error) {
);
};
Memory.prototype.securityEventsByUid = function (uid) {
if (! uid) {
Memory.prototype.securityEventsByUid = function(uid) {
if (!uid) {
return P.reject(error.notFound());
}
uid = uid.toString('hex');
const events = securityEvents[uid] || [];
function filterEvents (events, eventsLimit, uid) {
function filterEvents(events, eventsLimit, uid) {
const filteredEvents = [];
for (let i = 0; i < events.length; i++) {
@ -1155,20 +1156,26 @@ module.exports = function(log, error) {
return filteredEvents;
}
const filteredSecurityEvents = filterEvents(events, SECURITY_EVENTS_LIMIT, uid);
const filteredSecurityEvents = filterEvents(
events,
SECURITY_EVENTS_LIMIT,
uid
);
return P.resolve(
filteredSecurityEvents.map(ev => {
return {
name: ev.name,
createdAt: ev.createdAt,
verified: ev.verified
}
}).reverse()
filteredSecurityEvents
.map(ev => {
return {
name: ev.name,
createdAt: ev.createdAt,
verified: ev.verified,
};
})
.reverse()
);
};
Memory.prototype.deleteSecurityEventsByUid = function (uid) {
if (! uid) {
Memory.prototype.deleteSecurityEventsByUid = function(uid) {
if (!uid) {
return P.reject(error.notFound());
}
uid = uid.toString('hex');
@ -1702,25 +1709,27 @@ module.exports = function(log, error) {
Memory.prototype.reactivateAccountSubscription = async function(
uid,
subscriptionId,
subscriptionId
) {
uid = uid.toString('hex');
// Ensure user account exists
await getAccountByUid(uid);
const reactivated = Object.values(accountSubscriptions).some(subscription => {
if (
subscription.uid === uid &&
subscription.subscriptionId === subscriptionId &&
subscription.cancelledAt > 0
) {
subscription.cancelledAt = null;
return true;
}
const reactivated = Object.values(accountSubscriptions).some(
subscription => {
if (
subscription.uid === uid &&
subscription.subscriptionId === subscriptionId &&
subscription.cancelledAt > 0
) {
subscription.cancelledAt = null;
return true;
}
return false;
});
return false;
}
);
if (!reactivated) {
throw error.notFound();

Просмотреть файл

@ -843,7 +843,7 @@ module.exports = function(log, error) {
// Update : accounts
// Set : verifyHash = $2, authSalt = $3, wrapWrapKb = $4, verifierSetAt = $5, verifierVersion = $6
// Where : uid = $1
var RESET_ACCOUNT = 'CALL resetAccount_12(?, ?, ?, ?, ?, ?)';
var RESET_ACCOUNT = 'CALL resetAccount_13(?, ?, ?, ?, ?, ?)';
MySql.prototype.resetAccount = function(uid, data) {
return this.write(RESET_ACCOUNT, [

Просмотреть файл

@ -5,4 +5,4 @@
// The expected patch level of the database. Update if you add a new
// patch in the ./schema/ directory.
module.exports.level = 101;
module.exports.level = 102;

Просмотреть файл

@ -0,0 +1,44 @@
SET NAMES utf8mb4 COLLATE utf8mb4_bin;
CALL assertPatchLevel('101');
CREATE PROCEDURE `resetAccount_13` (
IN `uidArg` BINARY(16),
IN `verifyHashArg` BINARY(32),
IN `authSaltArg` BINARY(32),
IN `wrapWrapKbArg` BINARY(32),
IN `verifierSetAtArg` BIGINT UNSIGNED,
IN `verifierVersionArg` TINYINT UNSIGNED
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
DELETE FROM sessionTokens WHERE uid = uidArg;
DELETE FROM keyFetchTokens WHERE uid = uidArg;
DELETE FROM accountResetTokens WHERE uid = uidArg;
DELETE FROM passwordChangeTokens WHERE uid = uidArg;
DELETE FROM passwordForgotTokens WHERE uid = uidArg;
DELETE FROM recoveryKeys WHERE uid = uidArg;
DELETE devices, deviceCommands FROM devices LEFT JOIN deviceCommands
ON (deviceCommands.uid = devices.uid AND deviceCommands.deviceId = devices.id)
WHERE devices.uid = uidArg; DELETE FROM unverifiedTokens WHERE uid = uidArg;
UPDATE accounts
SET
verifyHash = verifyHashArg,
authSalt = authSaltArg,
wrapWrapKb = wrapWrapKbArg,
verifierSetAt = verifierSetAtArg,
verifierVersion = verifierVersionArg,
profileChangedAt = verifierSetAtArg
WHERE uid = uidArg;
COMMIT;
END;
UPDATE dbMetadata SET value = '102' WHERE name = 'schema-patch-level';

Просмотреть файл

@ -0,0 +1,5 @@
-- SET NAMES utf8mb4 COLLATE utf8mb4_bin;
-- DROP PROCEDURE `resetAccount_13`;
-- UPDATE dbMetadata SET value = '101' WHERE name = 'schema-patch-level';