cozy-harvest-lib 7.0.0 → 7.2.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 +44 -0
- package/dist/components/Routes.js +3 -1
- package/dist/models/ConnectionFlow.js +105 -15
- package/dist/models/ConnectionFlow.spec.js +108 -14
- package/package.json +4 -4
- package/src/components/Routes.jsx +2 -0
- package/src/models/ConnectionFlow.js +48 -0
- package/src/models/ConnectionFlow.spec.js +57 -0
- package/test/fixtures.js +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,50 @@
|
|
|
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
|
+
# [7.2.0](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@7.1.1...cozy-harvest-lib@7.2.0) (2022-01-31)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add the defaultFolderPath attribute to the account ([1e80f81](https://github.com/cozy/cozy-libs/commit/1e80f81))
|
|
12
|
+
* Some naming improvements + unit tests ([bc7e10d](https://github.com/cozy/cozy-libs/commit/bc7e10d))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## [7.1.1](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@7.1.0...cozy-harvest-lib@7.1.1) (2022-01-28)
|
|
19
|
+
|
|
20
|
+
**Note:** Version bump only for package cozy-harvest-lib
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# [7.1.0](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@7.0.1...cozy-harvest-lib@7.1.0) (2022-01-20)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Bug Fixes
|
|
30
|
+
|
|
31
|
+
* Setup visibility in the router ([8d67b3d](https://github.com/cozy/cozy-libs/commit/8d67b3d))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
* Do not allow multi accounts features for clientSide konnectors ([1a9d157](https://github.com/cozy/cozy-libs/commit/1a9d157))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## [7.0.1](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@7.0.0...cozy-harvest-lib@7.0.1) (2022-01-07)
|
|
43
|
+
|
|
44
|
+
**Note:** Version bump only for package cozy-harvest-lib
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
6
50
|
# [7.0.0](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@6.15.2...cozy-harvest-lib@7.0.0) (2022-01-07)
|
|
7
51
|
|
|
8
52
|
|
|
@@ -82,7 +82,9 @@ var Routes = function Routes(_ref) {
|
|
|
82
82
|
konnector: konnector,
|
|
83
83
|
accountId: match.params.accountId,
|
|
84
84
|
accountsAndTriggers: accountsAndTriggers,
|
|
85
|
-
onDismiss: onDismiss
|
|
85
|
+
onDismiss: onDismiss,
|
|
86
|
+
showNewAccountButton: !konnector.clientSide,
|
|
87
|
+
showAccountSelection: !konnector.clientSide
|
|
86
88
|
});
|
|
87
89
|
}
|
|
88
90
|
}), /*#__PURE__*/React.createElement(Route, {
|
|
@@ -20,6 +20,7 @@ import MicroEE from 'microee';
|
|
|
20
20
|
import get from 'lodash/get';
|
|
21
21
|
import Realtime from 'cozy-realtime';
|
|
22
22
|
import flag from 'cozy-flags';
|
|
23
|
+
import { Q } from 'cozy-client';
|
|
23
24
|
import { fetchReusableAccount, saveAccount as _saveAccount, ACCOUNTS_DOCTYPE } from '../connections/accounts';
|
|
24
25
|
import clone from 'lodash/clone';
|
|
25
26
|
import { launchTrigger, prepareTriggerAccount, fetchTrigger, ensureTrigger } from '../connections/triggers';
|
|
@@ -730,13 +731,21 @@ export var ConnectionFlow = /*#__PURE__*/function () {
|
|
|
730
731
|
|
|
731
732
|
case 5:
|
|
732
733
|
ensuredTrigger = _context9.sent;
|
|
734
|
+
_context9.next = 8;
|
|
735
|
+
return this.ensureDefaultFolderPathInAccount(client, {
|
|
736
|
+
trigger: ensuredTrigger,
|
|
737
|
+
account: account,
|
|
738
|
+
konnector: konnector
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
case 8:
|
|
733
742
|
logger.info("Trigger is ".concat(ensuredTrigger._id));
|
|
734
743
|
this.trigger = ensuredTrigger;
|
|
735
744
|
this.emit(UPDATE_EVENT);
|
|
736
|
-
_context9.next =
|
|
745
|
+
_context9.next = 13;
|
|
737
746
|
return this.launch();
|
|
738
747
|
|
|
739
|
-
case
|
|
748
|
+
case 13:
|
|
740
749
|
case "end":
|
|
741
750
|
return _context9.stop();
|
|
742
751
|
}
|
|
@@ -750,6 +759,87 @@ export var ConnectionFlow = /*#__PURE__*/function () {
|
|
|
750
759
|
|
|
751
760
|
return ensureTriggerAndLaunch;
|
|
752
761
|
}()
|
|
762
|
+
/**
|
|
763
|
+
* Ensures there is a defaultFolderPath attribute in the account
|
|
764
|
+
* if any folder is needed by the connector.
|
|
765
|
+
* The account is saved if any change is done to it.
|
|
766
|
+
* This defaultFolderPath is needed by the stack to recreate the
|
|
767
|
+
* destination folder if removed by any mean : drive application,
|
|
768
|
+
* desktop application etc
|
|
769
|
+
*
|
|
770
|
+
* @param {CozyClient} client - A cozy client
|
|
771
|
+
* @param {io.cozy.triggers} options.trigger
|
|
772
|
+
* @param {io.cozy.accounts} options.account
|
|
773
|
+
* @param {io.cozy.konnectors} options.konnector
|
|
774
|
+
*/
|
|
775
|
+
|
|
776
|
+
}, {
|
|
777
|
+
key: "ensureDefaultFolderPathInAccount",
|
|
778
|
+
value: function () {
|
|
779
|
+
var _ensureDefaultFolderPathInAccount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10(client, _ref4) {
|
|
780
|
+
var trigger, account, konnector, folderId, folder, result, savedAccount;
|
|
781
|
+
return _regeneratorRuntime.wrap(function _callee10$(_context10) {
|
|
782
|
+
while (1) {
|
|
783
|
+
switch (_context10.prev = _context10.next) {
|
|
784
|
+
case 0:
|
|
785
|
+
trigger = _ref4.trigger, account = _ref4.account, konnector = _ref4.konnector;
|
|
786
|
+
folderId = get(trigger, 'message.folder_to_save');
|
|
787
|
+
|
|
788
|
+
if (folderId) {
|
|
789
|
+
_context10.next = 4;
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return _context10.abrupt("return", account);
|
|
794
|
+
|
|
795
|
+
case 4:
|
|
796
|
+
_context10.prev = 4;
|
|
797
|
+
_context10.next = 7;
|
|
798
|
+
return client.query(Q('io.cozy.files').getById(folderId));
|
|
799
|
+
|
|
800
|
+
case 7:
|
|
801
|
+
result = _context10.sent;
|
|
802
|
+
folder = result.data;
|
|
803
|
+
_context10.next = 15;
|
|
804
|
+
break;
|
|
805
|
+
|
|
806
|
+
case 11:
|
|
807
|
+
_context10.prev = 11;
|
|
808
|
+
_context10.t0 = _context10["catch"](4);
|
|
809
|
+
logger.warn("ConnectionFlow.ensureDefaultFolderPath: folder ".concat(folderId, " does not exist. Could not ensure defaultFolderPath. ").concat(_context10.t0.message));
|
|
810
|
+
return _context10.abrupt("return", account);
|
|
811
|
+
|
|
812
|
+
case 15:
|
|
813
|
+
if (!(folder.path !== account.defaultFolderPath)) {
|
|
814
|
+
_context10.next = 21;
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
account.defaultFolderPath = folder.path;
|
|
819
|
+
_context10.next = 19;
|
|
820
|
+
return _saveAccount(client, konnector, account);
|
|
821
|
+
|
|
822
|
+
case 19:
|
|
823
|
+
savedAccount = _context10.sent;
|
|
824
|
+
return _context10.abrupt("return", savedAccount);
|
|
825
|
+
|
|
826
|
+
case 21:
|
|
827
|
+
return _context10.abrupt("return", account);
|
|
828
|
+
|
|
829
|
+
case 22:
|
|
830
|
+
case "end":
|
|
831
|
+
return _context10.stop();
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}, _callee10, null, [[4, 11]]);
|
|
835
|
+
}));
|
|
836
|
+
|
|
837
|
+
function ensureDefaultFolderPathInAccount(_x9, _x10) {
|
|
838
|
+
return _ensureDefaultFolderPathInAccount.apply(this, arguments);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
return ensureDefaultFolderPathInAccount;
|
|
842
|
+
}()
|
|
753
843
|
/**
|
|
754
844
|
* Launches the job and sets everything up to follow execution.
|
|
755
845
|
*/
|
|
@@ -757,41 +847,41 @@ export var ConnectionFlow = /*#__PURE__*/function () {
|
|
|
757
847
|
}, {
|
|
758
848
|
key: "launch",
|
|
759
849
|
value: function () {
|
|
760
|
-
var _launch = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
850
|
+
var _launch = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
|
|
761
851
|
var _this2 = this;
|
|
762
852
|
|
|
763
|
-
var
|
|
764
|
-
|
|
853
|
+
var _ref5,
|
|
854
|
+
_ref5$autoSuccessTime,
|
|
765
855
|
autoSuccessTimer,
|
|
766
856
|
computedAutoSuccessTimer,
|
|
767
857
|
launcher,
|
|
768
858
|
_iterator2,
|
|
769
859
|
_step2,
|
|
770
860
|
_loop,
|
|
771
|
-
|
|
861
|
+
_args11 = arguments;
|
|
772
862
|
|
|
773
|
-
return _regeneratorRuntime.wrap(function
|
|
863
|
+
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
|
|
774
864
|
while (1) {
|
|
775
|
-
switch (
|
|
865
|
+
switch (_context11.prev = _context11.next) {
|
|
776
866
|
case 0:
|
|
777
|
-
|
|
867
|
+
_ref5 = _args11.length > 0 && _args11[0] !== undefined ? _args11[0] : {}, _ref5$autoSuccessTime = _ref5.autoSuccessTimer, autoSuccessTimer = _ref5$autoSuccessTime === void 0 ? true : _ref5$autoSuccessTime;
|
|
778
868
|
computedAutoSuccessTimer = autoSuccessTimer && !get(this, 'konnector.clientSide');
|
|
779
869
|
logger.info('ConnectionFlow: Launching job...');
|
|
780
870
|
this.setState({
|
|
781
871
|
status: PENDING
|
|
782
872
|
});
|
|
783
|
-
|
|
873
|
+
_context11.next = 6;
|
|
784
874
|
return prepareTriggerAccount(this.client, this.trigger);
|
|
785
875
|
|
|
786
876
|
case 6:
|
|
787
|
-
this.account =
|
|
877
|
+
this.account = _context11.sent;
|
|
788
878
|
this.realtime.subscribe('updated', ACCOUNTS_DOCTYPE, this.account._id, this.handleAccountUpdated);
|
|
789
879
|
logger.info("ConnectionFlow: Subscribed to ".concat(ACCOUNTS_DOCTYPE, ":").concat(this.account._id));
|
|
790
|
-
|
|
880
|
+
_context11.next = 11;
|
|
791
881
|
return launchTrigger(this.client, this.trigger);
|
|
792
882
|
|
|
793
883
|
case 11:
|
|
794
|
-
this.job =
|
|
884
|
+
this.job = _context11.sent;
|
|
795
885
|
|
|
796
886
|
if (get(this, 'konnector.clientSide')) {
|
|
797
887
|
logger.info('This connector can be run by the launcher', this.konnector.slug);
|
|
@@ -855,10 +945,10 @@ export var ConnectionFlow = /*#__PURE__*/function () {
|
|
|
855
945
|
|
|
856
946
|
case 19:
|
|
857
947
|
case "end":
|
|
858
|
-
return
|
|
948
|
+
return _context11.stop();
|
|
859
949
|
}
|
|
860
950
|
}
|
|
861
|
-
},
|
|
951
|
+
}, _callee11, this);
|
|
862
952
|
}));
|
|
863
953
|
|
|
864
954
|
function launch() {
|
|
@@ -15,6 +15,7 @@ import KonnectorJobWatcher from './konnector/KonnectorJobWatcher';
|
|
|
15
15
|
import { konnectorPolicy as biKonnectorPolicy } from '../services/budget-insight';
|
|
16
16
|
import fixtures from '../../test/fixtures';
|
|
17
17
|
import sentryHub from '../sentry';
|
|
18
|
+
import { Q } from 'cozy-client';
|
|
18
19
|
jest.mock('../sentry', function () {
|
|
19
20
|
var mockScope = {
|
|
20
21
|
setTag: jest.fn()
|
|
@@ -161,6 +162,7 @@ var setup = function setup() {
|
|
|
161
162
|
trigger = _ref6.trigger;
|
|
162
163
|
|
|
163
164
|
var client = {
|
|
165
|
+
query: jest.fn(),
|
|
164
166
|
collection: jest.fn().mockReturnValue({
|
|
165
167
|
all: jest.fn().mockReturnValue({
|
|
166
168
|
data: []
|
|
@@ -630,14 +632,106 @@ describe('ConnectionFlow', function () {
|
|
|
630
632
|
}
|
|
631
633
|
}, _callee20);
|
|
632
634
|
})));
|
|
633
|
-
it('should
|
|
634
|
-
var _setup16,
|
|
635
|
+
it('should add the defaultFolderPath to the account when needed', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee23() {
|
|
636
|
+
var _setup16, flow, client;
|
|
635
637
|
|
|
636
|
-
return _regeneratorRuntime.wrap(function
|
|
638
|
+
return _regeneratorRuntime.wrap(function _callee23$(_context23) {
|
|
637
639
|
while (1) {
|
|
638
|
-
switch (
|
|
640
|
+
switch (_context23.prev = _context23.next) {
|
|
639
641
|
case 0:
|
|
640
|
-
_setup16 = setup(), client = _setup16.client;
|
|
642
|
+
_setup16 = setup(), flow = _setup16.flow, client = _setup16.client;
|
|
643
|
+
prepareTriggerAccount.mockResolvedValue(fixtures.updatedAccount);
|
|
644
|
+
ensureTrigger.mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
|
|
645
|
+
return _regeneratorRuntime.wrap(function _callee21$(_context21) {
|
|
646
|
+
while (1) {
|
|
647
|
+
switch (_context21.prev = _context21.next) {
|
|
648
|
+
case 0:
|
|
649
|
+
return _context21.abrupt("return", fixtures.createdTriggerWithFolder.attributes);
|
|
650
|
+
|
|
651
|
+
case 1:
|
|
652
|
+
case "end":
|
|
653
|
+
return _context21.stop();
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}, _callee21);
|
|
657
|
+
})));
|
|
658
|
+
client.query.mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee22() {
|
|
659
|
+
return _regeneratorRuntime.wrap(function _callee22$(_context22) {
|
|
660
|
+
while (1) {
|
|
661
|
+
switch (_context22.prev = _context22.next) {
|
|
662
|
+
case 0:
|
|
663
|
+
return _context22.abrupt("return", {
|
|
664
|
+
data: {
|
|
665
|
+
path: '/default/folder/path'
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
case 1:
|
|
670
|
+
case "end":
|
|
671
|
+
return _context22.stop();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}, _callee22);
|
|
675
|
+
})));
|
|
676
|
+
_context23.next = 6;
|
|
677
|
+
return flow.ensureTriggerAndLaunch(client, {
|
|
678
|
+
account: fixtures.existingAccount,
|
|
679
|
+
trigger: fixtures.existingTrigger,
|
|
680
|
+
konnector: fixtures.konnectorWithFolder
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
case 6:
|
|
684
|
+
expect(flow.account).toEqual(fixtures.updatedAccount);
|
|
685
|
+
expect(saveAccount).toHaveBeenCalledWith(client, fixtures.konnectorWithFolder, _objectSpread(_objectSpread({}, fixtures.existingAccount), {}, {
|
|
686
|
+
defaultFolderPath: '/default/folder/path'
|
|
687
|
+
}));
|
|
688
|
+
expect(client.query).toHaveBeenCalledWith(Q('io.cozy.files').getById(fixtures.createdTriggerWithFolder.attributes.message.folder_to_save));
|
|
689
|
+
|
|
690
|
+
case 9:
|
|
691
|
+
case "end":
|
|
692
|
+
return _context23.stop();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}, _callee23);
|
|
696
|
+
})));
|
|
697
|
+
it('should return unmodified account trigger folder does not exist', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee24() {
|
|
698
|
+
var _setup17, flow, client;
|
|
699
|
+
|
|
700
|
+
return _regeneratorRuntime.wrap(function _callee24$(_context24) {
|
|
701
|
+
while (1) {
|
|
702
|
+
switch (_context24.prev = _context24.next) {
|
|
703
|
+
case 0:
|
|
704
|
+
_setup17 = setup(), flow = _setup17.flow, client = _setup17.client;
|
|
705
|
+
prepareTriggerAccount.mockResolvedValue(fixtures.updatedAccount);
|
|
706
|
+
ensureTrigger.mockResolvedValue(fixtures.createdTriggerWithFolder.attributes);
|
|
707
|
+
client.query.mockRejectedValue(new Error('404'));
|
|
708
|
+
_context24.next = 6;
|
|
709
|
+
return flow.ensureTriggerAndLaunch(client, {
|
|
710
|
+
account: fixtures.existingAccount,
|
|
711
|
+
trigger: fixtures.existingTrigger,
|
|
712
|
+
konnector: fixtures.konnectorWithFolder
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
case 6:
|
|
716
|
+
expect(flow.account).toEqual(fixtures.updatedAccount);
|
|
717
|
+
expect(saveAccount).not.toHaveBeenCalled();
|
|
718
|
+
expect(client.query).toHaveBeenCalledWith(Q('io.cozy.files').getById(fixtures.createdTriggerWithFolder.attributes.message.folder_to_save));
|
|
719
|
+
|
|
720
|
+
case 9:
|
|
721
|
+
case "end":
|
|
722
|
+
return _context24.stop();
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}, _callee24);
|
|
726
|
+
})));
|
|
727
|
+
it('should call the launcher when needed', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee26() {
|
|
728
|
+
var _setup18, client, flow;
|
|
729
|
+
|
|
730
|
+
return _regeneratorRuntime.wrap(function _callee26$(_context26) {
|
|
731
|
+
while (1) {
|
|
732
|
+
switch (_context26.prev = _context26.next) {
|
|
733
|
+
case 0:
|
|
734
|
+
_setup18 = setup(), client = _setup18.client;
|
|
641
735
|
flow = new ConnectionFlow(client, fixtures.existingTrigger, fixtures.clientKonnector);
|
|
642
736
|
window.cozy = {
|
|
643
737
|
ClientConnectorLauncher: 'react-native'
|
|
@@ -645,22 +739,22 @@ describe('ConnectionFlow', function () {
|
|
|
645
739
|
window.ReactNativeWebView = {
|
|
646
740
|
postMessage: jest.fn()
|
|
647
741
|
};
|
|
648
|
-
ensureTrigger.mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
649
|
-
return _regeneratorRuntime.wrap(function
|
|
742
|
+
ensureTrigger.mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee25() {
|
|
743
|
+
return _regeneratorRuntime.wrap(function _callee25$(_context25) {
|
|
650
744
|
while (1) {
|
|
651
|
-
switch (
|
|
745
|
+
switch (_context25.prev = _context25.next) {
|
|
652
746
|
case 0:
|
|
653
|
-
return
|
|
747
|
+
return _context25.abrupt("return", fixtures.existingTrigger);
|
|
654
748
|
|
|
655
749
|
case 1:
|
|
656
750
|
case "end":
|
|
657
|
-
return
|
|
751
|
+
return _context25.stop();
|
|
658
752
|
}
|
|
659
753
|
}
|
|
660
|
-
},
|
|
754
|
+
}, _callee25);
|
|
661
755
|
})));
|
|
662
756
|
prepareTriggerAccount.mockResolvedValue(fixtures.updatedAccount);
|
|
663
|
-
|
|
757
|
+
_context26.next = 8;
|
|
664
758
|
return flow.ensureTriggerAndLaunch(client, {
|
|
665
759
|
account: fixtures.existingAccount,
|
|
666
760
|
trigger: fixtures.existingTrigger
|
|
@@ -680,10 +774,10 @@ describe('ConnectionFlow', function () {
|
|
|
680
774
|
|
|
681
775
|
case 10:
|
|
682
776
|
case "end":
|
|
683
|
-
return
|
|
777
|
+
return _context26.stop();
|
|
684
778
|
}
|
|
685
779
|
}
|
|
686
|
-
},
|
|
780
|
+
}, _callee26);
|
|
687
781
|
})));
|
|
688
782
|
delete window.cozy;
|
|
689
783
|
delete window.ReactNativeWebView;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-harvest-lib",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "Provides logic, modules and components for Cozy's harvest applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"babel-plugin-inline-react-svg": "^1.1.0",
|
|
54
54
|
"babel-preset-cozy-app": "^2.0.1",
|
|
55
55
|
"cozy-client": "17.6.1",
|
|
56
|
-
"cozy-device-helper": "^1.
|
|
56
|
+
"cozy-device-helper": "^1.16.1",
|
|
57
57
|
"cozy-flags": "^2.8.3",
|
|
58
58
|
"cozy-keys-lib": "3.8.0",
|
|
59
|
-
"cozy-realtime": "^4.0.
|
|
59
|
+
"cozy-realtime": "^4.0.2",
|
|
60
60
|
"cozy-ui": "^57.6.0",
|
|
61
61
|
"enzyme": "3.11.0",
|
|
62
62
|
"enzyme-adapter-react-16": "1.15.6",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"react-router-dom": "^5.0.1"
|
|
86
86
|
},
|
|
87
87
|
"sideEffects": false,
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "beff9977aff2347bbef342015b062f5c4b71c6cd"
|
|
89
89
|
}
|
|
@@ -85,6 +85,8 @@ const Routes = ({ konnectorRoot, konnector, onDismiss, datacardOptions }) => {
|
|
|
85
85
|
accountId={match.params.accountId}
|
|
86
86
|
accountsAndTriggers={accountsAndTriggers}
|
|
87
87
|
onDismiss={onDismiss}
|
|
88
|
+
showNewAccountButton={!konnector.clientSide}
|
|
89
|
+
showAccountSelection={!konnector.clientSide}
|
|
88
90
|
/>
|
|
89
91
|
)}
|
|
90
92
|
/>
|
|
@@ -3,6 +3,7 @@ import get from 'lodash/get'
|
|
|
3
3
|
|
|
4
4
|
import Realtime from 'cozy-realtime'
|
|
5
5
|
import flag from 'cozy-flags'
|
|
6
|
+
import { Q } from 'cozy-client'
|
|
6
7
|
|
|
7
8
|
import {
|
|
8
9
|
fetchReusableAccount,
|
|
@@ -474,12 +475,59 @@ export class ConnectionFlow {
|
|
|
474
475
|
konnector,
|
|
475
476
|
t
|
|
476
477
|
})
|
|
478
|
+
|
|
479
|
+
await this.ensureDefaultFolderPathInAccount(client, {
|
|
480
|
+
trigger: ensuredTrigger,
|
|
481
|
+
account,
|
|
482
|
+
konnector
|
|
483
|
+
})
|
|
484
|
+
|
|
477
485
|
logger.info(`Trigger is ${ensuredTrigger._id}`)
|
|
478
486
|
this.trigger = ensuredTrigger
|
|
479
487
|
this.emit(UPDATE_EVENT)
|
|
480
488
|
await this.launch()
|
|
481
489
|
}
|
|
482
490
|
|
|
491
|
+
/**
|
|
492
|
+
* Ensures there is a defaultFolderPath attribute in the account
|
|
493
|
+
* if any folder is needed by the connector.
|
|
494
|
+
* The account is saved if any change is done to it.
|
|
495
|
+
* This defaultFolderPath is needed by the stack to recreate the
|
|
496
|
+
* destination folder if removed by any mean : drive application,
|
|
497
|
+
* desktop application etc
|
|
498
|
+
*
|
|
499
|
+
* @param {CozyClient} client - A cozy client
|
|
500
|
+
* @param {io.cozy.triggers} options.trigger
|
|
501
|
+
* @param {io.cozy.accounts} options.account
|
|
502
|
+
* @param {io.cozy.konnectors} options.konnector
|
|
503
|
+
*/
|
|
504
|
+
async ensureDefaultFolderPathInAccount(
|
|
505
|
+
client,
|
|
506
|
+
{ trigger, account, konnector }
|
|
507
|
+
) {
|
|
508
|
+
const folderId = get(trigger, 'message.folder_to_save')
|
|
509
|
+
if (!folderId) {
|
|
510
|
+
return account
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
let folder
|
|
514
|
+
try {
|
|
515
|
+
const result = await client.query(Q('io.cozy.files').getById(folderId))
|
|
516
|
+
folder = result.data
|
|
517
|
+
} catch (err) {
|
|
518
|
+
logger.warn(
|
|
519
|
+
`ConnectionFlow.ensureDefaultFolderPath: folder ${folderId} does not exist. Could not ensure defaultFolderPath. ${err.message}`
|
|
520
|
+
)
|
|
521
|
+
return account
|
|
522
|
+
}
|
|
523
|
+
if (folder.path !== account.defaultFolderPath) {
|
|
524
|
+
account.defaultFolderPath = folder.path
|
|
525
|
+
const savedAccount = await saveAccount(client, konnector, account)
|
|
526
|
+
return savedAccount
|
|
527
|
+
}
|
|
528
|
+
return account
|
|
529
|
+
}
|
|
530
|
+
|
|
483
531
|
/**
|
|
484
532
|
* Launches the job and sets everything up to follow execution.
|
|
485
533
|
*/
|
|
@@ -12,6 +12,7 @@ import KonnectorJobWatcher from './konnector/KonnectorJobWatcher'
|
|
|
12
12
|
import { konnectorPolicy as biKonnectorPolicy } from '../services/budget-insight'
|
|
13
13
|
import fixtures from '../../test/fixtures'
|
|
14
14
|
import sentryHub from '../sentry'
|
|
15
|
+
import { Q } from 'cozy-client'
|
|
15
16
|
|
|
16
17
|
jest.mock('../sentry', () => {
|
|
17
18
|
const mockScope = {
|
|
@@ -90,6 +91,7 @@ const mockVaultClient = {
|
|
|
90
91
|
|
|
91
92
|
const setup = ({ trigger } = {}) => {
|
|
92
93
|
const client = {
|
|
94
|
+
query: jest.fn(),
|
|
93
95
|
collection: jest.fn().mockReturnValue({
|
|
94
96
|
all: jest.fn().mockReturnValue({
|
|
95
97
|
data: []
|
|
@@ -388,6 +390,61 @@ describe('ConnectionFlow', () => {
|
|
|
388
390
|
expect(flow.account).toEqual(fixtures.updatedAccount)
|
|
389
391
|
})
|
|
390
392
|
|
|
393
|
+
it('should add the defaultFolderPath to the account when needed', async () => {
|
|
394
|
+
const { flow, client } = setup()
|
|
395
|
+
prepareTriggerAccount.mockResolvedValue(fixtures.updatedAccount)
|
|
396
|
+
|
|
397
|
+
ensureTrigger.mockImplementation(
|
|
398
|
+
async () => fixtures.createdTriggerWithFolder.attributes
|
|
399
|
+
)
|
|
400
|
+
client.query.mockImplementation(async () => ({
|
|
401
|
+
data: {
|
|
402
|
+
path: '/default/folder/path'
|
|
403
|
+
}
|
|
404
|
+
}))
|
|
405
|
+
await flow.ensureTriggerAndLaunch(client, {
|
|
406
|
+
account: fixtures.existingAccount,
|
|
407
|
+
trigger: fixtures.existingTrigger,
|
|
408
|
+
konnector: fixtures.konnectorWithFolder
|
|
409
|
+
})
|
|
410
|
+
expect(flow.account).toEqual(fixtures.updatedAccount)
|
|
411
|
+
expect(saveAccount).toHaveBeenCalledWith(
|
|
412
|
+
client,
|
|
413
|
+
fixtures.konnectorWithFolder,
|
|
414
|
+
{
|
|
415
|
+
...fixtures.existingAccount,
|
|
416
|
+
defaultFolderPath: '/default/folder/path'
|
|
417
|
+
}
|
|
418
|
+
)
|
|
419
|
+
expect(client.query).toHaveBeenCalledWith(
|
|
420
|
+
Q('io.cozy.files').getById(
|
|
421
|
+
fixtures.createdTriggerWithFolder.attributes.message.folder_to_save
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
it('should return unmodified account trigger folder does not exist', async () => {
|
|
427
|
+
const { flow, client } = setup()
|
|
428
|
+
prepareTriggerAccount.mockResolvedValue(fixtures.updatedAccount)
|
|
429
|
+
|
|
430
|
+
ensureTrigger.mockResolvedValue(
|
|
431
|
+
fixtures.createdTriggerWithFolder.attributes
|
|
432
|
+
)
|
|
433
|
+
client.query.mockRejectedValue(new Error('404'))
|
|
434
|
+
await flow.ensureTriggerAndLaunch(client, {
|
|
435
|
+
account: fixtures.existingAccount,
|
|
436
|
+
trigger: fixtures.existingTrigger,
|
|
437
|
+
konnector: fixtures.konnectorWithFolder
|
|
438
|
+
})
|
|
439
|
+
expect(flow.account).toEqual(fixtures.updatedAccount)
|
|
440
|
+
expect(saveAccount).not.toHaveBeenCalled()
|
|
441
|
+
expect(client.query).toHaveBeenCalledWith(
|
|
442
|
+
Q('io.cozy.files').getById(
|
|
443
|
+
fixtures.createdTriggerWithFolder.attributes.message.folder_to_save
|
|
444
|
+
)
|
|
445
|
+
)
|
|
446
|
+
})
|
|
447
|
+
|
|
391
448
|
it('should call the launcher when needed', async () => {
|
|
392
449
|
const { client } = setup()
|
|
393
450
|
const flow = new ConnectionFlow(
|
package/test/fixtures.js
CHANGED
|
@@ -125,6 +125,20 @@ const fixtures = {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
},
|
|
128
|
+
createdTriggerWithFolder: {
|
|
129
|
+
id: 'created-trigger-id',
|
|
130
|
+
_type: 'io.cozy.triggers',
|
|
131
|
+
attributes: {
|
|
132
|
+
arguments: '0 0 0 * * 0',
|
|
133
|
+
type: '@cron',
|
|
134
|
+
worker: 'konnector',
|
|
135
|
+
message: {
|
|
136
|
+
account: 'updated-account-id',
|
|
137
|
+
konnector: 'konnectest',
|
|
138
|
+
folder_to_save: 'folder-id'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
128
142
|
launchedJob: {
|
|
129
143
|
type: 'io.cozy.jobs',
|
|
130
144
|
_id: 'lauched-job-id',
|