Fix shared folders issues including disappearing folders

pull/1/head
yflory 7 years ago
parent 4325ed4dde
commit f2baaf5b5b

@ -446,6 +446,7 @@ define(function () {
out.fm_tags_name = "Mot-clé";
out.fm_tags_used = "Nombre d'utilisations";
out.fm_restoreDrive = "Restauration de votre CryptDrive à une version antérieure. Pour de meilleurs résultats, veuillez éviter de modifier votre CryptDrive avant que cette restauration ne soit terminée.";
out.fm_moveNestedSF = "Les Drive partagés ne peuvent pas contenir d'autres Drive partagés. Le dossier {0} n'a pas été déplacé.";
// File - Context menu
out.fc_newfolder = "Nouveau dossier";
out.fc_newsharedfolder = "Nouveau Drive partagé";

@ -446,7 +446,8 @@ define(function () {
out.fm_deletedPads = "These pads no longer exist on the server, they've been removed from your CryptDrive: {0}";
out.fm_tags_name = "Tag name";
out.fm_tags_used = "Number of uses";
out.fm_restoreDrive = "Resetting your drive to an earlier state. For best results, avoid making changes to your drive until this process is complete."
out.fm_restoreDrive = "Resetting your drive to an earlier state. For best results, avoid making changes to your drive until this process is complete.";
out.fm_moveNestedSF = "Nested shared drive are not allowed. The folder {0} was not moved."; // XXX
// File - Context menu
out.fc_newfolder = "New folder";
out.fc_newsharedfolder = "New shared Drive";

@ -125,82 +125,86 @@ define([
id: 'cp-app-prop-owners',
}));
var expire = Messages.creation_expireFalse;
if (data.expire && typeof (data.expire) === "number") {
expire = new Date(data.expire).toLocaleString();
}
$('<label>', {'for': 'cp-app-prop-expire'}).text(Messages.creation_expiration)
.appendTo($d);
$d.append(UI.dialog.selectable(expire, {
id: 'cp-app-prop-expire',
}));
var hasPassword = data.password;
if (hasPassword) {
$('<label>', {'for': 'cp-app-prop-password'}).text(Messages.creation_passwordValue)
if (!data.noExpiration) {
var expire = Messages.creation_expireFalse;
if (data.expire && typeof (data.expire) === "number") {
expire = new Date(data.expire).toLocaleString();
}
$('<label>', {'for': 'cp-app-prop-expire'}).text(Messages.creation_expiration)
.appendTo($d);
var password = UI.passwordInput({
id: 'cp-app-prop-password',
readonly: 'readonly'
});
var $pwInput = $(password).find('.cp-password-input');
$pwInput.val(data.password).click(function () {
$pwInput[0].select();
});
$d.append(password);
$d.append(UI.dialog.selectable(expire, {
id: 'cp-app-prop-expire',
}));
}
var parsed = Hash.parsePadUrl(data.href || data.roHref);
if (owned && parsed.hashData.type === 'pad') {
var sframeChan = common.getSframeChannel();
var changePwTitle = Messages.properties_changePassword;
var changePwConfirm = Messages.properties_confirmChange;
if (!hasPassword) {
changePwTitle = Messages.properties_addPassword;
changePwConfirm = Messages.properties_confirmNew;
if (!data.noPassword) {
var hasPassword = data.password;
if (hasPassword) {
$('<label>', {'for': 'cp-app-prop-password'}).text(Messages.creation_passwordValue)
.appendTo($d);
var password = UI.passwordInput({
id: 'cp-app-prop-password',
readonly: 'readonly'
});
var $pwInput = $(password).find('.cp-password-input');
$pwInput.val(data.password).click(function () {
$pwInput[0].select();
});
$d.append(password);
}
$('<label>', {'for': 'cp-app-prop-change-password'})
.text(changePwTitle).appendTo($d);
var newPassword = UI.passwordInput({
id: 'cp-app-prop-change-password',
style: 'flex: 1;'
});
var passwordOk = h('button', Messages.properties_changePasswordButton);
var changePass = h('span.cp-password-container', [
newPassword,
passwordOk
]);
$(passwordOk).click(function () {
var newPass = $(newPassword).find('input').val();
if (data.password === newPass ||
(!data.password && !newPass)) {
return void UI.alert(Messages.properties_passwordSame);
var parsed = Hash.parsePadUrl(data.href || data.roHref);
if (owned && parsed.hashData.type === 'pad') {
var sframeChan = common.getSframeChannel();
var changePwTitle = Messages.properties_changePassword;
var changePwConfirm = Messages.properties_confirmChange;
if (!hasPassword) {
changePwTitle = Messages.properties_addPassword;
changePwConfirm = Messages.properties_confirmNew;
}
UI.confirm(changePwConfirm, function (yes) {
if (!yes) { return; }
sframeChan.query("Q_PAD_PASSWORD_CHANGE", {
href: data.href || data.roHref,
password: newPass
}, function (err, data) {
if (err || data.error) {
return void UI.alert(Messages.properties_passwordError);
}
UI.findOKButton().click();
// If we didn't have a password, we have to add the /p/
// If we had a password and we changed it to a new one, we just have to reload
// If we had a password and we removed it, we have to remove the /p/
if (data.warning) {
return void UI.alert(Messages.properties_passwordWarning, function () {
$('<label>', {'for': 'cp-app-prop-change-password'})
.text(changePwTitle).appendTo($d);
var newPassword = UI.passwordInput({
id: 'cp-app-prop-change-password',
style: 'flex: 1;'
});
var passwordOk = h('button', Messages.properties_changePasswordButton);
var changePass = h('span.cp-password-container', [
newPassword,
passwordOk
]);
$(passwordOk).click(function () {
var newPass = $(newPassword).find('input').val();
if (data.password === newPass ||
(!data.password && !newPass)) {
return void UI.alert(Messages.properties_passwordSame);
}
UI.confirm(changePwConfirm, function (yes) {
if (!yes) { return; }
sframeChan.query("Q_PAD_PASSWORD_CHANGE", {
href: data.href || data.roHref,
password: newPass
}, function (err, data) {
if (err || data.error) {
return void UI.alert(Messages.properties_passwordError);
}
UI.findOKButton().click();
// If we didn't have a password, we have to add the /p/
// If we had a password and we changed it to a new one, we just have to reload
// If we had a password and we removed it, we have to remove the /p/
if (data.warning) {
return void UI.alert(Messages.properties_passwordWarning, function () {
common.gotoURL(hasPassword && newPass ? undefined : (data.href || data.roHref));
}, {force: true});
}
return void UI.alert(Messages.properties_passwordSuccess, function () {
common.gotoURL(hasPassword && newPass ? undefined : (data.href || data.roHref));
}, {force: true});
}
return void UI.alert(Messages.properties_passwordSuccess, function () {
common.gotoURL(hasPassword && newPass ? undefined : (data.href || data.roHref));
}, {force: true});
}, {force: true});
});
});
});
});
$d.append(changePass);
$d.append(changePass);
}
}
cb(void 0, $d);

@ -94,8 +94,7 @@ define([
// Get the list of pads' channel ID in your drive
// This list is filtered so that it doesn't include pad owned by other users
// It now includes channels from shared folders
var edPublic = store.proxy.edPublic;
var list = store.manager.getChannelsList(edPublic, 'pin');
var list = store.manager.getChannelsList('pin');
// Get the avatar
var profile = store.proxy.profile;
@ -118,8 +117,7 @@ define([
};
var getExpirableChannelList = function () {
var edPublic = store.proxy.edPublic;
return store.manager.getChannelsList(edPublic, 'expirable');
return store.manager.getChannelsList('expirable');
};
var getCanonicalChannelList = function (expirable) {
@ -466,8 +464,7 @@ define([
};
var getOwnedPads = function () {
var edPublic = store.proxy.edPublic;
var list = store.manager.getChannelsList(edPublic, 'owned');
var list = store.manager.getChannelsList('owned');
if (store.proxy.todo) {
// No password for todo
list.push(Hash.hrefToHexChannelId('/todo/#' + store.proxy.todo, null));

@ -80,9 +80,8 @@ define([
};
// Find files in FILES_DATA that are not anymore in the drive, and remove them from
// FILES_DATA. If there are owned pads, remove them from server too, unless the flag tells
// us they're already removed
exp.checkDeletedFiles = function (isOwnPadRemoved, cb) {
// FILES_DATA. If there are owned pads, remove them from server too.
exp.checkDeletedFiles = function (cb) {
if (!loggedIn && !config.testMode) { return void cb(); }
var filesList = exp.getFiles([ROOT, 'hrefArray', TRASH]);
@ -93,8 +92,8 @@ define([
var fd = exp.isSharedFolder(id) ? files[SHARED_FOLDERS][id] : exp.getFileData(id);
var channelId = fd.channel;
// If trying to remove an owned pad, remove it from server also
if (!isOwnPadRemoved && !sharedFolder &&
fd.owners && fd.owners.indexOf(edPublic) !== -1 && channelId) {
if (!sharedFolder && fd.owners && fd.owners.indexOf(edPublic) !== -1
&& channelId) {
if (channelId) { ownedRemoved.push(channelId); }
removeOwnedChannel(channelId, function (obj) {
if (obj && obj.error) {
@ -132,7 +131,7 @@ define([
files[TRASH][obj.name].splice(idx, 1);
});
};
exp.deleteMultiplePermanently = function (paths, nocheck, isOwnPadRemoved, cb) {
exp.deleteMultiplePermanently = function (paths, nocheck, cb) {
var hrefPaths = paths.filter(function(x) { return exp.isPathIn(x, ['hrefArray']); });
var rootPaths = paths.filter(function(x) { return exp.isPathIn(x, [ROOT]); });
var trashPaths = paths.filter(function(x) { return exp.isPathIn(x, [TRASH]); });
@ -185,14 +184,14 @@ define([
// In some cases, we want to remove pads from a location without removing them from
// FILES_DATA (replaceHref)
if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved, cb); }
if (!nocheck) { exp.checkDeletedFiles(cb); }
else { cb(); }
};
// Move
// From another drive
exp.copyFromOtherDrive = function (path, element, data) {
exp.copyFromOtherDrive = function (path, element, data, key) {
// Copy files data
// We have to remove pads that are already in the current proxy to make sure
// we won't create duplicates
@ -241,7 +240,8 @@ define([
// Copy file or folder
var newParent = exp.find(path);
var newName = exp.getAvailableName(newParent, Hash.createChannelId());
var tempName = exp.isFile(element) ? Hash.createChannelId() : key;
var newName = exp.getAvailableName(newParent, tempName);
newParent[newName] = element;
};

@ -42,6 +42,13 @@ define([
/*
Tools
*/
var _ownedByMe = function (Env, owners) {
return Array.isArray(owners) && owners.indexOf(Env.edPublic) !== -1;
};
var _ownedByOther = function (Env, owners) {
return Array.isArray(owners) && owners.length &&
(!Env.edPublic || owners.indexOf(Env.edPublic) === -1);
};
var _getUserObjects = function (Env) {
var userObjects = [Env.user.userObject];
@ -206,21 +213,36 @@ define([
};
// Get a copy of the elements located in the given paths, with their files data
var _getCopyFromPaths = function (paths, userObject) {
// Note: This function is only called to move files from a proxy to another
var _getCopyFromPaths = function (Env, paths, userObject) {
var data = [];
paths.forEach(function (path) {
var toNotRemove = [];
paths.forEach(function (path, idx) {
var el = userObject.find(path);
var files = [];
var key = path[path.length - 1];
// Get the files ID from the current path (file or folder)
if (userObject.isFile(el)) {
files.push(el);
} else if (userObject.isSharedFolder(el)) {
files.push(el);
var obj = Env.folders[el].proxy.metadata || {};
if (obj) { key = obj.title; }
} else {
userObject.getFilesRecursively(el, files);
}
// Remove the shared folder from this list of files ID
files.filter(function (f) { return !userObject.isSharedFolder(f); });
// If the element is a folder and it contains a shared folder, abort!
// We don't want nested shared folders!
if (files.some(function (f) { return userObject.isSharedFolder(f); })) {
if (Env.cfg && Env.cfg.log) {
Env.cfg.log(Messages._getKey('fm_moveNestedSF', [key]));
}
toNotRemove.unshift(idx);
return;
}
// Deduplicate
files = Util.deduplicateString(files);
@ -237,9 +259,16 @@ define([
data.push({
el: el,
data: filesData
data: filesData,
key: key
});
});
// Remove from the "paths" array the elements that we don't want to move
toNotRemove.forEach(function (idx) {
paths.splice(idx, 1);
});
return data;
};
@ -264,27 +293,29 @@ define([
// Move from the main drive to a shared folder
// Copy the elements to the new location
var toCopy = _getCopyFromPaths(resolved.main, Env.user.userObject);
var toCopy = _getCopyFromPaths(Env, resolved.main, Env.user.userObject);
var newUserObject = newResolved.userObject;
var ownedPads = [];
toCopy.forEach(function (obj) {
newUserObject.copyFromOtherDrive(newResolved.path, obj.el, obj.data);
newUserObject.copyFromOtherDrive(newResolved.path, obj.el, obj.data, obj.key);
var _owned = Object.keys(obj.data).filter(function (id) {
var owners = obj.data[id].owners;
return Array.isArray(owners) && owners.indexOf(Env.edPublic) !== -1;
return _ownedByMe(Env, owners);
});
Array.prototype.push.apply(ownedPads, _owned);
});
var rootPath = resolved.main[0].slice();
rootPath.pop();
ownedPads = Util.deduplicateString(ownedPads);
ownedPads.forEach(function (id) {
Env.user.userObject.add(Number(id), rootPath);
});
if (resolved.main.length) {
var rootPath = resolved.main[0].slice();
rootPath.pop();
ownedPads = Util.deduplicateString(ownedPads);
ownedPads.forEach(function (id) {
Env.user.userObject.add(Number(id), rootPath);
});
// Remove the elements from the old location (without unpinning)
Env.user.userObject.delete(resolved.main, waitFor());
// Remove the elements from the old location (without unpinning)
Env.user.userObject.delete(resolved.main, waitFor());
}
}
}
var folderIds = Object.keys(resolved.folders);
@ -302,9 +333,9 @@ define([
var uoTo = newResolved.userObject;
// Copy the elements to the new location
var toCopy = _getCopyFromPaths(paths, uoFrom);
var toCopy = _getCopyFromPaths(Env, paths, uoFrom);
toCopy.forEach(function (obj) {
uoTo.copyFromOtherDrive(newResolved.path, obj.el, obj.data);
uoTo.copyFromOtherDrive(newResolved.path, obj.el, obj.data, obj.key);
});
// Remove the elements from the old location (without unpinning)
@ -415,7 +446,7 @@ define([
if (!Env.unpinPads || !_toUnpin) { return; }
Array.prototype.push.apply(toUnpin, _toUnpin);
ownedRemoved = _ownedRemoved;
}), data.nocheck, data.isOwnPadRemoved);
}));
}
}).nThen(function (waitFor) {
// Check if removed owned pads are duplicated is some shared folders
@ -440,7 +471,7 @@ define([
Env.folders[id].userObject.delete(resolved.folders[id], waitFor(function (err, _toUnpin) {
if (!Env.unpinPads || !_toUnpin) { return; }
Array.prototype.push.apply(toUnpin, _toUnpin);
}), data.nocheck, data.isOwnPadRemoved);
}));
});
}).nThen(function (waitFor) {
if (!Env.unpinPads) { return; }
@ -589,8 +620,7 @@ define([
*/
// Get the list of channels filtered by a type (expirable channels, owned channels, pin list)
var getChannelsList = function (Env, edPublic, type) {
//if (!edPublic) { return; }
var getChannelsList = function (Env, type) {
var result = [];
var addChannel = function (userObject) {
if (type === 'expirable') {
@ -599,8 +629,7 @@ define([
// Don't push duplicates
if (result.indexOf(data.channel) !== -1) { return; }
// Return pads owned by someone else or expired by time
if ((data.owners && data.owners.length && (!edPublic || data.owners.indexOf(edPublic) === -1))
|| (data.expire && data.expire < (+new Date()))) {
if (_ownedByOther(Env, data.owners) || (data.expire && data.expire < (+new Date()))) {
result.push(data.channel);
}
};
@ -611,8 +640,7 @@ define([
// Don't push duplicates
if (result.indexOf(data.channel) !== -1) { return; }
// Return owned pads
if (Array.isArray(data.owners) && data.owners.length &&
data.owners.indexOf(edPublic) !== -1) {
if (_ownedByMe(Env, data.owners)) {
result.push(data.channel);
}
};
@ -621,8 +649,7 @@ define([
return function (fileId) {
var data = userObject.getFileData(fileId);
// Don't pin pads owned by someone else
if (Array.isArray(data.owners) && data.owners.length &&
data.owners.indexOf(edPublic) === -1) { return; }
if (_ownedByOther(Env, data.owners)) { return; }
// Don't push duplicates
if (result.indexOf(data.channel) === -1) {
result.push(data.channel);
@ -631,8 +658,8 @@ define([
}
};
if (type === 'owned' && !edPublic) { return result; }
if (type === 'pin' && !edPublic) { return result; }
if (type === 'owned' && !Env.edPublic) { return result; }
if (type === 'pin' && !Env.edPublic) { return result; }
// Get the list of user objects
var userObjects = _getUserObjects(Env);
@ -646,8 +673,7 @@ define([
if (type === "owned") {
var sfOwned = Object.keys(Env.user.proxy[UserObject.SHARED_FOLDERS]).filter(function (fId) {
var owners = Env.user.proxy[UserObject.SHARED_FOLDERS][fId].owners;
if (Array.isArray(owners) && owners.length &&
owners.indexOf(edPublic) !== -1) { return true; }
if (_ownedByMe(Env, owners)) { return true; }
}).map(function (fId) {
return Env.user.proxy[UserObject.SHARED_FOLDERS][fId].channel;
});
@ -672,10 +698,22 @@ define([
p = resolved.path;
}
var todo = function () {
uo.pushData(pad, function (e, id) {
if (e) { return void cb(e); }
uo.add(id, p);
cb();
var error;
nThen(function (waitFor) {
uo.pushData(pad, waitFor(function (e, id) {
if (e) { error = e; return; }
uo.add(id, p);
}));
if (uo.id && _ownedByMe(Env, pad.owners)) {
// Creating an owned pad in a shared folder:
// We must add a copy in the user's personnal drive
Env.user.userObject.pushData(pad, waitFor(function (e, id) {
if (e) { error = e; return; }
Env.user.userObject.add(id, ['root']);
}));
}
}).nThen(function () {
cb(error);
});
};
if (!Env.pinPads) { return void todo(); }
@ -777,14 +815,11 @@ define([
}
}, cb);
};
var deleteInner = function (Env, paths, cb, nocheck, isOwnPadRemoved, noUnpin) {
var deleteInner = function (Env, paths, cb) {
return void Env.sframeChan.query("Q_DRIVE_USEROBJECT", {
cmd: "delete",
data: {
paths: paths,
nocheck: nocheck,
noUnpin: noUnpin,
isOwnPadRemoved: isOwnPadRemoved
}
}, cb);
};
@ -857,7 +892,7 @@ define([
};
var getSharedFolderData = function (Env, id) {
if (!Env.folders[id]) { return; }
if (!Env.folders[id]) { return {}; }
var obj = Env.folders[id].proxy.metadata || {};
for (var k in Env.user.proxy[UserObject.SHARED_FOLDERS][id] || {}) {
obj[k] = Env.user.proxy[UserObject.SHARED_FOLDERS][id][k];

@ -579,19 +579,18 @@ define([
// DELETE
// Permanently delete multiple files at once using a list of paths
// NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template)
exp.delete = function (paths, cb, nocheck, isOwnPadRemoved) {
exp.delete = function (paths, cb, nocheck) {
if (sframeChan) {
return void sframeChan.query("Q_DRIVE_USEROBJECT", {
cmd: "delete",
data: {
paths: paths,
nocheck: nocheck,
isOwnPadRemoved: isOwnPadRemoved
}
}, cb);
}
cb = cb || function () {};
exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved, cb);
exp.deleteMultiplePermanently(paths, nocheck, cb);
//if (typeof cb === "function") { cb(); }
};
exp.emptyTrash = function (cb) {
@ -602,7 +601,7 @@ define([
}, cb);
}
files[TRASH] = {};
exp.checkDeletedFiles(false, cb);
exp.checkDeletedFiles(cb);
};
// RENAME

@ -782,6 +782,7 @@
}
.cp-app-drive-toolbar-rightside {
float: right;
flex-shrink: 0;
& > * {
float: right;
}
@ -842,6 +843,8 @@
white-space: nowrap;
display: flex;
flex-flow: row-reverse;
flex-shrink: 1;
min-width: 50px;
max-width: 100%;
text-align: left;
.cp-app-drive-path-element {

@ -2750,12 +2750,13 @@ define([
if (!manager.isFolder(root[key])) { return; }
var newPath = path.slice();
newPath.push(key);
var nextPath = newPath.slice();
var isSharedFolder = manager.isSharedFolder(root[key]);
var $icon, isCurrentFolder, subfolder;
if (isSharedFolder) {
var fId = root[key];
// Fix path
newPath.push(manager.user.userObject.ROOT);
nextPath.push(manager.user.userObject.ROOT);
isCurrentFolder = manager.comparePath(newPath, currentPath);
// Subfolders?
var newRoot = manager.folders[fId].proxy[manager.user.userObject.ROOT];
@ -2779,7 +2780,7 @@ define([
$element.find('>.cp-app-drive-element-row')
.addClass('cp-app-drive-element-sharedf');
}
createTree($element, newPath);
createTree($element, nextPath);
});
};
@ -2957,6 +2958,8 @@ define([
if (manager.isSharedFolder(el)) {
delete data.roHref;
data.noPassword = true;
data.noExpiration = true;
}
UIElements.getProperties(common, data, cb);

Loading…
Cancel
Save