cozy-client 60.37.1 → 60.38.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.
@@ -3127,7 +3127,7 @@ var CozyClient = /*#__PURE__*/function () {
3127
3127
  CozyClient.hooks = CozyClient.hooks || {};
3128
3128
  CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
3129
3129
 
3130
- CozyClient.version = "60.37.1";
3130
+ CozyClient.version = "60.38.0";
3131
3131
 
3132
3132
  _microee.default.mixin(CozyClient);
3133
3133
 
@@ -27,6 +27,12 @@ Object.defineProperty(exports, "ensureFirstSlash", {
27
27
  return _urlHelper.ensureFirstSlash;
28
28
  }
29
29
  });
30
+ Object.defineProperty(exports, "isHttpUrl", {
31
+ enumerable: true,
32
+ get: function get() {
33
+ return _urlHelper.isHttpUrl;
34
+ }
35
+ });
30
36
  Object.defineProperty(exports, "fetchRegistrationDetails", {
31
37
  enumerable: true,
32
38
  get: function get() {
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.fetchRegistrationDetails = exports.rootCozyUrl = exports.InvalidCozyUrlError = exports.BlockedCozyError = exports.InvalidProtocolError = exports.InvalidRedirectLinkError = exports.deconstructRedirectLink = exports.deconstructCozyWebLinkWithSlug = exports.generateWebLink = exports.ensureFirstSlash = void 0;
8
+ exports.fetchRegistrationDetails = exports.isHttpUrl = exports.rootCozyUrl = exports.InvalidCozyUrlError = exports.BlockedCozyError = exports.InvalidProtocolError = exports.InvalidRedirectLinkError = exports.deconstructRedirectLink = exports.deconstructCozyWebLinkWithSlug = exports.generateWebLink = exports.ensureFirstSlash = void 0;
9
9
 
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
11
 
@@ -509,6 +509,23 @@ var isResponseAboutBlockedCozy = /*#__PURE__*/function () {
509
509
  return _ref5.apply(this, arguments);
510
510
  };
511
511
  }();
512
+ /**
513
+ * Check if the given value is an absolute URL using the http or https protocol
514
+ *
515
+ * @param {any} value - Value to check
516
+ * @returns {boolean} true if the value is an absolute http(s) URL
517
+ */
518
+
519
+
520
+ var isHttpUrl = function isHttpUrl(value) {
521
+ if (typeof value !== 'string') return false;
522
+
523
+ try {
524
+ return ['http:', 'https:'].includes(new URL(value).protocol);
525
+ } catch (e) {
526
+ return false;
527
+ }
528
+ };
512
529
  /**
513
530
  * Check if the given url uses the expected protocols (http or https). Throws otherwise
514
531
  *
@@ -516,6 +533,8 @@ var isResponseAboutBlockedCozy = /*#__PURE__*/function () {
516
533
  */
517
534
 
518
535
 
536
+ exports.isHttpUrl = isHttpUrl;
537
+
519
538
  var throwIfInvalidProtocol = function throwIfInvalidProtocol(url) {
520
539
  if (!['http:', 'https:'].includes(url.protocol)) {
521
540
  throw new InvalidProtocolError(url);
@@ -5,6 +5,7 @@ import {
5
5
  deconstructRedirectLink,
6
6
  generateWebLink,
7
7
  fetchRegistrationDetails,
8
+ isHttpUrl,
8
9
  rootCozyUrl,
9
10
  InvalidRedirectLinkError,
10
11
  InvalidCozyUrlError,
@@ -133,6 +134,28 @@ describe('deconstructWebLink', () => {
133
134
  )
134
135
  })
135
136
 
137
+ describe('isHttpUrl', () => {
138
+ it.each([
139
+ 'http://alice.cozy.localhost:8080',
140
+ 'https://calendar.example.com/'
141
+ ])('accepts %p', value => {
142
+ expect(isHttpUrl(value)).toBe(true)
143
+ })
144
+
145
+ it.each([
146
+ undefined,
147
+ null,
148
+ true,
149
+ '',
150
+ 'calendar.example.com',
151
+ 'not a url',
152
+ 'javascript:alert(1)',
153
+ 'ftp://example.com'
154
+ ])('rejects %p', value => {
155
+ expect(isHttpUrl(value)).toBe(false)
156
+ })
157
+ })
158
+
136
159
  describe('deconstructRedirectLink', () => {
137
160
  it.each([
138
161
  [
@@ -13,6 +13,8 @@ var _cozyFlags = _interopRequireDefault(require("cozy-flags"));
13
13
 
14
14
  var _get = _interopRequireDefault(require("lodash/get"));
15
15
 
16
+ var _helpers = require("../helpers");
17
+
16
18
  var STORE_SLUG = 'store';
17
19
  /**
18
20
  * Returns the store URL of an app/konnector
@@ -79,7 +81,6 @@ var isInstalled = function isInstalled() {
79
81
  });
80
82
  };
81
83
  /**
82
- *
83
84
  * @param {object} app io.cozy.apps document
84
85
  * @returns {string} url to the app
85
86
  */
@@ -88,6 +89,11 @@ var isInstalled = function isInstalled() {
88
89
  exports.isInstalled = isInstalled;
89
90
 
90
91
  var getUrl = function getUrl(app) {
92
+ if (app.standalone === true && app.client_url_flag) {
93
+ var clientUrl = (0, _cozyFlags.default)(app.client_url_flag);
94
+ if ((0, _helpers.isHttpUrl)(clientUrl)) return clientUrl;
95
+ }
96
+
91
97
  return app.links && app.links.related;
92
98
  };
93
99
  /**
@@ -124,6 +124,55 @@ describe('applications model', () => {
124
124
  })
125
125
  })
126
126
 
127
+ describe('getUrl', () => {
128
+ const related = 'http://calendar.cozy.tools:8080/'
129
+
130
+ beforeEach(() => {
131
+ flag.mockReset()
132
+ })
133
+
134
+ it('returns links.related when the app has no client_url_flag', () => {
135
+ expect(applications.getUrl({ links: { related } })).toBe(related)
136
+ })
137
+
138
+ it('returns the flag value of a standalone app when it is a valid URL', () => {
139
+ flag.mockReturnValue('https://calendar.example.com/')
140
+ const app = {
141
+ standalone: true,
142
+ client_url_flag: 'calendar.embedded-app-url',
143
+ links: { related }
144
+ }
145
+ expect(applications.getUrl(app)).toBe('https://calendar.example.com/')
146
+ expect(flag).toHaveBeenCalledWith('calendar.embedded-app-url')
147
+ })
148
+
149
+ it.each([null, true, 'not a url', 'javascript:alert(1)'])(
150
+ 'returns links.related when the flag value is %p',
151
+ value => {
152
+ flag.mockReturnValue(value)
153
+ const app = {
154
+ standalone: true,
155
+ client_url_flag: 'calendar.embedded-app-url',
156
+ links: { related }
157
+ }
158
+ expect(applications.getUrl(app)).toBe(related)
159
+ }
160
+ )
161
+
162
+ it.each([undefined, false])(
163
+ 'returns links.related when standalone is %p',
164
+ standalone => {
165
+ flag.mockReturnValue('https://mail.example.com/')
166
+ const app = {
167
+ standalone,
168
+ client_url_flag: 'mail.embedded-app-url',
169
+ links: { related }
170
+ }
171
+ expect(applications.getUrl(app)).toBe(related)
172
+ }
173
+ )
174
+ })
175
+
127
176
  describe('get store installation url', () => {
128
177
  const contactsApp = { slug: 'contacts' }
129
178
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-client",
3
- "version": "60.37.1",
3
+ "version": "60.38.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.node.js",
6
6
  "browser": "dist/index.js",
@@ -74,5 +74,5 @@
74
74
  "react-native-ios11-devicecheck": "^0.0.3"
75
75
  },
76
76
  "sideEffects": false,
77
- "gitHead": "a8f098dca99c56f285eaf48199313f064bc68d1c"
77
+ "gitHead": "7531ce634e310b15dbbe32958a71600a57e8ecad"
78
78
  }
@@ -1,3 +1,3 @@
1
1
  export { dehydrate } from "./dehydrateHelper";
2
- export { deconstructCozyWebLinkWithSlug, deconstructRedirectLink, generateWebLink, ensureFirstSlash, fetchRegistrationDetails, rootCozyUrl, InvalidRedirectLinkError, InvalidCozyUrlError, InvalidProtocolError, BlockedCozyError } from "./urlHelper";
2
+ export { deconstructCozyWebLinkWithSlug, deconstructRedirectLink, generateWebLink, ensureFirstSlash, isHttpUrl, fetchRegistrationDetails, rootCozyUrl, InvalidRedirectLinkError, InvalidCozyUrlError, InvalidProtocolError, BlockedCozyError } from "./urlHelper";
3
3
  export { editSettings, getQuery, getSettings, normalizeSettings, saveAfterFetchSettings } from "./settings";
@@ -26,6 +26,7 @@ export class InvalidCozyUrlError extends Error {
26
26
  url: any;
27
27
  }
28
28
  export function rootCozyUrl(url: URL): Promise<URL>;
29
+ export function isHttpUrl(value: any): boolean;
29
30
  export function fetchRegistrationDetails(url: URL): Promise<RegistrationDetails>;
30
31
  export type RegistrationDetails = {
31
32
  /**