diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index 8dac9550c416..f0bf569a732e 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -69,7 +69,7 @@
'
' +
'{{#each shareAttributes}}' +
'' +
- '' +
+ '' +
'' +
'' +
'{{/each}}' +
@@ -129,6 +129,9 @@
var cid = this.cid;
var shareWith = model.getShareWith(shareIndex);
+ // Check if reshare, and if so disable the checkboxes
+ var isReshare = model.hasReshare();
+
// Returns OC.Share.Types.ShareAttribute[] which were set for this
// share (and stored in DB)
var attributes = model.getShareAttributes(shareIndex);
@@ -137,19 +140,20 @@
attributes.map(function(attribute) {
// Check if the share attribute set for this file is still in
// registered share attributes and get its label
- var label = model.getRegisteredShareAttributeLabel(
+ var regAttr = model.getRegisteredShareAttribute(
attribute.scope,
attribute.key
);
- if (label) {
+ if (regAttr && regAttr.label) {
list.push({
cid: cid,
+ isReshare: isReshare,
shareWith: shareWith,
enabled: attribute.enabled,
scope: attribute.scope,
name: attribute.key,
- label: label
+ label: regAttr.label
});
} else {
OC.Notification.showTemporary(t('core', 'Share with ' +
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
index 021a8e1cf8de..05bb83d5da56 100644
--- a/core/js/shareitemmodel.js
+++ b/core/js/shareitemmodel.js
@@ -38,7 +38,7 @@
* @typedef {object} OC.Share.Types.ShareInfo
* @property {number} share_type
* @property {number} permissions
- * @property {string} attributes
+ * @property {OC.Share.Types.ShareAttribute[]} attributes
* @property {number} file_source optional
* @property {number} item_source
* @property {string} token
@@ -73,6 +73,7 @@
* @property {string} description
* @property {number[]} shareType
* @property {number[]} incompatiblePermissions
+ * @property {number[]} requiredPermissions
* @property {OC.Share.Types.ShareAttribute[]} incompatibleAttributes
*/
@@ -85,6 +86,13 @@
'storage', 'share_type', 'parent', 'stime'
];
+ /**
+ * Properties which are json and need to be parsed
+ */
+ var SHARE_RESPONSE_JSON_PROPS = [
+ 'attributes'
+ ];
+
/**
* @class OCA.Share.ShareItemModel
* @classdesc
@@ -171,10 +179,11 @@
}
properties.permissions = defaultPermissions & possiblePermissions;
+ // FIXME: simplify the logic by merging and then filtering
// Set default attributes for this share based on registered
// attributes (filtered by their incompatible permissions)
var newShareAttributes = [];
- var filteredRegisteredAttributes = this.filterRegisteredAttributes(properties.permissions);
+ var filteredRegisteredAttributes = this._filterRegisteredAttributes(properties.permissions);
_.map(filteredRegisteredAttributes, function(filteredRegisteredAttribute) {
var isCompatible = true;
// Check if this attribute can be added due to its incompatible attributes
@@ -233,12 +242,13 @@
var self = this;
options = options || {};
+ // FIXME: simplify the logic by merging and then filtering
// Set share attributes for this share based on registered
// attributes (filtered by their incompatible permissions
// and incompatible attributes)
var newShareAttributes = [];
var filteredAttributes = [];
- var filteredRegisteredAttributes = this.filterRegisteredAttributes(properties.permissions);
+ var filteredRegisteredAttributes = this._filterRegisteredAttributes(properties.permissions);
_.map(filteredRegisteredAttributes, function(filteredRegisteredAttribute) {
// Check if this allowed registered attribute
// is on the list of currently set properties,
@@ -785,9 +795,15 @@
// returns integers as string...
var i;
for (i = 0; i < SHARE_RESPONSE_INT_PROPS.length; i++) {
- var prop = SHARE_RESPONSE_INT_PROPS[i];
- if (!_.isUndefined(share[prop])) {
- share[prop] = parseInt(share[prop], 10);
+ var propInt = SHARE_RESPONSE_INT_PROPS[i];
+ if (!_.isUndefined(share[propInt])) {
+ share[propInt] = parseInt(share[propInt], 10);
+ }
+ }
+ for (i = 0; i < SHARE_RESPONSE_JSON_PROPS.length; i++) {
+ var propJson = SHARE_RESPONSE_JSON_PROPS[i];
+ if (!_.isUndefined(share[propJson])) {
+ share[propJson] = JSON.parse(share.attributes);
}
}
return share;
@@ -868,6 +884,25 @@
return _.uniq(result);
},
+ /**
+ * Returns share attributes for given share index
+ *
+ * @param shareIndex
+ * @returns OC.Share.Types.ShareAttribute[]
+ */
+ getShareAttributes: function(shareIndex) {
+ /** @type OC.Share.Types.ShareInfo **/
+ var share = this.get('shares')[shareIndex];
+ if(!_.isObject(share)) {
+ throw "Unknown Share";
+ }
+
+ if (_.isNull(share.attributes) || _.isUndefined(share.attributes)) {
+ return [];
+ }
+ return share.attributes;
+ },
+
/**
* Filter registered attributes by current share permissions
*
@@ -875,7 +910,7 @@
* @returns {OC.Share.Types.RegisteredShareAttribute[]}
* @private
*/
- filterRegisteredAttributes: function(permissions) {
+ _filterRegisteredAttributes: function(permissions) {
var filteredByPermissions = [];
for(var i in this._registeredAttributes) {
var compatible = true;
@@ -885,6 +920,11 @@
compatible = false;
}
}
+ for(var ii in attr.requiredPermissions) {
+ if (!this._hasPermission(permissions, attr.requiredPermissions[ii])) {
+ compatible = false;
+ }
+ }
if (compatible) {
filteredByPermissions.push(attr);
@@ -894,51 +934,30 @@
return filteredByPermissions;
},
- /**
- * Returns share attributes for given share index
- *
- * @param shareIndex
- * @returns OC.Share.Types.ShareAttribute[]
- */
- getShareAttributes: function(shareIndex) {
- /** @type OC.Share.Types.ShareInfo **/
- var share = this.get('shares')[shareIndex];
- if(!_.isObject(share)) {
- throw "Unknown Share";
- }
-
- if (_.isUndefined(share.attributes) || _.isUndefined(share.permissions)) {
- return [];
- }
-
- // Add attributes for this share
- var currentAttributes = JSON.parse(share.attributes);
- if (currentAttributes) {
- return currentAttributes;
- }
- return [];
- },
-
/**
* Returns share attribute label for given attribute scope and name. If
* attribute does not exist, null is returned.
*
* @param scope
* @param key
- * @returns string|null
+ * @returns {OC.Share.Types.RegisteredShareAttribute}
*/
- getRegisteredShareAttributeLabel: function(scope, key) {
+ getRegisteredShareAttribute: function(scope, key) {
for(var i in this._registeredAttributes) {
if (this._registeredAttributes[i].scope === scope
&& this._registeredAttributes[i].key === key) {
- return this._registeredAttributes[i].label;
+ return this._registeredAttributes[i];
}
}
return null;
},
/**
- * Apps can register default share attributes
+ * Apps can register default share attributes. The applications
+ * registering share attributes are required to follow the rules:
+ * attribute enabled -> functionality is added (e.g. can download)
+ * attribute disabled -> functionality is restricted
+ * incompatible attribute -> functionality is ignored
*
* @param {OC.Share.Types.RegisteredShareAttribute} $shareAttribute
*/
diff --git a/core/js/tests/specs/sharedialogshareelistview.js b/core/js/tests/specs/sharedialogshareelistview.js
index 910dc93269c4..ee2fc72b4bfe 100644
--- a/core/js/tests/specs/sharedialogshareelistview.js
+++ b/core/js/tests/specs/sharedialogshareelistview.js
@@ -45,14 +45,14 @@ describe('OC.Share.ShareDialogShareeListView', function () {
sharePermissions: 31
});
- var attributes = {
+ var properties = {
itemType: fileInfoModel.isDirectory() ? 'folder' : 'file',
itemSource: fileInfoModel.get('id'),
possiblePermissions: 31,
permissions: 31
};
- shareModel = new OC.Share.ShareItemModel(attributes, {
+ shareModel = new OC.Share.ShareItemModel(properties, {
configModel: configModel,
fileInfoModel: fileInfoModel
});
@@ -91,7 +91,8 @@ describe('OC.Share.ShareDialogShareeListView', function () {
describe('rendering', function() {
it('Renders shares', function() {
- shareModel.set('shares', [{
+ shareModel.set('shares', [
+ {
id: 100,
item_source: 123,
permissions: 1,
@@ -99,10 +100,12 @@ describe('OC.Share.ShareDialogShareeListView', function () {
share_with: 'user1',
share_with_displayname: 'User One',
share_with_additional_info: 'user1@example.com'
- }, {
+ },
+ {
id: 101,
item_source: 123,
permissions: 1,
+ attributes: [],
share_type: OC.Share.SHARE_TYPE_GROUP,
share_with: 'group1',
share_with_displayname: 'Group One'
@@ -122,9 +125,39 @@ describe('OC.Share.ShareDialogShareeListView', function () {
expect($li.find('.username').text()).toEqual('Group One (group)');
expect($li.find('.user-additional-info').length).toEqual(0);
});
+
+ it('renders share attribute correctly', function () {
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "test-attribute",
+ default: true,
+ label: "test attribute",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [],
+ incompatibleAttributes: []
+ });
+
+ shareModel.set('shares', [{
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [{ scope: 'test', key: 'test-attribute', enabled: true }],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ }]);
+
+ listView.render();
+ var $li = listView.$('li').eq(0);
+ var input = $li.find("input[name='test-attribute']");
+ expect(input.is(':checked')).toEqual(true);
+ expect($("label[for='" + input.attr('id') + "']").text()).toEqual('test attribute');
+ });
});
describe('Manages checkbox events correctly', function () {
+
it('Checks cruds boxes when edit box checked', function () {
shareModel.set('shares', [{
id: 100,
@@ -196,6 +229,7 @@ describe('OC.Share.ShareDialogShareeListView', function () {
expect(listView.$el.find("input[name='mailNotification']").length).toEqual(0);
});
+
it('displays error if email notification not sent', function () {
var notifStub = sinon.stub(OC.dialogs, 'alert');
shareModel.set('shares', [{
@@ -222,6 +256,197 @@ describe('OC.Share.ShareDialogShareeListView', function () {
expect(listView.$el.find("input[name='mailNotification']").hasClass('hidden')).toEqual(false);
});
+ it('unchecks share attribute when clicked on checked', function () {
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "test-attribute",
+ default: true,
+ label: "test attribute",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [],
+ incompatibleAttributes: []
+ });
+
+ shareModel.set('shares', [{
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [{ scope: 'test', key: 'test-attribute', enabled: true }],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ }]);
+
+ listView.render();
+ listView.$el.find("input[name='test-attribute']").click();
+ expect(listView.$el.find("input[name='test-attribute']").is(':checked')).toEqual(false);
+ expect(updateShareStub.calledOnce).toEqual(true);
+ });
+
+ it('shows share attribute checkbox when checking required permission', function () {
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "test-attribute",
+ default: true,
+ label: "test attribute",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [ OC.PERMISSION_UPDATE ],
+ incompatibleAttributes: []
+ });
+
+ shareModel.set('shares', [{
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ }]);
+
+ listView.render();
+
+ expect(listView.$el.find("input[name='test-attribute']").length > 0).toEqual(false);
+
+ updateShareStub.callsFake(function() {
+ // Updated share permission should now enable the permission
+ shareModel.set('shares', [{
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [{ scope: 'test', key: 'test-attribute', enabled: true }],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ }]);
+ });
+
+ // Click on update should cause attribute test-attribute
+ // to appear as requiredPermissions got satisfied
+ listView.$el.find("input[name='update']").click();
+ expect(listView.$el.find("input[name='test-attribute']").is(':checked')).toEqual(true);
+ expect(updateShareStub.calledOnce).toEqual(true);
+ });
+
+ it('shows share attribute checkbox when unchecking incompatible attribute', function () {
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "incompatible-attribute",
+ default: true,
+ label: "incompatible attribute",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [ ],
+ incompatibleAttributes: []
+ });
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "test-attribute",
+ default: true,
+ label: "test attribute",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [ ],
+ incompatibleAttributes: [{ scope: 'test', key: 'incompatible-attribute', enabled: true }]
+ });
+
+ shareModel.set('shares', [{
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [{ scope: 'test', key: 'incompatible-attribute', enabled: true }],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ }]);
+
+ listView.render();
+
+ expect(listView.$el.find("input[name='incompatible-attribute']").is(':checked')).toEqual(true);
+ expect(listView.$el.find("input[name='test-attribute']").length > 0).toEqual(false);
+
+ updateShareStub.callsFake(function() {
+ // Updated share permission should now enable the permission
+ shareModel.set('shares', [{
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [
+ { scope: 'test', key: 'incompatible-attribute', enabled: false },
+ { scope: 'test', key: 'test-attribute', enabled: true }
+ ],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ }]);
+ });
+
+ listView.$el.find("input[name='incompatible-attribute']").click();
+
+ expect(listView.$el.find("input[name='incompatible-attribute']").is(':checked')).toEqual(false);
+ expect(listView.$el.find("input[name='test-attribute']").is(':checked')).toEqual(true);
+ expect(updateShareStub.calledOnce).toEqual(true);
+ });
+
+ it('prevents checking/unchecking attribute when reshared', function () {
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "test-attribute-checked",
+ default: true,
+ label: "test attribute checked",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [],
+ incompatibleAttributes: []
+ });
+ shareModel.registerShareAttribute({
+ scope: "test",
+ key: "test-attribute-unchecked",
+ default: false,
+ label: "test attribute unchecked",
+ shareType : [],
+ incompatiblePermissions: [],
+ requiredPermissions: [],
+ incompatibleAttributes: []
+ });
+
+ shareModel.set('reshare', {
+ uid_owner: 100
+ });
+ shareModel.set('shares', [
+ {
+ id: 100,
+ item_source: 123,
+ permissions: 1,
+ attributes: [{ scope: 'test', key: 'test-attribute-checked', enabled: true }],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user1',
+ share_with_displayname: 'User One'
+ },
+ {
+ id: 101,
+ item_source: 123,
+ permissions: 1,
+ attributes: [{ scope: 'test', key: 'test-attribute-unchecked', enabled: false }],
+ share_type: OC.Share.SHARE_TYPE_USER,
+ share_with: 'user2',
+ share_with_displayname: 'User Two'
+ }
+ ]);
+
+ listView.render();
+
+ // Click should have no action
+ listView.$el.find("input[name='test-attribute-checked']").click();
+ expect(listView.$el.find("input[name='test-attribute-checked']").is(':checked')).toEqual(true);
+ listView.$el.find("input[name='test-attribute-unchecked']").click();
+ expect(listView.$el.find("input[name='test-attribute-unchecked']").is(':checked')).toEqual(false);
+
+ // Update never called when clicked
+ expect(updateShareStub.called).toEqual(false);
+ });
});
});
diff --git a/core/js/tests/specs/shareitemmodelSpec.js b/core/js/tests/specs/shareitemmodelSpec.js
index c71fec21700a..261408d42f11 100644
--- a/core/js/tests/specs/shareitemmodelSpec.js
+++ b/core/js/tests/specs/shareitemmodelSpec.js
@@ -47,13 +47,13 @@ describe('OC.Share.ShareItemModel', function() {
sharePermissions: 31
});
- var attributes = {
+ var properties = {
itemType: fileInfoModel.isDirectory() ? 'folder' : 'file',
itemSource: fileInfoModel.get('id'),
possiblePermissions: fileInfoModel.get('sharePermissions')
};
configModel = new OC.Share.ShareConfigModel();
- model = new OC.Share.ShareItemModel(attributes, {
+ model = new OC.Share.ShareItemModel(properties, {
configModel: configModel,
fileInfoModel: fileInfoModel
});
@@ -118,7 +118,7 @@ describe('OC.Share.ShareItemModel', function() {
fetchReshareStub = null;
});
- it('populates attributes with parsed response', function() {
+ it('populates properties with parsed response', function() {
/* jshint camelcase: false */
fetchReshareDeferred.resolve(makeOcsResponse([
{
@@ -133,6 +133,7 @@ describe('OC.Share.ShareItemModel', function() {
id: 100,
item_source: 123,
permissions: 31,
+ attributes: '[{"scope":"test","key":"test","enabled":false}]',
share_type: OC.Share.SHARE_TYPE_USER,
share_with: 'user1',
share_with_displayname: 'User One'
@@ -140,6 +141,7 @@ describe('OC.Share.ShareItemModel', function() {
id: 101,
item_source: 123,
permissions: 31,
+ attributes: '[]',
share_type: OC.Share.SHARE_TYPE_GROUP,
share_with: 'group',
share_with_displayname: 'group'
@@ -147,6 +149,7 @@ describe('OC.Share.ShareItemModel', function() {
id: 102,
item_source: 123,
permissions: 31,
+ attributes: '[]',
share_type: OC.Share.SHARE_TYPE_REMOTE,
share_with: 'foo@bar.com/baz',
share_with_displayname: 'foo@bar.com/baz'
@@ -200,6 +203,7 @@ describe('OC.Share.ShareItemModel', function() {
expect(shares.length).toEqual(3);
expect(shares[0].id).toEqual(100);
expect(shares[0].permissions).toEqual(31);
+ expect(shares[0].attributes).toEqual([{ scope: 'test', key: 'test', enabled: false }]);
expect(shares[0].share_type).toEqual(OC.Share.SHARE_TYPE_USER);
expect(shares[0].share_with).toEqual('user1');
expect(shares[0].share_with_displayname).toEqual('User One');
@@ -587,6 +591,328 @@ describe('OC.Share.ShareItemModel', function() {
});
});
+ describe('share attributes', function() {
+ beforeEach(function() {
+ model.set({
+ reshare: {},
+ shares: [],
+ _registeredAttributes: []
+ });
+ });
+
+ /**
+ * Creates dummy attribute
+ *
+ * @return {OC.Share.Types.RegisteredShareAttribute} registered attribute
+ */
+ function createRegisteredAttribute() {
+ return {
+ scope: "test",
+ key: "test",
+ default: true,
+ label: "test",
+ shareType : [
+ OC.Share.SHARE_TYPE_GROUP,
+ OC.Share.SHARE_TYPE_USER
+ ],
+ incompatiblePermissions: [],
+ requiredPermissions: [],
+ incompatibleAttributes: []
+ };
+ }
+
+ /**
+ * Parses attributes of share creation
+ * request (request send to the server)
+ *
+ * @return {OC.Share.Types.ShareAttribute[]}
+ */
+ function parseLastRequestAttributes() {
+ var requestBody = OC.parseQueryString(fakeServer.requests[0].requestBody);
+
+ var i = -1;
+ var attributes = [];
+ _.map(Object.keys(requestBody), function(key) {
+ if (key.indexOf('attributes') !== -1) {
+ if (key.indexOf('scope') !== -1) {
+ i = i + 1;
+ attributes.push({});
+ attributes[i].scope = requestBody[key];
+ }
+ if (key.indexOf('key') !== -1) {
+ attributes[i].key = requestBody[key];
+ }
+ if (key.indexOf('enabled') !== -1) {
+ attributes[i].enabled = JSON.parse(requestBody[key]);
+ }
+ }
+ });
+
+ //console.log(requestBody);
+ return attributes;
+ }
+
+ /**
+ * Tests sharing with the given possible attributes
+ *
+ * @param {int} permissionsToSet
+ * @param {OC.Share.Types.RegisteredShareAttribute[]} attributesToRegister
+ * @param {Object} sharePropertiesToUpdate
+ * @return {OC.Share.Types.ShareAttribute[]}
+ */
+ function testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate) {
+ model.set({
+ permissions: permissionsToSet,
+ possiblePermissions: permissionsToSet
+ });
+
+ _.map(attributesToRegister, function (attributeToRegister) {
+ model.registerShareAttribute(attributeToRegister);
+ });
+
+ if (Object.keys(sharePropertiesToUpdate).length > 0) {
+ // if there are properties to update, update share
+ model.updateShare(123, sharePropertiesToUpdate, {});
+ } {
+ // no share properties to update, so new share
+ model.addShare({
+ shareType: OC.Share.SHARE_TYPE_USER,
+ shareWith: 'user2'
+ });
+ }
+
+ return parseLastRequestAttributes();
+ }
+
+ describe('new share', function() {
+
+ it('returns no attributes when no registered attributes', function () {
+ // define test
+ var permissionsToSet = OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE;
+ var attributesToRegister = [];
+ var sharePropertiesToUpdate = {};
+
+ // define expected result and test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual([]);
+ });
+
+ it('uses registered attributes as default attributes', function () {
+ // define test
+ var permissionsToSet = OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE;
+ var attr1 = createRegisteredAttribute();
+ var attributesToRegister = [
+ attr1
+ ];
+ var sharePropertiesToUpdate = {};
+
+ // define expected result
+ var attributesToExpect = [
+ {scope: "test", key: "test", enabled: true}
+ ];
+
+ // test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual(attributesToExpect);
+ });
+
+ it('properly filters registered attributes', function () {
+ var attr1 = createRegisteredAttribute();
+ attr1.key = "requires-create";
+ attr1.incompatiblePermissions = [];
+ attr1.requiredPermissions = [OC.PERMISSION_CREATE];
+ attr1.incompatibleAttributes = [];
+
+ var attr2 = createRegisteredAttribute();
+ attr2.key = "requires-update";
+ attr2.incompatiblePermissions = [];
+ attr2.requiredPermissions = [OC.PERMISSION_UPDATE];
+ attr2.incompatibleAttributes = [];
+
+ var attr3 = createRegisteredAttribute();
+ attr3.key = "incompatible-create";
+ attr3.incompatiblePermissions = [OC.PERMISSION_CREATE];
+ attr3.requiredPermissions = [];
+ attr3.incompatibleAttributes = [];
+
+ var attr4 = createRegisteredAttribute();
+ attr4.key = "incompatible-update";
+ attr4.incompatiblePermissions = [OC.PERMISSION_UPDATE];
+ attr4.requiredPermissions = [];
+ attr4.incompatibleAttributes = [];
+
+ var attr5 = createRegisteredAttribute();
+ attr5.key = "incompatible-attribute-requires-update-true";
+ attr5.incompatiblePermissions = [];
+ attr5.requiredPermissions = [];
+ attr5.incompatibleAttributes = [{
+ scope: "test",
+ key: "requires-update",
+ enabled: true
+ }];
+
+ var attr6 = createRegisteredAttribute();
+ attr6.key = "incompatible-attribute-requires-update-false";
+ attr6.incompatiblePermissions = [];
+ attr6.requiredPermissions = [];
+ attr6.incompatibleAttributes = [{
+ scope: "test",
+ key: "requires-update",
+ enabled: false
+ }];
+
+ // register attribute
+ var permissionsToSet = OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE;
+ var attributesToRegister = [
+ attr1, attr2, attr3, attr4, attr5, attr6
+ ];
+
+ // this test does not update existing share
+ var sharePropertiesToUpdate = {};
+
+ // expect that new created share will have following attributes
+ var attributesToExpect = [
+ {scope: "test", key: "requires-update", enabled: true},
+ {scope: "test", key: "incompatible-create", enabled: true},
+ {
+ scope: "test",
+ key: "incompatible-attribute-requires-update-false",
+ enabled: true
+ }
+ ];
+
+ // test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual(attributesToExpect);
+ });
+ });
+
+ describe('update share', function() {
+ it('returns no attributes when update with new attribute but none registered (error handling scenario)', function() {
+ // define test
+ var permissionsToSet = OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE;
+ var attributesToRegister = [];
+ var sharePropertiesToUpdate = {
+ attributes: [
+ { scope: "test", key: "test", enabled: false }
+ ],
+ permissions: permissionsToSet
+ };
+
+ // define expected result and test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual([]);
+ });
+
+ it('updates attribute with new enabled value correctly', function() {
+ // define test
+ var permissionsToSet = OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE;
+
+ var attr1 = createRegisteredAttribute();
+ attr1.scope = "test";
+ attr1.key = "test";
+ attr1.default = true;
+ var attributesToRegister = [attr1];
+
+ var sharePropertiesToUpdate = {
+ attributes: [
+ { scope: "test", key: "test", enabled: false }
+ ],
+ permissions: permissionsToSet
+ };
+
+ // define expected result
+ var attributesToExpect = [
+ { scope: "test", key: "test", enabled: false }
+ ];
+
+ // test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual(attributesToExpect);
+ });
+
+ it('uses/hides attributes with permission filters of registered attributes', function() {
+ // define test
+ var permissionsToSet = OC.PERMISSION_READ;
+
+ var attr1 = createRegisteredAttribute();
+ attr1.key = "incompatible-create";
+ attr1.incompatiblePermissions = [ OC.PERMISSION_CREATE ];
+ attr1.requiredPermissions = [];
+ attr1.incompatibleAttributes = [];
+ var attr2 = createRegisteredAttribute();
+ attr2.key = "required-create";
+ attr2.incompatiblePermissions = [];
+ attr2.requiredPermissions = [ OC.PERMISSION_CREATE ];
+ attr2.incompatibleAttributes = [];
+
+ var attributesToRegister = [attr1, attr2];
+
+ var sharePropertiesToUpdate = {
+ permissions: OC.PERMISSION_READ | OC.PERMISSION_CREATE
+ };
+
+ // define expected result
+ var attributesToExpect = [
+ { scope: "test", key: "required-create", enabled: true }
+ ];
+
+ // test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual(attributesToExpect);
+ });
+
+ it('uses/hides attributes with attribute filter of registered attributes when permission changes', function() {
+ // define test
+ var permissionsToSet = OC.PERMISSION_READ | OC.PERMISSION_UPDATE;
+
+ // test attribute which is enabled only without update permission
+ var attr1 = createRegisteredAttribute();
+ attr1.key = "incompatible-update";
+ attr1.incompatiblePermissions = [ OC.PERMISSION_UPDATE ];
+ attr1.requiredPermissions = [ ];
+ attr1.incompatibleAttributes = [];
+
+ // test attribute which is not available when review attr is enabled
+ var attr2 = createRegisteredAttribute();
+ attr2.key = "incompatible-with-attribute";
+ attr2.incompatiblePermissions = [];
+ attr2.requiredPermissions = [];
+ attr2.incompatibleAttributes = [{ scope: "test", key: "incompatible-update", enabled: true }];
+
+ // test attribute that can always be registered
+ var attr3 = createRegisteredAttribute();
+ attr3.key = "test-attribute";
+ attr3.incompatiblePermissions = [];
+ attr3.requiredPermissions = [];
+ attr3.incompatibleAttributes = [];
+
+ var attributesToRegister = [attr1, attr2, attr3];
+
+ var sharePropertiesToUpdate = {
+ permissions: OC.PERMISSION_READ
+ };
+
+ // define expected result - restricted-options should not appear
+ var attributesToExpect = [
+ { scope: "test", key: "incompatible-update", enabled: true },
+ { scope: "test", key: "test-attribute", enabled: true }
+ ];
+
+ // test
+ expect(
+ testShareWithAttributes(permissionsToSet, attributesToRegister, sharePropertiesToUpdate)
+ ).toEqual(attributesToExpect);
+ });
+ });
+ });
+
describe('creating shares', function() {
it('sends POST method to endpoint with passed values', function() {
model.addShare({