cozy-client 27.16.0 → 27.18.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/dist/CozyClient.js +1 -1
- package/dist/flagship-certification/flagship-certification.js +22 -7
- package/dist/flagship-certification/flagship-certification.spec.js +215 -0
- package/dist/flagship-certification/store-attestation.js +1 -1
- package/dist/store/documents.js +9 -9
- package/dist/store/documents.spec.js +102 -53
- package/package.json +3 -3
package/dist/CozyClient.js
CHANGED
|
@@ -2464,7 +2464,7 @@ var CozyClient = /*#__PURE__*/function () {
|
|
|
2464
2464
|
CozyClient.hooks = CozyClient.hooks || {};
|
|
2465
2465
|
CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
|
|
2466
2466
|
|
|
2467
|
-
CozyClient.version = "27.
|
|
2467
|
+
CozyClient.version = "27.18.0";
|
|
2468
2468
|
|
|
2469
2469
|
_microee.default.mixin(CozyClient);
|
|
2470
2470
|
|
|
@@ -13,6 +13,8 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
|
|
|
13
13
|
|
|
14
14
|
var _CozyClient = _interopRequireDefault(require("../CozyClient"));
|
|
15
15
|
|
|
16
|
+
var _logger = _interopRequireDefault(require("../logger"));
|
|
17
|
+
|
|
16
18
|
var _storeAttestation = require("./store-attestation");
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -134,25 +136,38 @@ var certifyFlagship = /*#__PURE__*/function () {
|
|
|
134
136
|
throw new Error('[FLAGSHIP_CERTIFICATION] Certification configuration is not set');
|
|
135
137
|
|
|
136
138
|
case 2:
|
|
137
|
-
_context3.
|
|
139
|
+
_context3.prev = 2;
|
|
140
|
+
_context3.next = 5;
|
|
138
141
|
return getStackChallenge(client);
|
|
139
142
|
|
|
140
|
-
case
|
|
143
|
+
case 5:
|
|
141
144
|
stackChallengeNonce = _context3.sent;
|
|
142
|
-
_context3.next =
|
|
145
|
+
_context3.next = 8;
|
|
143
146
|
return (0, _storeAttestation.getAppAttestationFromStore)(stackChallengeNonce, certificationConfig);
|
|
144
147
|
|
|
145
|
-
case
|
|
148
|
+
case 8:
|
|
146
149
|
appAttestation = _context3.sent;
|
|
147
|
-
_context3.next =
|
|
150
|
+
_context3.next = 11;
|
|
148
151
|
return giveAppAttestationToStack(appAttestation, stackChallengeNonce, client);
|
|
149
152
|
|
|
150
|
-
case
|
|
153
|
+
case 11:
|
|
154
|
+
_context3.next = 17;
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
case 13:
|
|
158
|
+
_context3.prev = 13;
|
|
159
|
+
_context3.t0 = _context3["catch"](2);
|
|
160
|
+
|
|
161
|
+
_logger.default.warn('[FLAGSHIP_CERTIFICATION] Certification failed but the cozy-stack will continue with 2FA certification');
|
|
162
|
+
|
|
163
|
+
_logger.default.warn(_context3.t0.message);
|
|
164
|
+
|
|
165
|
+
case 17:
|
|
151
166
|
case "end":
|
|
152
167
|
return _context3.stop();
|
|
153
168
|
}
|
|
154
169
|
}
|
|
155
|
-
}, _callee3);
|
|
170
|
+
}, _callee3, null, [[2, 13]]);
|
|
156
171
|
}));
|
|
157
172
|
|
|
158
173
|
return function certifyFlagship(_x5, _x6) {
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { certifyFlagship } from './flagship-certification'
|
|
2
|
+
import { createMockClient } from '../mock'
|
|
3
|
+
|
|
4
|
+
import { getAppAttestationFromStore } from './store-attestation'
|
|
5
|
+
import logger from '../logger'
|
|
6
|
+
|
|
7
|
+
jest.mock('./store-attestation', () => ({
|
|
8
|
+
getAppAttestationFromStore: jest.fn()
|
|
9
|
+
}))
|
|
10
|
+
|
|
11
|
+
jest.mock('../logger', () => ({
|
|
12
|
+
warn: jest.fn()
|
|
13
|
+
}))
|
|
14
|
+
|
|
15
|
+
const getClientMock = () => {
|
|
16
|
+
const client = createMockClient({
|
|
17
|
+
clientOptions: {
|
|
18
|
+
oauth: {}
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
client.stackClient.oauthOptions = {
|
|
23
|
+
clientID: 'SOME_CLIENT_ID',
|
|
24
|
+
registrationAccessToken: 'SOME_REGISTRATION_ACCESS_TOKEN'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return client
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const mockCorrectChallengeRequest = client => {
|
|
31
|
+
client.stackClient.fetchJSON.mockResolvedValueOnce({
|
|
32
|
+
nonce: 'SOME_NONCE'
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const mockCorrectStoreApiRequest = () => {
|
|
37
|
+
getAppAttestationFromStore.mockResolvedValueOnce({
|
|
38
|
+
platform: 'android',
|
|
39
|
+
attestation: 'SOME_STORE_ATTESTATION',
|
|
40
|
+
keyId: 'SOME_KEY_ID'
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const mockCorrectCertificationConfig = () => {
|
|
45
|
+
return {
|
|
46
|
+
androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const getFetchJsonPostParams = (url, body = null) => {
|
|
51
|
+
return [
|
|
52
|
+
'POST',
|
|
53
|
+
url,
|
|
54
|
+
body,
|
|
55
|
+
{
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: 'Bearer SOME_REGISTRATION_ACCESS_TOKEN'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe('certifyFlagship', () => {
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
jest.restoreAllMocks()
|
|
66
|
+
getAppAttestationFromStore.mockReset()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should ask challenge to cozy-stack, call the store API and then send the result to the stack', async () => {
|
|
70
|
+
const client = getClientMock()
|
|
71
|
+
|
|
72
|
+
const certificationConfig = mockCorrectCertificationConfig()
|
|
73
|
+
|
|
74
|
+
mockCorrectChallengeRequest(client)
|
|
75
|
+
|
|
76
|
+
mockCorrectStoreApiRequest()
|
|
77
|
+
|
|
78
|
+
await certifyFlagship(certificationConfig, client)
|
|
79
|
+
|
|
80
|
+
expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
|
|
81
|
+
...getFetchJsonPostParams(`/auth/clients/SOME_CLIENT_ID/challenge`)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
expect(getAppAttestationFromStore).toHaveBeenCalledWith('SOME_NONCE', {
|
|
85
|
+
androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
|
|
89
|
+
...getFetchJsonPostParams(`/auth/clients/SOME_CLIENT_ID/attestation`, {
|
|
90
|
+
platform: 'android',
|
|
91
|
+
attestation: 'SOME_STORE_ATTESTATION',
|
|
92
|
+
challenge: 'SOME_NONCE',
|
|
93
|
+
keyId: 'SOME_KEY_ID'
|
|
94
|
+
})
|
|
95
|
+
)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('should throw if no certification config is provided', async () => {
|
|
99
|
+
const client = getClientMock()
|
|
100
|
+
|
|
101
|
+
const certificationConfig = undefined
|
|
102
|
+
|
|
103
|
+
mockCorrectChallengeRequest(client)
|
|
104
|
+
|
|
105
|
+
client.stackClient.fetchJSON.mockImplementationOnce(() => {
|
|
106
|
+
throw Error('SOME_STACK_CERTIFICATION_ERROR')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
mockCorrectStoreApiRequest()
|
|
110
|
+
|
|
111
|
+
await expect(certifyFlagship(certificationConfig, client)).rejects.toEqual(
|
|
112
|
+
new Error(
|
|
113
|
+
'[FLAGSHIP_CERTIFICATION] Certification configuration is not set'
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
expect(client.stackClient.fetchJSON).not.toHaveBeenCalled()
|
|
118
|
+
expect(getAppAttestationFromStore).not.toHaveBeenCalled()
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('should ask challenge to cozy-stack and then handle challenge query failure', async () => {
|
|
122
|
+
const client = getClientMock()
|
|
123
|
+
|
|
124
|
+
const certificationConfig = mockCorrectCertificationConfig()
|
|
125
|
+
|
|
126
|
+
// Mock errored stack challenge request
|
|
127
|
+
client.stackClient.fetchJSON.mockImplementation(() => {
|
|
128
|
+
throw Error('SOME_STACK_CHALLENGE_ERROR')
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
mockCorrectStoreApiRequest()
|
|
132
|
+
|
|
133
|
+
await certifyFlagship(certificationConfig, client)
|
|
134
|
+
|
|
135
|
+
expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
|
|
136
|
+
...getFetchJsonPostParams(`/auth/clients/SOME_CLIENT_ID/challenge`)
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
expect(logger.warn).toHaveBeenCalledWith(
|
|
140
|
+
'[FLAGSHIP_CERTIFICATION] Certification failed but the cozy-stack will continue with 2FA certification'
|
|
141
|
+
)
|
|
142
|
+
expect(logger.warn).toHaveBeenCalledWith(
|
|
143
|
+
'[FLAGSHIP_CERTIFICATION] Something went wrong while requesting a challenge from CozyStack:\nSOME_STACK_CHALLENGE_ERROR'
|
|
144
|
+
)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('should ask challenge to cozy-stack, call the store API and then handle store API failure', async () => {
|
|
148
|
+
const client = getClientMock()
|
|
149
|
+
|
|
150
|
+
const certificationConfig = mockCorrectCertificationConfig()
|
|
151
|
+
|
|
152
|
+
mockCorrectChallengeRequest(client)
|
|
153
|
+
|
|
154
|
+
// Mock errored store API
|
|
155
|
+
getAppAttestationFromStore.mockImplementationOnce(() => {
|
|
156
|
+
throw Error('SOME_STORE_API_ERROR')
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
await certifyFlagship(certificationConfig, client)
|
|
160
|
+
|
|
161
|
+
expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
|
|
162
|
+
...getFetchJsonPostParams(`/auth/clients/SOME_CLIENT_ID/challenge`)
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
expect(getAppAttestationFromStore).toHaveBeenCalledWith('SOME_NONCE', {
|
|
166
|
+
androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
expect(logger.warn).toHaveBeenCalledWith(
|
|
170
|
+
'[FLAGSHIP_CERTIFICATION] Certification failed but the cozy-stack will continue with 2FA certification'
|
|
171
|
+
)
|
|
172
|
+
expect(logger.warn).toHaveBeenCalledWith('SOME_STORE_API_ERROR')
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('should ask challenge to cozy-stack, call the store API, send the result to the stack and then handle cozy-stack certification failure', async () => {
|
|
176
|
+
const client = getClientMock()
|
|
177
|
+
|
|
178
|
+
const certificationConfig = mockCorrectCertificationConfig()
|
|
179
|
+
|
|
180
|
+
mockCorrectChallengeRequest(client)
|
|
181
|
+
|
|
182
|
+
// Mock errored stack certification request
|
|
183
|
+
client.stackClient.fetchJSON.mockImplementationOnce(() => {
|
|
184
|
+
throw Error('SOME_STACK_CERTIFICATION_ERROR')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
mockCorrectStoreApiRequest()
|
|
188
|
+
|
|
189
|
+
await certifyFlagship(certificationConfig, client)
|
|
190
|
+
|
|
191
|
+
expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
|
|
192
|
+
...getFetchJsonPostParams(`/auth/clients/SOME_CLIENT_ID/challenge`)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
expect(getAppAttestationFromStore).toHaveBeenCalledWith('SOME_NONCE', {
|
|
196
|
+
androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
|
|
200
|
+
...getFetchJsonPostParams(`/auth/clients/SOME_CLIENT_ID/attestation`, {
|
|
201
|
+
platform: 'android',
|
|
202
|
+
attestation: 'SOME_STORE_ATTESTATION',
|
|
203
|
+
challenge: 'SOME_NONCE',
|
|
204
|
+
keyId: 'SOME_KEY_ID'
|
|
205
|
+
})
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
expect(logger.warn).toHaveBeenCalledWith(
|
|
209
|
+
'[FLAGSHIP_CERTIFICATION] Certification failed but the cozy-stack will continue with 2FA certification'
|
|
210
|
+
)
|
|
211
|
+
expect(logger.warn).toHaveBeenCalledWith(
|
|
212
|
+
'[FLAGSHIP_CERTIFICATION] Something went wrong while giving attestation to CozyStack:\nSOME_STACK_CERTIFICATION_ERROR'
|
|
213
|
+
)
|
|
214
|
+
})
|
|
215
|
+
})
|
|
@@ -25,7 +25,7 @@ var validateAppMock = /*#__PURE__*/function () {
|
|
|
25
25
|
while (1) {
|
|
26
26
|
switch (_context.prev = _context.next) {
|
|
27
27
|
case 0:
|
|
28
|
-
throw new Error("
|
|
28
|
+
throw new Error("getAppAttestationFromStore can only be called from a React Native container");
|
|
29
29
|
|
|
30
30
|
case 1:
|
|
31
31
|
case "end":
|
package/dist/store/documents.js
CHANGED
|
@@ -159,16 +159,16 @@ var getCollectionFromSlice = function getCollectionFromSlice() {
|
|
|
159
159
|
return Object.values(state[doctype]);
|
|
160
160
|
};
|
|
161
161
|
/*
|
|
162
|
-
This method has been created in order to get a returned object
|
|
163
|
-
in `data` with the full set on information coming potentially from
|
|
164
|
-
|
|
162
|
+
This method has been created in order to get a returned object
|
|
163
|
+
in `data` with the full set on information coming potentially from
|
|
164
|
+
`included`
|
|
165
165
|
|
|
166
|
-
This method should be somewhere else. The `document` shall not be
|
|
167
|
-
|
|
166
|
+
This method should be somewhere else. The `document` shall not be
|
|
167
|
+
dealt with included / data and so on.
|
|
168
168
|
|
|
169
|
-
This method takes data and included and merge both sources
|
|
170
|
-
together. It should be always up
|
|
171
|
-
will be as full of
|
|
169
|
+
This method takes `data` and `included` and merge both sources
|
|
170
|
+
together. It should be always up-to-date. The returned object
|
|
171
|
+
will be as full of information as it can be.
|
|
172
172
|
*/
|
|
173
173
|
|
|
174
174
|
|
|
@@ -185,8 +185,8 @@ var extractAndMergeDocument = function extractAndMergeDocument(data, updatedStat
|
|
|
185
185
|
|
|
186
186
|
var sortedData = (0, _keyBy.default)(data, _helpers.properId);
|
|
187
187
|
var mergedData = Object.assign({}, updatedStateWithIncluded);
|
|
188
|
+
mergedData[doctype] = Object.assign({}, updatedStateWithIncluded[doctype]);
|
|
188
189
|
Object.values(sortedData).map(function (data) {
|
|
189
|
-
if (!mergedData[doctype]) mergedData[doctype] = {};
|
|
190
190
|
var id = (0, _helpers.properId)(data);
|
|
191
191
|
|
|
192
192
|
if (mergedData[doctype][id]) {
|
|
@@ -4,23 +4,25 @@ import {
|
|
|
4
4
|
} from './documents'
|
|
5
5
|
|
|
6
6
|
describe('extractAndMerge', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
const data = {
|
|
8
|
+
0: {
|
|
9
|
+
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
10
|
+
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
11
|
+
type: 'io.cozy.files',
|
|
12
|
+
_type: 'io.cozy.files',
|
|
13
|
+
blabla: 'new field'
|
|
14
|
+
},
|
|
15
|
+
1: {
|
|
16
|
+
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
17
|
+
type: 'io.cozy.files',
|
|
18
|
+
_type: 'io.cozy.files',
|
|
19
|
+
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
20
|
+
blibli: 'another new field'
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
}
|
|
23
|
+
const updatedStateWithIncluded = {
|
|
24
|
+
'io.cozy.files': {
|
|
25
|
+
b6ff135b34e041ffb2d4a4865f3e0a53: {
|
|
24
26
|
attributes: {
|
|
25
27
|
type: 'file',
|
|
26
28
|
name: 'IMG_0016.PNG',
|
|
@@ -38,7 +40,7 @@ describe('extractAndMerge', () => {
|
|
|
38
40
|
type: 'io.cozy.files',
|
|
39
41
|
_type: 'io.cozy.files'
|
|
40
42
|
},
|
|
41
|
-
|
|
43
|
+
b6ff135b34e041ffb2d4a4865f3e235f: {
|
|
42
44
|
attributes: {
|
|
43
45
|
type: 'file',
|
|
44
46
|
name: 'IMG_0054.PNG',
|
|
@@ -57,65 +59,112 @@ describe('extractAndMerge', () => {
|
|
|
57
59
|
_type: 'io.cozy.files'
|
|
58
60
|
}
|
|
59
61
|
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
it('should return the right data', () => {
|
|
60
65
|
const returnedDatas = extractAndMergeDocument(
|
|
61
66
|
data,
|
|
62
67
|
updatedStateWithIncluded
|
|
63
68
|
)
|
|
64
69
|
|
|
65
70
|
const manuallyMergedData = {
|
|
66
|
-
'0': {
|
|
67
|
-
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
68
|
-
_type: 'io.cozy.files',
|
|
69
|
-
attributes: {
|
|
70
|
-
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
71
|
-
name: 'IMG_0016.PNG',
|
|
72
|
-
type: 'file'
|
|
73
|
-
},
|
|
74
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
75
|
-
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e0a53' },
|
|
76
|
-
meta: { rev: '5-87840eceaab358e38aa8b6bb0d4577b1' },
|
|
77
|
-
relationships: {
|
|
78
|
-
parent: {
|
|
79
|
-
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
type: 'io.cozy.files'
|
|
83
|
-
},
|
|
84
|
-
'1': {
|
|
85
|
-
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
86
|
-
_type: 'io.cozy.files',
|
|
87
|
-
attributes: {
|
|
88
|
-
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
89
|
-
name: 'IMG_0054.PNG',
|
|
90
|
-
type: 'file'
|
|
91
|
-
},
|
|
92
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
93
|
-
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e235f' },
|
|
94
|
-
meta: { rev: '5-ca91c0dc02dafb38eb56070c1d80d62c' },
|
|
95
|
-
relationships: {
|
|
96
|
-
parent: {
|
|
97
|
-
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
type: 'io.cozy.files'
|
|
101
|
-
},
|
|
102
71
|
'io.cozy.files': {
|
|
103
72
|
b6ff135b34e041ffb2d4a4865f3e0a53: {
|
|
104
73
|
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
105
74
|
_type: 'io.cozy.files',
|
|
75
|
+
attributes: {
|
|
76
|
+
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
77
|
+
name: 'IMG_0016.PNG',
|
|
78
|
+
type: 'file'
|
|
79
|
+
},
|
|
80
|
+
blabla: 'new field',
|
|
106
81
|
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
82
|
+
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e0a53' },
|
|
83
|
+
meta: { rev: '5-87840eceaab358e38aa8b6bb0d4577b1' },
|
|
84
|
+
relationships: {
|
|
85
|
+
parent: {
|
|
86
|
+
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
87
|
+
}
|
|
88
|
+
},
|
|
107
89
|
type: 'io.cozy.files'
|
|
108
90
|
},
|
|
109
91
|
b6ff135b34e041ffb2d4a4865f3e235f: {
|
|
110
92
|
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
111
93
|
_type: 'io.cozy.files',
|
|
94
|
+
attributes: {
|
|
95
|
+
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
96
|
+
name: 'IMG_0054.PNG',
|
|
97
|
+
type: 'file'
|
|
98
|
+
},
|
|
99
|
+
blibli: 'another new field',
|
|
112
100
|
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
101
|
+
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e235f' },
|
|
102
|
+
meta: { rev: '5-ca91c0dc02dafb38eb56070c1d80d62c' },
|
|
103
|
+
relationships: {
|
|
104
|
+
parent: {
|
|
105
|
+
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
106
|
+
}
|
|
107
|
+
},
|
|
113
108
|
type: 'io.cozy.files'
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
}
|
|
117
112
|
expect(returnedDatas).toEqual(manuallyMergedData)
|
|
118
113
|
})
|
|
114
|
+
|
|
115
|
+
it(
|
|
116
|
+
'should assign a new object for doctype of document to update' +
|
|
117
|
+
'in order to allow selector to recompute their data when documents are updated',
|
|
118
|
+
() => {
|
|
119
|
+
const returnedDatas = extractAndMergeDocument(
|
|
120
|
+
data,
|
|
121
|
+
updatedStateWithIncluded
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
// Then
|
|
125
|
+
expect(
|
|
126
|
+
returnedDatas['io.cozy.files'] ===
|
|
127
|
+
updatedStateWithIncluded['io.cozy.files']
|
|
128
|
+
).toBeFalsy()
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
it(
|
|
133
|
+
'should assign a new object for doctype of document to update' +
|
|
134
|
+
'even if the mergedData is the same, because reselect createSelector update ' +
|
|
135
|
+
'according to object reference, not only value',
|
|
136
|
+
() => {
|
|
137
|
+
const dataAlreadyIncludedInUpdatedStateWithIncluded = {
|
|
138
|
+
0: {
|
|
139
|
+
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
140
|
+
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
141
|
+
type: 'io.cozy.files',
|
|
142
|
+
_type: 'io.cozy.files'
|
|
143
|
+
},
|
|
144
|
+
1: {
|
|
145
|
+
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
146
|
+
type: 'io.cozy.files',
|
|
147
|
+
_type: 'io.cozy.files',
|
|
148
|
+
_id: 'b6ff135b34e041ffb2d4a4865f3e235f'
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const returnedDatas = extractAndMergeDocument(
|
|
153
|
+
dataAlreadyIncludedInUpdatedStateWithIncluded,
|
|
154
|
+
updatedStateWithIncluded
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
// Then
|
|
158
|
+
expect(
|
|
159
|
+
returnedDatas['io.cozy.files'] ===
|
|
160
|
+
updatedStateWithIncluded['io.cozy.files']
|
|
161
|
+
).toBeFalsy()
|
|
162
|
+
|
|
163
|
+
expect(returnedDatas['io.cozy.files']).toEqual(
|
|
164
|
+
updatedStateWithIncluded['io.cozy.files']
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
)
|
|
119
168
|
})
|
|
120
169
|
|
|
121
170
|
describe('mergeDocumentsWithRelationships', () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-client",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.18.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.node.js",
|
|
6
6
|
"browser": "dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"cozy-device-helper": "^1.12.0",
|
|
22
22
|
"cozy-flags": "2.7.1",
|
|
23
23
|
"cozy-logger": "^1.6.0",
|
|
24
|
-
"cozy-stack-client": "^27.
|
|
24
|
+
"cozy-stack-client": "^27.17.0",
|
|
25
25
|
"json-stable-stringify": "^1.0.1",
|
|
26
26
|
"lodash": "^4.17.13",
|
|
27
27
|
"microee": "^0.0.6",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"react-native-ios11-devicecheck": "https://github.com/cozy/react-native-devicecheck#app-attest-v0.1"
|
|
72
72
|
},
|
|
73
73
|
"sideEffects": false,
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "df36e3ca46da4adab20629f869296d20942fbc75"
|
|
75
75
|
}
|