shareitemmodel.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. /*
  2. * Copyright (c) 2015
  3. *
  4. * This file is licensed under the Affero General Public License version 3
  5. * or later.
  6. *
  7. * See the COPYING-README file.
  8. *
  9. */
  10. (function() {
  11. if(!OC.Share) {
  12. OC.Share = {};
  13. OC.Share.Types = {};
  14. }
  15. /**
  16. * @typedef {object} OC.Share.Types.LinkShareInfo
  17. * @property {bool} isLinkShare
  18. * @property {string} token
  19. * @property {string|null} password
  20. * @property {string} link
  21. * @property {number} permissions
  22. * @property {Date} expiration
  23. * @property {number} stime share time
  24. */
  25. /**
  26. * @typedef {object} OC.Share.Types.Reshare
  27. * @property {string} uid_owner
  28. * @property {number} share_type
  29. * @property {string} share_with
  30. * @property {string} displayname_owner
  31. * @property {number} permissions
  32. */
  33. /**
  34. * @typedef {object} OC.Share.Types.ShareInfo
  35. * @property {number} share_type
  36. * @property {number} permissions
  37. * @property {number} file_source optional
  38. * @property {number} item_source
  39. * @property {string} token
  40. * @property {string} share_with
  41. * @property {string} share_with_displayname
  42. * @property {string} mail_send
  43. * @property {Date} expiration optional?
  44. * @property {number} stime optional?
  45. * @property {string} uid_owner
  46. * @property {string} displayname_owner
  47. */
  48. /**
  49. * @typedef {object} OC.Share.Types.ShareItemInfo
  50. * @property {OC.Share.Types.Reshare} reshare
  51. * @property {OC.Share.Types.ShareInfo[]} shares
  52. * @property {OC.Share.Types.LinkShareInfo|undefined} linkShare
  53. */
  54. /**
  55. * These properties are sometimes returned by the server as strings instead
  56. * of integers, so we need to convert them accordingly...
  57. */
  58. var SHARE_RESPONSE_INT_PROPS = [
  59. 'id', 'file_parent', 'mail_send', 'file_source', 'item_source', 'permissions',
  60. 'storage', 'share_type', 'parent', 'stime'
  61. ];
  62. /**
  63. * @class OCA.Share.ShareItemModel
  64. * @classdesc
  65. *
  66. * Represents the GUI of the share dialogue
  67. *
  68. * // FIXME: use OC Share API once #17143 is done
  69. *
  70. * // TODO: this really should be a collection of share item models instead,
  71. * where the link share is one of them
  72. */
  73. var ShareItemModel = OC.Backbone.Model.extend({
  74. /**
  75. * @type share id of the link share, if applicable
  76. */
  77. _linkShareId: null,
  78. initialize: function(attributes, options) {
  79. if(!_.isUndefined(options.configModel)) {
  80. this.configModel = options.configModel;
  81. }
  82. if(!_.isUndefined(options.fileInfoModel)) {
  83. /** @type {OC.Files.FileInfo} **/
  84. this.fileInfoModel = options.fileInfoModel;
  85. }
  86. _.bindAll(this, 'addShare');
  87. },
  88. defaults: {
  89. allowPublicUploadStatus: false,
  90. permissions: 0,
  91. linkShare: {}
  92. },
  93. /**
  94. * Saves the current link share information.
  95. *
  96. * This will trigger an ajax call and, if successful, refetch the model
  97. * afterwards. Callbacks "success", "error" and "complete" can be given
  98. * in the options object; "success" is called after a successful save
  99. * once the model is refetch, "error" is called after a failed save, and
  100. * "complete" is called both after a successful save and after a failed
  101. * save. Note that "complete" is called before "success" and "error" are
  102. * called (unlike in jQuery, in which it is called after them); this
  103. * ensures that "complete" is called even if refetching the model fails.
  104. *
  105. * TODO: this should be a separate model
  106. */
  107. saveLinkShare: function(attributes, options) {
  108. options = options || {};
  109. attributes = _.extend({}, attributes);
  110. var shareId = null;
  111. var call;
  112. // oh yeah...
  113. if (attributes.expiration) {
  114. attributes.expireDate = attributes.expiration;
  115. delete attributes.expiration;
  116. }
  117. if (this.get('linkShare') && this.get('linkShare').isLinkShare) {
  118. shareId = this.get('linkShare').id;
  119. // note: update can only update a single value at a time
  120. call = this.updateShare(shareId, attributes, options);
  121. } else {
  122. attributes = _.defaults(attributes, {
  123. password: '',
  124. passwordChanged: false,
  125. permissions: OC.PERMISSION_READ,
  126. expireDate: this.configModel.getDefaultExpirationDateString(),
  127. shareType: OC.Share.SHARE_TYPE_LINK
  128. });
  129. call = this.addShare(attributes, options);
  130. }
  131. return call;
  132. },
  133. removeLinkShare: function() {
  134. if (this.get('linkShare')) {
  135. return this.removeShare(this.get('linkShare').id);
  136. }
  137. },
  138. addShare: function(attributes, options) {
  139. var shareType = attributes.shareType;
  140. attributes = _.extend({}, attributes);
  141. // Default permissions are Edit (CRUD) and Share
  142. // Check if these permissions are possible
  143. var permissions = OC.PERMISSION_READ;
  144. if (this.updatePermissionPossible()) {
  145. permissions = permissions | OC.PERMISSION_UPDATE;
  146. }
  147. if (this.createPermissionPossible()) {
  148. permissions = permissions | OC.PERMISSION_CREATE;
  149. }
  150. if (this.deletePermissionPossible()) {
  151. permissions = permissions | OC.PERMISSION_DELETE;
  152. }
  153. if (this.configModel.get('isResharingAllowed') && (this.sharePermissionPossible())) {
  154. permissions = permissions | OC.PERMISSION_SHARE;
  155. }
  156. attributes.permissions = permissions;
  157. if (_.isUndefined(attributes.path)) {
  158. attributes.path = this.fileInfoModel.getFullPath();
  159. }
  160. return this._addOrUpdateShare({
  161. type: 'POST',
  162. url: this._getUrl('shares'),
  163. data: attributes,
  164. dataType: 'json'
  165. }, options);
  166. },
  167. updateShare: function(shareId, attrs, options) {
  168. return this._addOrUpdateShare({
  169. type: 'PUT',
  170. url: this._getUrl('shares/' + encodeURIComponent(shareId)),
  171. data: attrs,
  172. dataType: 'json'
  173. }, options);
  174. },
  175. _addOrUpdateShare: function(ajaxSettings, options) {
  176. var self = this;
  177. options = options || {};
  178. return $.ajax(
  179. ajaxSettings
  180. ).always(function() {
  181. if (_.isFunction(options.complete)) {
  182. options.complete(self);
  183. }
  184. }).done(function() {
  185. self.fetch().done(function() {
  186. if (_.isFunction(options.success)) {
  187. options.success(self);
  188. }
  189. });
  190. }).fail(function(xhr) {
  191. var msg = t('core', 'Error');
  192. var result = xhr.responseJSON;
  193. if (result && result.ocs && result.ocs.meta) {
  194. msg = result.ocs.meta.message;
  195. }
  196. if (_.isFunction(options.error)) {
  197. options.error(self, msg);
  198. } else {
  199. OC.dialogs.alert(msg, t('core', 'Error while sharing'));
  200. }
  201. });
  202. },
  203. /**
  204. * Deletes the share with the given id
  205. *
  206. * @param {int} shareId share id
  207. * @return {jQuery}
  208. */
  209. removeShare: function(shareId, options) {
  210. var self = this;
  211. options = options || {};
  212. return $.ajax({
  213. type: 'DELETE',
  214. url: this._getUrl('shares/' + encodeURIComponent(shareId)),
  215. }).done(function() {
  216. self.fetch({
  217. success: function() {
  218. if (_.isFunction(options.success)) {
  219. options.success(self);
  220. }
  221. }
  222. });
  223. }).fail(function(xhr) {
  224. var msg = t('core', 'Error');
  225. var result = xhr.responseJSON;
  226. if (result.ocs && result.ocs.meta) {
  227. msg = result.ocs.meta.message;
  228. }
  229. if (_.isFunction(options.error)) {
  230. options.error(self, msg);
  231. } else {
  232. OC.dialogs.alert(msg, t('core', 'Error removing share'));
  233. }
  234. });
  235. },
  236. /**
  237. * @returns {boolean}
  238. */
  239. isPublicUploadAllowed: function() {
  240. return this.get('allowPublicUploadStatus');
  241. },
  242. isPublicEditingAllowed: function() {
  243. return this.get('allowPublicEditingStatus');
  244. },
  245. /**
  246. * @returns {boolean}
  247. */
  248. isHideFileListSet: function() {
  249. return this.get('hideFileListStatus');
  250. },
  251. /**
  252. * @returns {boolean}
  253. */
  254. isFolder: function() {
  255. return this.get('itemType') === 'folder';
  256. },
  257. /**
  258. * @returns {boolean}
  259. */
  260. isFile: function() {
  261. return this.get('itemType') === 'file';
  262. },
  263. /**
  264. * whether this item has reshare information
  265. * @returns {boolean}
  266. */
  267. hasReshare: function() {
  268. var reshare = this.get('reshare');
  269. return _.isObject(reshare) && !_.isUndefined(reshare.uid_owner);
  270. },
  271. /**
  272. * whether this item has user share information
  273. * @returns {boolean}
  274. */
  275. hasUserShares: function() {
  276. return this.getSharesWithCurrentItem().length > 0;
  277. },
  278. /**
  279. * Returns whether this item has a link share
  280. *
  281. * @return {bool} true if a link share exists, false otherwise
  282. */
  283. hasLinkShare: function() {
  284. var linkShare = this.get('linkShare');
  285. if (linkShare && linkShare.isLinkShare) {
  286. return true;
  287. }
  288. return false;
  289. },
  290. /**
  291. * @returns {string}
  292. */
  293. getReshareOwner: function() {
  294. return this.get('reshare').uid_owner;
  295. },
  296. /**
  297. * @returns {string}
  298. */
  299. getReshareOwnerDisplayname: function() {
  300. return this.get('reshare').displayname_owner;
  301. },
  302. /**
  303. * @returns {string}
  304. */
  305. getReshareWith: function() {
  306. return this.get('reshare').share_with;
  307. },
  308. /**
  309. * @returns {string}
  310. */
  311. getReshareWithDisplayName: function() {
  312. var reshare = this.get('reshare');
  313. return reshare.share_with_displayname || reshare.share_with;
  314. },
  315. /**
  316. * @returns {number}
  317. */
  318. getReshareType: function() {
  319. return this.get('reshare').share_type;
  320. },
  321. getExpireDate: function(shareIndex) {
  322. return this._shareExpireDate(shareIndex);
  323. },
  324. /**
  325. * Returns all share entries that only apply to the current item
  326. * (file/folder)
  327. *
  328. * @return {Array.<OC.Share.Types.ShareInfo>}
  329. */
  330. getSharesWithCurrentItem: function() {
  331. var shares = this.get('shares') || [];
  332. var fileId = this.fileInfoModel.get('id');
  333. return _.filter(shares, function(share) {
  334. return share.item_source === fileId;
  335. });
  336. },
  337. /**
  338. * @param shareIndex
  339. * @returns {string}
  340. */
  341. getShareWith: function(shareIndex) {
  342. /** @type OC.Share.Types.ShareInfo **/
  343. var share = this.get('shares')[shareIndex];
  344. if(!_.isObject(share)) {
  345. throw "Unknown Share";
  346. }
  347. return share.share_with;
  348. },
  349. /**
  350. * @param shareIndex
  351. * @returns {string}
  352. */
  353. getShareWithDisplayName: function(shareIndex) {
  354. /** @type OC.Share.Types.ShareInfo **/
  355. var share = this.get('shares')[shareIndex];
  356. if(!_.isObject(share)) {
  357. throw "Unknown Share";
  358. }
  359. return share.share_with_displayname;
  360. },
  361. /**
  362. * @param shareIndex
  363. * @returns {string}
  364. */
  365. getSharedBy: function(shareIndex) {
  366. /** @type OC.Share.Types.ShareInfo **/
  367. var share = this.get('shares')[shareIndex];
  368. if(!_.isObject(share)) {
  369. throw "Unknown Share";
  370. }
  371. return share.uid_owner;
  372. },
  373. /**
  374. * @param shareIndex
  375. * @returns {string}
  376. */
  377. getSharedByDisplayName: function(shareIndex) {
  378. /** @type OC.Share.Types.ShareInfo **/
  379. var share = this.get('shares')[shareIndex];
  380. if(!_.isObject(share)) {
  381. throw "Unknown Share";
  382. }
  383. return share.displayname_owner;
  384. },
  385. /**
  386. * returns the array index of a sharee for a provided shareId
  387. *
  388. * @param shareId
  389. * @returns {number}
  390. */
  391. findShareWithIndex: function(shareId) {
  392. var shares = this.get('shares');
  393. if(!_.isArray(shares)) {
  394. throw "Unknown Share";
  395. }
  396. for(var i = 0; i < shares.length; i++) {
  397. var shareWith = shares[i];
  398. if(shareWith.id === shareId) {
  399. return i;
  400. }
  401. }
  402. throw "Unknown Sharee";
  403. },
  404. getShareType: function(shareIndex) {
  405. /** @type OC.Share.Types.ShareInfo **/
  406. var share = this.get('shares')[shareIndex];
  407. if(!_.isObject(share)) {
  408. throw "Unknown Share";
  409. }
  410. return share.share_type;
  411. },
  412. /**
  413. * whether a share from shares has the requested permission
  414. *
  415. * @param {number} shareIndex
  416. * @param {number} permission
  417. * @returns {boolean}
  418. * @private
  419. */
  420. _shareHasPermission: function(shareIndex, permission) {
  421. /** @type OC.Share.Types.ShareInfo **/
  422. var share = this.get('shares')[shareIndex];
  423. if(!_.isObject(share)) {
  424. throw "Unknown Share";
  425. }
  426. return (share.permissions & permission) === permission;
  427. },
  428. _shareExpireDate: function(shareIndex) {
  429. var share = this.get('shares')[shareIndex];
  430. if(!_.isObject(share)) {
  431. throw "Unknown Share";
  432. }
  433. var date2 = share.expiration;
  434. return date2;
  435. },
  436. /**
  437. * @return {int}
  438. */
  439. getPermissions: function() {
  440. return this.get('permissions');
  441. },
  442. /**
  443. * @returns {boolean}
  444. */
  445. sharePermissionPossible: function() {
  446. return (this.get('permissions') & OC.PERMISSION_SHARE) === OC.PERMISSION_SHARE;
  447. },
  448. /**
  449. * @param {number} shareIndex
  450. * @returns {boolean}
  451. */
  452. hasSharePermission: function(shareIndex) {
  453. return this._shareHasPermission(shareIndex, OC.PERMISSION_SHARE);
  454. },
  455. /**
  456. * @returns {boolean}
  457. */
  458. createPermissionPossible: function() {
  459. return (this.get('permissions') & OC.PERMISSION_CREATE) === OC.PERMISSION_CREATE;
  460. },
  461. /**
  462. * @param {number} shareIndex
  463. * @returns {boolean}
  464. */
  465. hasCreatePermission: function(shareIndex) {
  466. return this._shareHasPermission(shareIndex, OC.PERMISSION_CREATE);
  467. },
  468. /**
  469. * @returns {boolean}
  470. */
  471. updatePermissionPossible: function() {
  472. return (this.get('permissions') & OC.PERMISSION_UPDATE) === OC.PERMISSION_UPDATE;
  473. },
  474. /**
  475. * @param {number} shareIndex
  476. * @returns {boolean}
  477. */
  478. hasUpdatePermission: function(shareIndex) {
  479. return this._shareHasPermission(shareIndex, OC.PERMISSION_UPDATE);
  480. },
  481. /**
  482. * @returns {boolean}
  483. */
  484. deletePermissionPossible: function() {
  485. return (this.get('permissions') & OC.PERMISSION_DELETE) === OC.PERMISSION_DELETE;
  486. },
  487. /**
  488. * @param {number} shareIndex
  489. * @returns {boolean}
  490. */
  491. hasDeletePermission: function(shareIndex) {
  492. return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE);
  493. },
  494. hasReadPermission: function(shareIndex) {
  495. return this._shareHasPermission(shareIndex, OC.PERMISSION_READ);
  496. },
  497. /**
  498. * @returns {boolean}
  499. */
  500. editPermissionPossible: function() {
  501. return this.createPermissionPossible()
  502. || this.updatePermissionPossible()
  503. || this.deletePermissionPossible();
  504. },
  505. /**
  506. * @returns {boolean}
  507. */
  508. hasEditPermission: function(shareIndex) {
  509. return this.hasCreatePermission(shareIndex)
  510. || this.hasUpdatePermission(shareIndex)
  511. || this.hasDeletePermission(shareIndex);
  512. },
  513. /**
  514. * @returns {int}
  515. */
  516. linkSharePermissions: function() {
  517. if (!this.hasLinkShare()) {
  518. return -1;
  519. } else {
  520. return this.get('linkShare').permissions;
  521. }
  522. },
  523. _getUrl: function(base, params) {
  524. params = _.extend({format: 'json'}, params || {});
  525. return OC.linkToOCS('apps/files_sharing/api/v1', 2) + base + '?' + OC.buildQueryString(params);
  526. },
  527. _fetchShares: function() {
  528. var path = this.fileInfoModel.getFullPath();
  529. return $.ajax({
  530. type: 'GET',
  531. url: this._getUrl('shares', {path: path, reshares: true})
  532. });
  533. },
  534. _fetchReshare: function() {
  535. // only fetch original share once
  536. if (!this._reshareFetched) {
  537. var path = this.fileInfoModel.getFullPath();
  538. this._reshareFetched = true;
  539. return $.ajax({
  540. type: 'GET',
  541. url: this._getUrl('shares', {path: path, shared_with_me: true})
  542. });
  543. } else {
  544. return $.Deferred().resolve([{
  545. ocs: {
  546. data: [this.get('reshare')]
  547. }
  548. }]);
  549. }
  550. },
  551. /**
  552. * Group reshares into a single super share element.
  553. * Does this by finding the most precise share and
  554. * combines the permissions to be the most permissive.
  555. *
  556. * @param {Array} reshares
  557. * @return {Object} reshare
  558. */
  559. _groupReshares: function(reshares) {
  560. if (!reshares || !reshares.length) {
  561. return false;
  562. }
  563. var superShare = reshares.shift();
  564. var combinedPermissions = superShare.permissions;
  565. _.each(reshares, function(reshare) {
  566. // use share have higher priority than group share
  567. if (reshare.share_type === OC.Share.SHARE_TYPE_USER && superShare.share_type === OC.Share.SHARE_TYPE_GROUP) {
  568. superShare = reshare;
  569. }
  570. combinedPermissions |= reshare.permissions;
  571. });
  572. superShare.permissions = combinedPermissions;
  573. return superShare;
  574. },
  575. fetch: function(options) {
  576. var model = this;
  577. this.trigger('request', this);
  578. var deferred = $.when(
  579. this._fetchShares(),
  580. this._fetchReshare()
  581. );
  582. deferred.done(function(data1, data2) {
  583. model.trigger('sync', 'GET', this);
  584. var sharesMap = {};
  585. _.each(data1[0].ocs.data, function(shareItem) {
  586. sharesMap[shareItem.id] = shareItem;
  587. });
  588. var reshare = false;
  589. if (data2[0].ocs.data.length) {
  590. reshare = model._groupReshares(data2[0].ocs.data);
  591. }
  592. model.set(model.parse({
  593. shares: sharesMap,
  594. reshare: reshare
  595. }));
  596. if(!_.isUndefined(options) && _.isFunction(options.success)) {
  597. options.success();
  598. }
  599. });
  600. return deferred;
  601. },
  602. /**
  603. * Updates OC.Share.itemShares and OC.Share.statuses.
  604. *
  605. * This is required in case the user navigates away and comes back,
  606. * the share statuses from the old arrays are still used to fill in the icons
  607. * in the file list.
  608. */
  609. _legacyFillCurrentShares: function(shares) {
  610. var fileId = this.fileInfoModel.get('id');
  611. if (!shares || !shares.length) {
  612. delete OC.Share.statuses[fileId];
  613. OC.Share.currentShares = {};
  614. OC.Share.itemShares = [];
  615. return;
  616. }
  617. var currentShareStatus = OC.Share.statuses[fileId];
  618. if (!currentShareStatus) {
  619. currentShareStatus = {link: false};
  620. OC.Share.statuses[fileId] = currentShareStatus;
  621. }
  622. currentShareStatus.link = false;
  623. OC.Share.currentShares = {};
  624. OC.Share.itemShares = [];
  625. _.each(shares,
  626. /**
  627. * @param {OC.Share.Types.ShareInfo} share
  628. */
  629. function(share) {
  630. if (share.share_type === OC.Share.SHARE_TYPE_LINK) {
  631. OC.Share.itemShares[share.share_type] = true;
  632. currentShareStatus.link = true;
  633. } else {
  634. if (!OC.Share.itemShares[share.share_type]) {
  635. OC.Share.itemShares[share.share_type] = [];
  636. }
  637. OC.Share.itemShares[share.share_type].push(share.share_with);
  638. }
  639. }
  640. );
  641. },
  642. parse: function(data) {
  643. if(data === false) {
  644. console.warn('no data was returned');
  645. this.trigger('fetchError');
  646. return {};
  647. }
  648. var permissions = this.get('possiblePermissions');
  649. if(!_.isUndefined(data.reshare) && !_.isUndefined(data.reshare.permissions) && data.reshare.uid_owner !== OC.currentUser) {
  650. permissions = permissions & data.reshare.permissions;
  651. }
  652. var allowPublicUploadStatus = false;
  653. if(!_.isUndefined(data.shares)) {
  654. $.each(data.shares, function (key, value) {
  655. if (value.share_type === OC.Share.SHARE_TYPE_LINK) {
  656. allowPublicUploadStatus = (value.permissions & OC.PERMISSION_CREATE) ? true : false;
  657. return true;
  658. }
  659. });
  660. }
  661. var allowPublicEditingStatus = true;
  662. if(!_.isUndefined(data.shares)) {
  663. $.each(data.shares, function (key, value) {
  664. if (value.share_type === OC.Share.SHARE_TYPE_LINK) {
  665. allowPublicEditingStatus = (value.permissions & OC.PERMISSION_UPDATE) ? true : false;
  666. return true;
  667. }
  668. });
  669. }
  670. var hideFileListStatus = false;
  671. if(!_.isUndefined(data.shares)) {
  672. $.each(data.shares, function (key, value) {
  673. if (value.share_type === OC.Share.SHARE_TYPE_LINK) {
  674. hideFileListStatus = (value.permissions & OC.PERMISSION_READ) ? false : true;
  675. return true;
  676. }
  677. });
  678. }
  679. /** @type {OC.Share.Types.ShareInfo[]} **/
  680. var shares = _.map(data.shares, function(share) {
  681. // properly parse some values because sometimes the server
  682. // returns integers as string...
  683. var i;
  684. for (i = 0; i < SHARE_RESPONSE_INT_PROPS.length; i++) {
  685. var prop = SHARE_RESPONSE_INT_PROPS[i];
  686. if (!_.isUndefined(share[prop])) {
  687. share[prop] = parseInt(share[prop], 10);
  688. }
  689. }
  690. return share;
  691. });
  692. this._legacyFillCurrentShares(shares);
  693. var linkShare = { isLinkShare: false };
  694. // filter out the share by link
  695. shares = _.reject(shares,
  696. /**
  697. * @param {OC.Share.Types.ShareInfo} share
  698. */
  699. function(share) {
  700. var isShareLink =
  701. share.share_type === OC.Share.SHARE_TYPE_LINK
  702. && ( share.file_source === this.get('itemSource')
  703. || share.item_source === this.get('itemSource'));
  704. if (isShareLink) {
  705. /*
  706. * Ignore reshared link shares for now
  707. * FIXME: Find a way to display properly
  708. */
  709. if (share.uid_owner !== OC.currentUser) {
  710. return;
  711. }
  712. var link = window.location.protocol + '//' + window.location.host;
  713. if (!share.token) {
  714. // pre-token link
  715. var fullPath = this.fileInfoModel.get('path') + '/' +
  716. this.fileInfoModel.get('name');
  717. var location = '/' + OC.currentUser + '/files' + fullPath;
  718. var type = this.fileInfoModel.isDirectory() ? 'folder' : 'file';
  719. link += OC.linkTo('', 'public.php') + '?service=files&' +
  720. type + '=' + encodeURIComponent(location);
  721. } else {
  722. link += OC.generateUrl('/s/') + share.token;
  723. }
  724. linkShare = {
  725. isLinkShare: true,
  726. id: share.id,
  727. token: share.token,
  728. password: share.share_with,
  729. link: link,
  730. permissions: share.permissions,
  731. // currently expiration is only effective for link shares.
  732. expiration: share.expiration,
  733. stime: share.stime
  734. };
  735. return share;
  736. }
  737. },
  738. this
  739. );
  740. return {
  741. reshare: data.reshare,
  742. shares: shares,
  743. linkShare: linkShare,
  744. permissions: permissions,
  745. allowPublicUploadStatus: allowPublicUploadStatus,
  746. allowPublicEditingStatus: allowPublicEditingStatus,
  747. hideFileListStatus: hideFileListStatus
  748. };
  749. },
  750. /**
  751. * Parses a string to an valid integer (unix timestamp)
  752. * @param time
  753. * @returns {*}
  754. * @internal Only used to work around a bug in the backend
  755. */
  756. _parseTime: function(time) {
  757. if (_.isString(time)) {
  758. // skip empty strings and hex values
  759. if (time === '' || (time.length > 1 && time[0] === '0' && time[1] === 'x')) {
  760. return null;
  761. }
  762. time = parseInt(time, 10);
  763. if(isNaN(time)) {
  764. time = null;
  765. }
  766. }
  767. return time;
  768. },
  769. /**
  770. * Returns a list of share types from the existing shares.
  771. *
  772. * @return {Array.<int>} array of share types
  773. */
  774. getShareTypes: function() {
  775. var result;
  776. result = _.pluck(this.getSharesWithCurrentItem(), 'share_type');
  777. if (this.hasLinkShare()) {
  778. result.push(OC.Share.SHARE_TYPE_LINK);
  779. }
  780. return _.uniq(result);
  781. }
  782. });
  783. OC.Share.ShareItemModel = ShareItemModel;
  784. })();