Fix password change issues with cache

pull/1/head
yflory 4 years ago
parent e909987ed2
commit 550c5175aa

@ -2540,6 +2540,7 @@ define([
UIElements.onServerError = function (common, err, toolbar, cb) {
//if (["EDELETED", "EEXPIRED", "ERESTRICTED"].indexOf(err.type) === -1) { return; }
var priv = common.getMetadataMgr().getPrivateData();
var sframeChan = common.getSframeChannel();
var msg = err.type;
if (err.type === 'EEXPIRED') {
msg = Messages.expiredError;
@ -2549,10 +2550,25 @@ define([
if (toolbar && typeof toolbar.deleted === "function") { toolbar.deleted(); }
} else if (err.type === 'EDELETED') {
if (priv.burnAfterReading) { return void cb(); }
// View users have the wrong seed, thay can't retireve access directly
// Version 1 hashes don't support passwords
if (!priv.readOnly && !priv.oldVersionHash) {
sframeChan.event('EV_SHARE_OPEN', {hidden: true}); // Close share modal
UIElements.displayPasswordPrompt(common, {
fromServerError: true,
loaded: err.loaded,
});
if (toolbar && typeof toolbar.deleted === "function") { toolbar.deleted(); }
(cb || function () {})();
return;
}
msg = Messages.deletedError;
if (err.loaded) {
msg += Messages.errorCopy;
}
if (toolbar && typeof toolbar.deleted === "function") { toolbar.deleted(); }
} else if (err.type === 'ERESTRICTED') {
msg = Messages.restrictedError;
@ -2561,7 +2577,6 @@ define([
msg = Messages.oo_deletedVersion;
if (toolbar && typeof toolbar.failed === "function") { toolbar.failed(true); }
}
var sframeChan = common.getSframeChannel();
sframeChan.event('EV_SHARE_OPEN', {hidden: true});
UI.errorLoadingScreen(msg, Boolean(err.loaded), Boolean(err.loaded));
(cb || function () {})();
@ -2570,7 +2585,10 @@ define([
UIElements.displayPasswordPrompt = function (common, cfg, isError) {
var error;
if (isError) { error = setHTML(h('p.cp-password-error'), Messages.password_error); }
var info = h('p.cp-password-info', Messages.password_info);
var info_loaded = h('p.cp-password-info', Messages.password_info_loaded);
var password = UI.passwordInput({placeholder: Messages.password_placeholder});
var $password = $(password);
var button = h('button.btn.btn-primary', Messages.password_submit);
@ -2582,6 +2600,21 @@ define([
var submit = function () {
var value = $password.find('.cp-password-input').val();
// Password-prompt called from UIElements.onServerError
if (cfg.fromServerError) {
common.getSframeChannel().query('Q_PASSWORD_CHECK', value, function (err, obj) {
if (obj && obj.error) {
console.error(obj.error);
return void UI.warn(Messages.error);
}
// On success, outer will reload the page: this is a wrong password
UIElements.displayPasswordPrompt(common, cfg, true);
});
return;
}
// Initial load
UI.addLoadingScreen({newProgress: true});
if (window.CryptPad_updateLoadingProgress) {
window.CryptPad_updateLoadingProgress({
@ -2595,6 +2628,8 @@ define([
}
});
};
$password.find('.cp-password-input').on('keydown', function (e) { if (e.which === 13) { submit(); } });
$(button).on('click', function () { submit(); });
@ -2602,12 +2637,13 @@ define([
var block = h('div#cp-loading-password-prompt', [
error,
info,
cfg.loaded ? info_loaded : undefined,
h('p.cp-password-form', [
password,
button
])
]),
]);
UI.errorLoadingScreen(block);
UI.errorLoadingScreen(block, Boolean(cfg.loaded), Boolean(cfg.loaded));
$password.find('.cp-password-input').focus();
};

@ -481,10 +481,20 @@ define([
});
};
common.isNewChannel = function (href, password, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var channel = Hash.hrefToHexChannelId(href, password);
postMessage('IS_NEW_CHANNEL', {channel: channel}, function (obj) {
var error = obj && obj.error;
if (error) { return void cb(error); }
if (!obj) { return void cb('ERROR'); }
cb (null, obj.isNew);
}, {timeout: -1});
};
// This function is used when we want to open a pad. We first need
// to check if it exists. With the cached drive, we need to wait for
// the network to be available before we can continue.
common.isNewChannel = function (href, password, _cb) {
common.hasChannelHistory = function (href, password, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var channel = Hash.hrefToHexChannelId(href, password);
var error;
@ -2506,6 +2516,7 @@ define([
}
if (parsedNew.hashData) { oldHref = newHref; }
};
// XXX if you're in noDrive mode, check if an FS_hash is added and reload if that's the case
// Listen for login/logout in other tabs
window.addEventListener('storage', function (e) {
if (e.key !== Constants.userHashKey) { return; }

@ -1710,6 +1710,10 @@ define([
var onError = function (err) {
channel.bcast("PAD_ERROR", err);
if (err && err.type === "EDELETED" && Cache && Cache.clearChannel) {
Cache.clearChannel(data.channel);
}
// If this is a DELETED, EXPIRED or RESTRICTED pad, leave the channel
if (["EDELETED", "EEXPIRED", "ERESTRICTED"].indexOf(err.type) === -1) { return; }
Store.leavePad(null, data, function () {});
@ -1720,11 +1724,13 @@ define([
postMessage(clientId, "PAD_CACHE");
},
onCacheReady: function () {
channel.hasCache = true;
postMessage(clientId, "PAD_CACHE_READY");
},
onReady: function (pad) {
var padData = pad.metadata || {};
channel.data = padData;
channel.ready = true;
if (padData && padData.validateKey && store.messenger) {
store.messenger.storeValidateKey(data.channel, padData.validateKey);
}

@ -78,7 +78,7 @@ define([
};
var AppConfig;
var Test;
var password, newPadPassword;
var password, newPadPassword, newPadPasswordForce;
var initialPathInDrive;
var burnAfterReading;
@ -312,6 +312,7 @@ define([
newPadPassword = Crypto.decrypt(newPad.pw, uKey);
} catch (e) { console.error(e); }
}
if (newPad.f) { newPadPasswordForce = 1; }
if (newPad.d) {
Cryptpad.fromFileData = newPad.d;
var _parsed1 = Utils.Hash.parsePadUrl(Cryptpad.fromFileData.href);
@ -319,6 +320,7 @@ define([
delete Cryptpad.fromFileData;
}
}
} catch (e) {
console.error(e, parsed.hashData.newPadOpts);
}
@ -349,7 +351,7 @@ define([
}
// We now need to check if there is a password and if we know the correct password.
// We'll use getFileSize and isNewChannel to detect incorrect passwords.
// We'll use getFileSize and hasChannelHistory to detect incorrect passwords.
// First we'll get the password value from our drive (getPadAttribute), and we'll check
// if the channel is valid. If the pad is not stored in our drive, we'll test with an
@ -397,15 +399,15 @@ define([
}
};
if (parsed.type === "file") {
// `isNewChannel` doesn't work for files (not a channel)
// `hasChannelHistory` doesn't work for files (not a channel)
// `getFileSize` is not adapted to channels because of metadata
Cryptpad.getFileSize(currentPad.href, password, function (e, size) {
next(e, size === 0);
});
return;
}
// Not a file, so we can use `isNewChannel`
Cryptpad.isNewChannel(currentPad.href, password, next);
// Not a file, so we can use `hasChannelHistory`
Cryptpad.hasChannelHistory(currentPad.href, password, next);
});
sframeChan.event("EV_PAD_PASSWORD", cfg);
};
@ -474,17 +476,25 @@ define([
password = val;
}), parsed.getUrl());
}).nThen(function (w) {
// If we've already tested this password and this is a redirect, force
if (typeof(newPadPassword) !== "undefined" && newPadPasswordForce) {
password = newPadPassword;
return void todo();
}
// If the pad is not stored and we have a newPadPassword, it probably
// comes from a notification: password prompt pre-filled
if (!password && !stored && newPadPassword) {
passwordCfg.value = newPadPassword;
}
// Pad not stored && password required: always ask for the password
if (!stored && parsed.hashData.password) {
if (!stored && parsed.hashData.password && !newPadPasswordForce) {
return void askPassword(true, passwordCfg);
}
if (parsed.type === "file") {
// `isNewChannel` doesn't work for files (not a channel)
// `hasChannelHistory` doesn't work for files (not a channel)
// `getFileSize` is not adapted to channels because of metadata
Cryptpad.getFileSize(currentPad.href, password, w(function (e, size) {
if (size !== 0) { return void todo(); }
@ -493,8 +503,8 @@ define([
}));
return;
}
// Not a file, so we can use `isNewChannel`
Cryptpad.isNewChannel(currentPad.href, password, w(function(e, isNew) {
// Not a file, so we can use `hasChannelHistory`
Cryptpad.hasChannelHistory(currentPad.href, password, w(function(e, isNew) {
if (isNew && expire && expire < (+new Date())) {
sframeChan.event("EV_EXPIRED_ERROR");
waitFor.abort();
@ -541,8 +551,7 @@ define([
if (realtime) {
// TODO we probably don't need to check again for password-protected pads
// (we use isNewChannel to test the password...)
Cryptpad.isNewChannel(currentPad.href, password, waitFor(function (e, isNew) {
Cryptpad.hasChannelHistory(currentPad.href, password, waitFor(function (e, isNew) {
if (e) { return console.error(e); }
isNewFile = Boolean(isNew);
}));
@ -608,6 +617,7 @@ define([
feedbackAllowed: Utils.Feedback.state,
isPresent: parsed.hashData && parsed.hashData.present,
isEmbed: parsed.hashData && parsed.hashData.embed,
oldVersionHash: parsed.hashData && parsed.hashData.version < 2, // password
isHistoryVersion: parsed.hashData && parsed.hashData.versionHash,
notifications: notifs,
accounts: {
@ -1674,6 +1684,45 @@ define([
});
});
sframeChan.on('Q_PASSWORD_CHECK', function (pw, cb) {
Cryptpad.isNewChannel(currentPad.href, pw, function (e, isNew) {
if (isNew === false) {
var channel = Hash.hrefToHexChannelId(currentPad.href, pw);
nThen(function (w) {
// If the pad is stored, update its data
var _secret = Utils.Hash.getSecrets(parsed.type, parsed.hash, pw);
var chan = _secret.channel;
var editH = Utils.Hash.getEditHashFromKeys(_secret);
var viewH = Utils.Hash.getViewHashFromKeys(_secret);
var href = Utils.Hash.hashToHref(editH, parsed.type);
var roHref = Utils.Hash.hashToHref(viewH, parsed.type);
Cryptpad.setPadAttribute('password', password, w(), parsed.getUrl());
Cryptpad.setPadAttribute('channel', chan, w(), parsed.getUrl());
Cryptpad.setPadAttribute('href', href, w(), parsed.getUrl());
Cryptpad.setPadAttribute('roHref', roHref, w(), parsed.getUrl());
}).nThen(function () {
// Get redirect URL
var uHash = Utils.LocalStore.getUserHash();
var uSecret = Utils.Hash.getSecrets('drive', uHash);
var uKey = uSecret.keys.cryptKey;
var url = Utils.Hash.getNewPadURL(currentPad.href, {
pw: Crypto.encrypt(pw, uKey),
f: 1
});
// redirect
window.location.href = url;
document.location.reload();
});
return;
}
cb({
error: e
});
});
});
if (cfg.messaging) {
sframeChan.on('Q_CHAT_OPENPADCHAT', function (data, cb) {
Cryptpad.universal.execCommand({

Loading…
Cancel
Save