cozy-client 27.7.0 → 27.11.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 CHANGED
@@ -3,6 +3,56 @@
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
+ # [27.11.0](https://github.com/cozy/cozy-client/compare/v27.10.0...v27.11.0) (2022-01-13)
7
+
8
+
9
+ ### Features
10
+
11
+ * Change other_identity_document translations ([aebb1bf](https://github.com/cozy/cozy-client/commit/aebb1bff1721f17baf12b79c92440467b4549257))
12
+ * Move other_revenue in finance theme ([dcb54fa](https://github.com/cozy/cozy-client/commit/dcb54fa11eced184524d6c6c713636e8b7e2f06f))
13
+
14
+
15
+
16
+
17
+
18
+ # [27.10.0](https://github.com/cozy/cozy-client/compare/v27.9.0...v27.10.0) (2022-01-12)
19
+
20
+
21
+ ### Features
22
+
23
+ * Add activity theme ([44eb0a8](https://github.com/cozy/cozy-client/commit/44eb0a8d8b0bed4a5f081efe7cd42223d7935768))
24
+
25
+
26
+
27
+
28
+
29
+ # [27.9.0](https://github.com/cozy/cozy-client/compare/v27.8.0...v27.9.0) (2022-01-12)
30
+
31
+ **Note:** Version bump only for package cozy-client
32
+
33
+
34
+
35
+
36
+
37
+ # [27.8.0](https://github.com/cozy/cozy-client/compare/v27.7.0...v27.8.0) (2022-01-11)
38
+
39
+
40
+ ### Bug Fixes
41
+
42
+ * Rebuild `permission.d.ts` to fit CI version ([380db52](https://github.com/cozy/cozy-client/commit/380db528004e9a64b244a99bb238351fac4f2a05))
43
+ * UseQuery returns fetch method ([93e7f3d](https://github.com/cozy/cozy-client/commit/93e7f3d217353003795d43dfedf1397bb64815af))
44
+
45
+
46
+ ### Features
47
+
48
+ * Add `react-native-google-safetynet` module as peerDependencies ([cd4b37f](https://github.com/cozy/cozy-client/commit/cd4b37fc3353b702035e773b2b423ef7e7aa3156))
49
+ * Add `react-native-ios11-devicecheck` module as peerDependencies ([b9ed2e9](https://github.com/cozy/cozy-client/commit/b9ed2e9c42518a50961f5b233b5f6ae1894ed7d6))
50
+ * Add flagship certification mechanism ([fe8474c](https://github.com/cozy/cozy-client/commit/fe8474c3286393c996eb5704184de652aa8028fe))
51
+
52
+
53
+
54
+
55
+
6
56
  # [27.7.0](https://github.com/cozy/cozy-client/compare/v27.6.5...v27.7.0) (2022-01-03)
7
57
 
8
58
 
@@ -83,6 +83,8 @@ var _jsonStableStringify = _interopRequireDefault(require("json-stable-stringify
83
83
 
84
84
  var _promiseCache = _interopRequireDefault(require("./promise-cache"));
85
85
 
86
+ var _flagshipCertification = require("./flagship-certification/flagship-certification");
87
+
86
88
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
87
89
 
88
90
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -1958,9 +1960,18 @@ var CozyClient = /*#__PURE__*/function () {
1958
1960
  return stackClient.register();
1959
1961
 
1960
1962
  case 3:
1963
+ if (!stackClient.oauthOptions.shouldRequireFlagshipPermissions) {
1964
+ _context14.next = 6;
1965
+ break;
1966
+ }
1967
+
1968
+ _context14.next = 6;
1969
+ return (0, _flagshipCertification.certifyFlagship)(stackClient.oauthOptions.certificationConfig, this);
1970
+
1971
+ case 6:
1961
1972
  return _context14.abrupt("return", this.authorize(openURLCallback));
1962
1973
 
1963
- case 4:
1974
+ case 7:
1964
1975
  case "end":
1965
1976
  return _context14.stop();
1966
1977
  }
@@ -2452,7 +2463,7 @@ var CozyClient = /*#__PURE__*/function () {
2452
2463
  CozyClient.hooks = CozyClient.hooks || {};
2453
2464
  CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
2454
2465
 
2455
- CozyClient.version = "27.7.0";
2466
+ CozyClient.version = "27.11.0";
2456
2467
 
2457
2468
  _microee.default.mixin(CozyClient);
2458
2469
 
@@ -429,6 +429,11 @@
429
429
  "sourceCategory": "gov",
430
430
  "sourceSubCategory": "sport",
431
431
  "subjects": ["permit", "invoice"]
432
+ },
433
+ {
434
+ "label": "other_activity_document",
435
+ "sourceSubCategory": "sport",
436
+ "subjects": ["permit", "invoice"]
432
437
  }
433
438
  ],
434
439
  "purposeKnownValues": [
@@ -0,0 +1,96 @@
1
+ # Flagship certification
2
+
3
+ Flagship certification is the process of verifying that the current running app is a genuine Cozy application.
4
+
5
+ This verification is done by querying an app certificate from the app store (Apple AppStore or Google Play) and sending the resulting certificate to `cozy-stack`. Then `cozy-stack` will be able to an analyze the certificate and conclude if the app is genuine or not.
6
+
7
+ ## Nomenclature
8
+
9
+ - `flagship`: refers to the Cozy main application
10
+ - `store certification`: process of verifying app's genuineness through the platform's store
11
+ - `attestation`: result from the `store certification`
12
+ - `challenge`: unique token given to the app by `cozy-stack` that may be encrypted in the `attestation` as a proof of authenticity
13
+ - `nonce`: data type used to store the `challenge` token
14
+ - `SafetyNet`: Google's implementation of the `store certification`
15
+ - `AppAttest`: Apple's implementation of the `store certification`
16
+
17
+ ## Android certification
18
+
19
+ Android certification is based on [SafetyNet](https://developer.android.com/training/safetynet/index.html).
20
+
21
+ This process requires to query a `challenge` from `cozy-stack` and to use it to init the `store certification` process through `SafetyNet`. Then the received `attestation` is send to `cozy-stack` for verification.
22
+
23
+ The resulting `attestation` is in the form of a `JSON Web Signature` that embbed the following `JSON`:
24
+ ```json
25
+ {
26
+ "apkCertificateDigestSha256": [
27
+ "base64 encoded, SHA-256 hash of the certificate used to sign requesting app="
28
+ ],
29
+ "apkDigestSha256": "kNv83tJLFqwliYQ/6HUPCeGkBzLLCX/nvT+EF3OEB2I=",
30
+ "apkPackageName": "com.package.name.of.requesting.app",
31
+ "basicIntegrity": true,
32
+ "ctsProfileMatch": true,
33
+ "evaluationType": "BASIC",
34
+ "nonce": "R2Rra24fVm5xa2Mg",
35
+ "timestampMs": 9860437986543
36
+ }
37
+ ```
38
+
39
+ The `attestation`'s content is described in the SafetyNet's documentation: https://developer.android.com/training/safetynet/attestation#use-response-server
40
+
41
+ ## iOS certification
42
+
43
+ iOS certification is based on [AppAttest](https://developer.apple.com/documentation/devicecheck).
44
+
45
+ This process requires to query a `challenge` from `cozy-stack` and to use it to init the `store certification` process through `AppAttest`. Then the received `attestation` is send to `cozy-stack` for verification.
46
+
47
+ The resulting `attestation` is in the form of a `base64` token.
48
+
49
+ The `attestation`'s content is described in the `AppAttest`'s documentation: https://developer.apple.com/documentation/devicecheck/validating_apps_that_connect_to_your_server#3576643
50
+
51
+ ## Client's configuration
52
+
53
+ In order to configure `flagship` certification on an app, the OAuth property of `cozy-client` must contain `shouldRequireFlagshipPermissions` property set to `true` and `certificationConfig` property filled with required API keys.
54
+
55
+ Example of `cozy-client` configuration:
56
+ ```js
57
+ const client = await initClient(uri, {
58
+ scope: [
59
+ 'io.cozy.apps'
60
+ ],
61
+ oauth: {
62
+ redirectURI: 'REDIRECT_URI',
63
+ softwareID: 'YOUR_APP_ID',
64
+ clientKind: 'mobile',
65
+ clientName: 'YOUR_APP_NAME',
66
+ shouldRequireFlagshipPermissions: true,
67
+ certificationConfig: {
68
+ androidSafetyNetApiKey: 'YOUR_GOOGLE_SAFETY_NET_API_KEY'
69
+ }
70
+ },
71
+ ```
72
+
73
+ ## Stacks' configuration
74
+
75
+ In order to certify an app, the `cozy-stack` needs to have the following data:
76
+ - App's package name
77
+ - The app's package name is set on the react-native project
78
+ - It should be put in `flagship.apk_package_names` in the `cozy-stack`'s configuration file
79
+ - iOS app's id
80
+ - The iOS app's id is the concatenation of the developper team's id and the app's package name as defined in the XCode project
81
+ - If team's id is `ABCDEFGHIJ` and package name is `io.cozy.some_app` then the resulting app's id should be `ABCDEFGHIJ.io.cozy.some_app`
82
+ - It should be put in `flagship.apple_app_ids` in the `cozy-stack`'s configuration file
83
+ - Android app's certificate digest
84
+ - The Android certificate digest can be found in the Google Play app's Console, in `Configuration/App integrity` page
85
+ - On local dev environment, the dev certificate location is:
86
+ - On a ReactNative project: `<project_root>/android/app/debug.keystore`
87
+ - On an Android Studio project:
88
+ - On OSX: `~/.android/debug.keystore`
89
+ - On Windows: `%UserProfile%\.android\debug.keystore`
90
+ - On a Xamarin Project:
91
+ - On OSX: `~/.local/share/Xamarin/Mono for Android/debug.keystore`
92
+ - On Windows: `%LocalAppData%\Xamarin\Mono for Android\debug.keystore`
93
+ - To extract the certificat digest from local dev certificate:
94
+ - `keytool -list -v -keystore ./android/app/debug.keystore -alias androiddebugkey -storepass android -keypass android | grep "SHA256: " | cut -d " " -f 3 | xxd -r -p | openssl base64`
95
+ - The certificate digest is the `App signing key certificate` in SHA-256 format converted from HEX to base64
96
+ - It should be put in `flagship.apk_certificate_digests` in the `cozy-stack`'s configuration file
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.certifyFlagship = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _CozyClient = _interopRequireDefault(require("../CozyClient"));
15
+
16
+ var _storeAttestation = require("./store-attestation");
17
+
18
+ /**
19
+ * Request a challenge from the Stack that can be used to request the app attestation from the app store
20
+ *
21
+ * @param {CozyClient} client - the CozyClient instance
22
+ * @returns {Promise<string>} - the Nonce string returned by the stack
23
+ */
24
+ var getStackChallenge = /*#__PURE__*/function () {
25
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(client) {
26
+ var stackClient, result;
27
+ return _regenerator.default.wrap(function _callee$(_context) {
28
+ while (1) {
29
+ switch (_context.prev = _context.next) {
30
+ case 0:
31
+ _context.prev = 0;
32
+ stackClient = client.getStackClient();
33
+ _context.next = 4;
34
+ return stackClient.fetchJSON('POST', "/auth/clients/".concat(stackClient.oauthOptions.clientID, "/challenge"), null, {
35
+ headers: {
36
+ Authorization: stackClient.registrationAccessTokenToAuthHeader()
37
+ }
38
+ });
39
+
40
+ case 4:
41
+ result = _context.sent;
42
+ return _context.abrupt("return", result.nonce);
43
+
44
+ case 8:
45
+ _context.prev = 8;
46
+ _context.t0 = _context["catch"](0);
47
+ throw new Error('[FLAGSHIP_CERTIFICATION] Something went wrong while requesting a challenge from CozyStack:\n' + _context.t0.message);
48
+
49
+ case 11:
50
+ case "end":
51
+ return _context.stop();
52
+ }
53
+ }
54
+ }, _callee, null, [[0, 8]]);
55
+ }));
56
+
57
+ return function getStackChallenge(_x) {
58
+ return _ref.apply(this, arguments);
59
+ };
60
+ }();
61
+ /**
62
+ * Give the app attestation to the Stack
63
+ *
64
+ * @param {AttestationResult} appAttestation - the app attestation that was returned by the app store
65
+ * @param {string} nonce - the Nonce string retrieved from the stack
66
+ * @param {CozyClient} client - the CozyClient instance
67
+ */
68
+
69
+
70
+ var giveAppAttestationToStack = /*#__PURE__*/function () {
71
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(appAttestation, nonce, client) {
72
+ var platform, attestation, keyId, stackClient;
73
+ return _regenerator.default.wrap(function _callee2$(_context2) {
74
+ while (1) {
75
+ switch (_context2.prev = _context2.next) {
76
+ case 0:
77
+ _context2.prev = 0;
78
+ platform = appAttestation.platform, attestation = appAttestation.attestation, keyId = appAttestation.keyId;
79
+ stackClient = client.getStackClient();
80
+ _context2.next = 5;
81
+ return stackClient.fetchJSON('POST', "/auth/clients/".concat(stackClient.oauthOptions.clientID, "/attestation"), {
82
+ platform: platform,
83
+ attestation: attestation,
84
+ challenge: nonce,
85
+ keyId: keyId
86
+ }, {
87
+ headers: {
88
+ Authorization: stackClient.registrationAccessTokenToAuthHeader()
89
+ }
90
+ });
91
+
92
+ case 5:
93
+ _context2.next = 10;
94
+ break;
95
+
96
+ case 7:
97
+ _context2.prev = 7;
98
+ _context2.t0 = _context2["catch"](0);
99
+ throw new Error('[FLAGSHIP_CERTIFICATION] Something went wrong while giving attestation to CozyStack:\n' + _context2.t0.message);
100
+
101
+ case 10:
102
+ case "end":
103
+ return _context2.stop();
104
+ }
105
+ }
106
+ }, _callee2, null, [[0, 7]]);
107
+ }));
108
+
109
+ return function giveAppAttestationToStack(_x2, _x3, _x4) {
110
+ return _ref2.apply(this, arguments);
111
+ };
112
+ }();
113
+ /**
114
+ * Verify app's identity and integrity so the Stack can trust it
115
+ * Verification is done on Stack side by using information from the app's store (Google Play or Apple AppStore)
116
+ *
117
+ * @param {CertificationConfig} certificationConfig - the required configuration to access the stores API
118
+ * @param {CozyClient} client - the CozyClient instance
119
+ */
120
+
121
+
122
+ var certifyFlagship = /*#__PURE__*/function () {
123
+ var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(certificationConfig, client) {
124
+ var stackChallengeNonce, appAttestation;
125
+ return _regenerator.default.wrap(function _callee3$(_context3) {
126
+ while (1) {
127
+ switch (_context3.prev = _context3.next) {
128
+ case 0:
129
+ if (certificationConfig) {
130
+ _context3.next = 2;
131
+ break;
132
+ }
133
+
134
+ throw new Error('[FLAGSHIP_CERTIFICATION] Certification configuration is not set');
135
+
136
+ case 2:
137
+ _context3.next = 4;
138
+ return getStackChallenge(client);
139
+
140
+ case 4:
141
+ stackChallengeNonce = _context3.sent;
142
+ _context3.next = 7;
143
+ return (0, _storeAttestation.getAppAttestationFromStore)(stackChallengeNonce, certificationConfig);
144
+
145
+ case 7:
146
+ appAttestation = _context3.sent;
147
+ _context3.next = 10;
148
+ return giveAppAttestationToStack(appAttestation, stackChallengeNonce, client);
149
+
150
+ case 10:
151
+ case "end":
152
+ return _context3.stop();
153
+ }
154
+ }
155
+ }, _callee3);
156
+ }));
157
+
158
+ return function certifyFlagship(_x5, _x6) {
159
+ return _ref3.apply(this, arguments);
160
+ };
161
+ }();
162
+
163
+ exports.certifyFlagship = certifyFlagship;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.getAppAttestationFromStore = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _reactNativeGoogleSafetynet = _interopRequireDefault(require("react-native-google-safetynet"));
15
+
16
+ //@ts-ignore
17
+
18
+ /**
19
+ * Retrieve the app's attestation from the Google Play store
20
+ *
21
+ * @param {string} nonce - the Nonce string retrieved from the stack
22
+ * @param {CertificationConfig} certificationConfig - Configuration to access the stores certification API
23
+ * @returns {Promise<AttestationResult>} the app's attestation
24
+ */
25
+ var getAppAttestationFromStore = /*#__PURE__*/function () {
26
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(nonce, certificationConfig) {
27
+ var attestationResult;
28
+ return _regenerator.default.wrap(function _callee$(_context) {
29
+ while (1) {
30
+ switch (_context.prev = _context.next) {
31
+ case 0:
32
+ _context.prev = 0;
33
+ _context.next = 3;
34
+ return _reactNativeGoogleSafetynet.default.sendAttestationRequestJWT(nonce, certificationConfig.androidSafetyNetApiKey);
35
+
36
+ case 3:
37
+ attestationResult = _context.sent;
38
+ return _context.abrupt("return", {
39
+ platform: 'android',
40
+ attestation: attestationResult
41
+ });
42
+
43
+ case 7:
44
+ _context.prev = 7;
45
+ _context.t0 = _context["catch"](0);
46
+ throw new Error('[FLAGSHIP_CERTIFICATION] Something went wrong while requesting an attestation from Google Safetynet:\n' + _context.t0.message);
47
+
48
+ case 10:
49
+ case "end":
50
+ return _context.stop();
51
+ }
52
+ }
53
+ }, _callee, null, [[0, 7]]);
54
+ }));
55
+
56
+ return function getAppAttestationFromStore(_x, _x2) {
57
+ return _ref.apply(this, arguments);
58
+ };
59
+ }();
60
+
61
+ exports.getAppAttestationFromStore = getAppAttestationFromStore;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.getAppAttestationFromStore = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _reactNativeIos11Devicecheck = _interopRequireDefault(require("react-native-ios11-devicecheck"));
15
+
16
+ //@ts-ignore
17
+
18
+ /**
19
+ * Retrieve the app's attestation from the Apple AppStore
20
+ *
21
+ * @param {string} nonce - the Nonce string retrieved from the stack
22
+ * @param {CertificationConfig} certificationConfig - Configuration to access the stores certification API
23
+ * @returns {Promise<AttestationResult>} the app's attestation
24
+ */
25
+ var getAppAttestationFromStore = /*#__PURE__*/function () {
26
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(nonce, certificationConfig) {
27
+ var keyId, attestKey;
28
+ return _regenerator.default.wrap(function _callee$(_context) {
29
+ while (1) {
30
+ switch (_context.prev = _context.next) {
31
+ case 0:
32
+ _context.prev = 0;
33
+ _context.next = 3;
34
+ return _reactNativeIos11Devicecheck.default.generateKey();
35
+
36
+ case 3:
37
+ keyId = _context.sent;
38
+ _context.next = 6;
39
+ return _reactNativeIos11Devicecheck.default.attestKey(keyId, nonce);
40
+
41
+ case 6:
42
+ attestKey = _context.sent;
43
+ return _context.abrupt("return", {
44
+ platform: 'ios',
45
+ attestation: attestKey,
46
+ keyId: keyId
47
+ });
48
+
49
+ case 10:
50
+ _context.prev = 10;
51
+ _context.t0 = _context["catch"](0);
52
+ throw new Error('[FLAGSHIP_CERTIFICATION] Something went wrong while requesting an attestation from Apple DeviceCheck:\n' + _context.t0.message);
53
+
54
+ case 13:
55
+ case "end":
56
+ return _context.stop();
57
+ }
58
+ }
59
+ }, _callee, null, [[0, 10]]);
60
+ }));
61
+
62
+ return function getAppAttestationFromStore(_x, _x2) {
63
+ return _ref.apply(this, arguments);
64
+ };
65
+ }();
66
+
67
+ exports.getAppAttestationFromStore = getAppAttestationFromStore;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.getAppAttestationFromStore = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ /**
15
+ * Retrieve the app's attestation from the app's store
16
+ * /!\ This is a mock implementation that should never be called
17
+ *
18
+ * @param {string} nonce - the Nonce string retrieved from the stack
19
+ * @param {CertificationConfig} certificationConfig - Configuration to access the stores certification API
20
+ * @returns {Promise<AttestationResult>} the app's attestation
21
+ */
22
+ var validateAppMock = /*#__PURE__*/function () {
23
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(nonce, certificationConfig) {
24
+ return _regenerator.default.wrap(function _callee$(_context) {
25
+ while (1) {
26
+ switch (_context.prev = _context.next) {
27
+ case 0:
28
+ throw new Error("validateApp can only be called from a React Native container");
29
+
30
+ case 1:
31
+ case "end":
32
+ return _context.stop();
33
+ }
34
+ }
35
+ }, _callee);
36
+ }));
37
+
38
+ return function validateAppMock(_x, _x2) {
39
+ return _ref.apply(this, arguments);
40
+ };
41
+ }();
42
+
43
+ var getAppAttestationFromStore = validateAppMock;
44
+ exports.getAppAttestationFromStore = getAppAttestationFromStore;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * A JSON Web Signature
3
+ * @typedef {string} jws
4
+ */
5
+
6
+ /**
7
+ * A JSON Web Signature
8
+ * @typedef {string} base64string
9
+ */
10
+
11
+ /**
12
+ * An app attestation from the app store
13
+ * @typedef {object} AttestationResult
14
+ * @property {string} platform
15
+ * @property {jws|base64string} attestation
16
+ * @property {string} [keyId]
17
+ */
18
+
19
+ /**
20
+ * Configuration to access the stores certification API
21
+ * @typedef {object} CertificationConfig
22
+ * @property {string} androidSafetyNetApiKey
23
+ */
24
+ "use strict";
@@ -103,8 +103,12 @@ var useQuery = function useQuery(queryDefinition, options) {
103
103
  as: as
104
104
  });
105
105
  }, [as, client]);
106
+ var fetch = (0, _react.useCallback)(function () {
107
+ return client.query(definition, options);
108
+ }, [client, definition, options]);
106
109
  return _objectSpread(_objectSpread({}, queryState), {}, {
107
- fetchMore: fetchMore
110
+ fetchMore: fetchMore,
111
+ fetch: fetch
108
112
  });
109
113
  };
110
114
 
@@ -52,6 +52,46 @@ describe('use query', () => {
52
52
  })
53
53
  })
54
54
 
55
+ it('should share the same API than ObservableQuery', () => {
56
+ const {
57
+ hookResult: {
58
+ result: { current }
59
+ }
60
+ } = setupQuery({
61
+ queryOptions: {
62
+ as: 'simpsons'
63
+ },
64
+ queryDefinition: () => Q('io.cozy.simpsons')
65
+ })
66
+ expect(current).toMatchObject({
67
+ data: [
68
+ expect.objectContaining({ name: 'Homer' }),
69
+ expect.objectContaining({ name: 'Marge' })
70
+ ],
71
+ definition: expect.objectContaining({
72
+ doctype: 'io.cozy.simpsons'
73
+ })
74
+ })
75
+
76
+ expect(Object.keys(current)).toEqual(
77
+ expect.objectContaining([
78
+ 'id',
79
+ 'definition',
80
+ 'fetchStatus',
81
+ 'lastFetch',
82
+ 'lastUpdate',
83
+ 'lastErrorUpdate',
84
+ 'lastError',
85
+ 'hasMore',
86
+ 'count',
87
+ 'data',
88
+ 'bookmark',
89
+ 'options',
90
+ 'fetchMore',
91
+ 'fetch'
92
+ ])
93
+ )
94
+ })
55
95
  it('should query through the client in context', () => {
56
96
  const { client } = setupQuery({
57
97
  queryOptions: {
@@ -32,7 +32,7 @@ var buildItemsByLabel = function buildItemsByLabel(labels) {
32
32
  */
33
33
 
34
34
 
35
- var identityLabels = ['identity_photo', 'national_id_card', 'passport', 'residence_permit', 'family_record_book', 'birth_certificate', 'driver_license', 'citizen_registration_certificate', 'personal_sporting_licence', 'other_identity_document'];
35
+ var identityLabels = ['identity_photo', 'national_id_card', 'passport', 'residence_permit', 'family_record_book', 'birth_certificate', 'driver_license', 'citizen_registration_certificate', 'other_identity_document'];
36
36
  /**
37
37
  * @type {Array<FamilyLabel>}
38
38
  */
@@ -42,7 +42,7 @@ var familyLabels = ['family_record_book', 'birth_certificate', 'wedding', 'pacs'
42
42
  * @type {Array<WorkStudyLabels>}
43
43
  */
44
44
 
45
- var workStudyLabels = ['diploma', 'work_contract', 'pay_sheet', 'unemployment_benefit', 'pension', 'work_disability_recognition', 'other_revenue', 'gradebook', 'student_card', 'school_attendance_certificate', 'resume', 'motivation_letter', 'other_work_document'];
45
+ var workStudyLabels = ['diploma', 'work_contract', 'pay_sheet', 'unemployment_benefit', 'pension', 'work_disability_recognition', 'gradebook', 'student_card', 'school_attendance_certificate', 'resume', 'motivation_letter', 'other_work_document'];
46
46
  /**
47
47
  * @type {Array<HealthLabels>}
48
48
  */
@@ -58,11 +58,16 @@ var homeLabels = ['phone_invoice', 'isp_invoice', 'telecom_invoice', 'energy_inv
58
58
  */
59
59
 
60
60
  var transportLabels = ['driver_license', 'vehicle_registration', 'car_insurance', 'mechanic_invoice', 'transport_invoice', 'other_transport_document'];
61
+ /**
62
+ * @type {Array<ActivityLabels>}
63
+ */
64
+
65
+ var activityLabels = ['personal_sporting_licence', 'other_activity_document'];
61
66
  /**
62
67
  * @type {Array<FinanceLabels>}
63
68
  */
64
69
 
65
- var financeLabels = ['tax_return', 'tax_notice', 'tax_timetable', 'receipt', 'other_tax_document', 'bank_details', 'bank_statement', 'loan_agreement', 'payment_proof_family_allowance', 'other_bank_document'];
70
+ var financeLabels = ['tax_return', 'tax_notice', 'tax_timetable', 'receipt', 'other_tax_document', 'bank_details', 'bank_statement', 'loan_agreement', 'payment_proof_family_allowance', 'other_bank_document', 'other_revenue'];
66
71
  /**
67
72
  * @type {Array<InvoiceLabels>}
68
73
  */
@@ -107,11 +112,16 @@ var themesList = [{
107
112
  defaultItems: ['driver_license']
108
113
  }, {
109
114
  id: 'theme7',
115
+ label: 'activity',
116
+ icon: 'compass',
117
+ items: buildItemsByLabel(activityLabels)
118
+ }, {
119
+ id: 'theme8',
110
120
  label: 'finance',
111
121
  icon: 'bank',
112
122
  items: buildItemsByLabel(financeLabels)
113
123
  }, {
114
- id: 'theme8',
124
+ id: 'theme9',
115
125
  label: 'invoice',
116
126
  icon: 'bill',
117
127
  items: buildItemsByLabel(invoiceLabels)
@@ -33,7 +33,7 @@
33
33
  "birth_certificate": "Birth certificate",
34
34
  "citizen_registration_certificate": "Certificate of citizen registration",
35
35
  "driver_license": "Driving license",
36
- "other_identity_document": "Other identity",
36
+ "other_identity_document": "Other document of identity",
37
37
  "wedding": "Wedding contract",
38
38
  "pacs": "Civil union",
39
39
  "divorce": "Divorce",
@@ -98,7 +98,8 @@
98
98
  "other_bank_document": "Other banking document",
99
99
  "invoices": "Invoices",
100
100
  "personal_sporting_licence": "Sporting licence",
101
- "other_invoice": "Other invoice"
101
+ "other_invoice": "Other invoice",
102
+ "other_activity_document": "Other sports document"
102
103
  },
103
104
  "themes": {
104
105
  "identity": "Identity",
@@ -110,7 +111,8 @@
110
111
  "invoice": "Invoice",
111
112
  "others": "Others",
112
113
  "undefined": "Undefined",
113
- "finance": "Finance"
114
+ "finance": "Finance",
115
+ "activity": "Activities"
114
116
  }
115
117
  }
116
118
  }
@@ -33,7 +33,7 @@
33
33
  "birth_certificate": "Certificat de naissance",
34
34
  "citizen_registration_certificate": "Attestation de recensement citoyen",
35
35
  "driver_license": "Permis",
36
- "other_identity_document": "Autre identité",
36
+ "other_identity_document": "Autre document d'identité",
37
37
  "wedding": "Contrat de mariage",
38
38
  "pacs": "Attestation de PACS",
39
39
  "divorce": "Attestation de divorce",
@@ -98,7 +98,8 @@
98
98
  "other_bank_document": "Autre document bancaire",
99
99
  "invoices": "Factures",
100
100
  "personal_sporting_licence": "Licences sportives",
101
- "other_invoice": "Autre facture"
101
+ "other_invoice": "Autre facture",
102
+ "other_activity_document": "Autre document sportif"
102
103
  },
103
104
  "themes": {
104
105
  "identity": "Identité",
@@ -110,7 +111,8 @@
110
111
  "invoice": "Factures",
111
112
  "others": "Autres",
112
113
  "undefined": "Indéfini",
113
- "finance": "Finances"
114
+ "finance": "Finances",
115
+ "activity": "Activités & loisirs"
114
116
  }
115
117
  }
116
118
  }
package/dist/types.js CHANGED
@@ -280,7 +280,7 @@ var _dsl = require("./queries/dsl");
280
280
  *
281
281
  * @typedef {'family_record_book'|'birth_certificate'|'wedding'|'pacs'|'divorce'|'large_family_card'|'caf'|'other_family_document'|'payment_proof_family_allowance'} FamilyLabel
282
282
  *
283
- * @typedef {'diploma'|'work_contract'|'pay_sheet'|'unemployment_benefit'|'pension'|'other_revenue'|'gradebook'|'student_card'|'resume'|'motivation_letter'|'other_work_document'|'work_disability_recognition'|'school_attendance_certificate'} WorkStudyLabels
283
+ * @typedef {'diploma'|'work_contract'|'pay_sheet'|'unemployment_benefit'|'pension'|'gradebook'|'student_card'|'resume'|'motivation_letter'|'other_work_document'|'work_disability_recognition'|'school_attendance_certificate'} WorkStudyLabels
284
284
  *
285
285
  * @typedef {'health_certificate'|'health_book'|'national_health_insurance_card'|'health_insurance_card'|'prescription'|'health_invoice'|'national_health_insurance_right_certificate'|'work_disability_recognition'|'pregnancy_medical_certificate'|'other_health_document'} HealthLabels
286
286
  *
@@ -288,11 +288,13 @@ var _dsl = require("./queries/dsl");
288
288
  *
289
289
  * @typedef {'driver_license'|'vehicle_registration'|'car_insurance'|'mechanic_invoice'|'transport_invoice'|'other_transport_document'} TransportLabels
290
290
  *
291
- * @typedef {'tax_return'|'tax_notice'|'tax_timetable'|'receipt'|'other_tax_document'|'bank_details'|'bank_statement'|'loan_agreement'|'other_bank_document'|'payment_proof_family_allowance'} FinanceLabels
291
+ * @typedef {'tax_return'|'tax_notice'|'tax_timetable'|'receipt'|'other_tax_document'|'bank_details'|'bank_statement'|'loan_agreement'|'other_bank_document'|'payment_proof_family_allowance'|'other_revenue'} FinanceLabels
292
292
  *
293
293
  * @typedef {'phone_invoice'|'isp_invoice'|'telecom_invoice'|'energy_invoice'|'water_invoice'|'appliance_invoice'|'web_service_invoice'|'restaurant_invoice'|'work_invoice'|'transport_invoice'|'health_invoice'|'other_invoice'} InvoiceLabels
294
294
  *
295
- * @typedef {IdentityLabel|FamilyLabel|WorkStudyLabels|HealthLabels|HomeLabels|TransportLabels|FinanceLabels|InvoiceLabels} ItemsLabels
295
+ * @typedef {'personal_sporting_licence'|'other_activity_document'} ActivityLabels
296
+ *
297
+ * @typedef {IdentityLabel|FamilyLabel|WorkStudyLabels|HealthLabels|HomeLabels|TransportLabels|FinanceLabels|InvoiceLabels|ActivityLabels} ItemsLabels
296
298
  */
297
299
  var _default = {};
298
300
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-client",
3
- "version": "27.7.0",
3
+ "version": "27.11.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.6.5",
24
+ "cozy-stack-client": "^27.9.0",
25
25
  "json-stable-stringify": "^1.0.1",
26
26
  "lodash": "^4.17.13",
27
27
  "microee": "^0.0.6",
@@ -66,8 +66,10 @@
66
66
  "cozy-ui": ">34.0.0",
67
67
  "react": "^16.7.0",
68
68
  "react-native": "^0.65.0",
69
- "react-native-inappbrowser-reborn": "^3.5.1"
69
+ "react-native-google-safetynet": "0.0.4",
70
+ "react-native-inappbrowser-reborn": "^3.5.1",
71
+ "react-native-ios11-devicecheck": "https://github.com/cozy/react-native-devicecheck#app-attest-v0.1"
70
72
  },
71
73
  "sideEffects": false,
72
- "gitHead": "b301a3deef6018f8aa91ffcbcf1ad660b68711cd"
74
+ "gitHead": "97bc6226b59db1d7c41b96cffc0d48ce68d182ef"
73
75
  }
@@ -0,0 +1,2 @@
1
+ export function certifyFlagship(certificationConfig: CertificationConfig, client: CozyClient): Promise<void>;
2
+ import CozyClient from "../CozyClient";
@@ -0,0 +1 @@
1
+ export function getAppAttestationFromStore(nonce: string, certificationConfig: CertificationConfig): Promise<AttestationResult>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Retrieve the app's attestation from the app's store
3
+ * /!\ This is a mock implementation that should never be called
4
+ *
5
+ * @param {string} nonce - the Nonce string retrieved from the stack
6
+ * @param {CertificationConfig} certificationConfig - Configuration to access the stores certification API
7
+ * @returns {Promise<AttestationResult>} the app's attestation
8
+ */
9
+ export function getAppAttestationFromStore(nonce: string, certificationConfig: CertificationConfig): Promise<AttestationResult>;
@@ -0,0 +1 @@
1
+ export function getAppAttestationFromStore(nonce: string, certificationConfig: CertificationConfig): Promise<AttestationResult>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A JSON Web Signature
3
+ */
4
+ type jws = string;
5
+ /**
6
+ * A JSON Web Signature
7
+ */
8
+ type base64string = string;
9
+ /**
10
+ * An app attestation from the app store
11
+ */
12
+ type AttestationResult = {
13
+ platform: string;
14
+ attestation: jws | base64string;
15
+ keyId?: string;
16
+ };
17
+ /**
18
+ * Configuration to access the stores certification API
19
+ */
20
+ type CertificationConfig = {
21
+ androidSafetyNetApiKey: string;
22
+ };
@@ -52,7 +52,7 @@ export type Document = {
52
52
  _type: string;
53
53
  type: string;
54
54
  };
55
- export type PermissionVerb = "DELETE" | "PUT" | "POST" | "GET" | "ALL" | "PATCH";
55
+ export type PermissionVerb = "POST" | "DELETE" | "PUT" | "GET" | "ALL" | "PATCH";
56
56
  export type PermissionItem = {
57
57
  /**
58
58
  * - ALL, GET, PUT, PATCH, DELETE, POST…
package/types/types.d.ts CHANGED
@@ -317,11 +317,12 @@ export type QualificationAttributes = {
317
317
  };
318
318
  export type IdentityLabel = "identity_photo" | "national_id_card" | "passport" | "residence_permit" | "family_record_book" | "birth_certificate" | "driver_license" | "other_identity_document" | "citizen_registration_certificate" | "personal_sporting_licence";
319
319
  export type FamilyLabel = "family_record_book" | "birth_certificate" | "wedding" | "pacs" | "divorce" | "large_family_card" | "caf" | "other_family_document" | "payment_proof_family_allowance";
320
- export type WorkStudyLabels = "resume" | "diploma" | "work_contract" | "pay_sheet" | "unemployment_benefit" | "pension" | "other_revenue" | "gradebook" | "student_card" | "motivation_letter" | "other_work_document" | "work_disability_recognition" | "school_attendance_certificate";
320
+ export type WorkStudyLabels = "resume" | "diploma" | "work_contract" | "pay_sheet" | "unemployment_benefit" | "pension" | "gradebook" | "student_card" | "motivation_letter" | "other_work_document" | "work_disability_recognition" | "school_attendance_certificate";
321
321
  export type HealthLabels = "work_disability_recognition" | "health_certificate" | "health_book" | "national_health_insurance_card" | "health_insurance_card" | "prescription" | "health_invoice" | "national_health_insurance_right_certificate" | "pregnancy_medical_certificate" | "other_health_document";
322
322
  export type HomeLabels = "phone_invoice" | "isp_invoice" | "telecom_invoice" | "energy_invoice" | "water_invoice" | "house_sale_agreeement" | "building_permit" | "technical_diagnostic_record" | "lease" | "rent_receipt" | "house_insurance" | "work_quote" | "work_invoice" | "other_house_document" | "unfit_for_habitation_declaration" | "accommodation_proof";
323
323
  export type TransportLabels = "driver_license" | "vehicle_registration" | "car_insurance" | "mechanic_invoice" | "transport_invoice" | "other_transport_document";
324
- export type FinanceLabels = "payment_proof_family_allowance" | "tax_return" | "tax_notice" | "tax_timetable" | "receipt" | "other_tax_document" | "bank_details" | "bank_statement" | "loan_agreement" | "other_bank_document";
324
+ export type FinanceLabels = "payment_proof_family_allowance" | "tax_return" | "tax_notice" | "tax_timetable" | "receipt" | "other_tax_document" | "bank_details" | "bank_statement" | "loan_agreement" | "other_bank_document" | "other_revenue";
325
325
  export type InvoiceLabels = "health_invoice" | "phone_invoice" | "isp_invoice" | "telecom_invoice" | "energy_invoice" | "water_invoice" | "work_invoice" | "transport_invoice" | "appliance_invoice" | "web_service_invoice" | "restaurant_invoice" | "other_invoice";
326
- export type ItemsLabels = "resume" | "identity_photo" | "national_id_card" | "passport" | "residence_permit" | "family_record_book" | "birth_certificate" | "driver_license" | "other_identity_document" | "citizen_registration_certificate" | "personal_sporting_licence" | "wedding" | "pacs" | "divorce" | "large_family_card" | "caf" | "other_family_document" | "payment_proof_family_allowance" | "diploma" | "work_contract" | "pay_sheet" | "unemployment_benefit" | "pension" | "other_revenue" | "gradebook" | "student_card" | "motivation_letter" | "other_work_document" | "work_disability_recognition" | "school_attendance_certificate" | "health_certificate" | "health_book" | "national_health_insurance_card" | "health_insurance_card" | "prescription" | "health_invoice" | "national_health_insurance_right_certificate" | "pregnancy_medical_certificate" | "other_health_document" | "phone_invoice" | "isp_invoice" | "telecom_invoice" | "energy_invoice" | "water_invoice" | "house_sale_agreeement" | "building_permit" | "technical_diagnostic_record" | "lease" | "rent_receipt" | "house_insurance" | "work_quote" | "work_invoice" | "other_house_document" | "unfit_for_habitation_declaration" | "accommodation_proof" | "vehicle_registration" | "car_insurance" | "mechanic_invoice" | "transport_invoice" | "other_transport_document" | "tax_return" | "tax_notice" | "tax_timetable" | "receipt" | "other_tax_document" | "bank_details" | "bank_statement" | "loan_agreement" | "other_bank_document" | "appliance_invoice" | "web_service_invoice" | "restaurant_invoice" | "other_invoice";
326
+ export type ActivityLabels = "personal_sporting_licence" | "other_activity_document";
327
+ export type ItemsLabels = "resume" | "identity_photo" | "national_id_card" | "passport" | "residence_permit" | "family_record_book" | "birth_certificate" | "driver_license" | "other_identity_document" | "citizen_registration_certificate" | "personal_sporting_licence" | "wedding" | "pacs" | "divorce" | "large_family_card" | "caf" | "other_family_document" | "payment_proof_family_allowance" | "diploma" | "work_contract" | "pay_sheet" | "unemployment_benefit" | "pension" | "gradebook" | "student_card" | "motivation_letter" | "other_work_document" | "work_disability_recognition" | "school_attendance_certificate" | "health_certificate" | "health_book" | "national_health_insurance_card" | "health_insurance_card" | "prescription" | "health_invoice" | "national_health_insurance_right_certificate" | "pregnancy_medical_certificate" | "other_health_document" | "phone_invoice" | "isp_invoice" | "telecom_invoice" | "energy_invoice" | "water_invoice" | "house_sale_agreeement" | "building_permit" | "technical_diagnostic_record" | "lease" | "rent_receipt" | "house_insurance" | "work_quote" | "work_invoice" | "other_house_document" | "unfit_for_habitation_declaration" | "accommodation_proof" | "vehicle_registration" | "car_insurance" | "mechanic_invoice" | "transport_invoice" | "other_transport_document" | "tax_return" | "tax_notice" | "tax_timetable" | "receipt" | "other_tax_document" | "bank_details" | "bank_statement" | "loan_agreement" | "other_bank_document" | "other_revenue" | "appliance_invoice" | "web_service_invoice" | "restaurant_invoice" | "other_invoice" | "other_activity_document";
327
328
  import { QueryDefinition } from "./queries/dsl";