Fix sharing breadcrumbs

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2019-10-30 17:26:53 +01:00
parent eebcf89091
commit 5d2c89ca6c
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF
15 changed files with 164 additions and 7032 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,24 +0,0 @@
(window.webpackJsonpFilesSharing=window.webpackJsonpFilesSharing||[]).push([[5],{348:function(e,o,i){"use strict";i.r(o);var n=i(3),l=i(349),r=i(350),u=i(351),s=i.n(u),a={name:"CollaborationView",components:{CollectionList:i(103).a},computed:{fileId:function(){return this.$root.model&&this.$root.model.id?""+this.$root.model.id:null},filename:function(){return this.$root.model&&this.$root.model.name?""+this.$root.model.name:""}}},d=i(0),c=Object(d.a)(a,(function(){var t=this.$createElement,e=this._self._c||t;return this.fileId?e("CollectionList",{attrs:{id:this.fileId,type:"file",name:this.filename}}):this._e()}),[],!1,null,null,null).exports;i.d(o,"Vue",(function(){return n.default})),i.d(o,"View",(function(){return c})),
/**
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
n.default.prototype.t=t,r.Tooltip.options.defaultHtml=!1,n.default.component("PopoverMenu",r.PopoverMenu),n.default.directive("ClickOutside",s.a),n.default.directive("Tooltip",r.Tooltip),n.default.use(l.a)}}]);
//# sourceMappingURL=files_sharing.5.js.map?v=8e6d26aadf8403a07b5b

File diff suppressed because one or more lines are too long

View File

@ -20,10 +20,31 @@
if (!OCA.Sharing) {
OCA.Sharing = {}
}
OC.Share = _.extend(OC.Share || {}, {
SHARE_TYPE_USER: 0,
SHARE_TYPE_GROUP: 1,
SHARE_TYPE_LINK: 3,
SHARE_TYPE_EMAIL: 4,
SHARE_TYPE_REMOTE: 6,
SHARE_TYPE_CIRCLE: 7,
SHARE_TYPE_GUEST: 8,
SHARE_TYPE_REMOTE_GROUP: 9,
SHARE_TYPE_ROOM: 10
})
/**
* @namespace
*/
OCA.Sharing.Util = {
/**
* Regular expression for splitting parts of remote share owners:
* "user@example.com/path/to/owncloud"
* "user@anotherexample.com@example.com/path/to/owncloud
*/
_REMOTE_OWNER_REGEXP: new RegExp('^([^@]*)@(([^@]*)@)?([^/]*)([/](.*)?)?$'),
/**
* Initialize the sharing plugin.
*
@ -210,9 +231,7 @@
})
// register share breadcrumbs component
var shareTab = new OCA.Sharing.ShareTabView('sharing', {order: -20})
var breadCrumbSharingDetailView = new OCA.Sharing.ShareBreadCrumbView({ shareTab: shareTab })
var breadCrumbSharingDetailView = new OCA.Sharing.ShareBreadCrumbView()
fileList.registerBreadCrumbDetailView(breadCrumbSharingDetailView)
},
@ -313,9 +332,9 @@
// even if reshared, only show "Shared by"
if (ownerId) {
message = t('core', 'Shared by')
avatars = this._formatRemoteShare(ownerId, owner, message)
avatars = OCA.Sharing.Util._formatRemoteShare(ownerId, owner, message)
} else if (recipients) {
avatars = this._formatShareList(recipients)
avatars = OCA.Sharing.Util._formatShareList(recipients)
}
action.html(avatars).prepend(icon)
@ -334,6 +353,140 @@
}
icon.removeClass('icon-shared icon-public').addClass(iconClass)
},
/**
* Format a remote address
*
* @param {String} shareWith userid, full remote share, or whatever
* @param {String} shareWithDisplayName
* @param {String} message
* @returns {String} HTML code to display
*/
_formatRemoteShare: function(shareWith, shareWithDisplayName, message) {
var parts = OCA.Sharing.Util._REMOTE_OWNER_REGEXP.exec(shareWith)
if (!parts) {
// display avatar of the user
var avatar = '<span class="avatar" data-username="' + escapeHTML(shareWith) + '" title="' + message + ' ' + escapeHTML(shareWithDisplayName) + '"></span>'
var hidden = '<span class="hidden-visually">' + message + ' ' + escapeHTML(shareWithDisplayName) + '</span> '
return avatar + hidden
}
var userName = parts[1]
var userDomain = parts[3]
var server = parts[4]
var tooltip = message + ' ' + userName
if (userDomain) {
tooltip += '@' + userDomain
}
if (server) {
if (!userDomain) {
userDomain = '…'
}
tooltip += '@' + server
}
var html = '<span class="remoteAddress" title="' + escapeHTML(tooltip) + '">'
html += '<span class="username">' + escapeHTML(userName) + '</span>'
if (userDomain) {
html += '<span class="userDomain">@' + escapeHTML(userDomain) + '</span>'
}
html += '</span> '
return html
},
/**
* Loop over all recipients in the list and format them using
* all kind of fancy magic.
*
* @param {Object} recipients array of all the recipients
* @returns {String[]} modified list of recipients
*/
_formatShareList: function(recipients) {
var _parent = this
recipients = _.toArray(recipients)
recipients.sort(function(a, b) {
return a.shareWithDisplayName.localeCompare(b.shareWithDisplayName)
})
return $.map(recipients, function(recipient) {
return _parent._formatRemoteShare(recipient.shareWith, recipient.shareWithDisplayName, t('core', 'Shared with'))
})
},
/**
* Marks/unmarks a given file as shared by changing its action icon
* and folder icon.
*
* @param $tr file element to mark as shared
* @param hasShares whether shares are available
* @param hasLink whether link share is available
*/
markFileAsShared: function($tr, hasShares, hasLink) {
var action = $tr.find('.fileactions .action[data-action="Share"]')
var type = $tr.data('type')
var icon = action.find('.icon')
var message, recipients, avatars
var ownerId = $tr.attr('data-share-owner-id')
var owner = $tr.attr('data-share-owner')
var mountType = $tr.attr('data-mounttype')
var shareFolderIcon
var iconClass = 'icon-shared'
action.removeClass('shared-style')
// update folder icon
if (type === 'dir' && (hasShares || hasLink || ownerId)) {
if (typeof mountType !== 'undefined' && mountType !== 'shared-root' && mountType !== 'shared') {
shareFolderIcon = OC.MimeType.getIconUrl('dir-' + mountType)
} else if (hasLink) {
shareFolderIcon = OC.MimeType.getIconUrl('dir-public')
} else {
shareFolderIcon = OC.MimeType.getIconUrl('dir-shared')
}
$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')
$tr.attr('data-icon', shareFolderIcon)
} else if (type === 'dir') {
var isEncrypted = $tr.attr('data-e2eencrypted')
// FIXME: duplicate of FileList._createRow logic for external folder,
// need to refactor the icon logic into a single code path eventually
if (isEncrypted === 'true') {
shareFolderIcon = OC.MimeType.getIconUrl('dir-encrypted')
$tr.attr('data-icon', shareFolderIcon)
} else if (mountType && mountType.indexOf('external') === 0) {
shareFolderIcon = OC.MimeType.getIconUrl('dir-external')
$tr.attr('data-icon', shareFolderIcon)
} else {
shareFolderIcon = OC.MimeType.getIconUrl('dir')
// back to default
$tr.removeAttr('data-icon')
}
$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')
}
// update share action text / icon
if (hasShares || ownerId) {
recipients = $tr.data('share-recipient-data')
action.addClass('shared-style')
avatars = '<span>' + t('core', 'Shared') + '</span>'
// even if reshared, only show "Shared by"
if (ownerId) {
message = t('core', 'Shared by')
avatars = this._formatRemoteShare(ownerId, owner, message)
} else if (recipients) {
avatars = this._formatShareList(recipients)
}
action.html(avatars).prepend(icon)
if (ownerId || recipients) {
var avatarElement = action.find('.avatar')
avatarElement.each(function() {
$(this).avatar($(this).data('username'), 32)
})
action.find('span[title]').tooltip({ placement: 'top' })
}
} else {
action.html('<span class="hidden-visually">' + t('core', 'Shared') + '</span>').prepend(icon)
}
if (hasLink) {
iconClass = 'icon-public'
}
icon.removeClass('icon-shared icon-public').addClass(iconClass)
},
/**
* @param {Array} fileData

View File

@ -30,13 +30,6 @@
},
_dirInfo: undefined,
/** @type OCA.Sharing.ShareTabView */
_shareTab: undefined,
initialize: function(options) {
this._shareTab = options.shareTab
},
render: function(data) {
this._dirInfo = data.dirInfo || null
@ -72,28 +65,10 @@
dirInfo: self._dirInfo
})
})
this._shareTab.on('sharesChanged', function(shareModel) {
var shareTypes = []
var shares = shareModel.getSharesWithCurrentItem()
for (var i = 0; i < shares.length; i++) {
if (shareTypes.indexOf(shares[i].share_type) === -1) {
shareTypes.push(shares[i].share_type)
}
}
if (shareModel.hasLinkShares()) {
shareTypes.push(OC.Share.SHARE_TYPE_LINK)
}
// Since the dirInfo isn't updated we need to do this dark hackery
self._dirInfo.shareTypes = shareTypes
self.render({
dirInfo: self._dirInfo
})
})
OCA.Files.App.fileList.showDetailsView(fileInfoModel, 'sharing')
var path = fileInfoModel.attributes.path + '/' + fileInfoModel.attributes.name
OCA.Files.Sidebar.file = path
OCA.Files.Sidebar.activeTab = 'sharing'
}
})

View File

@ -1,240 +0,0 @@
/**
* @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('OCA.Sharing.ShareBreadCrumbView tests', function() {
var BreadCrumb = OCA.Files.BreadCrumb;
var SharedBreadCrum = OCA.Sharing.ShareBreadCrumbView;
describe('Rendering', function() {
var bc;
var sbc;
var shareTab;
beforeEach(function() {
bc = new BreadCrumb({
getCrumbUrl: function(part, index) {
// for testing purposes
return part.dir + '#' + index;
}
});
shareTab = new OCA.Sharing.ShareTabView();
sbc = new SharedBreadCrum({
shareTab: shareTab
});
bc.addDetailView(sbc);
});
afterEach(function() {
bc = null;
sbc = null;
shareModel = null;
});
it('Do not render in root', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/',
type: 'dir',
name: ''
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(0);
expect(bc.$el.find('.shared').length).toEqual(0);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Render in dir', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir'
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(1);
expect(bc.$el.find('.shared').length).toEqual(0);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Render shared if dir is shared with user', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_USER]
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(1);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Render shared if dir is shared with group', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_GROUP]
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(1);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Render shared if dir is shared by link', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_LINK]
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(0);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(1);
});
it('Render shared if dir is shared by circle', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_CIRCLE]
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(1);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Render shared if dir is shared with remote', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_REMOTE]
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(1);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Render link shared if at least one is a link share', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [
OC.Share.SHARE_TYPE_USER,
OC.Share.SHARE_TYPE_GROUP,
OC.Share.SHARE_TYPE_LINK,
OC.Share.SHARE_TYPE_EMAIL,
OC.Share.SHARE_TYPE_REMOTE,
OC.Share.SHARE_TYPE_CIRCLE
]
});
bc.setDirectoryInfo(dirInfo);
bc.setDirectory('/foo');
bc.render();
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(0);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(1);
});
it('Remove shared status from user share', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_USER]
});
bc.setDirectory('/foo');
bc.setDirectoryInfo(dirInfo);
bc.render();
var mock = sinon.createStubInstance(OCA.Files.FileList);
mock.showDetailsView = function() { };
OCA.Files.App.fileList = mock;
var spy = sinon.spy(mock, 'showDetailsView');
bc.$el.find('.icon-shared').click();
expect(spy.calledOnce).toEqual(true);
var model = sinon.createStubInstance(OC.Share.ShareItemModel);
model.getSharesWithCurrentItem = function() { return [] };
model.hasLinkShares = function() { return false; };
shareTab.trigger('sharesChanged', model);
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(1);
expect(bc.$el.find('.shared').length).toEqual(0);
expect(bc.$el.find('.icon-public').length).toEqual(0);
});
it('Add link share to user share', function() {
var dirInfo = new OC.Files.FileInfo({
id: 42,
path: '/foo',
type: 'dir',
shareTypes: [OC.Share.SHARE_TYPE_USER]
});
bc.setDirectory('/foo');
bc.setDirectoryInfo(dirInfo);
bc.render();
var mock = sinon.createStubInstance(OCA.Files.FileList);
mock.showDetailsView = function() { };
OCA.Files.App.fileList = mock;
var spy = sinon.spy(mock, 'showDetailsView');
bc.$el.find('.icon-shared').click();
expect(spy.calledOnce).toEqual(true);
var model = sinon.createStubInstance(OC.Share.ShareItemModel);
model.getSharesWithCurrentItem = function() { return [
{share_type: OC.Share.SHARE_TYPE_USER}
] };
model.hasLinkShares = function() { return true; };
shareTab.trigger('sharesChanged', model);
expect(bc.$el.hasClass('breadcrumb')).toEqual(true);
expect(bc.$el.find('.icon-shared').length).toEqual(0);
expect(bc.$el.find('.shared').length).toEqual(1);
expect(bc.$el.find('.icon-public').length).toEqual(1);
});
});
});

View File

@ -1,784 +0,0 @@
/*
* Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
*
* This file is licensed under the Affero General Public License version 3
* or later.
*
* See the COPYING-README file.
*
*/
describe('OCA.Sharing.FileList tests', function() {
var testFiles, alertStub, notificationStub, fileList;
beforeEach(function() {
alertStub = sinon.stub(OC.dialogs, 'alert');
notificationStub = sinon.stub(OC.Notification, 'show');
// init parameters and test table elements
$('#testArea').append(
'<div id="app-content-container">' +
// init horrible parameters
'<input type="hidden" id="dir" value="/"></input>' +
'<input type="hidden" id="permissions" value="31"></input>' +
// dummy controls
'<div id="controls">' +
' <div class="actions creatable"></div>' +
' <div class="notCreatable"></div>' +
'</div>' +
// dummy table
// TODO: at some point this will be rendered by the fileList class itself!
'<table id="filestable" class="list-container view-grid">' +
'<thead><tr>' +
'<th id="headerName" class="hidden column-name">' +
'<input type="checkbox" id="select_all_files" class="select-all">' +
'<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' +
'<span class="selectedActions hidden">' +
'</th>' +
'<th class="hidden column-mtime">' +
'<a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a>' +
'</th>' +
'<th class="column-expiration">' +
'<a class="columntitle"><span>Expiration date</span></a>' +
'</th>' +
'</tr></thead>' +
'<tbody id="fileList"></tbody>' +
'<tfoot></tfoot>' +
'</table>' +
'<div id="emptycontent">Empty content message</div>' +
'</div>'
);
OC.Plugins.register('OCA.Files.FileList', OCA.Files.TagsPlugin);
});
afterEach(function() {
testFiles = undefined;
fileList.destroy();
fileList = undefined;
notificationStub.restore();
alertStub.restore();
});
describe('loading file list for incoming shares', function() {
var ocsResponse;
var ocsResponseRemote;
beforeEach(function() {
fileList = new OCA.Sharing.FileList(
$('#app-content-container'), {
sharedWithUser: true
}
);
OCA.Sharing.Util.attach(fileList);
fileList.reload();
/* jshint camelcase: false */
ocsResponse = {
ocs: {
meta: {
status: 'ok',
statuscode: 100,
message: null
},
data: [{
id: 7,
item_type: 'file',
item_source: 49,
item_target: '/49',
file_source: 49,
file_target: '/local path/local name.txt',
path: 'files/something shared.txt',
permissions: 31,
stime: 11111,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
tags: [OC.TAG_FAVORITE],
mimetype: 'text/plain',
uid_owner: 'user2',
displayname_owner: 'User Two'
}]
}
};
/* jshint camelcase: false */
ocsResponseRemote = {
ocs: {
meta: {
status: 'ok',
statuscode: 100,
message: null
},
data: [{
id: 8,
remote: 'https://foo.bar/',
remote_id: 42,
share_token: 'abc',
name: '/a.txt',
owner: 'user3',
user: 'user1',
mountpoint: '/b.txt',
mountpoint_hash: 'def',
accepted: 1,
mimetype: 'text/plain',
mtime: 22222,
permissions: 31,
type: 'file',
file_id: 1337
}]
}
};
});
it('render file shares', function() {
expect(fakeServer.requests.length).toEqual(2);
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=true&include_tags=true'
);
expect(fakeServer.requests[1].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'remote_shares?format=json&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
fakeServer.requests[1].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponseRemote)
);
var $rows = fileList.$el.find('tbody tr');
expect($rows.length).toEqual(2);
var $tr = $rows.eq(0);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-owner')).toEqual('User Two');
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/remote.php/webdav/local%20path/local%20name.txt'
);
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
$tr = $rows.eq(1);
expect($tr.attr('data-id')).toEqual('1337');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('b.txt');
expect($tr.attr('data-path')).toEqual('');
expect($tr.attr('data-size')).not.toBeDefined();
expect(parseInt($tr.attr('data-permissions'), 10))
.toEqual(OC.PERMISSION_ALL); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
expect($tr.attr('data-mtime')).toEqual('22222000');
expect($tr.attr('data-share-owner')).toEqual('user3@foo.bar/');
expect($tr.attr('data-share-id')).toEqual('8');
expect($tr.attr('data-favorite')).not.toBeDefined();
expect($tr.attr('data-tags')).toEqual('');
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/remote.php/webdav/b.txt'
);
expect($tr.find('.nametext').text().trim()).toEqual('b.txt');
});
it('render folder shares', function() {
/* jshint camelcase: false */
ocsResponse.ocs.data[0] = _.extend(ocsResponse.ocs.data[0], {
item_type: 'folder',
file_target: '/local path/local name',
path: 'files/something shared',
});
ocsResponseRemote.ocs.data[0] = _.extend(ocsResponseRemote.ocs.data[0], {
type: 'dir',
mimetype: 'httpd/unix-directory',
name: '/a',
mountpoint: '/b'
});
expect(fakeServer.requests.length).toEqual(2);
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=true&include_tags=true'
);
expect(fakeServer.requests[1].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'remote_shares?format=json&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
fakeServer.requests[1].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponseRemote)
);
var $rows = fileList.$el.find('tbody tr');
expect($rows.length).toEqual(2);
var $tr = $rows.eq(0);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('dir');
expect($tr.attr('data-file')).toEqual('local name');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-owner')).toEqual('User Two');
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/index.php/apps/files' +
'?dir=/local%20path/local%20name'
);
expect($tr.find('.nametext').text().trim()).toEqual('local name');
$tr = $rows.eq(1);
expect($tr.attr('data-id')).toEqual('1337');
expect($tr.attr('data-type')).toEqual('dir');
expect($tr.attr('data-file')).toEqual('b');
expect($tr.attr('data-path')).toEqual('');
expect($tr.attr('data-size')).not.toBeDefined();
expect(parseInt($tr.attr('data-permissions'), 10))
.toEqual(OC.PERMISSION_ALL); // read and delete
expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
expect($tr.attr('data-mtime')).toEqual('22222000');
expect($tr.attr('data-share-owner')).toEqual('user3@foo.bar/');
expect($tr.attr('data-share-id')).toEqual('8');
expect($tr.attr('data-favorite')).not.toBeDefined();
expect($tr.attr('data-tags')).toEqual('');
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/index.php/apps/files' +
'?dir=/b'
);
expect($tr.find('.nametext').text().trim()).toEqual('b');
});
});
describe('loading file list for outgoing shares', function() {
var ocsResponse;
beforeEach(function() {
fileList = new OCA.Sharing.FileList(
$('#app-content-container'), {
sharedWithUser: false
}
);
OCA.Sharing.Util.attach(fileList);
fileList.reload();
/* jshint camelcase: false */
ocsResponse = {
ocs: {
meta: {
status: 'ok',
statuscode: 100,
message: null
},
data: [{
id: 7,
item_type: 'file',
item_source: 49,
file_source: 49,
path: '/local path/local name.txt',
permissions: 27,
stime: 11111,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user2',
share_with_displayname: 'User Two',
tags: [OC.TAG_FAVORITE],
mimetype: 'text/plain',
uid_owner: 'user1',
displayname_owner: 'User One'
}]
}
};
});
it('render file shares', function() {
var request;
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=false&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0);
expect($rows.length).toEqual(1);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-owner')).not.toBeDefined();
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/remote.php/webdav/local%20path/local%20name.txt'
);
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
});
it('render folder shares', function() {
var request;
/* jshint camelcase: false */
ocsResponse.ocs.data[0] = _.extend(ocsResponse.ocs.data[0], {
item_type: 'folder',
path: '/local path/local name',
});
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=false&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0);
expect($rows.length).toEqual(1);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('dir');
expect($tr.attr('data-file')).toEqual('local name');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-owner')).not.toBeDefined();
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/index.php/apps/files' +
'?dir=/local%20path/local%20name'
);
expect($tr.find('.nametext').text().trim()).toEqual('local name');
});
it('render link shares', function() {
/* jshint camelcase: false */
var request;
ocsResponse.ocs.data[0] = {
id: 7,
item_type: 'file',
item_source: 49,
file_source: 49,
path: '/local path/local name.txt',
permissions: 1,
stime: 11111,
share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null,
token: 'abc',
mimetype: 'text/plain',
uid_owner: 'user1',
displayname_owner: 'User One',
tags: [OC.TAG_FAVORITE]
};
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=false&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0);
expect($rows.length).toEqual(1);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-owner')).not.toBeDefined();
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() + '/remote.php/webdav/local%20path/local%20name.txt'
);
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
});
it('groups link shares with regular shares', function() {
/* jshint camelcase: false */
var request;
// link share
ocsResponse.ocs.data.push({
id: 8,
item_type: 'file',
item_source: 49,
file_source: 49,
path: '/local path/local name.txt',
permissions: 1,
stime: 11111,
share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null,
token: 'abc',
mimetype: 'text/plain',
uid_owner: 'user1',
displayname_owner: 'User One',
tags: [OC.TAG_FAVORITE],
});
// another share of the same file
ocsResponse.ocs.data.push({
id: 9,
item_type: 'file',
item_source: 49,
file_source: 49,
path: '/local path/local name.txt',
permissions: 27,
stime: 22222,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user3',
share_with_displayname: 'User Three',
mimetype: 'text/plain',
uid_owner: 'user1',
displayname_owner: 'User One'
});
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=false&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0);
expect($rows.length).toEqual(1);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
// always use the most recent stime
expect($tr.attr('data-mtime')).toEqual('22222000');
expect($tr.attr('data-share-owner')).not.toBeDefined();
expect($tr.attr('data-share-id')).toEqual('7,8,9');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() + '/remote.php/webdav/local%20path/local%20name.txt'
);
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
});
});
describe('loading file list for link shares', function() {
var ocsResponse;
beforeEach(function() {
fileList = new OCA.Sharing.FileList(
$('#app-content-container'), {
linksOnly: true
}
);
OCA.Sharing.Util.attach(fileList);
fileList.reload();
var expirationDateInADay = moment()
.add(1, 'days').format('YYYY-MM-DD HH:mm:ss');
/* jshint camelcase: false */
ocsResponse = {
ocs: {
meta: {
status: 'ok',
statuscode: 100,
message: null
},
data: [{
id: 7,
item_type: 'file',
item_source: 49,
file_source: 49,
path: '/local path/local name.txt',
permissions: 1,
stime: 11111,
expiration: null,
share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null,
token: 'abc',
mimetype: 'text/plain',
uid_owner: 'user1',
displayname_owner: 'User One',
tags: [OC.TAG_FAVORITE]
},{
id: 8,
item_type: 'file',
item_source: 50,
file_source: 50,
path: '/local path2/local name2.txt',
permissions: 1,
stime: 11112,
expiration: expirationDateInADay,
share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null,
token: 'abcd',
mimetype: 'text/plain2',
uid_owner: 'user2',
displayname_owner: 'User One2'
}]
}
};
});
it('render only link shares', function() {
/* jshint camelcase: false */
var request;
ocsResponse.ocs.data.push({
// non-link share
id: 8,
item_type: 'file',
item_source: 49,
file_source: 49,
path: '/local path/local name.txt',
permissions: 27,
stime: 11111,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user2',
share_with_displayname: 'User Two',
mimetype: 'text/plain',
uid_owner: 'user1',
displayname_owner: 'User One',
tags: [OC.TAG_FAVORITE]
});
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=false&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
// only renders the link share entries
var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0);
expect($rows.length).toEqual(2);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-recipient-data')).not.toBeDefined();
expect($tr.attr('data-share-owner')).not.toBeDefined();
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() + '/remote.php/webdav/local%20path/local%20name.txt'
);
expect($tr.attr('data-expiration')).toEqual('0');
expect($tr.find('td:last-child span').text()).toEqual('');
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
// change to next row
$tr = $rows.eq(1);
expect($tr.attr('data-id')).toEqual('50');
expect($tr.attr('data-file')).toEqual('local name2.txt');
expect($tr.attr('data-expiration')).not.toEqual('0');
expect($tr.attr('data-favorite')).not.toBeDefined();
expect($tr.attr('data-tags')).toEqual('');
expect($tr.find('td:last-child span').text()).toEqual('in a day');
});
it('does not show virtual token recipient as recipient when password was set', function() {
/* jshint camelcase: false */
var request;
// when a password is set, share_with contains an auth token
ocsResponse.ocs.data[0].share_with = 'abc01234/01234abc';
ocsResponse.ocs.data[0].share_with_displayname = 'abc01234/01234abc';
expect(fakeServer.requests.length).toEqual(1);
request = fakeServer.requests[0];
expect(request.url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1') +
'shares?format=json&shared_with_me=false&include_tags=true'
);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(ocsResponse)
);
// only renders the link share entry
var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0);
expect($rows.length).toEqual(2);
expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt');
expect($tr.attr('data-path')).toEqual('/local path');
expect($tr.attr('data-size')).not.toBeDefined();
expect($tr.attr('data-permissions')).toEqual('31'); // read and delete
expect($tr.attr('data-mime')).toEqual('text/plain');
expect($tr.attr('data-mtime')).toEqual('11111000');
expect($tr.attr('data-share-recipient-data')).not.toBeDefined();
expect($tr.attr('data-share-owner')).not.toBeDefined();
expect($tr.attr('data-share-id')).toEqual('7');
expect($tr.attr('data-favorite')).toEqual('true');
expect($tr.attr('data-tags')).toEqual(OC.TAG_FAVORITE);
expect($tr.find('a.name').attr('href')).toEqual(
OC.getRootPath() +
'/remote.php/webdav/local%20path/local%20name.txt');
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
});
});
describe('setting share permissions for files', function () {
beforeEach(function () {
var $content = $('<div id="content"></div>');
$('#testArea').append($content);
// dummy file list
var $div = $(
'<div>' +
'<table id="filestable" class="list-container view-grid">' +
'<thead></thead>' +
'<tbody id="fileList"></tbody>' +
'</table>' +
'</div>');
$('#content').append($div);
fileList = new OCA.Files.FileList($div);
OCA.Sharing.Util.attach(fileList);
});
it('external storage root folder', function () {
var $tr;
OC.Share.statuses = {1: {link: false, path: '/subdir'}};
fileList.setFiles([{
id: 1,
type: 'dir',
name: 'One.txt',
path: '/subdir',
mimetype: 'text/plain',
size: 12,
permissions: OC.PERMISSION_READ,
sharePermissions: OC.PERMISSION_READ,
etag: 'abc',
shareOwner: 'User One',
recipients: 'User Two',
mountType: 'external-root',
sharePermissions: OC.PERMISSION_READ,
}]);
$tr = fileList.$el.find('tr:first');
expect(parseInt($tr.attr('data-share-permissions'), 10)).toEqual(OC.PERMISSION_READ);
});
it('external storage root folder reshare', function () {
var $tr;
OC.Share.statuses = {1: {link: false, path: '/subdir'}};
fileList.setFiles([{
id: 1,
type: 'dir',
name: 'One.txt',
path: '/subdir',
mimetype: 'text/plain',
size: 12,
permissions: OC.PERMISSION_READ + OC.PERMISSION_SHARE,
sharePermissions: OC.PERMISSION_READ + OC.PERMISSION_SHARE,
etag: 'abc',
shareOwner: 'User One',
recipients: 'User Two',
mountType: 'external-root',
sharePermissions: OC.PERMISSION_READ | OC.PERMISSION_SHARE,
}]);
$tr = fileList.$el.find('tr:first');
expect(parseInt($tr.attr('data-share-permissions'), 10)).toEqual(OC.PERMISSION_READ + OC.PERMISSION_SHARE);
});
it('external storage root folder file', function () {
var $tr;
OC.Share.statuses = {1: {link: false, path: '/subdir'}};
fileList.setFiles([{
id: 1,
type: 'file',
name: 'One.txt',
path: '/subdir',
mimetype: 'text/plain',
size: 12,
permissions: OC.PERMISSION_READ,
sharePermissions: OC.PERMISSION_READ,
etag: 'abc',
shareOwner: 'User One',
recipients: 'User Two',
mountType: 'external-root'
}]);
$tr = fileList.$el.find('tr:first');
expect(parseInt($tr.attr('data-share-permissions'), 10))
.toEqual(OC.PERMISSION_READ);
});
});
});

View File

@ -1,371 +0,0 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('OC.Share tests', function() {
describe('markFileAsShared', function() {
var $file;
var tooltipStub;
beforeEach(function() {
tooltipStub = sinon.stub($.fn, 'tooltip');
$file = $('<tr><td class="filename"><div class="thumbnail"></div><span class="name">File name</span></td></tr>');
$file.find('.filename').append(
'<span class="fileactions">' +
'<a href="#" class="action action-share" data-action="Share">' +
'<img></img><span> Share</span>' +
'</a>' +
'</span>'
);
});
afterEach(function() {
$file = null;
tooltipStub.restore();
});
describe('displaying the share owner', function() {
function checkOwner(input, output, title) {
var $action;
$file.attr('data-share-owner', input);
$file.attr('data-share-owner-id', input);
OC.Share.markFileAsShared($file);
$action = $file.find('.action-share>span').parent();
expect($action.text().trim()).toEqual(output);
if (_.isString(title)) {
expect($action.find('.remoteAddress').attr('title')).toEqual(title);
} else {
expect($action.find('.remoteAddress').attr('title')).not.toBeDefined();
}
expect(tooltipStub.calledOnce).toEqual(true);
tooltipStub.reset();
}
it('displays the local share owner with "Shared by" prefix', function() {
checkOwner('User One', 'Shared by User One', null);
});
it('displays the user name part of a remote share owner', function() {
checkOwner(
'User One@someserver.com',
'User One@…',
'Shared by User One@someserver.com'
);
checkOwner(
'User One@someserver.com/',
'User One@…',
'Shared by User One@someserver.com'
);
checkOwner(
'User One@someserver.com/root/of/owncloud',
'User One@…',
'Shared by User One@someserver.com'
);
});
it('displays the user name part with domain of a remote share owner', function() {
checkOwner(
'User One@example.com@someserver.com',
'User One@example.com',
'Shared by User One@example.com@someserver.com'
);
checkOwner(
'User One@example.com@someserver.com/',
'User One@example.com',
'Shared by User One@example.com@someserver.com'
);
checkOwner(
'User One@example.com@someserver.com/root/of/owncloud',
'User One@example.com',
'Shared by User One@example.com@someserver.com'
);
});
});
describe('displaying the folder icon', function() {
function checkIcon(expectedImage) {
var imageUrl = OC.TestUtil.getImageUrl($file.find('.filename .thumbnail'));
expectedIcon = OC.imagePath('core', expectedImage);
expect(imageUrl).toEqual(expectedIcon);
}
it('shows a plain folder icon for non-shared folders', function() {
$file.attr('data-type', 'dir');
OC.Share.markFileAsShared($file);
checkIcon('filetypes/folder');
});
it('shows a shared folder icon for folders shared with another user', function() {
$file.attr('data-type', 'dir');
OC.Share.markFileAsShared($file, true);
checkIcon('filetypes/folder-shared');
});
it('shows a shared folder icon for folders shared with the current user', function() {
$file.attr('data-type', 'dir');
$file.attr('data-share-owner', 'someoneelse');
$file.attr('data-share-owner-id', 'someoneelse');
OC.Share.markFileAsShared($file);
checkIcon('filetypes/folder-shared');
});
it('shows a link folder icon for folders shared with link', function() {
$file.attr('data-type', 'dir');
OC.Share.markFileAsShared($file, false, true);
checkIcon('filetypes/folder-public');
});
it('shows a link folder icon for folders shared with both link and another user', function() {
$file.attr('data-type', 'dir');
OC.Share.markFileAsShared($file, true, true);
checkIcon('filetypes/folder-public');
});
it('shows a link folder icon for folders reshared with link', function() {
$file.attr('data-type', 'dir');
$file.attr('data-share-owner', 'someoneelse');
OC.Share.markFileAsShared($file, false, true);
checkIcon('filetypes/folder-public');
});
it('shows external storage icon if external mount point', function() {
$file.attr('data-type', 'dir');
$file.attr('data-mountType', 'external');
OC.Share.markFileAsShared($file, false, false);
checkIcon('filetypes/folder-external');
});
it('shows encrypted icon if encrypted folder', function() {
$file.attr('data-type', 'dir');
$file.attr('data-e2eencrypted', true);
OC.Share.markFileAsShared($file, false, false);
checkIcon('filetypes/folder-encrypted');
});
});
describe('displaying the recipients', function() {
function checkRecipients(input, output, title) {
var $action;
$file.attr('data-share-recipient-data', JSON.stringify(input));
OC.Share.markFileAsShared($file, true);
$action = $file.find('.action-share>span').parent();
expect($action.text().trim()).toEqual(output);
if (_.isString(title)) {
expect($action.find('.remoteAddress').attr('title')).toEqual(title);
} else if (_.isArray(title)) {
var tooltips = $action.find('.remoteAddress');
expect(tooltips.length).toEqual(title.length);
tooltips.each(function(i) {
expect($(this).attr('title')).toEqual(title[i]);
});
} else {
expect($action.find('.remoteAddress').attr('title')).not.toBeDefined();
}
expect(tooltipStub.calledOnce).toEqual(true);
tooltipStub.reset();
}
it('displays the local share owner as is', function() {
var input = {
0: {
shareWith: 'User One',
shareWithDisplayName: 'User One'
}
};
checkRecipients(input, 'Shared with User One', null);
});
it('displays the user name part of a remote recipient', function() {
var input = {
0: {
shareWith: 'User One@someserver.com',
shareWithDisplayName: 'User One@someserver.com'
}
};
checkRecipients(
input,
'User One@…',
'Shared with User One@someserver.com'
);
input = {
0: {
shareWith: 'User One@someserver.com/',
shareWithDisplayName: 'User One@someserver.com/'
}
};
checkRecipients(
input,
'User One@…',
'Shared with User One@someserver.com'
);
input = {
0: {
shareWith: 'User One@someserver.com/root/of/nextcloud',
shareWithDisplayName: 'User One@someserver.com/root/of/nextcloud'
}
};
checkRecipients(
input,
'User One@…',
'Shared with User One@someserver.com'
);
});
it('displays the user name part with domain of a remote share owner', function() {
var input = {
0: {
shareWith: 'User One@example.com@someserver.com',
shareWithDisplayName: 'User One@example.com@someserver.com'
}
};
checkRecipients(
input,
'User One@example.com',
'Shared with User One@example.com@someserver.com'
);
input = {
0: {
shareWith: 'User One@example.com@someserver.com/',
shareWithDisplayName: 'User One@example.com@someserver.com/'
}
};
checkRecipients(
input,
'User One@example.com',
'Shared with User One@example.com@someserver.com'
);
input = {
0: {
shareWith: 'User One@example.com@someserver.com/root/of/nextcloud',
shareWithDisplayName: 'User One@example.com@someserver.com/root/of/nextcloud'
}
};
checkRecipients(
input,
'User One@example.com',
'Shared with User One@example.com@someserver.com'
);
});
it('display multiple remote recipients', function() {
var input = {
0: {
shareWith: 'One@someserver.com',
shareWithDisplayName: 'One@someserver.com'
},
1: {
shareWith: 'two@otherserver.com',
shareWithDisplayName: 'two@otherserver.com'
}
};
checkRecipients(
input,
'One@… two@…',
['Shared with One@someserver.com', 'Shared with two@otherserver.com']
);
input = {
0: {
shareWith: 'One@someserver.com/',
shareWithDisplayName: 'One@someserver.com/'
},
1: {
shareWith: 'two@someserver.com',
shareWithDisplayName: 'two@someserver.com'
}
};
checkRecipients(
input,
'One@… two@…',
['Shared with One@someserver.com', 'Shared with two@otherserver.com']
);
input = {
0: {
shareWith: 'One@someserver.com/root/of/nextcloud',
shareWithDisplayName: 'One@someserver.com/root/of/nextcloud'
},
1: {
shareWith: 'two@someserver.com',
shareWithDisplayName: 'two@someserver.com'
}
};
checkRecipients(
input,
'One@… two@…',
['Shared with One@someserver.com', 'Shared with two@otherserver.com']
);
});
it('display mixed recipients', function() {
checkRecipients(
{
0: {
shareWith: 'One',
shareWithDisplayName: 'One'
},
1: {
shareWith: 'two@otherserver.com',
shareWithDisplayName: 'two@otherserver.com'
}
},
'Shared with One two@…',
['Shared with two@otherserver.com']
);
});
it('display multiple with divergent displaynames', function() {
var recipients = {
0: {
shareWith: 'One',
shareWithDisplayName: 'Yoko Ono',
_output: 'Shared with Yoko Ono'
},
1: {
shareWith: 'two@otherserver.com',
shareWithDisplayName: 'two@othererver.com',
_output: 'two@…'
},
2: {
shareWith: 'Three',
shareWithDisplayName: 'Green, Mina',
_output: 'Shared with Green, Mina'
}
};
// we cannot assume the locale, also because PhantomJS has a bug.
var sortArray = _.toArray(recipients)
.sort(function(a, b) {
return a.shareWithDisplayName.localeCompare(b.shareWithDisplayName);
});
var sortedOutput = _.map(sortArray, function(recipient) {
return recipient._output;
}).join(' ');
checkRecipients(
recipients,
sortedOutput,
['Shared with two@otherserver.com']
);
});
});
});
});

View File

@ -1,349 +0,0 @@
/**
*
* @copyright Copyright (c) 2015, Tom Needham (tom@owncloud.com)
* @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('OC.Share.ShareDialogLinkShareView', function () {
var configModel;
var shareModel;
var view;
beforeEach(function () {
var fileInfoModel = new OCA.Files.FileInfoModel({
id: 123,
name: 'shared_file_name.txt',
path: '/subdir',
size: 100,
mimetype: 'text/plain',
permissions: OC.PERMISSION_ALL,
sharePermissions: OC.PERMISSION_ALL
});
var attributes = {
itemType: fileInfoModel.isDirectory() ? 'folder' : 'file',
itemSource: fileInfoModel.get('id'),
possiblePermissions: OC.PERMISSION_ALL,
permissions: OC.PERMISSION_ALL
};
configModel = new OC.Share.ShareConfigModel({
enforcePasswordForPublicLink: false,
isResharingAllowed: true,
isDefaultExpireDateEnabled: false,
isDefaultExpireDateEnforced: false,
defaultExpireDate: 7
});
sinon.stub(configModel, 'isShareWithLinkAllowed');
shareModel = new OC.Share.ShareItemModel(attributes, {
configModel: configModel,
fileInfoModel: fileInfoModel
});
view = new OC.Share.ShareDialogLinkShareView({
configModel: configModel,
model: shareModel
});
});
afterEach(function () {
view.remove();
configModel.isShareWithLinkAllowed.restore();
});
describe('hide download', function () {
var $hideDownloadCheckbox;
var $workingIcon;
beforeEach(function () {
// Needed to render the view
configModel.isShareWithLinkAllowed.returns(true);
shareModel.set({
linkShares: [{
id: 123
}]
});
view.render();
$hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox');
$workingIcon = $hideDownloadCheckbox.prev('.icon-loading-small');
sinon.stub(shareModel, 'saveLinkShare');
expect($workingIcon.hasClass('hidden')).toBeTruthy();
});
afterEach(function () {
shareModel.saveLinkShare.restore();
});
it('is shown if the share is a file', function() {
expect($hideDownloadCheckbox.length).toBeTruthy();
});
it('is not shown if the share is a folder', function() {
shareModel.fileInfoModel.set('mimetype', 'httpd/unix-directory');
// Setting the item type also triggers the rendering
shareModel.set({
itemType: 'folder'
});
$hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox');
expect($hideDownloadCheckbox.length).toBeTruthy();
});
it('checkbox is checked when the setting is enabled', function () {
shareModel.set({
linkShares: [{
id: 123,
hideDownload: true
}]
});
view.render();
$hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox');
expect($hideDownloadCheckbox.is(':checked')).toEqual(true);
});
it('checkbox is not checked when the setting is disabled', function () {
expect($hideDownloadCheckbox.is(':checked')).toEqual(false);
});
it('enables the setting if clicked when unchecked', function () {
// Simulate the click by checking the checkbox and then triggering
// the "change" event.
$hideDownloadCheckbox.prop('checked', true);
$hideDownloadCheckbox.change();
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ hideDownload: true, cid: 123 }).calledOnce).toBeTruthy();
});
it('disables the setting if clicked when checked', function () {
shareModel.set({
linkShares: [{
id: 123,
hideDownload: true
}]
});
view.render();
$hideDownloadCheckbox = view.$el.find('.hideDownloadCheckbox');
$workingIcon = $hideDownloadCheckbox.prev('.icon-loading-small');
// Simulate the click by unchecking the checkbox and then triggering
// the "change" event.
$hideDownloadCheckbox.prop('checked', false);
$hideDownloadCheckbox.change();
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ hideDownload: false, cid: 123 }).calledOnce).toBeTruthy();
});
});
describe('onPasswordEntered', function () {
var $passwordText;
var $workingIcon;
beforeEach(function () {
// Needed to render the view
configModel.isShareWithLinkAllowed.returns(true);
shareModel.set({
linkShares: [{
id: 123,
password: 'password'
}]
});
view.render();
$passwordText = view.$el.find('.linkPassText');
$workingIcon = view.$el.find('.linkPassMenu .icon-loading-small');
sinon.stub(shareModel, 'saveLinkShare');
expect($passwordText.hasClass('hidden')).toBeFalsy();
expect($workingIcon.hasClass('hidden')).toBeTruthy();
$passwordText.val('myPassword');
});
afterEach(function () {
shareModel.saveLinkShare.restore();
});
it('shows the working icon when called', function () {
view.onPasswordEntered({target: view.$el.find('.linkPassText')});
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword', cid: 123 }).calledOnce).toBeTruthy();
});
it('hides the working icon when saving the password succeeds', function () {
view.onPasswordEntered({target: view.$el.find('.linkPassText')});
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword', cid: 123 }).calledOnce).toBeTruthy();
shareModel.saveLinkShare.yieldTo("complete", [shareModel]);
expect($workingIcon.hasClass('hidden')).toBeTruthy();
});
it('hides the working icon when saving the password fails', function () {
view.onPasswordEntered({target: view.$el.find('.linkPassText')});
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ password: 'myPassword', cid: 123 }).calledOnce).toBeTruthy();
shareModel.saveLinkShare.yieldTo("complete", [shareModel]);
shareModel.saveLinkShare.yieldTo("error", [shareModel, "The error message"]);
expect($workingIcon.hasClass('hidden')).toBeTruthy();
});
});
describe('protect password by Talk', function () {
var $passwordByTalkCheckbox;
var $workingIcon;
beforeEach(function () {
// Needed to render the view
configModel.isShareWithLinkAllowed.returns(true);
// "Enable" Talk
OC.appswebroots['spreed'] = OC.getRootPath() + '/apps/files/';
shareModel.set({
linkShares: [{
id: 123,
password: 'password'
}]
});
view.render();
$passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox');
$workingIcon = $passwordByTalkCheckbox.prev('.icon-loading-small');
sinon.stub(shareModel, 'saveLinkShare');
expect($workingIcon.hasClass('hidden')).toBeTruthy();
});
afterEach(function () {
shareModel.saveLinkShare.restore();
});
it('is shown if Talk is enabled and there is a password set', function() {
expect($passwordByTalkCheckbox.length).toBeTruthy();
});
it('is not shown if Talk is enabled but there is no password set', function() {
// Changing the password value also triggers the rendering
shareModel.set({
linkShares: [{
id: 123
}]
});
$passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox');
expect($passwordByTalkCheckbox.length).toBeFalsy();
});
it('is not shown if there is a password set but Talk is not enabled', function() {
// "Disable" Talk
delete OC.appswebroots['spreed'];
view.render();
$passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox');
expect($passwordByTalkCheckbox.length).toBeFalsy();
});
it('checkbox is checked when the setting is enabled', function () {
shareModel.set({
linkShares: [{
id: 123,
password: 'password',
sendPasswordByTalk: true
}]
});
view.render();
$passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox');
expect($passwordByTalkCheckbox.is(':checked')).toEqual(true);
});
it('checkbox is not checked when the setting is disabled', function () {
expect($passwordByTalkCheckbox.is(':checked')).toEqual(false);
});
it('enables the setting if clicked when unchecked', function () {
// Simulate the click by checking the checkbox and then triggering
// the "change" event.
$passwordByTalkCheckbox.prop('checked', true);
$passwordByTalkCheckbox.change();
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ sendPasswordByTalk: true, cid: 123 }).calledOnce).toBeTruthy();
});
it('disables the setting if clicked when checked', function () {
shareModel.set({
linkShares: [{
id: 123,
password: 'password',
sendPasswordByTalk: true
}]
});
view.render();
$passwordByTalkCheckbox = view.$el.find('.passwordByTalkCheckbox');
$workingIcon = $passwordByTalkCheckbox.prev('.icon-loading-small');
// Simulate the click by unchecking the checkbox and then triggering
// the "change" event.
$passwordByTalkCheckbox.prop('checked', false);
$passwordByTalkCheckbox.change();
expect($workingIcon.hasClass('hidden')).toBeFalsy();
expect(shareModel.saveLinkShare.withArgs({ sendPasswordByTalk: false, cid: 123 }).calledOnce).toBeTruthy();
});
});
});

View File

@ -1,242 +0,0 @@
/**
* ownCloud
*
* @author Tom Needham
* @copyright 2015 Tom Needham <tom@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('OC.Share.ShareDialogShareeListView', function () {
var oldCurrentUser;
var fileInfoModel;
var configModel;
var shareModel;
var listView;
var updateShareStub;
beforeEach(function () {
/* jshint camelcase:false */
oldAppConfig = _.extend({}, OC.appConfig.core);
OC.appConfig.core.enforcePasswordForPublicLink = false;
fileInfoModel = new OCA.Files.FileInfoModel({
id: 123,
name: 'shared_file_name.txt',
path: '/subdir',
size: 100,
mimetype: 'text/plain',
permissions: 31,
sharePermissions: 31
});
var attributes = {
itemType: fileInfoModel.isDirectory() ? 'folder' : 'file',
itemSource: fileInfoModel.get('id'),
possiblePermissions: 31,
permissions: 31
};
shareModel = new OC.Share.ShareItemModel(attributes, {
configModel: configModel,
fileInfoModel: fileInfoModel
});
configModel = new OC.Share.ShareConfigModel({
enforcePasswordForPublicLink: false,
isResharingAllowed: true,
isDefaultExpireDateEnabled: false,
isDefaultExpireDateEnforced: false,
defaultExpireDate: 7
});
listView = new OC.Share.ShareDialogShareeListView({
configModel: configModel,
model: shareModel
});
// required for proper event propagation when simulating clicks in some cases (jquery bugs)
$('#testArea').append(listView.$el);
shareModel.set({
linkShares: []
});
oldCurrentUser = OC.currentUser;
OC.currentUser = 'user0';
updateShareStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'updateShare');
});
afterEach(function () {
OC.currentUser = oldCurrentUser;
/* jshint camelcase:false */
OC.appConfig.core = oldAppConfig;
listView.remove();
updateShareStub.restore();
});
describe('Sets correct initial checkbox state', function () {
it('marks edit box as unchecked for file shares without edit permissions', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'file'
}]);
listView.render();
expect(listView.$el.find("input[name='edit']").is(':not(:checked)')).toEqual(true);
});
it('marks edit box as checked for file shares', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1 | OC.PERMISSION_UPDATE,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'file'
}]);
listView.render();
expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true);
});
it('marks edit box as indeterminate when only some permissions are given', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1 | OC.PERMISSION_UPDATE,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'folder'
}]);
shareModel.set('itemType', 'folder');
listView.render();
expect(listView.$el.find("input[name='edit']").is(':indeterminate')).toEqual(true);
});
it('marks edit box as indeterminate when only some permissions are given for sharee with special characters', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1 | OC.PERMISSION_UPDATE,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user _.@-\'',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'folder'
}]);
shareModel.set('itemType', 'folder');
listView.render();
expect(listView.$el.find("input[name='edit']").is(':indeterminate')).toEqual(true);
});
it('Checks edit box when all permissions are given', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1 | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'folder'
}]);
shareModel.set('itemType', 'folder');
listView.render();
expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true);
});
it('Checks edit box when all permissions are given for sharee with special characters', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1 | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user _.@-\'',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'folder'
}]);
shareModel.set('itemType', 'folder');
listView.render();
expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true);
});
});
describe('Manages checkbox events correctly', function () {
it('Checks cruds boxes when edit box checked', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
}]);
shareModel.set('itemType', 'folder');
listView.render();
listView.$el.find("input[name='edit']").click();
expect(listView.$el.find("input[name='update']").is(':checked')).toEqual(true);
expect(updateShareStub.calledOnce).toEqual(true);
});
it('marks edit box as indeterminate when some of create/update/delete are checked', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'folder'
}]);
shareModel.set('itemType', 'folder');
listView.render();
listView.$el.find("input[name='update']").click();
expect(listView.$el.find("input[name='edit']").is(':indeterminate')).toEqual(true);
expect(updateShareStub.calledOnce).toEqual(true);
});
it('Checks edit box when all of create/update/delete are checked', function () {
shareModel.set('shares', [{
id: 100,
item_source: 123,
permissions: 1 | OC.PERMISSION_CREATE | OC.PERMISSION_DELETE,
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One',
uid_owner: OC.getCurrentUser().uid,
itemType: 'folder'
}]);
shareModel.set('itemType', 'folder');
listView.render();
listView.$el.find("input[name='update']").click();
expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true);
expect(updateShareStub.calledOnce).toEqual(true);
});
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff