cozy-sharing 37.3.0 → 37.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +11 -0
- package/dist/SharingProvider.js +16 -16
- package/dist/SharingProvider.spec.js +5 -0
- package/dist/queries/queries.js +0 -9
- package/dist/state.js +24 -50
- package/dist/state.spec.js +6 -11
- package/package.json +3 -3
- package/src/SharingProvider.jsx +6 -6
- package/src/SharingProvider.spec.jsx +1 -0
- package/src/queries/queries.js +0 -8
- package/src/state.js +21 -37
- package/src/state.spec.js +6 -12
- package/tsconfig.json +4 -0
- package/types.d.ts +46 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [37.5.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@37.4.0...cozy-sharing@37.5.0) (2026-08-25)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **cozy-sharing:** Export recipient types ([ca5fd55](https://github.com/cozy/cozy-libs/commit/ca5fd554471320993cd89eaca33a65a09d2ecc46))
|
|
11
|
+
|
|
12
|
+
# [37.4.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@37.3.0...cozy-sharing@37.4.0) (2026-08-25)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- Build sharing link staticaly instead of using io.cozy.apps ([285f608](https://github.com/cozy/cozy-libs/commit/285f60883c5f60c5c306a2d7a0a7f00c6d1de238))
|
|
17
|
+
|
|
6
18
|
# [37.3.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@37.2.12...cozy-sharing@37.3.0) (2026-08-24)
|
|
7
19
|
|
|
8
20
|
### Features
|
package/README.md
CHANGED
|
@@ -82,6 +82,17 @@ const MyComp = () => {
|
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### Recipient types
|
|
86
|
+
|
|
87
|
+
`SharingMember` and `SharingGroup` model the values returned by the stack.
|
|
88
|
+
`cozy-sharing` adds display metadata and returns `SharingMemberRecipient` or
|
|
89
|
+
`SharingGroupRecipient` from its recipient selectors. TypeScript consumers can
|
|
90
|
+
use their union when both are possible:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import type { SharingRecipient } from 'cozy-sharing/types'
|
|
94
|
+
```
|
|
95
|
+
|
|
85
96
|
***
|
|
86
97
|
|
|
87
98
|
## How it works
|
package/dist/SharingProvider.js
CHANGED
|
@@ -40,7 +40,6 @@ import { fetchFilesPaths } from './helpers/files';
|
|
|
40
40
|
import { getSharingObject, createSharingInStore, updateSharingInStore } from './helpers/sharings';
|
|
41
41
|
import { getShortcode } from './helpers/shortcodes';
|
|
42
42
|
import { SynchronousJobQueue } from './helpers/synchronousJobQueue';
|
|
43
|
-
import { fetchApps } from './queries/queries';
|
|
44
43
|
import reducer, { receiveSharings, addSharing, updateSharing, addSharingLink, updateSharingLink, revokeSharingLink, revokeRecipient, revokeGroup as revokeGroupFromState, revokeSelf, receivePaths, isOwner as _isOwner, isSharedDrive as _isSharedDrive, isOrgSharedDrive as _isOrgSharedDrive, canLeave as _canLeave, canReshare as _canReshare, getOwner as _getOwner, getRecipients as _getRecipients, getSharingById as _getSharingById, getExternalSharingIds, getSharingForSelf as _getSharingForSelf, getSharingType as _getSharingType, getSharingLink as _getSharingLink, getSharedDocIdsBySharings, getDocumentSharing, getDocumentPermissions as _getDocumentPermissions, getPermissionDocIds, hasSharedParent as _hasSharedParent, hasSharedChild as _hasSharedChild, getSharedParentPath as _getSharedParentPath, getSharedDriveSharingType, SHARING_TYPE } from './state';
|
|
45
44
|
var log = minilog('SharingProvider');
|
|
46
45
|
var SHARING_DOCTYPE = 'io.cozy.sharings';
|
|
@@ -1156,6 +1155,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
|
|
|
1156
1155
|
});
|
|
1157
1156
|
|
|
1158
1157
|
var _instanceUri = props.client.getStackClient().uri;
|
|
1158
|
+
var subDomainType = props.client.getInstanceOptions().subdomain;
|
|
1159
1159
|
var documentType = props.documentType || 'Document';
|
|
1160
1160
|
|
|
1161
1161
|
var onShared = props.onShared || function () {};
|
|
@@ -1167,6 +1167,8 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
|
|
|
1167
1167
|
permissions: [],
|
|
1168
1168
|
sharedFolderPaths: [],
|
|
1169
1169
|
documentType: documentType,
|
|
1170
|
+
instanceUri: _instanceUri,
|
|
1171
|
+
subDomainType: subDomainType,
|
|
1170
1172
|
isOwner: function isOwner(docId) {
|
|
1171
1173
|
return _isOwner(_this2.state, docId);
|
|
1172
1174
|
},
|
|
@@ -1266,7 +1268,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
|
|
|
1266
1268
|
key: "fetchAllSharings",
|
|
1267
1269
|
value: function () {
|
|
1268
1270
|
var _fetchAllSharings = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
|
|
1269
|
-
var _this$props, doctype, client, _yield$Promise$all, _yield$Promise$all2, sharings, permissions,
|
|
1271
|
+
var _this$props, doctype, client, _yield$Promise$all, _yield$Promise$all2, sharings, permissions, sharedDocIds, resp, folderPaths, filePaths;
|
|
1270
1272
|
|
|
1271
1273
|
return _regeneratorRuntime.wrap(function _callee21$(_context21) {
|
|
1272
1274
|
while (1) switch (_context21.prev = _context21.next) {
|
|
@@ -1288,60 +1290,58 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
|
|
|
1288
1290
|
_context21.next = 7;
|
|
1289
1291
|
return Promise.all([this.sharingCol.findByDoctype(doctype, {
|
|
1290
1292
|
withSharedDocs: false
|
|
1291
|
-
}), this.permissionCol.findLinksByDoctype(doctype)
|
|
1293
|
+
}), this.permissionCol.findLinksByDoctype(doctype)]);
|
|
1292
1294
|
|
|
1293
1295
|
case 7:
|
|
1294
1296
|
_yield$Promise$all = _context21.sent;
|
|
1295
|
-
_yield$Promise$all2 = _slicedToArray(_yield$Promise$all,
|
|
1297
|
+
_yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
|
|
1296
1298
|
sharings = _yield$Promise$all2[0];
|
|
1297
1299
|
permissions = _yield$Promise$all2[1];
|
|
1298
|
-
apps = _yield$Promise$all2[2];
|
|
1299
1300
|
this.dispatch(receiveSharings({
|
|
1300
1301
|
instanceUri: client.options.uri,
|
|
1301
1302
|
sharings: sharings.data,
|
|
1302
|
-
permissions: permissions.data
|
|
1303
|
-
apps: apps.data
|
|
1303
|
+
permissions: permissions.data
|
|
1304
1304
|
}));
|
|
1305
1305
|
this.setState({
|
|
1306
1306
|
hasLoadedAtLeastOnePage: true
|
|
1307
1307
|
});
|
|
1308
|
-
_context21.next =
|
|
1308
|
+
_context21.next = 15;
|
|
1309
1309
|
return fetchNextPermissions(permissions, this.dispatch, this.permissionCol);
|
|
1310
1310
|
|
|
1311
|
-
case
|
|
1311
|
+
case 15:
|
|
1312
1312
|
if (!(doctype === 'io.cozy.files')) {
|
|
1313
|
-
_context21.next =
|
|
1313
|
+
_context21.next = 25;
|
|
1314
1314
|
break;
|
|
1315
1315
|
}
|
|
1316
1316
|
|
|
1317
1317
|
sharedDocIds = getSharedDocIdsBySharings(sharings);
|
|
1318
|
-
_context21.next =
|
|
1318
|
+
_context21.next = 19;
|
|
1319
1319
|
return client.collection(doctype).all({
|
|
1320
1320
|
keys: sharedDocIds
|
|
1321
1321
|
});
|
|
1322
1322
|
|
|
1323
|
-
case
|
|
1323
|
+
case 19:
|
|
1324
1324
|
resp = _context21.sent;
|
|
1325
1325
|
folderPaths = resp.data.filter(function (f) {
|
|
1326
1326
|
return f.type === 'directory' && !f.trashed;
|
|
1327
1327
|
}).map(function (f) {
|
|
1328
1328
|
return f.path;
|
|
1329
1329
|
});
|
|
1330
|
-
_context21.next =
|
|
1330
|
+
_context21.next = 23;
|
|
1331
1331
|
return fetchFilesPaths(client, doctype, resp.data.filter(function (f) {
|
|
1332
1332
|
return f.type !== 'directory' && !f.trashed;
|
|
1333
1333
|
}));
|
|
1334
1334
|
|
|
1335
|
-
case
|
|
1335
|
+
case 23:
|
|
1336
1336
|
filePaths = _context21.sent;
|
|
1337
1337
|
this.dispatch(receivePaths([].concat(_toConsumableArray(folderPaths), _toConsumableArray(filePaths))));
|
|
1338
1338
|
|
|
1339
|
-
case
|
|
1339
|
+
case 25:
|
|
1340
1340
|
this.setState({
|
|
1341
1341
|
allLoaded: true
|
|
1342
1342
|
});
|
|
1343
1343
|
|
|
1344
|
-
case
|
|
1344
|
+
case 26:
|
|
1345
1345
|
case "end":
|
|
1346
1346
|
return _context21.stop();
|
|
1347
1347
|
}
|
|
@@ -1081,6 +1081,11 @@ describe('updateSharingMemberType', function () {
|
|
|
1081
1081
|
uri: 'http://cozy.local'
|
|
1082
1082
|
};
|
|
1083
1083
|
},
|
|
1084
|
+
getInstanceOptions: function getInstanceOptions() {
|
|
1085
|
+
return {
|
|
1086
|
+
subdomain: 'nested'
|
|
1087
|
+
};
|
|
1088
|
+
},
|
|
1084
1089
|
collection: jest.fn().mockReturnValue({})
|
|
1085
1090
|
};
|
|
1086
1091
|
instance = setupProvider(mockClient, {}, _objectSpread(_objectSpread({}, reducer()), {}, {
|
package/dist/queries/queries.js
CHANGED
|
@@ -2,15 +2,6 @@ import { Q, fetchPolicies } from 'cozy-client';
|
|
|
2
2
|
import { Contact, Group } from '../models';
|
|
3
3
|
var DEFAULT_CACHE_TIMEOUT_QUERIES = 9 * 60 * 1000;
|
|
4
4
|
var defaultFetchPolicy = fetchPolicies.olderThan(DEFAULT_CACHE_TIMEOUT_QUERIES);
|
|
5
|
-
export var fetchApps = function fetchApps() {
|
|
6
|
-
return {
|
|
7
|
-
definition: Q('io.cozy.apps'),
|
|
8
|
-
options: {
|
|
9
|
-
as: 'io.cozy.apps',
|
|
10
|
-
fetchPolicy: defaultFetchPolicy
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
5
|
export var buildSharingsByIdQuery = function buildSharingsByIdQuery(sharingId) {
|
|
15
6
|
return {
|
|
16
7
|
definition: Q('io.cozy.sharings').getById(sharingId),
|
package/dist/state.js
CHANGED
|
@@ -10,6 +10,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
10
10
|
|
|
11
11
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
12
12
|
|
|
13
|
+
import { generateWebLink } from 'cozy-client';
|
|
13
14
|
import flag from 'cozy-flags';
|
|
14
15
|
import { getShortcode } from './helpers/shortcodes';
|
|
15
16
|
var RECEIVE_SHARINGS = 'RECEIVE_SHARINGS';
|
|
@@ -32,9 +33,7 @@ export var receiveSharings = function receiveSharings(_ref) {
|
|
|
32
33
|
_ref$sharings = _ref.sharings,
|
|
33
34
|
sharings = _ref$sharings === void 0 ? [] : _ref$sharings,
|
|
34
35
|
_ref$permissions = _ref.permissions,
|
|
35
|
-
permissions = _ref$permissions === void 0 ? [] : _ref$permissions
|
|
36
|
-
_ref$apps = _ref.apps,
|
|
37
|
-
apps = _ref$apps === void 0 ? [] : _ref$apps;
|
|
36
|
+
permissions = _ref$permissions === void 0 ? [] : _ref$permissions;
|
|
38
37
|
return {
|
|
39
38
|
type: RECEIVE_SHARINGS,
|
|
40
39
|
data: {
|
|
@@ -43,8 +42,7 @@ export var receiveSharings = function receiveSharings(_ref) {
|
|
|
43
42
|
(isSharingADrive(s) || !areAllRecipientsRevoked(s)) && !hasBeenSelfRevoked(s, instanceUri)
|
|
44
43
|
);
|
|
45
44
|
}),
|
|
46
|
-
permissions: permissions
|
|
47
|
-
apps: apps
|
|
45
|
+
permissions: permissions
|
|
48
46
|
}
|
|
49
47
|
};
|
|
50
48
|
};
|
|
@@ -302,19 +300,6 @@ var permissions = function permissions() {
|
|
|
302
300
|
}
|
|
303
301
|
};
|
|
304
302
|
|
|
305
|
-
var apps = function apps() {
|
|
306
|
-
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
307
|
-
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
308
|
-
|
|
309
|
-
switch (action.type) {
|
|
310
|
-
case RECEIVE_SHARINGS:
|
|
311
|
-
return action.data.apps;
|
|
312
|
-
|
|
313
|
-
default:
|
|
314
|
-
return state;
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
|
-
|
|
318
303
|
var sharings = function sharings() {
|
|
319
304
|
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
320
305
|
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
@@ -395,7 +380,6 @@ var reducer = function reducer() {
|
|
|
395
380
|
byDocId: byDocId(state.byDocId, action),
|
|
396
381
|
sharings: sharings(state.sharings, action),
|
|
397
382
|
permissions: permissions(state.permissions, action),
|
|
398
|
-
apps: apps(state.apps, action),
|
|
399
383
|
sharedPaths: sharedPaths(state.sharedPaths, action)
|
|
400
384
|
};
|
|
401
385
|
};
|
|
@@ -446,10 +430,14 @@ export var getOwner = function getOwner(state, docId) {
|
|
|
446
430
|
return r.status === 'owner';
|
|
447
431
|
});
|
|
448
432
|
};
|
|
433
|
+
/** @returns {import('../types').SharingRecipient[]} */
|
|
434
|
+
|
|
449
435
|
export var getRecipients = function getRecipients(state, docId) {
|
|
450
436
|
var sharings = getDocumentSharings(state, docId);
|
|
451
437
|
return getRecipientsFromSharings(sharings, docId);
|
|
452
438
|
};
|
|
439
|
+
/** @returns {import('../types').SharingRecipient[]} */
|
|
440
|
+
|
|
453
441
|
export var getRecipientsFromSharing = function getRecipientsFromSharing(sharing, docId) {
|
|
454
442
|
if (!sharing) {
|
|
455
443
|
return [];
|
|
@@ -482,6 +470,8 @@ var getRecipientType = function getRecipientType(sharing, member, documentType)
|
|
|
482
470
|
|
|
483
471
|
return documentType;
|
|
484
472
|
};
|
|
473
|
+
/** @returns {import('../types').SharingMemberRecipient[]} */
|
|
474
|
+
|
|
485
475
|
|
|
486
476
|
var getRecipientsWithoutGroups = function getRecipientsWithoutGroups(sharings, docId) {
|
|
487
477
|
var recipients = sharings.map(function (sharing) {
|
|
@@ -509,6 +499,8 @@ var getRecipientsWithoutGroups = function getRecipientsWithoutGroups(sharings, d
|
|
|
509
499
|
|
|
510
500
|
return recipients;
|
|
511
501
|
};
|
|
502
|
+
/** @returns {import('../types').SharingRecipient[]} */
|
|
503
|
+
|
|
512
504
|
|
|
513
505
|
export var getRecipientsWithGroups = function getRecipientsWithGroups(sharings, docId) {
|
|
514
506
|
var recipients = sharings.flatMap(function (sharing) {
|
|
@@ -616,10 +608,6 @@ var getPermissionById = function getPermissionById(state, id) {
|
|
|
616
608
|
});
|
|
617
609
|
};
|
|
618
610
|
|
|
619
|
-
var getApps = function getApps(state) {
|
|
620
|
-
return state.apps;
|
|
621
|
-
};
|
|
622
|
-
|
|
623
611
|
export var hasSharedParent = function hasSharedParent(state, documentPath) {
|
|
624
612
|
if (!state.sharedPaths || !documentPath) {
|
|
625
613
|
return false; // hasSharedParent should not occur
|
|
@@ -785,47 +773,33 @@ export var isReadOnlySharing = function isReadOnlySharing(sharing, docId) {
|
|
|
785
773
|
return directorySharingType === SHARING_TYPE.TWO_WAY || fileSharingType === SHARING_TYPE.TWO_WAY ? false : true;
|
|
786
774
|
};
|
|
787
775
|
|
|
788
|
-
var
|
|
789
|
-
var appUrl = getAppUrlForDoctype(state, documentType);
|
|
790
|
-
|
|
776
|
+
var getSlugForDoctype = function getSlugForDoctype(documentType) {
|
|
791
777
|
switch (documentType) {
|
|
792
778
|
case 'Notes':
|
|
793
|
-
return
|
|
794
|
-
|
|
795
|
-
default:
|
|
796
|
-
return "".concat(appUrl, "public?sharecode=").concat(sharecode);
|
|
797
|
-
}
|
|
798
|
-
};
|
|
799
|
-
|
|
800
|
-
var getAppUrlForDoctype = function getAppUrlForDoctype(state, documentType) {
|
|
801
|
-
var apps = getApps(state);
|
|
802
|
-
|
|
803
|
-
switch (documentType) {
|
|
804
|
-
case 'Notes':
|
|
805
|
-
return getAppUrl(apps, 'notes');
|
|
779
|
+
return 'notes';
|
|
806
780
|
|
|
807
781
|
case 'Files':
|
|
808
782
|
case 'Document':
|
|
809
|
-
return
|
|
783
|
+
return 'drive';
|
|
810
784
|
|
|
811
785
|
case 'Albums':
|
|
812
|
-
return
|
|
786
|
+
return 'photos';
|
|
813
787
|
|
|
814
788
|
default:
|
|
815
789
|
throw new Error("Sharing link: don't know which app to use for doctype ".concat(documentType));
|
|
816
790
|
}
|
|
817
791
|
};
|
|
818
792
|
|
|
819
|
-
var
|
|
820
|
-
var
|
|
821
|
-
|
|
793
|
+
var buildSharingLink = function buildSharingLink(state, documentType, sharecode) {
|
|
794
|
+
var slug = getSlugForDoctype(documentType);
|
|
795
|
+
var link = generateWebLink({
|
|
796
|
+
cozyUrl: state.instanceUri,
|
|
797
|
+
slug: slug,
|
|
798
|
+
subDomainType: state.subDomainType,
|
|
799
|
+
pathname: slug === 'notes' ? '/public/' : '/public',
|
|
800
|
+
searchParams: [['sharecode', sharecode]]
|
|
822
801
|
});
|
|
823
|
-
|
|
824
|
-
if (!app) {
|
|
825
|
-
throw new Error("Sharing link: app ".concat(appName, " not installed"));
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
return app.links.related;
|
|
802
|
+
return link.replace(/#\/$/, '');
|
|
829
803
|
};
|
|
830
804
|
/**
|
|
831
805
|
*
|
package/dist/state.spec.js
CHANGED
|
@@ -5,7 +5,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
5
5
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
6
|
|
|
7
7
|
import reducer, { receiveSharings, addSharing, addSharingLink, updateSharingLink, revokeSharingLink, getRecipients, getRecipientsFromSharing, revokeGroup, revokeRecipient, revokeSelf, updateSharing, matchingInstanceName, getSharingLink, hasSharedParent, hasSharedChild, getSharedDocIdsBySharings, getSharingType, getPermissionDocIds, getDocumentSharingType, getSharedParentPath, getExternalSharingIds, getRecipientsWithGroups } from './state';
|
|
8
|
-
import { SHARING_1, SHARING_2, SHARING_3, SHARING_READ_ONLY, PERM_1, PERM_2, PERM_WITHOUT_DOC, SHARING_NO_ACTIVE, SHARING_WITH_SHORTCUT
|
|
8
|
+
import { SHARING_1, SHARING_2, SHARING_3, SHARING_READ_ONLY, PERM_1, PERM_2, PERM_WITHOUT_DOC, SHARING_NO_ACTIVE, SHARING_WITH_SHORTCUT } from '../__tests__/fixtures';
|
|
9
9
|
describe('Sharing state', function () {
|
|
10
10
|
it('should have a default state', function () {
|
|
11
11
|
var state = reducer();
|
|
@@ -13,7 +13,6 @@ describe('Sharing state', function () {
|
|
|
13
13
|
byDocId: {},
|
|
14
14
|
sharings: [],
|
|
15
15
|
permissions: [],
|
|
16
|
-
apps: [],
|
|
17
16
|
sharedPaths: []
|
|
18
17
|
});
|
|
19
18
|
});
|
|
@@ -392,8 +391,7 @@ describe('Sharing state', function () {
|
|
|
392
391
|
describe('selectors', function () {
|
|
393
392
|
var state = reducer(reducer(reducer(undefined, receiveSharings({
|
|
394
393
|
sharings: [SHARING_1, SHARING_2, SHARING_2, SHARING_WITH_SHORTCUT],
|
|
395
|
-
permissions: [PERM_1]
|
|
396
|
-
apps: APPS
|
|
394
|
+
permissions: [PERM_1]
|
|
397
395
|
})), addSharing(SHARING_3)), addSharing(SHARING_3));
|
|
398
396
|
it('should list all sharing recipients for a doc', function () {
|
|
399
397
|
expect(getRecipients(state, 'folder_1')).toEqual([{
|
|
@@ -532,23 +530,20 @@ describe('generating a sharing link', function () {
|
|
|
532
530
|
beforeEach(function () {
|
|
533
531
|
state = reducer(reducer(undefined, receiveSharings({
|
|
534
532
|
sharings: [SHARING_1, SHARING_2],
|
|
535
|
-
permissions: [PERM_1, PERM_2]
|
|
536
|
-
apps: APPS
|
|
533
|
+
permissions: [PERM_1, PERM_2]
|
|
537
534
|
})));
|
|
535
|
+
state.instanceUri = 'https://cozy.tools';
|
|
536
|
+
state.subDomainType = 'nested';
|
|
538
537
|
});
|
|
539
538
|
it('should use the correct app', function () {
|
|
540
539
|
expect(getSharingLink(state, 'folder_1', 'Document')).toBe('https://drive.cozy.tools/public?sharecode=longcode');
|
|
541
540
|
expect(getSharingLink(state, 'folder_1', 'Files')).toBe('https://drive.cozy.tools/public?sharecode=longcode');
|
|
542
541
|
expect(getSharingLink(state, 'folder_1', 'Albums')).toBe('https://photos.cozy.tools/public?sharecode=longcode');
|
|
543
542
|
});
|
|
544
|
-
it('should throw when no
|
|
543
|
+
it('should throw when no doctype mapping is found', function () {
|
|
545
544
|
expect(function () {
|
|
546
545
|
return getSharingLink(state, 'folder_1', 'made up for the test');
|
|
547
546
|
}).toThrow("Sharing link: don't know which app to use for doctype made up for the test");
|
|
548
|
-
state.apps = [];
|
|
549
|
-
expect(function () {
|
|
550
|
-
return getSharingLink(state, 'folder_1', 'Document');
|
|
551
|
-
}).toThrow('Sharing link: app drive not installed');
|
|
552
547
|
});
|
|
553
548
|
it('should use long codes', function () {
|
|
554
549
|
expect(getSharingLink(state, 'folder_1', 'Document')).toBe('https://drive.cozy.tools/public?sharecode=longcode');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "37.
|
|
3
|
+
"version": "37.5.0",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"cozy-intent": "^2.31.1",
|
|
60
60
|
"cozy-minilog": "^3.10.1",
|
|
61
61
|
"cozy-ui": "^140.5.0",
|
|
62
|
-
"cozy-ui-plus": "^12.3.
|
|
62
|
+
"cozy-ui-plus": "^12.3.9",
|
|
63
63
|
"jest": "30.3.0",
|
|
64
64
|
"jest-environment-jsdom": "30.3.0",
|
|
65
65
|
"react": "16.12.0",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"sideEffects": [
|
|
86
86
|
"*.css"
|
|
87
87
|
],
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "814149b46bd8ddbc22384fd5dda8a14dc41ee806"
|
|
89
89
|
}
|
package/src/SharingProvider.jsx
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
} from './helpers/sharings'
|
|
18
18
|
import { getShortcode } from './helpers/shortcodes'
|
|
19
19
|
import { SynchronousJobQueue } from './helpers/synchronousJobQueue'
|
|
20
|
-
import { fetchApps } from './queries/queries'
|
|
21
20
|
import reducer, {
|
|
22
21
|
receiveSharings,
|
|
23
22
|
addSharing,
|
|
@@ -62,6 +61,7 @@ export class SharingProvider extends Component {
|
|
|
62
61
|
constructor(props, context) {
|
|
63
62
|
super(props, context)
|
|
64
63
|
const instanceUri = props.client.getStackClient().uri
|
|
64
|
+
const subDomainType = props.client.getInstanceOptions().subdomain
|
|
65
65
|
const documentType = props.documentType || 'Document'
|
|
66
66
|
const onShared = props.onShared || (() => {})
|
|
67
67
|
|
|
@@ -72,6 +72,8 @@ export class SharingProvider extends Component {
|
|
|
72
72
|
permissions: [],
|
|
73
73
|
sharedFolderPaths: [],
|
|
74
74
|
documentType,
|
|
75
|
+
instanceUri,
|
|
76
|
+
subDomainType,
|
|
75
77
|
isOwner: docId => isOwner(this.state, docId),
|
|
76
78
|
isSharedDrive: docId => isSharedDrive(this.state, docId),
|
|
77
79
|
isOrgSharedDrive: docId => isOrgSharedDrive(this.state, docId),
|
|
@@ -207,17 +209,15 @@ export class SharingProvider extends Component {
|
|
|
207
209
|
return
|
|
208
210
|
}
|
|
209
211
|
const { doctype, client } = this.props
|
|
210
|
-
const [sharings, permissions
|
|
212
|
+
const [sharings, permissions] = await Promise.all([
|
|
211
213
|
this.sharingCol.findByDoctype(doctype, { withSharedDocs: false }),
|
|
212
|
-
this.permissionCol.findLinksByDoctype(doctype)
|
|
213
|
-
client.fetchQueryAndGetFromState(fetchApps())
|
|
214
|
+
this.permissionCol.findLinksByDoctype(doctype)
|
|
214
215
|
])
|
|
215
216
|
this.dispatch(
|
|
216
217
|
receiveSharings({
|
|
217
218
|
instanceUri: client.options.uri,
|
|
218
219
|
sharings: sharings.data,
|
|
219
|
-
permissions: permissions.data
|
|
220
|
-
apps: apps.data
|
|
220
|
+
permissions: permissions.data
|
|
221
221
|
})
|
|
222
222
|
)
|
|
223
223
|
this.setState({ hasLoadedAtLeastOnePage: true })
|
|
@@ -778,6 +778,7 @@ describe('updateSharingMemberType', () => {
|
|
|
778
778
|
beforeEach(() => {
|
|
779
779
|
const mockClient = {
|
|
780
780
|
getStackClient: () => ({ uri: 'http://cozy.local' }),
|
|
781
|
+
getInstanceOptions: () => ({ subdomain: 'nested' }),
|
|
781
782
|
collection: jest.fn().mockReturnValue({})
|
|
782
783
|
}
|
|
783
784
|
|
package/src/queries/queries.js
CHANGED
|
@@ -8,14 +8,6 @@ const defaultFetchPolicy = fetchPolicies.olderThan(
|
|
|
8
8
|
DEFAULT_CACHE_TIMEOUT_QUERIES
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
export const fetchApps = () => ({
|
|
12
|
-
definition: Q('io.cozy.apps'),
|
|
13
|
-
options: {
|
|
14
|
-
as: 'io.cozy.apps',
|
|
15
|
-
fetchPolicy: defaultFetchPolicy
|
|
16
|
-
}
|
|
17
|
-
})
|
|
18
|
-
|
|
19
11
|
export const buildSharingsByIdQuery = sharingId => ({
|
|
20
12
|
definition: Q('io.cozy.sharings').getById(sharingId),
|
|
21
13
|
options: {
|
package/src/state.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { generateWebLink } from 'cozy-client'
|
|
1
2
|
import flag from 'cozy-flags'
|
|
2
3
|
|
|
3
4
|
import { getShortcode } from './helpers/shortcodes'
|
|
@@ -21,8 +22,7 @@ export const SHARING_TYPE = {
|
|
|
21
22
|
export const receiveSharings = ({
|
|
22
23
|
instanceUri,
|
|
23
24
|
sharings = [],
|
|
24
|
-
permissions = []
|
|
25
|
-
apps = []
|
|
25
|
+
permissions = []
|
|
26
26
|
}) => ({
|
|
27
27
|
type: RECEIVE_SHARINGS,
|
|
28
28
|
data: {
|
|
@@ -32,8 +32,7 @@ export const receiveSharings = ({
|
|
|
32
32
|
(isSharingADrive(s) || !areAllRecipientsRevoked(s)) &&
|
|
33
33
|
!hasBeenSelfRevoked(s, instanceUri)
|
|
34
34
|
),
|
|
35
|
-
permissions
|
|
36
|
-
apps
|
|
35
|
+
permissions
|
|
37
36
|
}
|
|
38
37
|
})
|
|
39
38
|
export const addSharing = (data, path) => ({
|
|
@@ -231,15 +230,6 @@ const permissions = (state = [], action) => {
|
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
232
|
|
|
234
|
-
const apps = (state = [], action) => {
|
|
235
|
-
switch (action.type) {
|
|
236
|
-
case RECEIVE_SHARINGS:
|
|
237
|
-
return action.data.apps
|
|
238
|
-
default:
|
|
239
|
-
return state
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
233
|
const sharings = (state = [], action) => {
|
|
244
234
|
switch (action.type) {
|
|
245
235
|
case RECEIVE_SHARINGS:
|
|
@@ -295,7 +285,6 @@ const reducer = (state = {}, action = {}) => ({
|
|
|
295
285
|
byDocId: byDocId(state.byDocId, action),
|
|
296
286
|
sharings: sharings(state.sharings, action),
|
|
297
287
|
permissions: permissions(state.permissions, action),
|
|
298
|
-
apps: apps(state.apps, action),
|
|
299
288
|
sharedPaths: sharedPaths(state.sharedPaths, action)
|
|
300
289
|
})
|
|
301
290
|
export default reducer
|
|
@@ -352,11 +341,13 @@ export const canReshare = (state, docId, instanceUri) => {
|
|
|
352
341
|
export const getOwner = (state, docId) =>
|
|
353
342
|
getRecipients(state, docId).find(r => r.status === 'owner')
|
|
354
343
|
|
|
344
|
+
/** @returns {import('../types').SharingRecipient[]} */
|
|
355
345
|
export const getRecipients = (state, docId) => {
|
|
356
346
|
const sharings = getDocumentSharings(state, docId)
|
|
357
347
|
return getRecipientsFromSharings(sharings, docId)
|
|
358
348
|
}
|
|
359
349
|
|
|
350
|
+
/** @returns {import('../types').SharingRecipient[]} */
|
|
360
351
|
export const getRecipientsFromSharing = (sharing, docId) => {
|
|
361
352
|
if (!sharing) {
|
|
362
353
|
return []
|
|
@@ -390,6 +381,7 @@ const getRecipientType = (sharing, member, documentType) => {
|
|
|
390
381
|
return documentType
|
|
391
382
|
}
|
|
392
383
|
|
|
384
|
+
/** @returns {import('../types').SharingMemberRecipient[]} */
|
|
393
385
|
const getRecipientsWithoutGroups = (sharings, docId) => {
|
|
394
386
|
const recipients = sharings
|
|
395
387
|
.map(sharing => {
|
|
@@ -411,6 +403,7 @@ const getRecipientsWithoutGroups = (sharings, docId) => {
|
|
|
411
403
|
return recipients
|
|
412
404
|
}
|
|
413
405
|
|
|
406
|
+
/** @returns {import('../types').SharingRecipient[]} */
|
|
414
407
|
export const getRecipientsWithGroups = (sharings, docId) => {
|
|
415
408
|
const recipients = sharings.flatMap(sharing => {
|
|
416
409
|
const type = getDocumentSharingType(sharing, docId)
|
|
@@ -503,8 +496,6 @@ export const getDocumentPermissions = (state, docId) =>
|
|
|
503
496
|
const getPermissionById = (state, id) =>
|
|
504
497
|
state.permissions.find(s => s.id === id)
|
|
505
498
|
|
|
506
|
-
const getApps = state => state.apps
|
|
507
|
-
|
|
508
499
|
export const hasSharedParent = (state, documentPath) => {
|
|
509
500
|
if (!state.sharedPaths || !documentPath) {
|
|
510
501
|
return false // hasSharedParent should not occur
|
|
@@ -666,26 +657,15 @@ export const isReadOnlySharing = (sharing, docId) => {
|
|
|
666
657
|
: true
|
|
667
658
|
}
|
|
668
659
|
|
|
669
|
-
const
|
|
670
|
-
const appUrl = getAppUrlForDoctype(state, documentType)
|
|
671
|
-
switch (documentType) {
|
|
672
|
-
case 'Notes':
|
|
673
|
-
return `${appUrl}public/?sharecode=${sharecode}`
|
|
674
|
-
default:
|
|
675
|
-
return `${appUrl}public?sharecode=${sharecode}`
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
const getAppUrlForDoctype = (state, documentType) => {
|
|
680
|
-
const apps = getApps(state)
|
|
660
|
+
const getSlugForDoctype = documentType => {
|
|
681
661
|
switch (documentType) {
|
|
682
662
|
case 'Notes':
|
|
683
|
-
return
|
|
663
|
+
return 'notes'
|
|
684
664
|
case 'Files':
|
|
685
665
|
case 'Document':
|
|
686
|
-
return
|
|
666
|
+
return 'drive'
|
|
687
667
|
case 'Albums':
|
|
688
|
-
return
|
|
668
|
+
return 'photos'
|
|
689
669
|
default:
|
|
690
670
|
throw new Error(
|
|
691
671
|
`Sharing link: don't know which app to use for doctype ${documentType}`
|
|
@@ -693,12 +673,16 @@ const getAppUrlForDoctype = (state, documentType) => {
|
|
|
693
673
|
}
|
|
694
674
|
}
|
|
695
675
|
|
|
696
|
-
const
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
676
|
+
const buildSharingLink = (state, documentType, sharecode) => {
|
|
677
|
+
const slug = getSlugForDoctype(documentType)
|
|
678
|
+
const link = generateWebLink({
|
|
679
|
+
cozyUrl: state.instanceUri,
|
|
680
|
+
slug,
|
|
681
|
+
subDomainType: state.subDomainType,
|
|
682
|
+
pathname: slug === 'notes' ? '/public/' : '/public',
|
|
683
|
+
searchParams: [['sharecode', sharecode]]
|
|
684
|
+
})
|
|
685
|
+
return link.replace(/#\/$/, '')
|
|
702
686
|
}
|
|
703
687
|
|
|
704
688
|
/**
|
package/src/state.spec.js
CHANGED
|
@@ -31,8 +31,7 @@ import {
|
|
|
31
31
|
PERM_2,
|
|
32
32
|
PERM_WITHOUT_DOC,
|
|
33
33
|
SHARING_NO_ACTIVE,
|
|
34
|
-
SHARING_WITH_SHORTCUT
|
|
35
|
-
APPS
|
|
34
|
+
SHARING_WITH_SHORTCUT
|
|
36
35
|
} from '../__tests__/fixtures'
|
|
37
36
|
|
|
38
37
|
describe('Sharing state', () => {
|
|
@@ -42,7 +41,6 @@ describe('Sharing state', () => {
|
|
|
42
41
|
byDocId: {},
|
|
43
42
|
sharings: [],
|
|
44
43
|
permissions: [],
|
|
45
|
-
apps: [],
|
|
46
44
|
sharedPaths: []
|
|
47
45
|
})
|
|
48
46
|
})
|
|
@@ -509,8 +507,7 @@ describe('Sharing state', () => {
|
|
|
509
507
|
undefined,
|
|
510
508
|
receiveSharings({
|
|
511
509
|
sharings: [SHARING_1, SHARING_2, SHARING_2, SHARING_WITH_SHORTCUT],
|
|
512
|
-
permissions: [PERM_1]
|
|
513
|
-
apps: APPS
|
|
510
|
+
permissions: [PERM_1]
|
|
514
511
|
})
|
|
515
512
|
),
|
|
516
513
|
addSharing(SHARING_3)
|
|
@@ -677,11 +674,12 @@ describe('generating a sharing link', () => {
|
|
|
677
674
|
undefined,
|
|
678
675
|
receiveSharings({
|
|
679
676
|
sharings: [SHARING_1, SHARING_2],
|
|
680
|
-
permissions: [PERM_1, PERM_2]
|
|
681
|
-
apps: APPS
|
|
677
|
+
permissions: [PERM_1, PERM_2]
|
|
682
678
|
})
|
|
683
679
|
)
|
|
684
680
|
)
|
|
681
|
+
state.instanceUri = 'https://cozy.tools'
|
|
682
|
+
state.subDomainType = 'nested'
|
|
685
683
|
})
|
|
686
684
|
|
|
687
685
|
it('should use the correct app', () => {
|
|
@@ -696,16 +694,12 @@ describe('generating a sharing link', () => {
|
|
|
696
694
|
)
|
|
697
695
|
})
|
|
698
696
|
|
|
699
|
-
it('should throw when no
|
|
697
|
+
it('should throw when no doctype mapping is found', () => {
|
|
700
698
|
expect(() =>
|
|
701
699
|
getSharingLink(state, 'folder_1', 'made up for the test')
|
|
702
700
|
).toThrow(
|
|
703
701
|
"Sharing link: don't know which app to use for doctype made up for the test"
|
|
704
702
|
)
|
|
705
|
-
state.apps = []
|
|
706
|
-
expect(() => getSharingLink(state, 'folder_1', 'Document')).toThrow(
|
|
707
|
-
'Sharing link: app drive not installed'
|
|
708
|
-
)
|
|
709
703
|
})
|
|
710
704
|
|
|
711
705
|
it('should use long codes', () => {
|
package/tsconfig.json
ADDED
package/types.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Member fields returned by the stack sharing API. */
|
|
2
|
+
export interface SharingMember {
|
|
3
|
+
email?: string
|
|
4
|
+
groups?: number[]
|
|
5
|
+
instance?: string
|
|
6
|
+
name?: string
|
|
7
|
+
only_in_groups?: boolean
|
|
8
|
+
public_name?: string
|
|
9
|
+
read_only?: boolean
|
|
10
|
+
status: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Group fields returned by the stack sharing API. */
|
|
14
|
+
export interface SharingGroup {
|
|
15
|
+
addedBy: number
|
|
16
|
+
color?: string
|
|
17
|
+
id?: string
|
|
18
|
+
name: string
|
|
19
|
+
read_only: boolean
|
|
20
|
+
revoked?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Member enriched by cozy-sharing for display. */
|
|
24
|
+
export type SharingMemberRecipient = SharingMember & {
|
|
25
|
+
avatarPath: string
|
|
26
|
+
/** Stable display identifier generated by cozy-sharing. */
|
|
27
|
+
index: string
|
|
28
|
+
/** Position in the members array returned by the stack. */
|
|
29
|
+
memberIndex: number
|
|
30
|
+
sharingId: string
|
|
31
|
+
type: 'one-way' | 'two-way'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Group enriched by cozy-sharing for display. */
|
|
35
|
+
export type SharingGroupRecipient = SharingGroup & {
|
|
36
|
+
/** Position in the groups array returned by the stack. */
|
|
37
|
+
groupIndex: number
|
|
38
|
+
/** Stable display identifier generated by cozy-sharing. */
|
|
39
|
+
index: string
|
|
40
|
+
members: SharingMemberRecipient[]
|
|
41
|
+
owner: SharingMemberRecipient
|
|
42
|
+
sharingId: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Member or group returned by cozy-sharing recipient selectors. */
|
|
46
|
+
export type SharingRecipient = SharingMemberRecipient | SharingGroupRecipient
|