diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js
index 008d53217..4b3dddd81 100644
--- a/customize.dist/translations/messages.js
+++ b/customize.dist/translations/messages.js
@@ -600,6 +600,11 @@ define(function () {
out.settings_templateSkip = "Skip the template selection modal";
out.settings_templateSkipHint = "When you create a new empty pad, if you have stored templates for this type of pad, a modal appears to ask if you want to use a template. Here you can choose to never show this modal and so to never use a template.";
+ out.settings_ownDriveTitle = "Drive migration"; // XXX
+ out.settings_ownDriveHint = "Migrating your drive to the new version will give you access to new features..."; // XXX
+ out.settings_ownDriveButton = "Migrate"; // XXX
+ out.settings_ownDriveConfirm = "Are you sure?"; // XXX
+
out.settings_changePasswordTitle = "Change your password"; // XXX
out.settings_changePasswordHint = "Change your account's password without losing its data. You have to enter your existing password once, and the new password you want twice.
" +
"We can't reset your password if you forget it so be very careful!"; // XXX
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index c08b40888..1193e7303 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -699,6 +699,72 @@ define([
});
};
+ common.ownUserDrive = function (Crypt, edPublic, cb) {
+ var hash = LocalStore.getUserHash();
+ //var href = '/drive/#' + hash;
+ var secret = Hash.getSecrets('drive', hash);
+ var newHash, newHref, newSecret;
+ Nthen(function (waitFor) {
+ // Check if our drive is already owned
+ common.anonRpcMsg('GET_METADATA', secret.channel, waitFor(function (err, obj) {
+ if (err || obj.error) { return; }
+ if (obj.owners && Array.isArray(obj.owners) &&
+ obj.owners.indexOf(edPublic) !== -1) {
+ waitFor.abort();
+ cb({
+ error: 'ALREADY_OWNED'
+ });
+ }
+ }));
+ }).nThen(function (waitFor) {
+ waitFor.abort(); // TODO remove this line
+ // Create a new user hash
+ // Get the current content, store it in the new user file
+ // and make sure the new user drive is owned
+ newHash = Hash.createRandomHash('drive');
+ newHref = '/drive/#' + newHash;
+ newSecret = Hash.getSecrets('drive', newHash);
+
+ var optsPut = {
+ owners: [edPublic]
+ };
+
+ Crypt.get(hash, waitFor(function (err, val) {
+ if (err) {
+ waitFor.abort();
+ return void cb({ error: err });
+ }
+ Crypt.put(newHash, val, waitFor(function (err) {
+ if (err) {
+ waitFor.abort();
+ return void cb({ error: err });
+ }
+ }), optsPut);
+ }));
+ }).nThen(function (waitFor) {
+ // Migration success
+ // TODO: Replace user hash in login block
+ }).nThen(function (waitFor) {
+ // New drive hash is in login block, unpin the old one and pin the new one
+ common.unpinPads([secret.channel], waitFor());
+ common.pinPads([newSecret.channel], waitFor());
+ }).nThen(function (waitFor) {
+ // Login block updated
+ // TODO: logout everywhere
+ // * It should wipe localStorage.User_hash, ...
+ // * login will get the new value from loginBlock and store it in localStorage
+ // * SharedWorker will reconnect with the new value in other locations
+ // TODO: then DISCONNECT here
+ common.logoutFromAll(waitFor(function () {
+ postMessage("DISCONNECT");
+ }));
+ }).nThen(function () {
+ // We have the new drive, with the new login block
+ // TODO: maybe reload automatically?
+ cb({ state: true });
+ });
+ };
+
// Loading events
common.loading = {};
common.loading.onDriveEvent = Util.mkEvent();
diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js
index 84aaa1b26..1caabfe4c 100644
--- a/www/common/sframe-common-outer.js
+++ b/www/common/sframe-common-outer.js
@@ -661,6 +661,10 @@ define([
Cryptpad.changePadPassword(Cryptget, href, data.password, edPublic, cb);
});
+ sframeChan.on('Q_OWN_USER_DRIVE', function (data, cb) {
+ Cryptpad.ownUserDrive(Cryptget, edPublic, cb);
+ });
+
sframeChan.on('Q_WRITE_LOGIN_BLOCK', function (data, cb) {
Cryptpad.writeLoginBlock(data, cb);
});
diff --git a/www/common/sframe-protocol.js b/www/common/sframe-protocol.js
index fc77676d2..26251938f 100644
--- a/www/common/sframe-protocol.js
+++ b/www/common/sframe-protocol.js
@@ -238,6 +238,9 @@ define({
// Change pad password
'Q_PAD_PASSWORD_CHANGE': true,
+ // Migrate drive to owned drive
+ 'Q_OWN_USER_DRIVE': true,
+
// Loading events to display in the loading screen
'EV_LOADING_INFO': true,
// Critical error outside the iframe during loading screen
diff --git a/www/settings/inner.js b/www/settings/inner.js
index d88b0daa2..f05f58052 100644
--- a/www/settings/inner.js
+++ b/www/settings/inner.js
@@ -53,6 +53,7 @@ define([
'cp-settings-thumbnails',
'cp-settings-userfeedback',
'cp-settings-change-password',
+ 'cp-settings-migrate',
'cp-settings-delete'
],
'creation': [
@@ -494,6 +495,49 @@ define([
return $div;
};
+ create['migrate'] = function () {
+ // TODO
+ // if (!loginBlock) { return; }
+ // if (alreadyMigrated) { return; }
+ if (!common.isLoggedIn()) { return; }
+
+ var $div = $('