Display a shared folder in the drive

This commit is contained in:
yflory 2018-07-09 14:36:55 +02:00
parent 0c9dfc1fb5
commit e0cc1a6eb6
8 changed files with 176 additions and 48 deletions

View File

@ -83,6 +83,11 @@ define([
cb(obj); cb(obj);
}); });
}; };
common.getSharedFolder = function (id, cb) {
postMessage("GET_SHARED_FOLDER", id, function (obj) {
cb(obj);
});
};
// Settings and ready // Settings and ready
common.mergeAnonDrive = function (cb) { common.mergeAnonDrive = function (cb) {
var data = { var data = {

View File

@ -38,7 +38,7 @@ define([
Realtime.whenRealtimeSyncs(store.realtime, waitFor()); Realtime.whenRealtimeSyncs(store.realtime, waitFor());
if (store.sharedFolders) { if (store.sharedFolders) {
for (var k in store.sharedFolders) { for (var k in store.sharedFolders) {
Realtime.whenRealtimeSync(store.sharedFolders[k].realtime, waitFor()); Realtime.whenRealtimeSyncs(store.sharedFolders[k].realtime, waitFor());
} }
} }
}).nThen(function () { cb(); }); }).nThen(function () { cb(); });
@ -61,6 +61,13 @@ define([
onSync(cb); onSync(cb);
}; };
Store.getSharedFolder = function (clientId, id, cb) {
if (store.manager.folders[id]) {
return void cb(store.manager.folders[id].proxy);
}
cb({});
};
Store.hasSigningKeys = function () { Store.hasSigningKeys = function () {
if (!store.proxy) { return; } if (!store.proxy) { return; }
return typeof(store.proxy.edPrivate) === 'string' && return typeof(store.proxy.edPrivate) === 'string' &&
@ -1166,7 +1173,7 @@ define([
var id; var id;
nThen(function (waitFor) { nThen(function (waitFor) {
// TODO XXX get the folder data (href, title, ...) // TODO XXX get the folder data (href, title, ...)
var folderData = {}; var folderData = data.folderData || {};
// 1. add the shared folder to our list of shared folders // 1. add the shared folder to our list of shared folders
store.userObject.pushSharedFolder(folderData, waitFor(function (err, folderId) { store.userObject.pushSharedFolder(folderData, waitFor(function (err, folderId) {
if (err) { if (err) {
@ -1177,6 +1184,7 @@ define([
})); }));
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
// 2a. add the shared folder to the path in our drive // 2a. add the shared folder to the path in our drive
console.log('adding');
store.userObject.add(id, path); store.userObject.add(id, path);
onSync(waitFor()); onSync(waitFor());
@ -1189,6 +1197,23 @@ define([
cb(); cb();
}); });
}; };
store.createSharedFolder = function () {
// XXX
var hash = Hash.createRandomHash('folder');
var href = '/folder/#' + hash;
var secret = Hash.getSecrets('folder', hash);
Store.addSharedFolder(null, {
path: ['root'],
folderData: {
href: href,
roHref: '/folder/#' + Hash.getViewHashFromKeys(secret),
channel: secret.channel,
title: "Test",
}
}, function () {
console.log('done');
});
};
// Drive // Drive

View File

@ -52,6 +52,7 @@ define([
GET_PAD_DATA: Store.getPadData, GET_PAD_DATA: Store.getPadData,
GET_STRONGER_HASH: Store.getStrongerHash, GET_STRONGER_HASH: Store.getStrongerHash,
INCREMENT_TEMPLATE_USE: Store.incrementTemplateUse, INCREMENT_TEMPLATE_USE: Store.incrementTemplateUse,
GET_SHARED_FOLDER: Store.getSharedFolder,
// Messaging // Messaging
INVITE_FROM_USERLIST: Store.inviteFromUserlist, INVITE_FROM_USERLIST: Store.inviteFromUserlist,
ADD_DIRECT_MESSAGE_HANDLERS: Store.addDirectMessageHandlers, ADD_DIRECT_MESSAGE_HANDLERS: Store.addDirectMessageHandlers,

View File

@ -69,6 +69,23 @@ define([
}); });
}; };
exp.pushSharedFolder = function (data, cb) {
if (typeof cb !== "function") { cb = function () {}; }
var todo = function () {
var id = Util.createRandomInteger();
files[SHARED_FOLDERS][id] = data;
cb(null, id);
};
if (!loggedIn || !AppConfig.enablePinning || config.testMode) {
return void cb("EAUTH");
}
if (!pinPads) { return void cb('EAUTH'); }
pinPads([data.channel], function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
todo();
});
};
// FILES DATA // FILES DATA
var spliceFileData = function (id) { var spliceFileData = function (id) {
delete files[FILES_DATA][id]; delete files[FILES_DATA][id];
@ -191,6 +208,7 @@ define([
var toRemove = []; var toRemove = [];
Object.keys(data).forEach(function (id) { Object.keys(data).forEach(function (id) {
id = Number(id);
// Find and maybe update existing pads with the same channel id // Find and maybe update existing pads with the same channel id
var d = data[id]; var d = data[id];
var found = false; var found = false;
@ -332,9 +350,9 @@ define([
}; };
exp.add = function (id, path) { exp.add = function (id, path) {
// TODO WW
if (!loggedIn && !config.testMode) { return; } if (!loggedIn && !config.testMode) { return; }
var data = files[FILES_DATA][id]; id = Number(id);
var data = files[FILES_DATA][id] || files[SHARED_FOLDERS][id];
if (!data || typeof(data) !== "object") { return; } if (!data || typeof(data) !== "object") { return; }
var newPath = path, parentEl; var newPath = path, parentEl;
if (path && !Array.isArray(path)) { if (path && !Array.isArray(path)) {
@ -438,7 +456,6 @@ define([
}); });
delete files[OLD_FILES_DATA]; delete files[OLD_FILES_DATA];
delete files.migrate; delete files.migrate;
console.log('done');
todo(); todo();
}; };
if (exp.rt) { if (exp.rt) {
@ -581,7 +598,7 @@ define([
}); });
}; };
var fixFilesData = function () { var fixFilesData = function () {
if (typeof files[FILES_DATA] !== "object") { debug("OLD_FILES_DATA was not an object"); files[FILES_DATA] = {}; } if (typeof files[FILES_DATA] !== "object") { debug("FILES_DATA was not an object"); files[FILES_DATA] = {}; }
var fd = files[FILES_DATA]; var fd = files[FILES_DATA];
var rootFiles = exp.getFiles([ROOT, TRASH, 'hrefArray']); var rootFiles = exp.getFiles([ROOT, TRASH, 'hrefArray']);
var root = exp.find([ROOT]); var root = exp.find([ROOT]);
@ -649,7 +666,8 @@ define([
secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); secret = Hash.getSecrets(parsed.type, parsed.hash, el.password);
} }
el.channel = secret.channel; el.channel = secret.channel;
console.log('Adding missing channel in filesData ', el.channel); console.log(el);
debug('Adding missing channel in filesData ', el.channel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }

View File

@ -7,17 +7,20 @@ define([
var getConfig = function (Env) { var getConfig = function (Env) {
var cfg = {}; var cfg = {};
for (var k in Env.cfg) { cfg[k] = Env[k]; } for (var k in Env.cfg) { cfg[k] = Env.cfg[k]; }
return cfg; return cfg;
}; };
// Add a shared folder to the list // Add a shared folder to the list
var addProxy = function (Env, id, proxy, leave) { var addProxy = function (Env, id, proxy, leave) {
var cfg = getConfig(); var cfg = getConfig(Env);
cfg.sharedFolder = true; cfg.sharedFolder = true;
cfg.id = id; cfg.id = id;
var userObject = UserObject.init(proxy, Env.cfg); var userObject = UserObject.init(proxy, cfg);
userObject.fixFiles(); if (userObject.fixFiles) {
// Only in outer
userObject.fixFiles();
}
Env.folders[id] = { Env.folders[id] = {
proxy: proxy, proxy: proxy,
userObject: userObject, userObject: userObject,
@ -98,7 +101,9 @@ define([
} }
var current; var current;
var uo = Env.user.userObject; var uo = Env.user.userObject;
for (var i=2; i<=path.length; i++) { // We don't need to check the last element of the path because we only need to split it
// when the path contains an element inside the shared folder
for (var i=2; i<path.length; i++) {
current = uo.find(path.slice(0,i)); current = uo.find(path.slice(0,i));
if (uo.isSharedFolder(current)) { if (uo.isSharedFolder(current)) {
res = { res = {
@ -193,13 +198,21 @@ define([
// Copy the elements to the new location // Copy the elements to the new location
var toCopy = _getCopyFromPaths(resolved.main, Env.user.userObject); var toCopy = _getCopyFromPaths(resolved.main, Env.user.userObject);
var newUserObject = newResolved.userObject; var newUserObject = newResolved.userObject;
newUserObject.copyFromOtherDrive(newResolved.path, toCopy.el, toCopy.data); var ownedPads = [];
toCopy.forEach(function (obj) {
newUserObject.copyFromOtherDrive(newResolved.path, obj.el, obj.data);
var _owned = Object.keys(obj.data).filter(function (id) {
var owners = obj.data[id].owners;
return Array.isArray(owners) && owners.indexOf(Env.edPublic) !== -1;
});
Array.prototype.push.apply(ownedPads, _owned);
});
// Filter owned pads so that we won't remove them from our drive var rootPath = resolved.main[0].slice();
var toRemove = resolved.main.slice(); rootPath.pop();
toRemove.filter(function (id) { ownedPads = Util.deduplicateString(ownedPads);
var owners = Env.user.userObject.getFileData(id).owners; ownedPads.forEach(function (id) {
return !Array.isArray(owners) || owners.indexOf(Env.edPublic) === -1; Env.user.userObject.add(Number(id), rootPath);
}); });
// Remove the elements from the old location (without unpinning) // Remove the elements from the old location (without unpinning)
@ -222,7 +235,9 @@ define([
// Copy the elements to the new location // Copy the elements to the new location
var toCopy = _getCopyFromPaths(paths, uoFrom); var toCopy = _getCopyFromPaths(paths, uoFrom);
uoTo.copyFromOtherDrive(newResolved.path, toCopy.el, toCopy.data); toCopy.forEach(function (obj) {
uoTo.copyFromOtherDrive(newResolved.path, obj.el, obj.data);
});
// Remove the elements from the old location (without unpinning) // Remove the elements from the old location (without unpinning)
uoFrom.delete(paths, waitFor(), false, false, true); uoFrom.delete(paths, waitFor(), false, false, true);
@ -409,16 +424,18 @@ define([
} }
}; };
} }
return function (fileId) { if (type === "pin") {
var data = userObject.getFileData(fileId); return function (fileId) {
// Don't pin pads owned by someone else var data = userObject.getFileData(fileId);
if (Array.isArray(data.owners) && data.owners.length && // Don't pin pads owned by someone else
data.owners.indexOf(edPublic) === -1) { return; } if (Array.isArray(data.owners) && data.owners.length &&
// Don't push duplicates data.owners.indexOf(edPublic) === -1) { return; }
if (result.indexOf(data.channel) === -1) { // Don't push duplicates
result.push(data.channel); if (result.indexOf(data.channel) === -1) {
} result.push(data.channel);
}; }
};
}
}; };
// Get the list of user objects // Get the list of user objects
@ -429,6 +446,13 @@ define([
files.forEach(addChannel(uo)); files.forEach(addChannel(uo));
}); });
if (type === "pin") {
var sfChannels = Object.keys(Env.folders).map(function (fId) {
return Env.user.proxy[UserObject.SHARED_FOLDERS][fId].channel;
});
Array.prototype.push.apply(result, sfChannels);
}
return result; return result;
}; };
@ -574,7 +598,7 @@ define([
var find = function (Env, path) { var find = function (Env, path) {
var resolved = _resolvePath(Env, path); var resolved = _resolvePath(Env, path);
return resolved.userObject.find(path); return resolved.userObject.find(resolved.path);
}; };
var getTitle = function (Env, id, type) { var getTitle = function (Env, id, type) {
@ -660,7 +684,14 @@ define([
var isFolder = function (Env, el) { var isFolder = function (Env, el) {
return Env.user.userObject.isFolder(el); return Env.user.userObject.isFolder(el);
}; };
var isSharedFolder = function (Env, el) {
return Env.user.userObject.isSharedFolder(el);
};
var isFolderEmpty = function (Env, el) { var isFolderEmpty = function (Env, el) {
if (Env.folders[el]) {
var uo = Env.folders[el].userObject;
return uo.isFolderEmpty(uo.find[uo.ROOT]);
}
return Env.user.userObject.isFolderEmpty(el); return Env.user.userObject.isFolderEmpty(el);
}; };
var isPathIn = function (Env, path, categories) { var isPathIn = function (Env, path, categories) {
@ -676,9 +707,17 @@ define([
return Env.user.userObject.comparePath(a, b); return Env.user.userObject.comparePath(a, b);
}; };
var hasSubfolder = function (Env, el, trashRoot) { var hasSubfolder = function (Env, el, trashRoot) {
if (Env.folders[el]) {
var uo = Env.folders[el].userObject;
return uo.hasSubfolder(uo.find[uo.ROOT]);
}
return Env.user.userObject.hasSubfolder(el, trashRoot); return Env.user.userObject.hasSubfolder(el, trashRoot);
}; };
var hasFile = function (Env, el, trashRoot) { var hasFile = function (Env, el, trashRoot) {
if (Env.folders[el]) {
var uo = Env.folders[el].userObject;
return uo.hasFile(uo.find[uo.ROOT]);
}
return Env.user.userObject.hasFile(el, trashRoot); return Env.user.userObject.hasFile(el, trashRoot);
}; };
@ -726,6 +765,7 @@ define([
// Generic // Generic
isFile: callWithEnv(isFile), isFile: callWithEnv(isFile),
isFolder: callWithEnv(isFolder), isFolder: callWithEnv(isFolder),
isSharedFolder: callWithEnv(isSharedFolder),
isFolderEmpty: callWithEnv(isFolderEmpty), isFolderEmpty: callWithEnv(isFolderEmpty),
isPathIn: callWithEnv(isPathIn), isPathIn: callWithEnv(isPathIn),
isSubpath: callWithEnv(isSubpath), isSubpath: callWithEnv(isSubpath),

View File

@ -31,7 +31,7 @@ define([
exp.TEMPLATE = TEMPLATE; exp.TEMPLATE = TEMPLATE;
exp.SHARED_FOLDERS = SHARED_FOLDERS; exp.SHARED_FOLDERS = SHARED_FOLDERS;
exp.sharedFolder = config.sharedFolder; var sharedFolder = exp.sharedFolder = config.sharedFolder;
exp.id = config.id; exp.id = config.id;
// Logging // Logging
@ -71,7 +71,12 @@ define([
var compareFiles = function (fileA, fileB) { return fileA === fileB; }; var compareFiles = function (fileA, fileB) { return fileA === fileB; };
var isSharedFolder = exp.isSharedFolder = function (element) {
if (sharedFolder) { return false; } // No recursive shared folders
return Boolean(files[SHARED_FOLDERS][element]);
};
var isFile = exp.isFile = function (element, allowStr) { var isFile = exp.isFile = function (element, allowStr) {
if (isSharedFolder(element)) { return false; }
return typeof(element) === "number" || return typeof(element) === "number" ||
((typeof(files[OLD_FILES_DATA]) !== "undefined" || allowStr) ((typeof(files[OLD_FILES_DATA]) !== "undefined" || allowStr)
&& typeof(element) === "string"); && typeof(element) === "string");
@ -84,15 +89,12 @@ define([
}; };
var isFolder = exp.isFolder = function (element) { var isFolder = exp.isFolder = function (element) {
return typeof(element) === "object"; return typeof(element) === "object" || isSharedFolder(element);
}; };
exp.isFolderEmpty = function (element) { exp.isFolderEmpty = function (element) {
if (!isFolder(element)) { return false; } if (!isFolder(element)) { return false; }
return Object.keys(element).length === 0; return Object.keys(element).length === 0;
}; };
exp.isSharedFolder = function (element) {
return Boolean(files[SHARED_FOLDERS][element]);
};
exp.hasSubfolder = function (element, trashRoot) { exp.hasSubfolder = function (element, trashRoot) {
if (!isFolder(element)) { return false; } if (!isFolder(element)) { return false; }
@ -311,7 +313,7 @@ define([
} }
}; };
if (isFile(root)) { if (isFile(root) || isSharedFolder(root)) {
if (compareFiles(file, root)) { if (compareFiles(file, root)) {
if (paths.indexOf(path) === -1) { if (paths.indexOf(path) === -1) {
paths.push(path); paths.push(path);
@ -331,6 +333,7 @@ define([
return _findFileInRoot([ROOT], file); return _findFileInRoot([ROOT], file);
}; };
var _findFileInHrefArray = function (rootName, file) { var _findFileInHrefArray = function (rootName, file) {
if (sharedFolder) { return []; }
if (!files[rootName]) { return []; } if (!files[rootName]) { return []; }
var unsorted = files[rootName].slice(); var unsorted = files[rootName].slice();
var ret = []; var ret = [];
@ -341,6 +344,7 @@ define([
return ret; return ret;
}; };
var _findFileInTrash = function (path, file) { var _findFileInTrash = function (path, file) {
if (sharedFolder) { return []; }
var root = find(path); var root = find(path);
var paths = []; var paths = [];
var addPaths = function (p) { var addPaths = function (p) {
@ -602,7 +606,7 @@ define([
var element = find(path); var element = find(path);
// Folders // Folders
if (isFolder(element)) { if (isFolder(element) && !isSharedFolder(element)) {
var parentPath = path.slice(); var parentPath = path.slice();
var oldName = parentPath.pop(); var oldName = parentPath.pop();
if (!newName || !newName.trim() || oldName === newName) { return; } if (!newName || !newName.trim() || oldName === newName) { return; }
@ -617,8 +621,13 @@ define([
return; return;
} }
// Files // Files or Shared folder
var data = files[FILES_DATA][element]; var data;
if (isSharedFolder(element)) {
data = files[SHARED_FOLDERS][element];
} else {
data = files[FILES_DATA][element];
}
if (!data) { return; } if (!data) { return; }
if (!newName || newName.trim() === "") { if (!newName || newName.trim() === "") {
delete data.filename; delete data.filename;

View File

@ -210,6 +210,23 @@ define([
for (var k in objRef) { delete objRef[k]; } for (var k in objRef) { delete objRef[k]; }
$.extend(true, objRef, objToCopy); $.extend(true, objRef, objToCopy);
}; };
var updateSharedFolders = function (sframeChan, drive, folders, cb) {
if (!drive || !drive.sharedFolders) {
return void cb();
}
nThen(function (waitFor) {
Object.keys(drive.sharedFolders).forEach(function (fId) {
sframeChan.query('Q_DRIVE_GETOBJECT', {
sharedFolder: fId
}, waitFor(function (err, newObj) {
folders[fId] = folders[fId] || {};
copyObjectValue(folders[fId], newObj);
}));
});
}).nThen(function () {
cb();
});
};
var updateObject = function (sframeChan, obj, cb) { var updateObject = function (sframeChan, obj, cb) {
sframeChan.query('Q_DRIVE_GETOBJECT', null, function (err, newObj) { sframeChan.query('Q_DRIVE_GETOBJECT', null, function (err, newObj) {
copyObjectValue(obj, newObj); copyObjectValue(obj, newObj);
@ -314,15 +331,11 @@ define([
config.loggedIn = APP.loggedIn; config.loggedIn = APP.loggedIn;
config.sframeChan = sframeChan; config.sframeChan = sframeChan;
var manager = ProxyManager.createInner(files, sframeChan, config); var manager = ProxyManager.createInner(files, sframeChan, config);
Object.keys(folders).forEach(function (id) { Object.keys(folders).forEach(function (id) {
var f = folders[id]; var f = folders[id];
// f.data => metadata (href, title, password...) manager.addProxy(id, f);
// f.proxy => listmap
// f.id => id?
manager.addProxy(id, f.proxy);
}); });
var $tree = APP.$tree = $("#cp-app-drive-tree"); var $tree = APP.$tree = $("#cp-app-drive-tree");
@ -1166,7 +1179,10 @@ define([
var $target = $(target); var $target = $(target);
var $el = findDataHolder($target); var $el = findDataHolder($target);
var newPath = $el.data('path'); var newPath = $el.data('path');
if ((!newPath || manager.isFile(manager.find(newPath))) var dropEl = newPath && manager.find(newPath);
if (newPath && manager.isSharedFolder(dropEl)) {
newPath.push(manager.user.userObject.ROOT);
} else if ((!newPath || manager.isFile(dropEl))
&& $target.parents('#cp-app-drive-content')) { && $target.parents('#cp-app-drive-content')) {
newPath = currentPath; newPath = currentPath;
} }
@ -2293,6 +2309,11 @@ define([
var isTags = path[0] === TAGS; var isTags = path[0] === TAGS;
var root = isVirtual ? undefined : manager.find(path); var root = isVirtual ? undefined : manager.find(path);
if (manager.isSharedFolder(root)) {
path.push(manager.user.userObject.ROOT);
root = manager.find(path);
if (!root) { return; }
}
if (!isVirtual && typeof(root) === "undefined") { if (!isVirtual && typeof(root) === "undefined") {
log(Messages.fm_unknownFolderError); log(Messages.fm_unknownFolderError);
debug("Unable to locate the selected directory: ", path); debug("Unable to locate the selected directory: ", path);
@ -2434,7 +2455,9 @@ define([
} }
updateObject(sframeChan, proxy, function () { updateObject(sframeChan, proxy, function () {
copyObjectValue(files, proxy.drive); copyObjectValue(files, proxy.drive);
_displayDirectory(path, force); updateSharedFolders(sframeChan, files, folders, function () {
_displayDirectory(path, force);
});
}); });
}; };
@ -3058,8 +3081,9 @@ define([
};*/ };*/
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
updateObject(sframeChan, proxy, waitFor()); updateObject(sframeChan, proxy, waitFor(function () {
// XXX Load shared folders updateSharedFolders(sframeChan, proxy.drive, folders, waitFor());
}));
}).nThen(function () { }).nThen(function () {
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
var metadataMgr = common.getMetadataMgr(); var metadataMgr = common.getMetadataMgr();

View File

@ -53,6 +53,12 @@ define([
Cryptpad.userObjectCommand(data, cb); Cryptpad.userObjectCommand(data, cb);
}); });
sframeChan.on('Q_DRIVE_GETOBJECT', function (data, cb) { sframeChan.on('Q_DRIVE_GETOBJECT', function (data, cb) {
if (data && data.sharedFolder) {
Cryptpad.getSharedFolder(data.sharedFolder, function (obj) {
cb(obj);
});
return;
}
Cryptpad.getUserObject(function (obj) { Cryptpad.getUserObject(function (obj) {
cb(obj); cb(obj);
}); });