]> source.dussan.org Git - nextcloud-server.git/commitdiff
Share dialog use OCS API
authorVincent Petry <pvince81@owncloud.com>
Fri, 22 Jan 2016 16:30:18 +0000 (17:30 +0100)
committerVincent Petry <pvince81@owncloud.com>
Thu, 28 Jan 2016 14:25:34 +0000 (15:25 +0100)
core/js/share.js
core/js/sharedialogexpirationview.js
core/js/sharedialoglinkshareview.js
core/js/sharedialogshareelistview.js
core/js/shareitemmodel.js
core/js/tests/specs/sharedialogshareelistview.js
core/js/tests/specs/sharedialogviewSpec.js
core/js/tests/specs/shareitemmodelSpec.js

index e14e19a25433236649057f8411416a4ee9f471b4..9baa34d9bb7d6b86843e2316a77cfef91bf01b88 100644 (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) {
                var configModel = new OC.Share.ShareConfigModel();
                var attributes = {itemType: itemType, itemSource: itemSource, possiblePermissions: possiblePermissions};
index eef440c9af5c4036e871d4b759c4111c2630170a..fa5c0c00986912266b1d2bcc8873399f09a2066b 100644 (file)
@@ -93,8 +93,9 @@
                        this.$el.find('.expirationDateContainer').toggleClass('hidden', !state);
                        if (!state) {
                                // discard expiration date
-                               this.model.setExpirationDate('');
-                               this.model.saveLinkShare();
+                               this.model.saveLinkShare({
+                                       expireDate: ''
+                               });
                        }
                },
 
                        $target.tooltip('hide');
                        $target.removeClass('error');
 
-                       this.model.setExpirationDate($target.val());
-                       this.model.saveLinkShare(null, {
+                       this.model.saveLinkShare({
+                               expiration: moment($target.val(), 'DD-MM-YYYY').format('YYYY-MM-DD')
+                       }, {
                                error: function(model, message) {
                                        if (!message) {
                                                $target.attr('title', t('core', 'Error setting expiration date'));
index 452599fb7f248813fbec0ca55f90f5dc255f80a2..efae618ba9953c8ddfa005f968e9042c95b73558 100644 (file)
                onShowPasswordClick: function() {
                        this.$el.find('.linkPass').slideToggle(OC.menuSpeed);
                        if(!this.$el.find('.showPasswordCheckbox').is(':checked')) {
-                               this.model.setPassword('');
-                               this.model.saveLinkShare();
+                               this.model.saveLinkShare({
+                                       password: ''
+                               });
                        } else {
                                this.$el.find('.linkPassText').focus();
                        }
                },
 
                onPasswordEntered: function() {
-                       var self = this;
                        var $loading = this.$el.find('.linkPass .icon-loading-small');
                        if (!$loading.hasClass('hidden')) {
                                // still in process
                                .removeClass('hidden')
                                .addClass('inlineblock');
 
-                       this.model.setPassword(password);
-                       this.model.saveLinkShare({}, {
+                       this.model.saveLinkShare({
+                               password: password
+                       }, {
                                error: function(model, msg) {
                                        $loading.removeClass('inlineblock').addClass('hidden');
                                        $input.addClass('error');
                onAllowPublicUploadChange: function() {
                        var $checkbox = this.$('.publicUploadCheckbox');
                        $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) {
index 5728fbfd210d3b5dfb39be0e3942b512ab388409..e26421dcaedb9dad61c5a94c089798ce4508cf42 100644 (file)
        var TEMPLATE =
                        '<ul id="shareWithList" class="shareWithList">' +
                        '{{#each sharees}}' +
-                       '    {{#if isCollection}}' +
-                       '    <li data-collection="{{collectionID}}">{{text}}</li>' +
-                       '    {{/if}}' +
-                       '    {{#unless isCollection}}' +
-                       '    <li data-share-type="{{shareType}}" data-share-with="{{shareWith}}" title="{{shareWith}}">' +
+                       '    <li data-share-id="{{shareId}}" 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>' +
                        '        {{#if avatarEnabled}}' +
                        '        <div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
@@ -56,7 +52,6 @@
                        '        </div>' +
                        '        {{/unless}}' +
                        '    </li>' +
-                       '    {{/unless}}' +
                        '{{/each}}' +
                        '</ul>'
                ;
                /** @type {Function} **/
                _template: undefined,
 
-               /** @type {boolean} **/
-               showLink: true,
-
-               /** @type {object} **/
-               _collections: {},
-
                events: {
                        'click .unshare': 'onUnshare',
                        'click .permissions': 'onPermissionChange',
                        });
                },
 
-               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
                                shareWith: shareWith,
                                shareWithDisplayName: shareWithDisplayName,
                                shareType: shareType,
+                               shareId: this.model.get('shares')[shareIndex].id,
                                modSeed: shareType !== OC.Share.SHARE_TYPE_USER,
                                isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE
                        });
                                deletePermission: OC.PERMISSION_DELETE
                        };
 
-                       this._collections = {};
-
                        if(!this.model.hasUserShares()) {
                                return [];
                        }
                        var shares = this.model.get('shares');
                        var list = [];
                        for(var index = 0; index < shares.length; index++) {
-                               if(this.model.isCollection(index)) {
-                                       this.processCollectionShare(index);
-                               } else {
-                                       // first empty {} is necessary, otherwise we get in trouble
-                                       // with references
-                                       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;
                },
                },
 
                onUnshare: function(event) {
+                       var self = this;
                        var $element = $(event.target);
                        if (!$element.is('a')) {
                                $element = $element.closest('a');
                        $loading.removeClass('hidden');
 
                        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;
                },
 
                onPermissionChange: function(event) {
                        var $element = $(event.target);
                        var $li = $element.closest('li');
+                       var shareId = $li.data('share-id');
                        var shareType = $li.data('share-type');
                        var shareWith = $li.attr('data-share-with');
 
                                permissions |= $(checkbox).data('permissions');
                        });
 
-                       this.model.setPermissions(shareType, shareWith, permissions);
+                       this.model.updateShare(shareId, {permissions: permissions});
                },
 
                onCrudsToggle: function(event) {
index ae3cb0ce2e30cf4bf81f51e5c153af6a5e0f91b9..c9fc85c91b2832d839db4db07b64e2a0c40957d6 100644 (file)
         * @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
         * @property {string} uid_owner
@@ -51,7 +44,6 @@
         * @property {string} share_with
         * @property {string} share_with_displayname
         * @property {string} mail_send
-        * @property {OC.Share.Types.Collection|undefined} collection
         * @property {Date} expiration optional?
         * @property {number} stime optional?
         */
         * where the link share is one of them
         */
        var ShareItemModel = OC.Backbone.Model.extend({
+               /**
+                * @type share id of the link share, if applicable
+                */
+               _linkShareId: null,
+
                initialize: function(attributes, options) {
                        if(!_.isUndefined(options.configModel)) {
                                this.configModel = options.configModel;
                 * TODO: this should be a separate model
                 */
                saveLinkShare: function(attributes, options) {
-                       var model = this;
-                       var itemType = this.get('itemType');
-                       var itemSource = this.get('itemSource');
-
-                       // TODO: use backbone's default value mechanism once this is a separate model
-                       var requiredAttributes = [
-                               { name: 'password', defaultValue: '' },
-                               { name: 'passwordChanged', defaultValue: false },
-                               { name: 'permissions', defaultValue: OC.PERMISSION_READ },
-                               { name: 'expiration', defaultValue: this.configModel.getDefaultExpirationDateString() }
-                       ];
-
-                       attributes = attributes || {};
-
-                       // get attributes from the model and fill in with default values
-                       _.each(requiredAttributes, function(attribute) {
-                               // 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;
-                                       }
-                               }
-                       });
+                       options = options || {};
+                       attributes = _.extend({}, attributes);
 
-                       var password = {
-                               password: attributes.password,
-                               passwordChanged: attributes.passwordChanged
-                       };
+                       var shareId = null;
+                       var call;
 
-                       OC.Share.share(
-                               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;
-                                       }
+                       // oh yeah...
+                       if (attributes.expiration) {
+                               attributes.expireDate = attributes.expiration;
+                               delete attributes.expiration;
+                       }
 
-                                       if (options && _.isFunction(options.error)) {
-                                               options.error(model, msg);
-                                       } else {
-                                               OC.dialogs.alert(msg, t('core', 'Error while sharing'));
-                                       }
-                               }
-                       );
-               },
+                       if (this.get('linkShare') && this.get('linkShare').isLinkShare) {
+                               shareId = this.get('linkShare').id;
 
-               removeLinkShare: function() {
-                       this.removeShare(OC.Share.SHARE_TYPE_LINK, '');
-               },
+                               // note: update can only update a single value at a time
+                               call = this.updateShare(shareId, attributes);
+                       } else {
+                               attributes = _.defaults(attributes, {
+                                       password: '',
+                                       passwordChanged: false,
+                                       permissions: OC.PERMISSION_READ,
+                                       expireDate: this.configModel.getDefaultExpirationDateString(),
+                                       shareType: OC.Share.SHARE_TYPE_LINK
+                               });
 
-               /**
-                * 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;
+                               call = this.addShare(attributes);
                        }
 
-                       this.get('linkShare').permissions = permissions;
+                       return call;
                },
 
-               /**
-                * 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;
+               removeLinkShare: function() {
+                       if (this.get('linkShare')) {
+                               return this.removeShare(this.get('linkShare').id);
+                       }
                },
 
                addShare: function(attributes, options) {
                        var shareType = attributes.shareType;
-                       var shareWith = attributes.shareWith;
-                       var fileName = this.fileInfoModel.get('name');
                        options = options || {};
+                       attributes = _.extend({}, attributes);
 
                        // Default permissions are Edit (CRUD) and Share
                        // Check if these permissions are possible
                                }
                        }
 
-                       var model = this;
-                       var itemType = this.get('itemType');
-                       var itemSource = this.get('itemSource');
-                       OC.Share.share(itemType, itemSource, shareType, shareWith, permissions, fileName, options.expiration, function() {
-                               model.fetch();
-                       });
-               },
+                       attributes.permissions = permissions;
+                       if (_.isUndefined(attributes.path)) {
+                               attributes.path = this.fileInfoModel.getFullPath();
+                       }
 
-               setPermissions: function(shareType, shareWith, permissions) {
-                       var itemType = this.get('itemType');
-                       var itemSource = this.get('itemSource');
+                       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;
+                               }
 
-                       // TODO: in the future, only set the permissions on the model but don't save directly
-                       OC.Share.setPermissions(itemType, itemSource, shareType, shareWith, permissions);
+                               if (_.isFunction(options.error)) {
+                                       options.error(self, msg);
+                               } else {
+                                       OC.dialogs.alert(msg, t('core', 'Error while sharing'));
+                               }
+                       });
                },
 
-               removeShare: function(shareType, shareWith) {
-                       var model = this;
-                       var itemType = this.get('itemType');
-                       var itemSource = this.get('itemSource');
+               updateShare: function(shareId, attrs) {
+                       var self = this;
+                       return $.ajax({
+                               type: 'PUT',
+                               url: this._getUrl('shares/' + encodeURIComponent(shareId)),
+                               data: attrs,
+                               dataType: 'json'
+                       }).done(function() {
+                               self.fetch();
+                       });
+               },
 
-                       OC.Share.unshare(itemType, itemSource, shareType, shareWith, function() {
-                               model.fetch();
+               /**
+                * Deletes the share with the given id
+                *
+                * @param {int} shareId share id
+                * @return {jQuery}
+                */
+               removeShare: function(shareId) {
+                       var self = this;
+                       return $.ajax({
+                               type: 'DELETE',
+                               url: this._getUrl('shares/' + encodeURIComponent(shareId)),
+                       }).done(function() {
+                               self.fetch();
                        });
                },
 
                        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}
                 */
                                   || 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() {
                        var model = 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.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;
                },
 
                /**
                parse: function(data) {
                        if(data === false) {
                                console.warn('no data was returned');
-                               trigger('fetchError');
+                               this.trigger('fetchError');
                                return {};
                        }
 
                                                }
                                                linkShare = {
                                                        isLinkShare: true,
+                                                       id: share.id,
                                                        token: share.token,
                                                        password: share.share_with,
                                                        link: link,
index 44611d0d964313f24c46879e1b490216f75cf1cf..cef97469753de6096911c4ea074d81d4de9bfca1 100644 (file)
@@ -27,7 +27,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
        var configModel;
        var shareModel;
        var listView;
-       var setPermissionsStub;
+       var updateShareStub;
 
        beforeEach(function () {
                /* jshint camelcase:false */
@@ -81,7 +81,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
 
                oldCurrentUser = OC.currentUser;
                OC.currentUser = 'user0';
-               setPermissionsStub = sinon.stub(listView.model, 'setPermissions');
+               updateShareStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'updateShare');
        });
 
        afterEach(function () {
@@ -89,7 +89,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
                /* jshint camelcase:false */
                oc_appconfig.core = oldAppConfig;
                listView.remove();
-               setPermissionsStub.restore();
+               updateShareStub.restore();
        });
 
        describe('Manages checkbox events correctly', function () {
@@ -105,7 +105,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
                        listView.render();
                        listView.$el.find("input[name='edit']").click();
                        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 () {
@@ -120,7 +120,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
                        listView.render();
                        listView.$el.find("input[name='update']").click();
                        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 () {
index 63cfe5299ae0882154c19438e150520e65a00f12..6899e625c454649ba0c6e177cebf4d0827e54e26 100644 (file)
@@ -28,8 +28,10 @@ describe('OC.Share.ShareDialogView', function() {
        var avatarStub;
        var placeholderStub;
        var oldCurrentUser;
+       var saveLinkShareStub;
 
        var fetchStub;
+       var notificationStub;
 
        var configModel;
        var shareModel;
@@ -46,6 +48,7 @@ describe('OC.Share.ShareDialogView', function() {
                oc_appconfig.core.enforcePasswordForPublicLink = false;
 
                fetchStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'fetch');
+               saveLinkShareStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'saveLinkShare');
 
                fileInfoModel = new OCA.Files.FileInfoModel({
                        id: 123,
@@ -116,6 +119,7 @@ describe('OC.Share.ShareDialogView', function() {
 
                dialog.remove();
                fetchStub.restore();
+               saveLinkShareStub.restore();
 
                autocompleteStub.restore();
                avatarStub.restore();
@@ -128,55 +132,32 @@ describe('OC.Share.ShareDialogView', function() {
                it('update password on focus out', function() {
                        $('#allowShareWithLink').val('yes');
 
+                       dialog.model.set('linkShare', {
+                               isLinkShare: true
+                       });
                        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
                        dialog.$el.find('[name=showPassword]').click();
                        dialog.$el.find('.linkPassText').focus();
                        dialog.$el.find('.linkPassText').val('foo');
                        dialog.$el.find('.linkPassText').focusout();
 
-                       expect(fakeServer.requests[1].method).toEqual('POST');
-                       var body = OC.parseQueryString(fakeServer.requests[1].requestBody);
-                       expect(body['shareWith[password]']).toEqual('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('**********');
+                       expect(saveLinkShareStub.calledOnce).toEqual(true);
+                       expect(saveLinkShareStub.firstCall.args[0]).toEqual({
+                               password: 'foo'
+                       });
                });
                it('update password on enter', function() {
                        $('#allowShareWithLink').val('yes');
 
+                       dialog.model.set('linkShare', {
+                               isLinkShare: true
+                       });
                        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 and enter password
                        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').trigger(new $.Event('keyup', {keyCode: 13}));
 
-                       expect(fakeServer.requests[1].method).toEqual('POST');
-                       var body = OC.parseQueryString(fakeServer.requests[1].requestBody);
-                       expect(body['shareWith[password]']).toEqual('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('**********');
+                       expect(saveLinkShareStub.calledOnce).toEqual(true);
+                       expect(saveLinkShareStub.firstCall.args[0]).toEqual({
+                               password: 'foo'
+                       });
                });
                it('shows share with link checkbox when allowed', function() {
                        $('#allowShareWithLink').val('yes');
@@ -241,16 +206,11 @@ describe('OC.Share.ShareDialogView', function() {
                it('autofocus link text when clicked', function() {
                        $('#allowShareWithLink').val('yes');
 
+                       dialog.model.set('linkShare', {
+                               isLinkShare: true
+                       });
                        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 selectStub = sinon.stub($.fn, 'select');
                        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() {
                it('shows remote share info when allowed', function() {
                        configModel.set({
@@ -1093,5 +953,61 @@ describe('OC.Share.ShareDialogView', function() {
                                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);
+               });
        });
 });
index 28daf8603933ea8947d3f46d8c574e677232b270..d696b159e471547980df009b8ee44ff5221d43c7 100644 (file)
 
 /* global oc_appconfig */
 describe('OC.Share.ShareItemModel', function() {
-       var loadItemStub;
+       var fetchSharesStub, fetchReshareStub;
+       var fetchSharesDeferred, fetchReshareDeferred;
        var fileInfoModel, configModel, model;
        var oldCurrentUser;
 
        beforeEach(function() {
                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({
                        id: 123,
@@ -52,27 +58,70 @@ describe('OC.Share.ShareItemModel', function() {
                });
        });
        afterEach(function() {
-               loadItemStub.restore();
+               if (fetchSharesStub) {
+                       fetchSharesStub.restore();
+               }
+               if (fetchReshareStub) {
+                       fetchReshareStub.restore();
+               }
                OC.currentUser = oldCurrentUser;
        });
 
+       function makeOcsResponse(data) {
+               return [{
+                       ocs: {
+                               data: data
+                       }
+               }];
+       }
+
        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();
 
-                       expect(loadItemStub.calledOnce).toEqual(true);
-                       expect(loadItemStub.calledWith('file', 123)).toEqual(true);
+                       expect(fetchSharesStub.calledOnce).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() {
-                       loadItemStub.yields({
-                               /* jshint camelcase: false */
-                               reshare: {
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([
+                               {
                                        share_type: OC.Share.SHARE_TYPE_USER,
                                        uid_owner: 'owner',
                                        displayname_owner: 'Owner',
                                        permissions: 31
-                               },
-                               shares: [{
+                               }
+                       ]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([
+                               {
                                        id: 100,
                                        item_source: 123,
                                        permissions: 31,
@@ -112,8 +161,9 @@ describe('OC.Share.ShareItemModel', function() {
                                        storage: 1,
                                        token: 'tehtoken',
                                        uid_owner: 'root'
-                               }]
-                       });
+                               }
+                       ]));
+
                        model.fetch();
 
                        var shares = model.get('shares');
@@ -130,10 +180,9 @@ describe('OC.Share.ShareItemModel', function() {
                        // TODO: check more attributes
                });
                it('does not parse link share when for a different file', function() {
-                       loadItemStub.yields({
-                               reshare: [],
-                               /* jshint camelcase: false */
-                               shares: [{
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
                                        displayname_owner: 'root',
                                        expiration: null,
                                        file_source: 456,
@@ -152,7 +201,7 @@ describe('OC.Share.ShareItemModel', function() {
                                        token: 'tehtoken',
                                        uid_owner: 'root'
                                }]
-                       });
+                       ));
 
                        model.fetch();
 
@@ -164,10 +213,9 @@ describe('OC.Share.ShareItemModel', function() {
                        expect(linkShare.isLinkShare).toEqual(false);
                });
                it('parses correct link share when a nested link share exists along with parent one', function() {
-                       loadItemStub.yields({
-                               reshare: [],
-                               /* jshint camelcase: false */
-                               shares: [{
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
                                        displayname_owner: 'root',
                                        expiration: '2015-10-12 00:00:00',
                                        file_source: 123,
@@ -204,7 +252,7 @@ describe('OC.Share.ShareItemModel', function() {
                                        token: 'anothertoken',
                                        uid_owner: 'root'
                                }]
-                       });
+                       ));
 
                        model.fetch();
 
@@ -219,26 +267,26 @@ describe('OC.Share.ShareItemModel', function() {
                        // TODO: check child too
                });
                it('reduces reshare permissions to the ones from the original share', function() {
-                       loadItemStub.yields({
-                               reshare: {
-                                       permissions: OC.PERMISSION_READ,
-                                       uid_owner: 'user1'
-                               },
-                               shares: []
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([{
+                               id: 123,
+                               permissions: OC.PERMISSION_READ,
+                               uid_owner: 'user1'
+                       }]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([]));
                        model.fetch();
 
                        // no resharing allowed
                        expect(model.get('permissions')).toEqual(OC.PERMISSION_READ);
                });
                it('reduces reshare permissions to possible permissions', function() {
-                       loadItemStub.yields({
-                               reshare: {
-                                       permissions: OC.PERMISSION_ALL,
-                                       uid_owner: 'user1'
-                               },
-                               shares: []
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([{
+                               id: 123,
+                               permissions: OC.PERMISSION_ALL,
+                               uid_owner: 'user1'
+                       }]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([]));
 
                        model.set('possiblePermissions', OC.PERMISSION_READ);
                        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() {
                        OC.currentUser = 'user1';
-                       loadItemStub.yields({
-                               reshare: {},
-                               shares: []
-                       });
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([]));
 
                        model.fetch();
 
@@ -259,9 +305,9 @@ describe('OC.Share.ShareItemModel', function() {
                        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() {
-                       loadItemStub.yields({
-                               reshare: {},
-                               shares: [{
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
                                        displayname_owner: 'root',
                                        expiration: '2015-10-12 00:00:00',
                                        file_source: '123',
@@ -280,7 +326,7 @@ describe('OC.Share.ShareItemModel', function() {
                                        token: 'tehtoken',
                                        uid_owner: 'root'
                                }]
-                       });
+                       ));
 
                        model.fetch();
 
@@ -306,55 +352,50 @@ describe('OC.Share.ShareItemModel', function() {
        });
        describe('hasUserShares', function() {
                it('returns false when no user shares exist', function() {
-                       loadItemStub.yields({
-                               reshare: {},
-                               shares: []
-                       });
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([]));
 
                        model.fetch();
 
                        expect(model.hasUserShares()).toEqual(false);
                });
                it('returns true when user shares exist on the current item', function() {
-                       loadItemStub.yields({
-                               reshare: {},
-                               shares: [{
-                                       id: 1,
-                                       share_type: OC.Share.SHARE_TYPE_USER,
-                                       share_with: 'user1',
-                                       item_source: '123'
-                               }]
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
+                               id: 1,
+                               share_type: OC.Share.SHARE_TYPE_USER,
+                               share_with: 'user1',
+                               item_source: '123'
+                       }]));
 
                        model.fetch();
 
                        expect(model.hasUserShares()).toEqual(true);
                });
                it('returns true when group shares exist on the current item', function() {
-                       loadItemStub.yields({
-                               reshare: {},
-                               shares: [{
-                                       id: 1,
-                                       share_type: OC.Share.SHARE_TYPE_GROUP,
-                                       share_with: 'group1',
-                                       item_source: '123'
-                               }]
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
+                               id: 1,
+                               share_type: OC.Share.SHARE_TYPE_GROUP,
+                               share_with: 'group1',
+                               item_source: '123'
+                       }]));
 
                        model.fetch();
 
                        expect(model.hasUserShares()).toEqual(true);
                });
                it('returns false when share exist on parent item', function() {
-                       loadItemStub.yields({
-                               reshare: {},
-                               shares: [{
-                                       id: 1,
-                                       share_type: OC.Share.SHARE_TYPE_GROUP,
-                                       share_with: 'group1',
-                                       item_source: '111'
-                               }]
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
+                               id: 1,
+                               share_type: OC.Share.SHARE_TYPE_GROUP,
+                               share_with: 'group1',
+                               item_source: '111'
+                       }]));
 
                        model.fetch();
 
@@ -381,27 +422,28 @@ describe('OC.Share.ShareItemModel', function() {
 
        describe('sendEmailPrivateLink', function() {
                it('succeeds', function() {
-                       loadItemStub.yields({
-                               shares: [{
-                                       displayname_owner: 'root',
-                                       expiration: null,
-                                       file_source: 123,
-                                       file_target: '/folder',
-                                       id: 20,
-                                       item_source: '123',
-                                       item_type: 'folder',
-                                       mail_send: '0',
-                                       parent: null,
-                                       path: '/folder',
-                                       permissions: OC.PERMISSION_READ,
-                                       share_type: OC.Share.SHARE_TYPE_LINK,
-                                       share_with: null,
-                                       stime: 1403884258,
-                                       storage: 1,
-                                       token: 'tehtoken',
-                                       uid_owner: 'root'
-                               }]
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
+                               displayname_owner: 'root',
+                               expiration: null,
+                               file_source: 123,
+                               file_target: '/folder',
+                               id: 20,
+                               item_source: '123',
+                               item_type: 'folder',
+                               mail_send: '0',
+                               parent: null,
+                               path: '/folder',
+                               permissions: OC.PERMISSION_READ,
+                               share_type: OC.Share.SHARE_TYPE_LINK,
+                               share_with: null,
+                               stime: 1403884258,
+                               storage: 1,
+                               token: 'tehtoken',
+                               uid_owner: 'root'
+                       }]));
+
                        model.fetch();
 
                        var res = model.sendEmailPrivateLink('foo@bar.com');
@@ -430,27 +472,28 @@ describe('OC.Share.ShareItemModel', function() {
                });
 
                it('fails', function() {
-                       loadItemStub.yields({
-                               shares: [{
-                                       displayname_owner: 'root',
-                                       expiration: null,
-                                       file_source: 123,
-                                       file_target: '/folder',
-                                       id: 20,
-                                       item_source: '123',
-                                       item_type: 'folder',
-                                       mail_send: '0',
-                                       parent: null,
-                                       path: '/folder',
-                                       permissions: OC.PERMISSION_READ,
-                                       share_type: OC.Share.SHARE_TYPE_LINK,
-                                       share_with: null,
-                                       stime: 1403884258,
-                                       storage: 1,
-                                       token: 'tehtoken',
-                                       uid_owner: 'root'
-                               }]
-                       });
+                       /* jshint camelcase: false */
+                       fetchReshareDeferred.resolve(makeOcsResponse([]));
+                       fetchSharesDeferred.resolve(makeOcsResponse([{
+                               displayname_owner: 'root',
+                               expiration: null,
+                               file_source: 123,
+                               file_target: '/folder',
+                               id: 20,
+                               item_source: '123',
+                               item_type: 'folder',
+                               mail_send: '0',
+                               parent: null,
+                               path: '/folder',
+                               permissions: OC.PERMISSION_READ,
+                               share_type: OC.Share.SHARE_TYPE_LINK,
+                               share_with: null,
+                               stime: 1403884258,
+                               storage: 1,
+                               token: 'tehtoken',
+                               uid_owner: 'root'
+                       }]));
+
                        model.fetch();
 
                        var res = model.sendEmailPrivateLink('foo@bar.com');
@@ -478,5 +521,194 @@ describe('OC.Share.ShareItemModel', function() {
                        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-7-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'
+                       );
+               });
+       });
 });