Merge pull request #21860 from owncloud/sharedialog-ocs-adapter

Share dialog use OCS API
This commit is contained in:
Vincent Petry 2016-01-28 16:56:29 +01:00
commit 8b3d7d09d5
9 changed files with 616 additions and 543 deletions

View File

@ -387,13 +387,6 @@ OC.Share = _.extend(OC.Share || {}, {
} }
}); });
}, },
setPermissions:function(itemType, itemSource, shareType, shareWith, permissions) {
$.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'setPermissions', itemType: itemType, itemSource: itemSource, shareType: shareType, shareWith: shareWith, permissions: permissions }, function(result) {
if (!result || result.status !== 'success') {
OC.dialogs.alert(t('core', 'Error while changing permissions'), t('core', 'Error'));
}
});
},
showDropDown:function(itemType, itemSource, appendTo, link, possiblePermissions, filename) { showDropDown:function(itemType, itemSource, appendTo, link, possiblePermissions, filename) {
var configModel = new OC.Share.ShareConfigModel(); var configModel = new OC.Share.ShareConfigModel();
var attributes = {itemType: itemType, itemSource: itemSource, possiblePermissions: possiblePermissions}; var attributes = {itemType: itemType, itemSource: itemSource, possiblePermissions: possiblePermissions};

View File

@ -8,6 +8,8 @@
* *
*/ */
/* global moment */
(function() { (function() {
if (!OC.Share) { if (!OC.Share) {
OC.Share = {}; OC.Share = {};
@ -73,13 +75,10 @@
getDefaultExpirationDateString: function () { getDefaultExpirationDateString: function () {
var expireDateString = ''; var expireDateString = '';
if (this.get('isDefaultExpireDateEnabled')) { if (this.get('isDefaultExpireDateEnabled')) {
var date = new Date().getTime(); var date = moment.utc();
var expireAfterMs = this.get('defaultExpireDate') * 24 * 60 * 60 * 1000; var expireAfterDays = this.get('defaultExpireDate');
var expireDate = new Date(date + expireAfterMs); date.add(expireAfterDays, 'days');
var month = expireDate.getMonth() + 1; expireDateString = date.format('YYYY-MM-DD 00:00:00');
var year = expireDate.getFullYear();
var day = expireDate.getDate();
expireDateString = year + "-" + month + '-' + day + ' 00:00:00';
} }
return expireDateString; return expireDateString;
} }

View File

@ -93,8 +93,9 @@
this.$el.find('.expirationDateContainer').toggleClass('hidden', !state); this.$el.find('.expirationDateContainer').toggleClass('hidden', !state);
if (!state) { if (!state) {
// discard expiration date // discard expiration date
this.model.setExpirationDate(''); this.model.saveLinkShare({
this.model.saveLinkShare(); expireDate: ''
});
} }
}, },
@ -103,8 +104,9 @@
$target.tooltip('hide'); $target.tooltip('hide');
$target.removeClass('error'); $target.removeClass('error');
this.model.setExpirationDate($target.val()); this.model.saveLinkShare({
this.model.saveLinkShare(null, { expiration: moment($target.val(), 'DD-MM-YYYY').format('YYYY-MM-DD')
}, {
error: function(model, message) { error: function(model, message) {
if (!message) { if (!message) {
$target.attr('title', t('core', 'Error setting expiration date')); $target.attr('title', t('core', 'Error setting expiration date'));

View File

@ -157,8 +157,9 @@
onShowPasswordClick: function() { onShowPasswordClick: function() {
this.$el.find('.linkPass').slideToggle(OC.menuSpeed); this.$el.find('.linkPass').slideToggle(OC.menuSpeed);
if(!this.$el.find('.showPasswordCheckbox').is(':checked')) { if(!this.$el.find('.showPasswordCheckbox').is(':checked')) {
this.model.setPassword(''); this.model.saveLinkShare({
this.model.saveLinkShare(); password: ''
});
} else { } else {
this.$el.find('.linkPassText').focus(); this.$el.find('.linkPassText').focus();
} }
@ -171,7 +172,6 @@
}, },
onPasswordEntered: function() { onPasswordEntered: function() {
var self = this;
var $loading = this.$el.find('.linkPass .icon-loading-small'); var $loading = this.$el.find('.linkPass .icon-loading-small');
if (!$loading.hasClass('hidden')) { if (!$loading.hasClass('hidden')) {
// still in process // still in process
@ -189,8 +189,9 @@
.removeClass('hidden') .removeClass('hidden')
.addClass('inlineblock'); .addClass('inlineblock');
this.model.setPassword(password); this.model.saveLinkShare({
this.model.saveLinkShare({}, { password: password
}, {
error: function(model, msg) { error: function(model, msg) {
$loading.removeClass('inlineblock').addClass('hidden'); $loading.removeClass('inlineblock').addClass('hidden');
$input.addClass('error'); $input.addClass('error');
@ -204,8 +205,15 @@
onAllowPublicUploadChange: function() { onAllowPublicUploadChange: function() {
var $checkbox = this.$('.publicUploadCheckbox'); var $checkbox = this.$('.publicUploadCheckbox');
$checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock');
this.model.setPublicUpload($checkbox.is(':checked'));
this.model.saveLinkShare(); var permissions = OC.PERMISSION_READ;
if($checkbox.is(':checked')) {
permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ;
}
this.model.saveLinkShare({
permissions: permissions
});
}, },
_onEmailPrivateLink: function(event) { _onEmailPrivateLink: function(event) {

View File

@ -16,11 +16,7 @@
var TEMPLATE = var TEMPLATE =
'<ul id="shareWithList" class="shareWithList">' + '<ul id="shareWithList" class="shareWithList">' +
'{{#each sharees}}' + '{{#each sharees}}' +
' {{#if isCollection}}' + ' <li data-share-id="{{shareId}}" data-share-type="{{shareType}}" data-share-with="{{shareWith}}" title="{{shareWith}}">' +
' <li data-collection="{{collectionID}}">{{text}}</li>' +
' {{/if}}' +
' {{#unless isCollection}}' +
' <li data-share-type="{{shareType}}" data-share-with="{{shareWith}}" title="{{shareWith}}">' +
' <a href="#" class="unshare"><span class="icon-loading-small hidden"></span><img class="svg" alt="{{unshareLabel}}" title="{{unshareLabel}}" src="{{unshareImage}}" /></a>' + ' <a href="#" class="unshare"><span class="icon-loading-small hidden"></span><img class="svg" alt="{{unshareLabel}}" title="{{unshareLabel}}" src="{{unshareImage}}" /></a>' +
' {{#if avatarEnabled}}' + ' {{#if avatarEnabled}}' +
' <div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' + ' <div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
@ -56,7 +52,6 @@
' </div>' + ' </div>' +
' {{/unless}}' + ' {{/unless}}' +
' </li>' + ' </li>' +
' {{/unless}}' +
'{{/each}}' + '{{/each}}' +
'</ul>' '</ul>'
; ;
@ -81,12 +76,6 @@
/** @type {Function} **/ /** @type {Function} **/
_template: undefined, _template: undefined,
/** @type {boolean} **/
showLink: true,
/** @type {object} **/
_collections: {},
events: { events: {
'click .unshare': 'onUnshare', 'click .unshare': 'onUnshare',
'click .permissions': 'onPermissionChange', 'click .permissions': 'onPermissionChange',
@ -107,23 +96,6 @@
}); });
}, },
processCollectionShare: function(shareIndex) {
var type = this.model.getCollectionType(shareIndex);
var id = this.model.getCollectionPath(shareIndex);
if(type !== 'file' && type !== 'folder') {
id = this.model.getCollectionSource(shareIndex);
}
var displayName = this.model.getShareWithDisplayName(shareIndex);
if(!_.isUndefined(this._collections[id])) {
this._collections[id].text = this._collections[id].text + ", " + displayName;
} else {
this._collections[id] = {};
this._collections[id].text = t('core', 'Shared in {item} with {user}', {'item': id, user: displayName});
this._collections[id].id = id;
this._collections[id].isCollection = true;
}
},
/** /**
* *
* @param {OC.Share.Types.ShareInfo} shareInfo * @param {OC.Share.Types.ShareInfo} shareInfo
@ -156,6 +128,7 @@
shareWith: shareWith, shareWith: shareWith,
shareWithDisplayName: shareWithDisplayName, shareWithDisplayName: shareWithDisplayName,
shareType: shareType, shareType: shareType,
shareId: this.model.get('shares')[shareIndex].id,
modSeed: shareType !== OC.Share.SHARE_TYPE_USER, modSeed: shareType !== OC.Share.SHARE_TYPE_USER,
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE
}); });
@ -187,8 +160,6 @@
deletePermission: OC.PERMISSION_DELETE deletePermission: OC.PERMISSION_DELETE
}; };
this._collections = {};
if(!this.model.hasUserShares()) { if(!this.model.hasUserShares()) {
return []; return [];
} }
@ -196,15 +167,10 @@
var shares = this.model.get('shares'); var shares = this.model.get('shares');
var list = []; var list = [];
for(var index = 0; index < shares.length; index++) { for(var index = 0; index < shares.length; index++) {
if(this.model.isCollection(index)) { // first empty {} is necessary, otherwise we get in trouble
this.processCollectionShare(index); // with references
} else { list.push(_.extend({}, universal, this.getShareeObject(index)));
// first empty {} is necessary, otherwise we get in trouble
// with references
list.push(_.extend({}, universal, this.getShareeObject(index)));
}
} }
list = _.union(_.values(this._collections), list);
return list; return list;
}, },
@ -244,6 +210,7 @@
}, },
onUnshare: function(event) { onUnshare: function(event) {
var self = this;
var $element = $(event.target); var $element = $(event.target);
if (!$element.is('a')) { if (!$element.is('a')) {
$element = $element.closest('a'); $element = $element.closest('a');
@ -257,17 +224,24 @@
$loading.removeClass('hidden'); $loading.removeClass('hidden');
var $li = $element.closest('li'); var $li = $element.closest('li');
var shareType = $li.data('share-type');
var shareWith = $li.attr('data-share-with');
this.model.removeShare(shareType, shareWith); var shareId = $li.data('share-id');
self.model.removeShare(shareId)
.done(function() {
$li.remove();
})
.fail(function() {
$loading.addClass('hidden');
OC.Notification.showTemporary(t('core', 'Could not unshare'));
});
return false; return false;
}, },
onPermissionChange: function(event) { onPermissionChange: function(event) {
var $element = $(event.target); var $element = $(event.target);
var $li = $element.closest('li'); var $li = $element.closest('li');
var shareId = $li.data('share-id');
var shareType = $li.data('share-type'); var shareType = $li.data('share-type');
var shareWith = $li.attr('data-share-with'); var shareWith = $li.attr('data-share-with');
@ -289,7 +263,7 @@
permissions |= $(checkbox).data('permissions'); permissions |= $(checkbox).data('permissions');
}); });
this.model.setPermissions(shareType, shareWith, permissions); this.model.updateShare(shareId, {permissions: permissions});
}, },
onCrudsToggle: function(event) { onCrudsToggle: function(event) {

View File

@ -25,13 +25,6 @@
* @property {number} stime share time * @property {number} stime share time
*/ */
/**
* @typedef {object} OC.Share.Types.Collection
* @property {string} item_type
* @property {string} path
* @property {string} item_source TODO: verify
*/
/** /**
* @typedef {object} OC.Share.Types.Reshare * @typedef {object} OC.Share.Types.Reshare
* @property {string} uid_owner * @property {string} uid_owner
@ -51,7 +44,6 @@
* @property {string} share_with * @property {string} share_with
* @property {string} share_with_displayname * @property {string} share_with_displayname
* @property {string} mail_send * @property {string} mail_send
* @property {OC.Share.Types.Collection|undefined} collection
* @property {Date} expiration optional? * @property {Date} expiration optional?
* @property {number} stime optional? * @property {number} stime optional?
*/ */
@ -84,6 +76,11 @@
* where the link share is one of them * where the link share is one of them
*/ */
var ShareItemModel = OC.Backbone.Model.extend({ var ShareItemModel = OC.Backbone.Model.extend({
/**
* @type share id of the link share, if applicable
*/
_linkShareId: null,
initialize: function(attributes, options) { initialize: function(attributes, options) {
if(!_.isUndefined(options.configModel)) { if(!_.isUndefined(options.configModel)) {
this.configModel = options.configModel; this.configModel = options.configModel;
@ -110,118 +107,48 @@
* TODO: this should be a separate model * TODO: this should be a separate model
*/ */
saveLinkShare: function(attributes, options) { saveLinkShare: function(attributes, options) {
var model = this; options = options || {};
var itemType = this.get('itemType'); attributes = _.extend({}, attributes);
var itemSource = this.get('itemSource');
// TODO: use backbone's default value mechanism once this is a separate model var shareId = null;
var requiredAttributes = [ var call;
{ name: 'password', defaultValue: '' },
{ name: 'passwordChanged', defaultValue: false },
{ name: 'permissions', defaultValue: OC.PERMISSION_READ },
{ name: 'expiration', defaultValue: this.configModel.getDefaultExpirationDateString() }
];
attributes = attributes || {}; // oh yeah...
if (attributes.expiration) {
attributes.expireDate = attributes.expiration;
delete attributes.expiration;
}
// get attributes from the model and fill in with default values if (this.get('linkShare') && this.get('linkShare').isLinkShare) {
_.each(requiredAttributes, function(attribute) { shareId = this.get('linkShare').id;
// a provided options overrides a present value of the link
// share. If neither is given, the default value is used.
if(_.isUndefined(attribute[attribute.name])) {
attributes[attribute.name] = attribute.defaultValue;
var currentValue = model.get('linkShare')[attribute.name];
if(!_.isUndefined(currentValue)) {
attributes[attribute.name] = currentValue;
}
}
});
var password = { // note: update can only update a single value at a time
password: attributes.password, call = this.updateShare(shareId, attributes);
passwordChanged: attributes.passwordChanged } else {
}; attributes = _.defaults(attributes, {
password: '',
passwordChanged: false,
permissions: OC.PERMISSION_READ,
expireDate: this.configModel.getDefaultExpirationDateString(),
shareType: OC.Share.SHARE_TYPE_LINK
});
OC.Share.share( call = this.addShare(attributes);
itemType, }
itemSource,
OC.Share.SHARE_TYPE_LINK,
password,
attributes.permissions,
this.fileInfoModel.get('name'),
attributes.expiration,
function(result) {
if (!result || result.status !== 'success') {
model.fetch({
success: function() {
if (options && _.isFunction(options.success)) {
options.success(model);
}
}
});
} else {
if (options && _.isFunction(options.error)) {
options.error(model);
}
}
},
function(result) {
var msg = t('core', 'Error');
if (result.data && result.data.message) {
msg = result.data.message;
}
if (options && _.isFunction(options.error)) { return call;
options.error(model, msg);
} else {
OC.dialogs.alert(msg, t('core', 'Error while sharing'));
}
}
);
}, },
removeLinkShare: function() { removeLinkShare: function() {
this.removeShare(OC.Share.SHARE_TYPE_LINK, ''); if (this.get('linkShare')) {
}, return this.removeShare(this.get('linkShare').id);
/**
* Sets the public upload flag
*
* @param {bool} allow whether public upload is allowed
*/
setPublicUpload: function(allow) {
var permissions = OC.PERMISSION_READ;
if(allow) {
permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ;
} }
this.get('linkShare').permissions = permissions;
},
/**
* Sets the expiration date of the public link
*
* @param {string} expiration expiration date
*/
setExpirationDate: function(expiration) {
this.get('linkShare').expiration = expiration;
},
/**
* Set password of the public link share
*
* @param {string} password
*/
setPassword: function(password) {
this.get('linkShare').password = password;
this.get('linkShare').passwordChanged = true;
}, },
addShare: function(attributes, options) { addShare: function(attributes, options) {
var shareType = attributes.shareType; var shareType = attributes.shareType;
var shareWith = attributes.shareWith;
var fileName = this.fileInfoModel.get('name');
options = options || {}; options = options || {};
attributes = _.extend({}, attributes);
// Default permissions are Edit (CRUD) and Share // Default permissions are Edit (CRUD) and Share
// Check if these permissions are possible // Check if these permissions are possible
@ -243,29 +170,64 @@
} }
} }
var model = this; attributes.permissions = permissions;
var itemType = this.get('itemType'); if (_.isUndefined(attributes.path)) {
var itemSource = this.get('itemSource'); attributes.path = this.fileInfoModel.getFullPath();
OC.Share.share(itemType, itemSource, shareType, shareWith, permissions, fileName, options.expiration, function() { }
model.fetch();
var self = this;
return $.ajax({
type: 'POST',
url: this._getUrl('shares'),
data: attributes,
dataType: 'json'
}).done(function() {
self.fetch({
success: function() {
if (_.isFunction(options.success)) {
options.success(self);
}
}
});
}).fail(function(result) {
var msg = t('core', 'Error');
if (result.ocs && result.ocs.meta) {
msg = result.ocs.meta.message;
}
if (_.isFunction(options.error)) {
options.error(self, msg);
} else {
OC.dialogs.alert(msg, t('core', 'Error while sharing'));
}
}); });
}, },
setPermissions: function(shareType, shareWith, permissions) { updateShare: function(shareId, attrs) {
var itemType = this.get('itemType'); var self = this;
var itemSource = this.get('itemSource'); return $.ajax({
type: 'PUT',
// TODO: in the future, only set the permissions on the model but don't save directly url: this._getUrl('shares/' + encodeURIComponent(shareId)),
OC.Share.setPermissions(itemType, itemSource, shareType, shareWith, permissions); data: attrs,
dataType: 'json'
}).done(function() {
self.fetch();
});
}, },
removeShare: function(shareType, shareWith) { /**
var model = this; * Deletes the share with the given id
var itemType = this.get('itemType'); *
var itemSource = this.get('itemSource'); * @param {int} shareId share id
* @return {jQuery}
OC.Share.unshare(itemType, itemSource, shareType, shareWith, function() { */
model.fetch(); removeShare: function(shareId) {
var self = this;
return $.ajax({
type: 'DELETE',
url: this._getUrl('shares/' + encodeURIComponent(shareId)),
}).done(function() {
self.fetch();
}); });
}, },
@ -320,71 +282,6 @@
return false; return false;
}, },
/**
* @param {number} shareIndex
* @returns {string}
*/
getCollectionType: function(shareIndex) {
/** @type OC.Share.Types.ShareInfo **/
var share = this.get('shares')[shareIndex];
if(!_.isObject(share)) {
throw "Unknown Share";
} else if(_.isUndefined(share.collection)) {
throw "Share is not a collection";
}
return share.collection.item_type;
},
/**
* @param {number} shareIndex
* @returns {string}
*/
getCollectionPath: function(shareIndex) {
/** @type OC.Share.Types.ShareInfo **/
var share = this.get('shares')[shareIndex];
if(!_.isObject(share)) {
throw "Unknown Share";
} else if(_.isUndefined(share.collection)) {
throw "Share is not a collection";
}
return share.collection.path;
},
/**
* @param {number} shareIndex
* @returns {string}
*/
getCollectionSource: function(shareIndex) {
/** @type OC.Share.Types.ShareInfo **/
var share = this.get('shares')[shareIndex];
if(!_.isObject(share)) {
throw "Unknown Share";
} else if(_.isUndefined(share.collection)) {
throw "Share is not a collection";
}
return share.collection.item_source;
},
/**
* @param {number} shareIndex
* @returns {boolean}
*/
isCollection: function(shareIndex) {
/** @type OC.Share.Types.ShareInfo **/
var share = this.get('shares')[shareIndex];
if(!_.isObject(share)) {
throw "Unknown Share";
}
if(_.isUndefined(share.collection)) {
return false;
}
return true;
},
/** /**
* @returns {string} * @returns {string}
*/ */
@ -635,13 +532,64 @@
|| this.hasDeletePermission(shareIndex); || this.hasDeletePermission(shareIndex);
}, },
_getUrl: function(base, params) {
params = _.extend({format: 'json'}, params || {});
return OC.linkToOCS('apps/files_sharing/api/v1', 2) + base + '?' + OC.buildQueryString(params);
},
_fetchShares: function() {
var path = this.fileInfoModel.getFullPath();
return $.ajax({
type: 'GET',
url: this._getUrl('shares', {path: path, reshares: true})
});
},
_fetchReshare: function() {
// only fetch original share once
if (!this._reshareFetched) {
var path = this.fileInfoModel.getFullPath();
this._reshareFetched = true;
return $.ajax({
type: 'GET',
url: this._getUrl('shares', {path: path, shared_with_me: true})
});
} else {
return $.Deferred().resolve([{
ocs: {
data: [this.get('reshare')]
}
}]);
}
},
fetch: function() { fetch: function() {
var model = this; var model = this;
this.trigger('request', this); this.trigger('request', this);
OC.Share.loadItem(this.get('itemType'), this.get('itemSource'), function(data) {
var deferred = $.when(
this._fetchShares(),
this._fetchReshare()
);
deferred.done(function(data1, data2) {
model.trigger('sync', 'GET', this); model.trigger('sync', 'GET', this);
model.set(model.parse(data)); var sharesMap = {};
_.each(data1[0].ocs.data, function(shareItem) {
sharesMap[shareItem.id] = shareItem;
});
var reshare = false;
if (data2[0].ocs.data.length) {
reshare = data2[0].ocs.data[0];
}
model.set(model.parse({
shares: sharesMap,
reshare: reshare
}));
}); });
return deferred;
}, },
/** /**
@ -690,7 +638,7 @@
parse: function(data) { parse: function(data) {
if(data === false) { if(data === false) {
console.warn('no data was returned'); console.warn('no data was returned');
trigger('fetchError'); this.trigger('fetchError');
return {}; return {};
} }
@ -752,6 +700,7 @@
} }
linkShare = { linkShare = {
isLinkShare: true, isLinkShare: true,
id: share.id,
token: share.token, token: share.token,
password: share.share_with, password: share.share_with,
link: link, link: link,

View File

@ -27,7 +27,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
var configModel; var configModel;
var shareModel; var shareModel;
var listView; var listView;
var setPermissionsStub; var updateShareStub;
beforeEach(function () { beforeEach(function () {
/* jshint camelcase:false */ /* jshint camelcase:false */
@ -81,7 +81,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
oldCurrentUser = OC.currentUser; oldCurrentUser = OC.currentUser;
OC.currentUser = 'user0'; OC.currentUser = 'user0';
setPermissionsStub = sinon.stub(listView.model, 'setPermissions'); updateShareStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'updateShare');
}); });
afterEach(function () { afterEach(function () {
@ -89,7 +89,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
/* jshint camelcase:false */ /* jshint camelcase:false */
oc_appconfig.core = oldAppConfig; oc_appconfig.core = oldAppConfig;
listView.remove(); listView.remove();
setPermissionsStub.restore(); updateShareStub.restore();
}); });
describe('Manages checkbox events correctly', function () { describe('Manages checkbox events correctly', function () {
@ -105,7 +105,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
listView.render(); listView.render();
listView.$el.find("input[name='edit']").click(); listView.$el.find("input[name='edit']").click();
expect(listView.$el.find("input[name='update']").is(':checked')).toEqual(true); expect(listView.$el.find("input[name='update']").is(':checked')).toEqual(true);
expect(setPermissionsStub.called).toEqual(true); expect(updateShareStub.calledOnce).toEqual(true);
}); });
it('Checks edit box when create/update/delete are checked', function () { it('Checks edit box when create/update/delete are checked', function () {
@ -120,7 +120,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
listView.render(); listView.render();
listView.$el.find("input[name='update']").click(); listView.$el.find("input[name='update']").click();
expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true); expect(listView.$el.find("input[name='edit']").is(':checked')).toEqual(true);
expect(setPermissionsStub.called).toEqual(true); expect(updateShareStub.calledOnce).toEqual(true);
}); });
it('shows cruds checkboxes when toggled', function () { it('shows cruds checkboxes when toggled', function () {

View File

@ -28,8 +28,10 @@ describe('OC.Share.ShareDialogView', function() {
var avatarStub; var avatarStub;
var placeholderStub; var placeholderStub;
var oldCurrentUser; var oldCurrentUser;
var saveLinkShareStub;
var fetchStub; var fetchStub;
var notificationStub;
var configModel; var configModel;
var shareModel; var shareModel;
@ -46,6 +48,7 @@ describe('OC.Share.ShareDialogView', function() {
oc_appconfig.core.enforcePasswordForPublicLink = false; oc_appconfig.core.enforcePasswordForPublicLink = false;
fetchStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'fetch'); fetchStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'fetch');
saveLinkShareStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'saveLinkShare');
fileInfoModel = new OCA.Files.FileInfoModel({ fileInfoModel = new OCA.Files.FileInfoModel({
id: 123, id: 123,
@ -116,6 +119,7 @@ describe('OC.Share.ShareDialogView', function() {
dialog.remove(); dialog.remove();
fetchStub.restore(); fetchStub.restore();
saveLinkShareStub.restore();
autocompleteStub.restore(); autocompleteStub.restore();
avatarStub.restore(); avatarStub.restore();
@ -128,55 +132,32 @@ describe('OC.Share.ShareDialogView', function() {
it('update password on focus out', function() { it('update password on focus out', function() {
$('#allowShareWithLink').val('yes'); $('#allowShareWithLink').val('yes');
dialog.model.set('linkShare', {
isLinkShare: true
});
dialog.render(); dialog.render();
// Toggle linkshare
dialog.$el.find('.linkCheckbox').click();
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({data: {token: 'xyz'}, status: 'success'})
);
// Enable password, enter password and focusout // Enable password, enter password and focusout
dialog.$el.find('[name=showPassword]').click(); dialog.$el.find('[name=showPassword]').click();
dialog.$el.find('.linkPassText').focus(); dialog.$el.find('.linkPassText').focus();
dialog.$el.find('.linkPassText').val('foo'); dialog.$el.find('.linkPassText').val('foo');
dialog.$el.find('.linkPassText').focusout(); dialog.$el.find('.linkPassText').focusout();
expect(fakeServer.requests[1].method).toEqual('POST'); expect(saveLinkShareStub.calledOnce).toEqual(true);
var body = OC.parseQueryString(fakeServer.requests[1].requestBody); expect(saveLinkShareStub.firstCall.args[0]).toEqual({
expect(body['shareWith[password]']).toEqual('foo'); password: 'foo'
expect(body['shareWith[passwordChanged]']).toEqual('true'); });
fetchStub.reset();
// Set password response
fakeServer.requests[1].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({data: {token: 'xyz'}, status: 'success'})
);
expect(fetchStub.calledOnce).toEqual(true);
// fetching the model will rerender the view
dialog.render();
expect(dialog.$el.find('.linkPassText').val()).toEqual('');
expect(dialog.$el.find('.linkPassText').attr('placeholder')).toEqual('**********');
}); });
it('update password on enter', function() { it('update password on enter', function() {
$('#allowShareWithLink').val('yes'); $('#allowShareWithLink').val('yes');
dialog.model.set('linkShare', {
isLinkShare: true
});
dialog.render(); dialog.render();
// Toggle linkshare // Toggle linkshare
dialog.$el.find('.linkCheckbox').click(); dialog.$el.find('.linkCheckbox').click();
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({data: {token: 'xyz'}, status: 'success'})
);
// Enable password and enter password // Enable password and enter password
dialog.$el.find('[name=showPassword]').click(); dialog.$el.find('[name=showPassword]').click();
@ -184,26 +165,10 @@ describe('OC.Share.ShareDialogView', function() {
dialog.$el.find('.linkPassText').val('foo'); dialog.$el.find('.linkPassText').val('foo');
dialog.$el.find('.linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); dialog.$el.find('.linkPassText').trigger(new $.Event('keyup', {keyCode: 13}));
expect(fakeServer.requests[1].method).toEqual('POST'); expect(saveLinkShareStub.calledOnce).toEqual(true);
var body = OC.parseQueryString(fakeServer.requests[1].requestBody); expect(saveLinkShareStub.firstCall.args[0]).toEqual({
expect(body['shareWith[password]']).toEqual('foo'); password: 'foo'
expect(body['shareWith[passwordChanged]']).toEqual('true'); });
fetchStub.reset();
// Set password response
fakeServer.requests[1].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({data: {token: 'xyz'}, status: 'success'})
);
expect(fetchStub.calledOnce).toEqual(true);
// fetching the model will rerender the view
dialog.render();
expect(dialog.$el.find('.linkPassText').val()).toEqual('');
expect(dialog.$el.find('.linkPassText').attr('placeholder')).toEqual('**********');
}); });
it('shows share with link checkbox when allowed', function() { it('shows share with link checkbox when allowed', function() {
$('#allowShareWithLink').val('yes'); $('#allowShareWithLink').val('yes');
@ -241,16 +206,11 @@ describe('OC.Share.ShareDialogView', function() {
it('autofocus link text when clicked', function() { it('autofocus link text when clicked', function() {
$('#allowShareWithLink').val('yes'); $('#allowShareWithLink').val('yes');
dialog.model.set('linkShare', {
isLinkShare: true
});
dialog.render(); dialog.render();
// Toggle linkshare
dialog.$el.find('.linkCheckbox').click();
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({data: {token: 'xyz'}, status: 'success'})
);
var focusStub = sinon.stub($.fn, 'focus'); var focusStub = sinon.stub($.fn, 'focus');
var selectStub = sinon.stub($.fn, 'select'); var selectStub = sinon.stub($.fn, 'select');
dialog.$el.find('.linkText').click(); dialog.$el.find('.linkText').click();
@ -603,106 +563,6 @@ describe('OC.Share.ShareDialogView', function() {
}); });
}); });
}); });
describe('share permissions', function() {
beforeEach(function() {
oc_appconfig.core.resharingAllowed = true;
});
/**
* Tests sharing with the given possible permissions
*
* @param {int} possiblePermissions
* @return {int} permissions sent to the server
*/
function testWithPermissions(possiblePermissions) {
shareModel.set({
permissions: possiblePermissions,
possiblePermissions: possiblePermissions
});
dialog.render();
var autocompleteOptions = autocompleteStub.getCall(0).args[0];
// simulate autocomplete selection
autocompleteOptions.select(new $.Event('select'), {
item: {
label: 'User Two',
value: {
shareType: OC.Share.SHARE_TYPE_USER,
shareWith: 'user2'
}
}
});
autocompleteStub.reset();
var requestBody = OC.parseQueryString(_.last(fakeServer.requests).requestBody);
return parseInt(requestBody.permissions, 10);
}
describe('regular sharing', function() {
it('shares with given permissions with default config', function() {
shareModel.set({
reshare: {},
shares: []
});
expect(
testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE);
expect(
testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_SHARE);
});
it('removes share permission when not allowed', function() {
configModel.set('isResharingAllowed', false);
shareModel.set({
reshare: {},
shares: []
});
expect(
testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE);
});
it('automatically adds READ permission even when not specified', function() {
configModel.set('isResharingAllowed', false);
shareModel.set({
reshare: {},
shares: []
});
expect(
testWithPermissions(OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_UPDATE);
});
it('does not show sharing options when sharing not allowed', function() {
shareModel.set({
reshare: {},
shares: [],
permissions: OC.PERMISSION_READ
});
dialog.render();
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
});
it('shows reshare owner', function() {
shareModel.set({
reshare: {
uid_owner: 'user1'
},
shares: [],
permissions: OC.PERMISSION_READ
});
dialog.render();
expect(dialog.$el.find('.resharerInfoView .reshare').length).toEqual(1);
});
it('does not show reshare owner if owner is current user', function() {
shareModel.set({
reshare: {
uid_owner: OC.currentUser
},
shares: [],
permissions: OC.PERMISSION_READ
});
dialog.render();
expect(dialog.$el.find('.resharerInfoView .reshare').length).toEqual(0);
});
});
});
describe('remote sharing', function() { describe('remote sharing', function() {
it('shows remote share info when allowed', function() { it('shows remote share info when allowed', function() {
configModel.set({ configModel.set({
@ -1093,5 +953,61 @@ describe('OC.Share.ShareDialogView', function() {
expect(el.hasClass('user')).toEqual(true); expect(el.hasClass('user')).toEqual(true);
}); });
}); });
it('calls addShare after selection', function() {
dialog.render();
var addShareStub = sinon.stub(shareModel, 'addShare');
var autocompleteOptions = autocompleteStub.getCall(0).args[0];
autocompleteOptions.select(new $.Event('select'), {
item: {
label: 'User Two',
value: {
shareType: OC.Share.SHARE_TYPE_USER,
shareWith: 'user2'
}
}
});
expect(addShareStub.calledOnce).toEqual(true);
expect(addShareStub.firstCall.args[0]).toEqual({
shareType: OC.Share.SHARE_TYPE_USER,
shareWith: 'user2'
});
addShareStub.restore();
});
});
describe('reshare permissions', function() {
it('does not show sharing options when sharing not allowed', function() {
shareModel.set({
reshare: {},
shares: [],
permissions: OC.PERMISSION_READ
});
dialog.render();
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
});
it('shows reshare owner', function() {
shareModel.set({
reshare: {
uid_owner: 'user1'
},
shares: [],
permissions: OC.PERMISSION_READ
});
dialog.render();
expect(dialog.$el.find('.resharerInfoView .reshare').length).toEqual(1);
});
it('does not show reshare owner if owner is current user', function() {
shareModel.set({
reshare: {
uid_owner: OC.currentUser
},
shares: [],
permissions: OC.PERMISSION_READ
});
dialog.render();
expect(dialog.$el.find('.resharerInfoView .reshare').length).toEqual(0);
});
}); });
}); });

View File

@ -21,14 +21,20 @@
/* global oc_appconfig */ /* global oc_appconfig */
describe('OC.Share.ShareItemModel', function() { describe('OC.Share.ShareItemModel', function() {
var loadItemStub; var fetchSharesStub, fetchReshareStub;
var fetchSharesDeferred, fetchReshareDeferred;
var fileInfoModel, configModel, model; var fileInfoModel, configModel, model;
var oldCurrentUser; var oldCurrentUser;
beforeEach(function() { beforeEach(function() {
oldCurrentUser = OC.currentUser; oldCurrentUser = OC.currentUser;
loadItemStub = sinon.stub(OC.Share, 'loadItem'); fetchSharesDeferred = new $.Deferred();
fetchSharesStub = sinon.stub(OC.Share.ShareItemModel.prototype, '_fetchShares')
.returns(fetchSharesDeferred.promise());
fetchReshareDeferred = new $.Deferred();
fetchReshareStub = sinon.stub(OC.Share.ShareItemModel.prototype, '_fetchReshare')
.returns(fetchReshareDeferred.promise());
fileInfoModel = new OCA.Files.FileInfoModel({ fileInfoModel = new OCA.Files.FileInfoModel({
id: 123, id: 123,
@ -52,27 +58,70 @@ describe('OC.Share.ShareItemModel', function() {
}); });
}); });
afterEach(function() { afterEach(function() {
loadItemStub.restore(); if (fetchSharesStub) {
fetchSharesStub.restore();
}
if (fetchReshareStub) {
fetchReshareStub.restore();
}
OC.currentUser = oldCurrentUser; OC.currentUser = oldCurrentUser;
}); });
function makeOcsResponse(data) {
return [{
ocs: {
data: data
}
}];
}
describe('Fetching and parsing', function() { describe('Fetching and parsing', function() {
it('fetching calls loadItem with the correct arguments', function() { it('fetches both outgoing shares and the current incoming share', function() {
model.fetch(); model.fetch();
expect(loadItemStub.calledOnce).toEqual(true); expect(fetchSharesStub.calledOnce).toEqual(true);
expect(loadItemStub.calledWith('file', 123)).toEqual(true); expect(fetchReshareStub.calledOnce).toEqual(true);
});
it('fetches shares for the current path', function() {
fetchSharesStub.restore();
model._fetchShares();
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('GET');
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1', 2) +
'shares?format=json&path=%2Fsubdir%2Fshared_file_name.txt&reshares=true'
);
fetchSharesStub = null;
});
it('fetches reshare for the current path', function() {
fetchReshareStub.restore();
model._fetchReshare();
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('GET');
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1', 2) +
'shares?format=json&path=%2Fsubdir%2Fshared_file_name.txt&shared_with_me=true'
);
fetchReshareStub = null;
}); });
it('populates attributes with parsed response', function() { it('populates attributes with parsed response', function() {
loadItemStub.yields({ /* jshint camelcase: false */
/* jshint camelcase: false */ fetchReshareDeferred.resolve(makeOcsResponse([
reshare: { {
share_type: OC.Share.SHARE_TYPE_USER, share_type: OC.Share.SHARE_TYPE_USER,
uid_owner: 'owner', uid_owner: 'owner',
displayname_owner: 'Owner', displayname_owner: 'Owner',
permissions: 31 permissions: 31
}, }
shares: [{ ]));
fetchSharesDeferred.resolve(makeOcsResponse([
{
id: 100, id: 100,
item_source: 123, item_source: 123,
permissions: 31, permissions: 31,
@ -112,8 +161,9 @@ describe('OC.Share.ShareItemModel', function() {
storage: 1, storage: 1,
token: 'tehtoken', token: 'tehtoken',
uid_owner: 'root' uid_owner: 'root'
}] }
}); ]));
model.fetch(); model.fetch();
var shares = model.get('shares'); var shares = model.get('shares');
@ -130,10 +180,9 @@ describe('OC.Share.ShareItemModel', function() {
// TODO: check more attributes // TODO: check more attributes
}); });
it('does not parse link share when for a different file', function() { it('does not parse link share when for a different file', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: [], fetchReshareDeferred.resolve(makeOcsResponse([]));
/* jshint camelcase: false */ fetchSharesDeferred.resolve(makeOcsResponse([{
shares: [{
displayname_owner: 'root', displayname_owner: 'root',
expiration: null, expiration: null,
file_source: 456, file_source: 456,
@ -152,7 +201,7 @@ describe('OC.Share.ShareItemModel', function() {
token: 'tehtoken', token: 'tehtoken',
uid_owner: 'root' uid_owner: 'root'
}] }]
}); ));
model.fetch(); model.fetch();
@ -164,10 +213,9 @@ describe('OC.Share.ShareItemModel', function() {
expect(linkShare.isLinkShare).toEqual(false); expect(linkShare.isLinkShare).toEqual(false);
}); });
it('parses correct link share when a nested link share exists along with parent one', function() { it('parses correct link share when a nested link share exists along with parent one', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: [], fetchReshareDeferred.resolve(makeOcsResponse([]));
/* jshint camelcase: false */ fetchSharesDeferred.resolve(makeOcsResponse([{
shares: [{
displayname_owner: 'root', displayname_owner: 'root',
expiration: '2015-10-12 00:00:00', expiration: '2015-10-12 00:00:00',
file_source: 123, file_source: 123,
@ -204,7 +252,7 @@ describe('OC.Share.ShareItemModel', function() {
token: 'anothertoken', token: 'anothertoken',
uid_owner: 'root' uid_owner: 'root'
}] }]
}); ));
model.fetch(); model.fetch();
@ -219,26 +267,26 @@ describe('OC.Share.ShareItemModel', function() {
// TODO: check child too // TODO: check child too
}); });
it('reduces reshare permissions to the ones from the original share', function() { it('reduces reshare permissions to the ones from the original share', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: { fetchReshareDeferred.resolve(makeOcsResponse([{
permissions: OC.PERMISSION_READ, id: 123,
uid_owner: 'user1' permissions: OC.PERMISSION_READ,
}, uid_owner: 'user1'
shares: [] }]));
}); fetchSharesDeferred.resolve(makeOcsResponse([]));
model.fetch(); model.fetch();
// no resharing allowed // no resharing allowed
expect(model.get('permissions')).toEqual(OC.PERMISSION_READ); expect(model.get('permissions')).toEqual(OC.PERMISSION_READ);
}); });
it('reduces reshare permissions to possible permissions', function() { it('reduces reshare permissions to possible permissions', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: { fetchReshareDeferred.resolve(makeOcsResponse([{
permissions: OC.PERMISSION_ALL, id: 123,
uid_owner: 'user1' permissions: OC.PERMISSION_ALL,
}, uid_owner: 'user1'
shares: [] }]));
}); fetchSharesDeferred.resolve(makeOcsResponse([]));
model.set('possiblePermissions', OC.PERMISSION_READ); model.set('possiblePermissions', OC.PERMISSION_READ);
model.fetch(); model.fetch();
@ -248,10 +296,8 @@ describe('OC.Share.ShareItemModel', function() {
}); });
it('allows owner to share their own share when they are also the recipient', function() { it('allows owner to share their own share when they are also the recipient', function() {
OC.currentUser = 'user1'; OC.currentUser = 'user1';
loadItemStub.yields({ fetchReshareDeferred.resolve(makeOcsResponse([]));
reshare: {}, fetchSharesDeferred.resolve(makeOcsResponse([]));
shares: []
});
model.fetch(); model.fetch();
@ -259,9 +305,9 @@ describe('OC.Share.ShareItemModel', function() {
expect(model.get('permissions') & OC.PERMISSION_SHARE).toEqual(OC.PERMISSION_SHARE); expect(model.get('permissions') & OC.PERMISSION_SHARE).toEqual(OC.PERMISSION_SHARE);
}); });
it('properly parses integer values when the server is in the mood of returning ints as string', function() { it('properly parses integer values when the server is in the mood of returning ints as string', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: {}, fetchReshareDeferred.resolve(makeOcsResponse([]));
shares: [{ fetchSharesDeferred.resolve(makeOcsResponse([{
displayname_owner: 'root', displayname_owner: 'root',
expiration: '2015-10-12 00:00:00', expiration: '2015-10-12 00:00:00',
file_source: '123', file_source: '123',
@ -280,7 +326,7 @@ describe('OC.Share.ShareItemModel', function() {
token: 'tehtoken', token: 'tehtoken',
uid_owner: 'root' uid_owner: 'root'
}] }]
}); ));
model.fetch(); model.fetch();
@ -306,55 +352,50 @@ describe('OC.Share.ShareItemModel', function() {
}); });
describe('hasUserShares', function() { describe('hasUserShares', function() {
it('returns false when no user shares exist', function() { it('returns false when no user shares exist', function() {
loadItemStub.yields({ fetchReshareDeferred.resolve(makeOcsResponse([]));
reshare: {}, fetchSharesDeferred.resolve(makeOcsResponse([]));
shares: []
});
model.fetch(); model.fetch();
expect(model.hasUserShares()).toEqual(false); expect(model.hasUserShares()).toEqual(false);
}); });
it('returns true when user shares exist on the current item', function() { it('returns true when user shares exist on the current item', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: {}, fetchReshareDeferred.resolve(makeOcsResponse([]));
shares: [{ fetchSharesDeferred.resolve(makeOcsResponse([{
id: 1, id: 1,
share_type: OC.Share.SHARE_TYPE_USER, share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1', share_with: 'user1',
item_source: '123' item_source: '123'
}] }]));
});
model.fetch(); model.fetch();
expect(model.hasUserShares()).toEqual(true); expect(model.hasUserShares()).toEqual(true);
}); });
it('returns true when group shares exist on the current item', function() { it('returns true when group shares exist on the current item', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: {}, fetchReshareDeferred.resolve(makeOcsResponse([]));
shares: [{ fetchSharesDeferred.resolve(makeOcsResponse([{
id: 1, id: 1,
share_type: OC.Share.SHARE_TYPE_GROUP, share_type: OC.Share.SHARE_TYPE_GROUP,
share_with: 'group1', share_with: 'group1',
item_source: '123' item_source: '123'
}] }]));
});
model.fetch(); model.fetch();
expect(model.hasUserShares()).toEqual(true); expect(model.hasUserShares()).toEqual(true);
}); });
it('returns false when share exist on parent item', function() { it('returns false when share exist on parent item', function() {
loadItemStub.yields({ /* jshint camelcase: false */
reshare: {}, fetchReshareDeferred.resolve(makeOcsResponse([]));
shares: [{ fetchSharesDeferred.resolve(makeOcsResponse([{
id: 1, id: 1,
share_type: OC.Share.SHARE_TYPE_GROUP, share_type: OC.Share.SHARE_TYPE_GROUP,
share_with: 'group1', share_with: 'group1',
item_source: '111' item_source: '111'
}] }]));
});
model.fetch(); model.fetch();
@ -381,27 +422,28 @@ describe('OC.Share.ShareItemModel', function() {
describe('sendEmailPrivateLink', function() { describe('sendEmailPrivateLink', function() {
it('succeeds', function() { it('succeeds', function() {
loadItemStub.yields({ /* jshint camelcase: false */
shares: [{ fetchReshareDeferred.resolve(makeOcsResponse([]));
displayname_owner: 'root', fetchSharesDeferred.resolve(makeOcsResponse([{
expiration: null, displayname_owner: 'root',
file_source: 123, expiration: null,
file_target: '/folder', file_source: 123,
id: 20, file_target: '/folder',
item_source: '123', id: 20,
item_type: 'folder', item_source: '123',
mail_send: '0', item_type: 'folder',
parent: null, mail_send: '0',
path: '/folder', parent: null,
permissions: OC.PERMISSION_READ, path: '/folder',
share_type: OC.Share.SHARE_TYPE_LINK, permissions: OC.PERMISSION_READ,
share_with: null, share_type: OC.Share.SHARE_TYPE_LINK,
stime: 1403884258, share_with: null,
storage: 1, stime: 1403884258,
token: 'tehtoken', storage: 1,
uid_owner: 'root' token: 'tehtoken',
}] uid_owner: 'root'
}); }]));
model.fetch(); model.fetch();
var res = model.sendEmailPrivateLink('foo@bar.com'); var res = model.sendEmailPrivateLink('foo@bar.com');
@ -430,27 +472,28 @@ describe('OC.Share.ShareItemModel', function() {
}); });
it('fails', function() { it('fails', function() {
loadItemStub.yields({ /* jshint camelcase: false */
shares: [{ fetchReshareDeferred.resolve(makeOcsResponse([]));
displayname_owner: 'root', fetchSharesDeferred.resolve(makeOcsResponse([{
expiration: null, displayname_owner: 'root',
file_source: 123, expiration: null,
file_target: '/folder', file_source: 123,
id: 20, file_target: '/folder',
item_source: '123', id: 20,
item_type: 'folder', item_source: '123',
mail_send: '0', item_type: 'folder',
parent: null, mail_send: '0',
path: '/folder', parent: null,
permissions: OC.PERMISSION_READ, path: '/folder',
share_type: OC.Share.SHARE_TYPE_LINK, permissions: OC.PERMISSION_READ,
share_with: null, share_type: OC.Share.SHARE_TYPE_LINK,
stime: 1403884258, share_with: null,
storage: 1, stime: 1403884258,
token: 'tehtoken', storage: 1,
uid_owner: 'root' token: 'tehtoken',
}] uid_owner: 'root'
}); }]));
model.fetch(); model.fetch();
var res = model.sendEmailPrivateLink('foo@bar.com'); var res = model.sendEmailPrivateLink('foo@bar.com');
@ -478,5 +521,194 @@ describe('OC.Share.ShareItemModel', function() {
expect(res.state()).toEqual('rejected'); expect(res.state()).toEqual('rejected');
}); });
}); });
describe('share permissions', function() {
beforeEach(function() {
oc_appconfig.core.resharingAllowed = true;
});
/**
* Tests sharing with the given possible permissions
*
* @param {int} possiblePermissions
* @return {int} permissions sent to the server
*/
function testWithPermissions(possiblePermissions) {
model.set({
permissions: possiblePermissions,
possiblePermissions: possiblePermissions
});
model.addShare({
shareType: OC.Share.SHARE_TYPE_USER,
shareWith: 'user2'
});
var requestBody = OC.parseQueryString(_.last(fakeServer.requests).requestBody);
return parseInt(requestBody.permissions, 10);
}
describe('regular sharing', function() {
it('shares with given permissions with default config', function() {
configModel.set('isResharingAllowed', true);
model.set({
reshare: {},
shares: []
});
expect(
testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE);
expect(
testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_SHARE);
});
it('removes share permission when not allowed', function() {
configModel.set('isResharingAllowed', false);
model.set({
reshare: {},
shares: []
});
expect(
testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE);
});
it('automatically adds READ permission even when not specified', function() {
configModel.set('isResharingAllowed', false);
model.set({
reshare: {},
shares: []
});
expect(
testWithPermissions(OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE)
).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_UPDATE);
});
});
});
describe('saveLinkShare', function() {
var addShareStub;
var updateShareStub;
beforeEach(function() {
addShareStub = sinon.stub(model, 'addShare');
updateShareStub = sinon.stub(model, 'updateShare');
});
afterEach(function() {
addShareStub.restore();
updateShareStub.restore();
});
it('creates a new share if no link share exists', function() {
model.set({
linkShare: {
isLinkShare: false
}
});
model.saveLinkShare();
expect(addShareStub.calledOnce).toEqual(true);
expect(addShareStub.firstCall.args[0]).toEqual({
password: '',
passwordChanged: false,
permissions: OC.PERMISSION_READ,
expireDate: '',
shareType: OC.Share.SHARE_TYPE_LINK
});
expect(updateShareStub.notCalled).toEqual(true);
});
it('creates a new share with default expiration date', function() {
var clock = sinon.useFakeTimers(Date.UTC(2015, 6, 17, 1, 2, 0, 3));
configModel.set({
isDefaultExpireDateEnabled: true,
defaultExpireDate: 7
});
model.set({
linkShare: {
isLinkShare: false
}
});
model.saveLinkShare();
expect(addShareStub.calledOnce).toEqual(true);
expect(addShareStub.firstCall.args[0]).toEqual({
password: '',
passwordChanged: false,
permissions: OC.PERMISSION_READ,
expireDate: '2015-07-24 00:00:00',
shareType: OC.Share.SHARE_TYPE_LINK
});
expect(updateShareStub.notCalled).toEqual(true);
clock.restore();
});
it('updates link share if it exists', function() {
model.set({
linkShare: {
isLinkShare: true,
id: 123
}
});
model.saveLinkShare({
password: 'test'
});
expect(addShareStub.notCalled).toEqual(true);
expect(updateShareStub.calledOnce).toEqual(true);
expect(updateShareStub.firstCall.args[0]).toEqual(123);
expect(updateShareStub.firstCall.args[1]).toEqual({
password: 'test'
});
});
});
describe('creating shares', function() {
it('sends POST method to endpoint with passed values', function() {
model.addShare({
shareType: OC.Share.SHARE_TYPE_GROUP,
shareWith: 'group1'
});
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('POST');
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1', 2) +
'shares?format=json'
);
expect(OC.parseQueryString(fakeServer.requests[0].requestBody)).toEqual({
path: '/subdir/shared_file_name.txt',
permissions: '' + OC.PERMISSION_READ,
shareType: '' + OC.Share.SHARE_TYPE_GROUP,
shareWith: 'group1'
});
});
});
describe('updating shares', function() {
it('sends PUT method to endpoint with passed values', function() {
model.updateShare(123, {
permissions: OC.PERMISSION_READ | OC.PERMISSION_SHARE
});
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('PUT');
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1', 2) +
'shares/123?format=json'
);
expect(OC.parseQueryString(fakeServer.requests[0].requestBody)).toEqual({
permissions: '' + (OC.PERMISSION_READ | OC.PERMISSION_SHARE)
});
});
});
describe('removing shares', function() {
it('sends DELETE method to endpoint with share id', function() {
model.removeShare(123);
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('DELETE');
expect(fakeServer.requests[0].url).toEqual(
OC.linkToOCS('apps/files_sharing/api/v1', 2) +
'shares/123?format=json'
);
});
});
}); });