diff --git a/customize.dist/src/less2/include/drive.less b/customize.dist/src/less2/include/drive.less index 0eb400587..28d539e48 100644 --- a/customize.dist/src/less2/include/drive.less +++ b/customize.dist/src/less2/include/drive.less @@ -158,6 +158,10 @@ user-select: none; } + .cp-app-drive-element-restricted { + background: rgba(0,0,0,0.1); + } + .cp-app-drive-element-droppable { background-color: @drive_droppable-bg; color: #222; diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 93c36597a..f3960f3b5 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -130,6 +130,7 @@ define([ //var $ownerIcon = $('', {"class": "fa fa-id-card"}); var $tagsIcon = $('', {"class": "fa " + faTags}); var $passwordIcon = $('', {"class": "fa fa-lock"}); + var $restrictedIcon = $('', {"class": "fa fa-ban"}); var $expirableIcon = $('', {"class": "fa fa-clock-o"}); var $separator = $('
', {"class": "dropdown-divider"}); @@ -1211,6 +1212,9 @@ define([ if (!$element.is('.cp-app-drive-element-owned')) { hide.push('deleteowned'); } + if ($element.is('.cp-app-drive-element-restricted')) { + hide.push('rename', 'download', 'share', 'access', 'color'); + } if ($element.is('.cp-app-drive-element-notrash')) { // We can't delete elements in virtual categories hide.push('delete'); @@ -1966,7 +1970,8 @@ define([ var $ro; if (manager.isSharedFolder(element)) { var data = manager.getSharedFolderData(element); - key = data && data.title ? data.title : key; + var fId = element; + key = data.title || data.lastTitle; element = manager.folders[element].proxy[manager.user.userObject.ROOT]; $span.addClass('cp-app-drive-element-sharedf'); _addOwnership($span, $state, data); @@ -1981,6 +1986,11 @@ define([ $ro.attr('title', Messages.readonly); } + if (files.restrictedFolders[fId]) { + var $restricted = $restrictedIcon.clone().appendTo($state); + $restricted.attr('title', Messages.fm_restricted); + } + var $shared = $sharedIcon.clone().appendTo($state); $shared.attr('title', Messages.fm_canBeShared); } else if ($content.data('readOnlyFolder') || APP.readOnly) { @@ -1989,14 +1999,14 @@ define([ } var sf = manager.hasSubfolder(element); - var files = manager.hasFile(element); + var hasFiles = manager.hasFile(element); var $name = $('', {'class': 'cp-app-drive-element-name'}).text(key); var $subfolders = $('', { 'class': 'cp-app-drive-element-folders cp-app-drive-element-list' }).text(sf); var $files = $('', { 'class': 'cp-app-drive-element-files cp-app-drive-element-list' - }).text(files); + }).text(hasFiles); var $filler = $('', { 'class': 'cp-app-drive-element-filler cp-app-drive-element-list' }); @@ -2051,6 +2061,7 @@ define([ return $shareBlock; }; + Messages.fm_restricted = "Forbidden access"; // XXX // Create the "li" element corresponding to the file/folder located in "path" var createElement = function (path, elPath, root, isFolder) { // Forbid drag&drop inside the trash @@ -2068,32 +2079,38 @@ define([ element = root[key]; } + var restricted = files.restrictedFolders[element]; var isSharedFolder = manager.isSharedFolder(element); var $icon = !isFolder ? getFileIcon(element) : undefined; var ro = manager.isReadOnlyFile(element); // ro undefined means it's an old hash which doesn't support read-only - var roClass = typeof(ro) === 'undefined' ?' cp-app-drive-element-noreadonly' : - ro ? ' cp-app-drive-element-readonly' : ''; - var liClass = 'cp-app-drive-element-file cp-app-drive-element' + roClass; + var roClass = typeof(ro) === 'undefined' ? '.cp-app-drive-element-noreadonly' : + ro ? '.cp-app-drive-element-readonly' : ''; + var liClass = '.cp-app-drive-element-file'; + var restrictedClass = restricted ? '.cp-app-drive-element-restricted' : ''; if (isSharedFolder) { - liClass = 'cp-app-drive-element-folder cp-app-drive-element'; + liClass = '.cp-app-drive-element-folder'; $icon = $sharedFolderIcon.clone(); $icon.css("color", getFolderColor(path.concat(elPath))); } else if (isFolder) { - liClass = 'cp-app-drive-element-folder cp-app-drive-element'; + liClass = '.cp-app-drive-element-folder'; $icon = manager.isFolderEmpty(root[key]) ? $folderEmptyIcon.clone() : $folderIcon.clone(); $icon.css("color", getFolderColor(path.concat(elPath))); } - var $element = $('
  • ', { - draggable: true, - 'class': 'cp-app-drive-element-row' - }); + var classes = restrictedClass + roClass + liClass; + var $element = $(h('li.cp-app-drive-element.cp-app-drive-element-row' + classes, { + draggable: true + })); $element.data('path', newPath); if (isElementSelected($element)) { selectElement($element); } $element.prepend($icon).dblclick(function () { + if (restricted) { + UI.warn(Messages.fm_restricted); + return; + } if (isFolder) { APP.displayDirectory(newPath); return; @@ -2117,8 +2134,7 @@ define([ } e.stopPropagation(); }); - $element.addClass(liClass); - var droppable = !isTrash && !APP.$content.data('readOnlyFolder'); + var droppable = !isTrash && !APP.$content.data('readOnlyFolder') && !restricted; addDragAndDropHandlers($element, newPath, isFolder, droppable); $element.click(function(e) { e.stopPropagation(); @@ -3697,6 +3713,9 @@ define([ e.stopPropagation(); APP.displayDirectory(path); }); + if (files.restrictedFolders[isSharedFolder]) { + $elementRow.addClass('cp-app-drive-element-restricted'); + } var $element = $('
  • ').append($elementRow); if (draggable) { $elementRow.attr('draggable', true); } if (collapsable) { @@ -3775,7 +3794,7 @@ define([ if (!manager.isFolder(root[key])) { return; } var newPath = path.slice(); newPath.push(key); - var isSharedFolder = manager.isSharedFolder(root[key]); + var isSharedFolder = manager.isSharedFolder(root[key]) && root[key]; var sfId = manager.isInSharedFolder(newPath) || (isSharedFolder && root[key]); var $icon, isCurrentFolder, subfolder; if (isSharedFolder) { @@ -4068,6 +4087,10 @@ define([ else if ($this.hasClass('cp-app-drive-context-open')) { paths.forEach(function (p) { var el = manager.find(p.path); + if (files.restrictedFolders[el]) { + UI.warn(Messages.fm_restricted); + return; + } openFile(el, false, true); }); } @@ -4655,7 +4678,6 @@ define([ }); } */ - var deprecated = files.sharedFoldersTemp; var nt = nThen; var passwordModal = function (fId, data, cb) { var content = []; @@ -4711,6 +4733,7 @@ define([ onClose: cb }); }; + var deprecated = files.sharedFoldersTemp; if (typeof (deprecated) === "object" && APP.editable && Object.keys(deprecated).length) { Object.keys(deprecated).forEach(function (fId) { var data = deprecated[fId]; @@ -4727,7 +4750,6 @@ define([ }); } - return { refresh: refresh, close: function () { diff --git a/www/common/inner/access.js b/www/common/inner/access.js index 190af4279..d3084dbe6 100644 --- a/www/common/inner/access.js +++ b/www/common/inner/access.js @@ -371,8 +371,7 @@ define([ var parsed = Hash.parsePadUrl(data.href || data.roHref); var owned = Modal.isOwned(Env, data); var disabled = !owned || !parsed.hashData || parsed.hashData.type !== 'pad'; - var allowDisabled = parsed.type === 'drive'; - if (disabled || allowDisabled) { return void cb(); } + if (disabled) { return void cb(); } opts = opts || {}; diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index c87edc17d..eb04c7310 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2188,6 +2188,8 @@ define([ }); }; registerProxyEvents = function (proxy, fId) { + if (!proxy) { return; } + if (proxy.deprecated || proxy.restricted) { return; } if (!fId) { // Listen for shared folder password change proxy.on('change', ['drive', UserObject.SHARED_FOLDERS], function (o, n, p) { diff --git a/www/common/outer/sharedfolder.js b/www/common/outer/sharedfolder.js index cbeae1cbd..3c85492f9 100644 --- a/www/common/outer/sharedfolder.js +++ b/www/common/outer/sharedfolder.js @@ -225,6 +225,7 @@ define([ sf.teams.forEach(function (obj) { obj.store.manager.restrictedProxy(obj.id, secret.channel); }); + delete allSharedFolders[secret.channel]; return void cb(); } } diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js index df46cb884..7e458df23 100644 --- a/www/common/proxy-manager.js +++ b/www/common/proxy-manager.js @@ -68,7 +68,7 @@ define([ }; var restrictedProxy = function (Env, id) { - var lm = { proxy: { deprecated: true } }; + var lm = { proxy: { restricted: true, root: {}, filesData: {} } }; removeProxy(Env, id); addProxy(Env, id, lm, function () {}); return void Env.Store.refreshDriveUI(); diff --git a/www/drive/inner.js b/www/drive/inner.js index 5d60e9a4c..553454bc5 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -42,6 +42,7 @@ define([ if (!drive || !drive.sharedFolders) { return void cb(); } + var r = drive.restrictedFolders = drive.restrictedFolders || {}; var oldIds = Object.keys(folders); nThen(function (waitFor) { Object.keys(drive.sharedFolders).forEach(function (fId) { @@ -60,7 +61,11 @@ define([ APP.newSharedFolder = null; } } - if (newObj && newObj.deprecated) { + if (newObj && newObj.restricted) { + r[fId] = drive.sharedFolders[fId]; + if (!r[fId].title) { r[fId].title = r[fId].lastTitle; } + } + if (newObj && (newObj.deprecated /*|| newObj.restricted*/)) { delete folders[fId]; delete drive.sharedFolders[fId]; if (manager && manager.folders) { diff --git a/www/teams/inner.js b/www/teams/inner.js index 86b8acf47..2d9690b99 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -55,6 +55,7 @@ define([ if (!drive || !drive.sharedFolders) { return void cb(); } + var r = drive.restrictedFolders = drive.restrictedFolders || {}; var oldIds = Object.keys(folders); nThen(function (waitFor) { Object.keys(drive.sharedFolders).forEach(function (fId) { @@ -65,7 +66,10 @@ define([ sframeChan.query('Q_DRIVE_GETOBJECT', { sharedFolder: fId }, waitFor(function (err, newObj) { - if (newObj && newObj.deprecated) { + if (newObj && newObj.restricted) { + r[fId] = drive.sharedFolders[fId]; + } + if (newObj && (newObj.deprecated || newObj.restricted)) { delete folders[fId]; delete drive.sharedFolders[fId]; if (manager && manager.folders) {