From 88021f226473db1dcacdee32e4eb13f0ad290f7c Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 24 Jan 2017 18:14:29 +0100 Subject: [PATCH] Anonymous pads fo anonymous users --- customize.dist/fsStore.js | 18 +++++-- www/common/cryptpad-common.js | 19 +++++-- www/common/fileObject.js | 65 +++++++++++++++++------- www/drive/file.css | 2 +- www/drive/main.js | 96 +++++++++++++++++++++++++---------- 5 files changed, 145 insertions(+), 55 deletions(-) diff --git a/customize.dist/fsStore.js b/customize.dist/fsStore.js index 1ab788dc4..dcf36927b 100644 --- a/customize.dist/fsStore.js +++ b/customize.dist/fsStore.js @@ -39,6 +39,11 @@ define([ cb(void 0, map); }; + Store.setDrive = function (key, val, cb) { + storeObj.drive[key] = val; + cb(); + }; + var safeGet = window.safeGet = function (key) { return storeObj[key]; }; @@ -56,6 +61,10 @@ define([ cb(void 0, res); }; + Store.getDrive = function (key, cb) { + cb(void 0, storeObj.drive[key]); + }; + var safeRemove = function (key) { delete storeObj[key]; }; @@ -127,7 +136,7 @@ define([ }; var onReady = function (f, proxy, storageKey) { - filesOp = FO.init(proxy, { + filesOp = FO.init(proxy.drive, { storageKey: storageKey }); storeObj = proxy; @@ -179,10 +188,13 @@ define([ } }).on('ready', function () { if (ready) { return; } - if (!rt.proxy[Cryptpad.storageKey] || !Cryptpad.isArray(rt.proxy[Cryptpad.storageKey])) { + if (!rt.proxy.drive || typeof(rt.proxy.drive) !== 'object') { rt.proxy.drive = {}; } + var drive = rt.proxy.drive; + // Creating a new anon drive: import anon pads from localStorage + if (!drive[Cryptpad.storageKey] || !Cryptpad.isArray(drive[Cryptpad.storageKey])) { var oldStore = Cryptpad.getStore(true); oldStore.get(Cryptpad.storageKey, function (err, s) { - rt.proxy[Cryptpad.storageKey] = s; + drive[Cryptpad.storageKey] = s; onReady(f, rt.proxy, Cryptpad.storageKey); }); return; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 9ae31a238..1daf1fe73 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -80,7 +80,7 @@ define([ var logout = common.logout = function (cb) { [ - fileHashKey, +// fileHashKey, userHashKey, ].forEach(function (k) { sessionStorage.removeItem(k); @@ -88,6 +88,9 @@ define([ delete localStorage[k]; delete sessionStorage[k]; }); + if (!localStorage[fileHashKey]) { + localStorage[fileHashKey] = common.createRandomHash(); + } if (cb) { cb(); } }; @@ -101,6 +104,11 @@ define([ return hash; }; + var isLoggedIn = common.isLoggedIn = function () { + //return typeof getStore().getLoginName() === "string"; + return typeof getUserHash() === "string"; + }; + // var isArray = function (o) { return Object.prototype.toString.call(o) === '[object Array]'; }; var isArray = common.isArray = $.isArray; @@ -444,7 +452,7 @@ define([ // STORAGE /* fetch and migrate your pad history from localStorage */ var getRecentPads = common.getRecentPads = function (cb, legacy) { - getStore(legacy).get(storageKey, function (err, recentPads) { + getStore(legacy).getDrive(storageKey, function (err, recentPads) { if (isArray(recentPads)) { cb(void 0, migrateRecentPads(recentPads)); return; @@ -456,7 +464,7 @@ define([ // STORAGE /* commit a list of pads to localStorage */ var setRecentPads = common.setRecentPads = function (pads, cb, legacy) { - getStore(legacy).set(storageKey, pads, function (err, data) { + getStore(legacy).setDrive(storageKey, pads, function (err, data) { cb(err, data); }); }; @@ -566,8 +574,11 @@ define([ if (!contains) { var data = makePad(href, name); + if (common.initialPath) { + data.owner = 1; // TODO use owner id here? + } renamed.push(data); - if (USE_FS_STORE && typeof(getStore().addPad) === "function") { + if (USE_FS_STORE && common.initialPath && typeof(getStore().addPad) === "function") { getStore().addPad(href, common.initialPath, name); } } diff --git a/www/common/fileObject.js b/www/common/fileObject.js index 7398ffc7d..4137a0f84 100644 --- a/www/common/fileObject.js +++ b/www/common/fileObject.js @@ -8,6 +8,7 @@ define([ var ROOT = "root"; var UNSORTED = "unsorted"; var FILES_DATA = "filesData"; + var ANON = "anon"; // virtual path var TRASH = "trash"; var TEMPLATE = "template"; var NEW_FOLDER_NAME = Messages.fm_newFolder; @@ -57,6 +58,9 @@ define([ var isPathInTrash = exp.isPathInTrash = function (path) { return path[0] && path[0] === TRASH; }; + var isPathInAnon = exp.isPathInAnon = function (path) { + return path[0] && path[0] === ANON; + }; var isPathInFilesData = exp.isPathInFilesData = function (path) { return path[0] && path[0] === FILES_DATA; @@ -227,6 +231,13 @@ define([ return ret; }; + /*var getAnonFiles = exp.getAnonFiles = function () { + if (!files[ANON]) { + files[ANON] = []; + } + return files[ANON].slice(); + };*///TODO + var removeFileFromRoot = function (root, href) { if (isFile(root)) { return; } for (var e in root) { @@ -688,6 +699,11 @@ define([ }); }; + var isAnonFile = exp.isAnonFile = function (file) { + var data = getFileData(file); + return !data.owner; + }; + var fixFiles = exp.fixFiles = function () { // Explore the tree and check that everything is correct: // * 'root', 'trash', 'unsorted' and 'filesData' exist and are objects @@ -709,6 +725,11 @@ define([ debug("An element in ROOT was not a folder nor a file. ", element[el]); element[el] = undefined; delete element[el]; + } else if (isFile(element[el])) { + if (isAnonFile(element[el])) { + debug("An element in ROOT was an anonymous file. ", element[el]); + delete element[el]; + } } else if (isFolder(element[el])) { fixRoot(element[el]); } @@ -721,6 +742,7 @@ define([ var addToClean = function (obj, idx) { if (typeof(obj) !== "object") { toClean.push(idx); return; } if (!isFile(obj.element) && !isFolder(obj.element)) { toClean.push(idx); return; } + if (isFile(obj.element) && isAnonFile(obj.element)) { toClean.push(idx); return; } if (!$.isArray(obj.path)) { toClean.push(idx); return; } }; for (var el in tr) { @@ -745,15 +767,12 @@ define([ var templateFiles = getTemplateFiles(); var toClean = []; us.forEach(function (el, idx) { - if (!isFile(el) || rootFiles.indexOf(el) !== -1 || templateFiles.indexOf(el) !== -1) { + if (!isFile(el) || rootFiles.indexOf(el) !== -1 || templateFiles.indexOf(el) !== -1 || isAnonFile(el)) { toClean.push(idx); } }); - toClean.forEach(function (el) { - var idx = us.indexOf(el); - if (idx !== -1) { - us.splice(idx, 1); - } + toClean.forEach(function (idx) { + us.splice(idx, 1); }); }; var fixTemplate = function () { @@ -764,36 +783,44 @@ define([ var unsortedFiles = getUnsortedFiles(); var toClean = []; us.forEach(function (el, idx) { - if (!isFile(el) || rootFiles.indexOf(el) !== -1 || unsortedFiles.indexOf(el) !== -1) { + if (!isFile(el) || rootFiles.indexOf(el) !== -1 || unsortedFiles.indexOf(el) !== -1 || isAnonFile(el)) { toClean.push(idx); } }); - toClean.forEach(function (el) { - var idx = us.indexOf(el); - if (idx !== -1) { - us.splice(idx, 1); - } + toClean.forEach(function (idx) { + us.splice(idx, 1); }); }; + /*var fixAnon = function () { + if (!$.isArray(files[ANON])) { debug("ANON was not an array"); files[FILES_DATA] = []; } + };*/// TODO var fixFilesData = function () { if (!$.isArray(files[FILES_DATA])) { debug("FILES_DATA was not an array"); files[FILES_DATA] = []; } var fd = files[FILES_DATA]; var rootFiles = getRootFiles(); var unsortedFiles = getUnsortedFiles(); + var templateFiles = getTemplateFiles(); var trashFiles = getTrashFiles(); + //var anonFiles = getAnonFiles(); var toClean = []; fd.forEach(function (el, idx) { if (typeof(el) !== "object") { debug("An element in filesData was not an object.", el); toClean.push(el); - } else { - if (rootFiles.indexOf(el.href) === -1 - && unsortedFiles.indexOf(el.href) === -1 - && trashFiles.indexOf(el.href) === -1) { - debug("An element in filesData was not in ROOT, UNSORTED or TRASH.", el); - files[UNSORTED].push(el.href); - } + return; } + if (el.owner + && rootFiles.indexOf(el.href) === -1 + && unsortedFiles.indexOf(el.href) === -1 + && templateFiles.indexOf(el.href) === -1 + && trashFiles.indexOf(el.href) === -1) { + debug("An element in filesData was not in ROOT, UNSORTED or TRASH.", el); + files[UNSORTED].push(el.href); + return; + } + /*if (!el.owner && anonFiles.indexOf(el.href) === -1) { + files[ANON].push(el.href); + }*/// TODO }); toClean.forEach(function (el) { var idx = fd.indexOf(el); diff --git a/www/drive/file.css b/www/drive/file.css index 2fad2fd94..d6c1f2274 100644 --- a/www/drive/file.css +++ b/www/drive/file.css @@ -97,7 +97,7 @@ li { text-decoration: underline; } -#tree #trashTree, #tree #unsortedTree, #tree #templateTree, #tree #allfilesTree { +#tree .category2 { margin-top: 2em; } diff --git a/www/drive/main.js b/www/drive/main.js index 308beed83..d1d89ee35 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -26,7 +26,8 @@ define([ var APP = window.APP = { $bar: $iframe.find('#toolbar'), editable: false, - Cryptpad: Cryptpad + Cryptpad: Cryptpad, + loggedIn: Cryptpad.isLoggedIn() }; var stringify = APP.stringify = function (obj) { @@ -43,6 +44,11 @@ define([ var TEMPLATE_NAME = Messages.fm_templateName; var TRASH = "trash"; var TRASH_NAME = Messages.fm_trashName; + + // anon: Virtual path, not stored in the object but extracted from FILES_DATA + var ANON = "anon"; + var ANON_NAME = Messages.fm_anonName || 'Anon pads......'; + var LOCALSTORAGE_LAST = "cryptpad-file-lastOpened"; var LOCALSTORAGE_OPENED = "cryptpad-file-openedFolders"; var LOCALSTORAGE_VIEWMODE = "cryptpad-file-viewMode"; @@ -130,7 +136,8 @@ define([ else { $iframe.find('[draggable="false"]').attr('draggable', true); } }; - var init = function (files) { + var init = function (proxy) { + var files = proxy.drive; var isOwnDrive = function () { return Cryptpad.getUserHash() === APP.hash || localStorage.FS_hash === APP.hash; }; @@ -166,7 +173,7 @@ define([ // FILE MANAGER // _WORKGROUP_ and other people drive : display Documents as main page - var currentPath = module.currentPath = isOwnDrive() ? getLastOpenedFolder() : [ROOT]; + var currentPath = module.currentPath = APP.loggedIn ? isOwnDrive() ? getLastOpenedFolder() : [ROOT] : [ANON]; var lastSelectTime; var selectedElement; @@ -725,6 +732,7 @@ define([ else if (name === TRASH && path.length === 1) { name = TRASH_NAME; } else if (name === UNSORTED && path.length === 1) { name = UNSORTED_NAME; } else if (name === TEMPLATE && path.length === 1) { name = TEMPLATE_NAME; } + else if (name === ANON && path.length === 1) { name = ANON_NAME; } else if (name === FILES_DATA && path.length === 1) { name = FILES_DATA_NAME; } else if (filesOp.isPathInTrash(path)) { name = getTrashTitle(path); } var $title = $('

').text(name); @@ -749,19 +757,19 @@ define([ var $box = $('
', {'class': 'info-box'}); var msg; switch (path[0]) { - case 'root': + case ROOT: msg = Messages.fm_info_root; break; - case 'unsorted': + case UNSORTED: msg = Messages.fm_info_unsorted; break; - case 'template': + case TEMPLATE: msg = Messages.fm_info_template; break; - case 'trash': + case TRASH: msg = Messages.fm_info_trash; break; - case Cryptpad.storageKey: + case FILES_DATA: msg = Messages.fm_info_allFiles; break; default: @@ -836,12 +844,13 @@ define([ options.push({tag: 'hr'}); } AppConfig.availablePadTypes.forEach(function (type) { + var path = filesOp.comparePath(currentPath, [ANON]) ? '' : '/#?path=' + encodeURIComponent(currentPath); options.push({ tag: 'a', attributes: { 'class': 'newdoc', 'data-type': type, - 'href': '/' + type + '/#?path=' + encodeURIComponent(currentPath), + 'href': '/' + type + path, 'target': '_blank' }, content: Messages.type[type] @@ -1060,7 +1069,7 @@ define([ // Unsorted element are represented by "href" in an array: they don't have a filename // and they don't hav a hierarchical structure (folder/subfolders) - var displayHrefArray = function ($container, rootName) { + var displayHrefArray = function ($container, rootName, draggable) { var unsorted = files[rootName]; if (rootName === UNSORTED && allFilesSorted()) { return; } var $fileHeader = getFileListHeader(false); @@ -1081,7 +1090,7 @@ define([ var $name = $('', { 'class': 'file-element element' }); addFileData(href, file.title, $name, false); var $element = $('
  • ', { - draggable: true + draggable: draggable }).append($icon).append($name).dblclick(function () { openFile(href); }); @@ -1092,17 +1101,22 @@ define([ onElementClick(e, $element, path); }); $element.contextmenu(openDefaultContextMenu); - addDragAndDropHandlers($element, path, false, false); + if (draggable) { + addDragAndDropHandlers($element, path, false, false); + } $container.append($element); }); }; - var displayAllFiles = function ($container) { + var displayAllFiles = function ($container, anon) { var allfiles = files[FILES_DATA]; if (allfiles.length === 0) { return; } var $fileHeader = getFileListHeader(false); $container.append($fileHeader); - var keys = allfiles; + var keys = allfiles.filter(function (el) { + return anon && !el.owner || !anon && el.owner; + }); + var sortedFiles = sortElements(false, [FILES_DATA], keys, Cryptpad.getLSAttribute(SORT_FILE_BY), !getSortFileDesc(), false, true); sortedFiles.forEach(function (file) { var $icon = $fileIcon.clone(); @@ -1183,9 +1197,10 @@ define([ var isUnsorted = filesOp.comparePath(path, [UNSORTED]); var isTemplate = filesOp.comparePath(path, [TEMPLATE]); var isAllFiles = filesOp.comparePath(path, [FILES_DATA]); + var isAnon = filesOp.comparePath(path, [ANON]); var root = filesOp.findElement(files, path); - if (typeof(root) === "undefined") { + if (typeof(root) === "undefined" && !isAnon) { log(Messages.fm_unknownFolderError); debug("Unable to locate the selected directory: ", path); var parentPath = path.slice(); @@ -1221,9 +1236,12 @@ define([ var $fileHeader = getFileListHeader(true); if (isUnsorted || isTemplate) { - displayHrefArray($list, path[0]); + // 3rd parameter is "draggable": anon pads shouldn't be draggable + displayHrefArray($list, path[0], !isAnon); } else if (isAllFiles) { - displayAllFiles($list); + displayAllFiles($list, false); + } else if (isAnon) { + displayAllFiles($list, true); } else if (isTrashRoot) { displayTrashRoot($list, $folderHeader, $fileHeader); } else { @@ -1352,7 +1370,7 @@ define([ var isOpened = filesOp.comparePath(path, currentPath); var $unsortedElement = createTreeElement(UNSORTED_NAME, $icon, [UNSORTED], false, true, false, isOpened); $unsortedElement.addClass('root'); - var $unsortedList = $('
      ', { id: 'unsortedTree' }).append($unsortedElement); + var $unsortedList = $('
        ', { id: 'unsortedTree', 'class': 'category2' }).append($unsortedElement); $container.append($unsortedList); }; @@ -1361,7 +1379,7 @@ define([ var isOpened = filesOp.comparePath(path, currentPath); var $element = createTreeElement(TEMPLATE_NAME, $icon, [TEMPLATE], false, true, false, isOpened); $element.addClass('root'); - var $list = $('
          ', { id: 'templateTree' }).append($element); + var $list = $('
            ', { id: 'templateTree', 'class': 'category2' }).append($element); $container.append($list); }; @@ -1370,7 +1388,19 @@ define([ var isOpened = filesOp.comparePath(path, currentPath); var $allfilesElement = createTreeElement(FILES_DATA_NAME, $icon, [FILES_DATA], false, false, false, isOpened); $allfilesElement.addClass('root'); - var $allfilesList = $('
              ', { id: 'allfilesTree' }).append($allfilesElement); + var $allfilesList = $('
                ', { id: 'allfilesTree', 'class': 'category2' }).append($allfilesElement); + $container.append($allfilesList); + }; + + var createAnonFiles = function ($container, path, anonUser) { + var $icon = $unsortedIcon.clone(); + var isOpened = filesOp.comparePath(path, currentPath); + var $allfilesElement = createTreeElement(ANON_NAME, $icon, [ANON], false, false, false, isOpened); + $allfilesElement.addClass('root'); + var $allfilesList = $('
                  ', { id: 'anonTree', 'class': 'category2' }).append($allfilesElement); + if (anonUser) { + $allfilesList.removeClass('category2'); + } $container.append($allfilesList); }; @@ -1390,16 +1420,21 @@ define([ $trashElement.contextmenu(openTrashTreeContextMenu); if (isOpened) { $trash.addClass('active'); } - var $trashList = $('
                    ', { id: 'trashTree' }).append($trashElement); + var $trashList = $('
                      ', { id: 'trashTree', 'class': 'category2' }).append($trashElement); $container.append($trashList); }; var resetTree = module.resetTree = function () { $tree.html(''); + if (!APP.loggedIn) { + createAnonFiles($tree, [ANON], true); + return; + } createTree($tree, [ROOT]); if (!isWorkgroup()) { createUnsorted($tree, [UNSORTED]); createTemplate($tree, [TEMPLATE]); + createAnonFiles($tree, [ANON]); createAllFiles($tree, [FILES_DATA]); } createTrash($tree, [TRASH]); @@ -1646,16 +1681,19 @@ define([ onRefresh.to = window.setTimeout(refresh, 500); } }; - files.on('change', [], function (o, n, p) { + proxy.on('change', [], function (o, n, p) { var path = arguments[2]; - if ((filesOp.isPathInUnsorted(currentPath) && filesOp.isPathInUnsorted(path)) || - (filesOp.isPathInTemplate(currentPath) && filesOp.isPathInTemplate(path)) || - (path.length >= currentPath.length && filesOp.isSubpath(path, currentPath)) || - (filesOp.isPathInTrash(currentPath) && filesOp.isPathInTrash(path))) { + if (path[0] !== 'drive') { return false; } + path = path.slice(1); + var cPath = filesOp.isPathInAnon(currentPath) ? [FILES_DATA] : currentPath.slice(); + if ((filesOp.isPathInUnsorted(cPath) && filesOp.isPathInUnsorted(path)) || + (filesOp.isPathInTemplate(cPath) && filesOp.isPathInTemplate(path)) || + (path.length >= cPath.length && filesOp.isSubpath(path, cPath)) || + (filesOp.isPathInTrash(cPath) && filesOp.isPathInTrash(path))) { // Reload after a few ms to make sure all the change events have been received onRefresh.refresh(); } else if (path.length && path[0] === FILES_DATA) { - if (filesOp.isPathInHrefArray(currentPath)) { + if (filesOp.isPathInHrefArray(cPath) || filesOp.isPathInAnon(path)) { onRefresh.refresh(); } else { refreshFilesData(); @@ -1791,8 +1829,9 @@ define([ module.files = proxy; if (JSON.stringify(proxy) === '{}') { var store = Cryptpad.getStore(true); + var drive = proxy.drive = {}; store.get(Cryptpad.storageKey, function (err, s) { - proxy[FILES_DATA] = s; + drive[FILES_DATA] = s; initLocalStorage(); init(proxy); APP.userList.onChange(); @@ -1800,6 +1839,7 @@ define([ }); return; } + if (!proxy.drive || typeof(proxy.drive) !== 'object') { proxy.drive = {}; } initLocalStorage(); init(proxy); APP.userList.onChange();