diff --git a/manifest.konnector b/manifest.konnector index 18cabefb2977618281296ba253bd5bd7c906f355..2b7c44f64191713486682c6bc72da69c03837825 100755 --- a/manifest.konnector +++ b/manifest.konnector @@ -1,5 +1,5 @@ { - "version": "1.0.3", + "version": "1.0.4", "name": "GRDF", "type": "konnector", "language": "node", @@ -60,5 +60,6 @@ } } }, - "manifest_version": "2" -} + "manifest_version": "2", + "on_delete_account": "onDeleteAccount.js" +} \ No newline at end of file diff --git a/package.json b/package.json index abce1af539dd2c792f6781d6c991c6a022ea812e..d491313b1d2d67e7b7f1cdfa16b169126a51a7de 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grdf", - "version": "1.0.3", + "version": "1.0.4", "description": "", "repository": { "type": "git", @@ -28,6 +28,7 @@ "start": "node ./src/index.js", "dev": "cozy-konnector-dev", "standalone": "cozy-konnector-standalone", + "onDeleteAccount": "cozy-konnector-dev src/onDeleteAccount.js", "pretest": "npm run clean", "clean": "rm -rf ./data", "build": "webpack", @@ -39,6 +40,7 @@ }, "dependencies": { "axios": "^0.20.0", + "cozy-client": "23.22.0", "cozy-konnector-libs": "4.34.5", "husky": "4.3.0", "jsonwebtoken": "^8.5.1", diff --git a/src/CozyUtils.js b/src/CozyUtils.js new file mode 100644 index 0000000000000000000000000000000000000000..091957b0a24af364dc4c5806e66154df1f8af167 --- /dev/null +++ b/src/CozyUtils.js @@ -0,0 +1,96 @@ +const { log } = require('cozy-konnector-libs') +const CozyClient = require('cozy-client').default +const { Q } = require('cozy-client') + +const { + APP_NAME, + DOCTYPE_ACCOUNTS, + DOCTYPE_ACCOUNTS_VERSION +} = require('./constants') + +function getAccessToken(environment) { + try { + if (environment === 'development') { + const cozyCredentials = JSON.parse(process.env.COZY_CREDENTIALS) + return cozyCredentials.token.accessToken + } else { + return process.env.COZY_CREDENTIALS.trim() + } + } catch (err) { + log( + 'error', + `Please provide proper COZY_CREDENTIALS environment variable. ${process.env.COZY_CREDENTIALS} is not OK` + ) + + throw err + } +} + +function getCozyUrl() { + if (process.env.COZY_URL === undefined) { + log('error', 'Please provide COZY_URL environment variable.') + throw new Error('COZY_URL environment variable is absent/not valid') + } else { + return process.env.COZY_URL + } +} + +function getSchema() { + return { + accounts: { + doctype: DOCTYPE_ACCOUNTS, + doctypeVersion: DOCTYPE_ACCOUNTS_VERSION + } + } +} + +function initCozyClient(accountId) { + const environment = + process.env.NODE_ENV === 'none' ? 'production' : process.env.NODE_ENV + try { + const uri = getCozyUrl(environment) + const token = getAccessToken(environment) + const appMetadata = { + slug: APP_NAME, + sourceAccount: accountId, + version: '1.0.3' + } + const schema = getSchema() + return new CozyClient({ uri, token, appMetadata, schema }) + } catch (err) { + log('error', 'Unable to initialize cozy client') + throw err + } +} + +class CozyUtils { + constructor(accountId) { + this.client = initCozyClient(accountId) + } + + /* + Update io.cozy.accounts auth.accountName field + */ + async getAccountInfos(accountId) { + try { + log('debug', 'SENDING FIND HARVEST ECOLYO REQUEST ACCOUNT : ' + accountId) + const query = Q(DOCTYPE_ACCOUNTS) + // eslint-disable-next-line @typescript-eslint/camelcase + .where({ account_type: 'grdfgrandlyon' }) + .limitBy(1) + const { data: accounts } = await this.client.query(query) + return accounts[0] ? accounts[0] : null + } catch (err) { + log( + 'warn', + `Error while trying to fetch account info (for ${accountId}): ${err.message}` + ) + } + } + + save(params) { + return this.client.save(params) + } +} + +module.exports = CozyUtils diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000000000000000000000000000000000000..957d04b782f0bccc8bd376475f9a30cd7fae7bc1 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,20 @@ +const APP_NAME = `konnector-grdfgrandlyon` + +const DOCTYPE_ACCOUNTS = 'io.cozy.accounts' +const DOCTYPE_ACCOUNTS_VERSION = 1 +const DOCTYPE_CONTACTS = 'io.cozy.contacts' +const DOCTYPE_CONTACTS_ACCOUNT = 'io.cozy.contacts.accounts' +const DOCTYPE_CONTACTS_VERSION = 2 +const DOCTYPE_CONTACTS_ACCOUNT_VERSION = 1 +const SHOULD_SYNC_ORPHAN_DEFAULT_VALUE = true + +module.exports = { + APP_NAME, + DOCTYPE_ACCOUNTS, + DOCTYPE_ACCOUNTS_VERSION, + DOCTYPE_CONTACTS, + DOCTYPE_CONTACTS_ACCOUNT, + DOCTYPE_CONTACTS_VERSION, + DOCTYPE_CONTACTS_ACCOUNT_VERSION, + SHOULD_SYNC_ORPHAN_DEFAULT_VALUE +} diff --git a/src/helpers/getAccountRev.js b/src/helpers/getAccountRev.js new file mode 100644 index 0000000000000000000000000000000000000000..7d7e5b44e10b01d2f24032a5f8392b9d4d2b4a2f --- /dev/null +++ b/src/helpers/getAccountRev.js @@ -0,0 +1,12 @@ +function getAccountRev() { + try { + return process.env.NODE_ENV === 'development' || + process.env.NODE_ENV === 'test' + ? 'fakeAccountRev' + : JSON.parse(process.env.COZY_FIELDS).account_rev + } catch (err) { + throw new Error(`You must provide 'account' in COZY_FIELDS: ${err.message}`) + } +} + +module.exports = getAccountRev diff --git a/src/helpers/getAccountSecret.js b/src/helpers/getAccountSecret.js new file mode 100644 index 0000000000000000000000000000000000000000..7a1ead76c2a435241928ec74a4f9677bce058662 --- /dev/null +++ b/src/helpers/getAccountSecret.js @@ -0,0 +1,14 @@ +function getAccountSecret() { + try { + return process.env.NODE_ENV === 'development' || + process.env.NODE_ENV === 'test' + ? 'fakeAccountSecret' + : JSON.parse(process.env.COZY_PARAMETERS).secret + } catch (err) { + throw new Error( + `You must provide 'account-types' in COZY_PARAMETERS: ${err.message}` + ) + } +} + +module.exports = getAccountSecret diff --git a/src/index.js b/src/index.js index 6dec2afa0c1303276beaea8a555950dae84e0db2..fe11af19711f17a3d21185d285d63a12b153aa20 100755 --- a/src/index.js +++ b/src/index.js @@ -57,7 +57,6 @@ async function start(fields) { fields.access_token ) { id_pce = this._account.oauth_callback_results.pce - log('debug', 'THE ID_PCE SENDING TO GETDATA : ' + id_pce) const grdfData = await getData(fields.access_token, id_pce) if (grdfData) { @@ -91,7 +90,6 @@ async function start(fields) { // Retrieve data from grdf API async function getData(token, idPCE) { - log('debug', 'ENTERING GETDATA') var myHeaders = new Headers() myHeaders.append('Content-Type', 'application/x-ndjson') myHeaders.append('Authorization', 'Bearer ' + token) @@ -108,13 +106,12 @@ async function getData(token, idPCE) { startDate + '&date_fin=' + endDate - log('debug', 'GET DATA URL ' + url) const rep = await fetch(url, requestOptions) .then(async response => { if (response.status !== 200) { throw new Error(response.status + ' - ' + response.statusText) } - return await response.text() + return response.text() }) .then(result => { return result.match(/.+/g).map(s => { @@ -186,7 +183,7 @@ async function storeData(data, doctype, filterKeys) { const filteredDocuments = await hydrateAndFilter(data, doctype, { keys: filterKeys }) - return await addData(filteredDocuments, doctype) + return addData(filteredDocuments, doctype) } /** diff --git a/src/onDeleteAccount.js b/src/onDeleteAccount.js new file mode 100644 index 0000000000000000000000000000000000000000..32e3050a8a4671ef663a6bab9de94da3015472a1 --- /dev/null +++ b/src/onDeleteAccount.js @@ -0,0 +1,184 @@ +const { cozyClient, log } = require("cozy-konnector-libs"); +const getAccountId = require("./helpers/getAccountId"); +const getAccountRev = require("./helpers/getAccountRev"); +const getAccountSecret = require("./helpers/getAccountSecret"); +const moment = require("moment"); +require("moment-timezone"); +moment.locale("fr"); // set the language +moment.tz.setDefault("Europe/Paris"); // set the timezone + +async function onDeleteAccount(accountId) { + const accountRev = getAccountRev(); + if (accountRev) { + try { + let body = ""; + let access_token = ""; + body = await cozyClient.fetchJSON( + "GET", + `/data/io.cozy.accounts/${accountId}?rev=${accountRev}` + ); + if (body.oauth.access_token) { + access_token = body.oauth.access_token; + } else { + throw new Error( + "cozyClient.fetchJson account_rev has encountered an error" + ); + } + if (moment().diff(body.oauth.expires_at) > 0) { + // token is expired, need a new one. grdf does not provide a refresh token + // so we request a new one from a client_credentials query + // first we fetch credentials secrets from account-type + const accountSecret = getAccountSecret(); + if (accountSecret) { + var myTokenHeaders = new Headers(); + myTokenHeaders.append( + "Content-Type", + "application/x-www-form-urlencoded" + ); + var urlencoded = new URLSearchParams(); + urlencoded.append("grant_type", "client_credentials"); + urlencoded.append("client_id", accountSecret.client_id); + urlencoded.append("client_secret", accountSecret.client_secret); + urlencoded.append("scope", "/adict/v1"); + + var requestOptionsToken = { + method: "POST", + headers: myTokenHeaders, + body: urlencoded, + redirect: "follow" + }; + + access_token = await fetch( + "https://sofit-sso-oidc.grdf.fr/openam/oauth2/realms/externeGrdf/access_token", + requestOptionsToken + ) + .then(async response => { + if (response.status !== 200) { + throw new Error(response.status + " - " + response.statusText); + } + return response.text(); + }) + .then(result => { + return result.match(/.+/g).map(s => { + result = JSON.parse(s); + if (result.access_token) { + return result.access_token; + } + }); + }) + .catch(error => { + log("debug", "Error from get access_token [onDeleteAccount]"); + throw error; + }); + } else { + throw new Error( + "Access Token is expired and konnector failed to get a new one" + ); + } + } + + var myHeaders = new Headers(); + myHeaders.append("Content-Type", "application/json"); + myHeaders.append("Accept", "application/x-ndjson"); + myHeaders.append("Authorization", "Bearer " + access_token); + var raw = JSON.stringify({ + role_tiers: ["AUTORISE_CONTRAT_FOURNITURE"], + etat_droit_acces: ["Active"], + id_pce: [body.oauth_callback_results.pce] + }); + var requestOptions = { + method: "POST", + headers: myHeaders, + body: raw, + redirect: "follow" + }; + + let accessRights = await fetch( + "https://api.grdf.fr/adict/v1/droits_acces", + requestOptions + ) + .then(async response => { + if (response.status !== 200) { + throw new Error(response.status + " - " + response.statusText); + } + return response.text(); + }) + .then(result => { + return result.match(/.+/g).map(s => { + result = JSON.parse(s); + if (result.id_droit_acces !== null) { + return result.id_droit_acces; + } + }); + }) + .catch(error => { + log("debug", "Error from get droits_access"); + throw error; + }); + + // remove unwanted commas + accessRights = accessRights.toString().replace(/,\s*$/, ""); + if (accessRights) { + var myDeleteHeaders = new Headers(); + myDeleteHeaders.append("Cache-Control", "no-cache"); + myDeleteHeaders.append("Content-Type", "application/json"); + myDeleteHeaders.append("Authorization", "Bearer " + access_token); + + var deleteRaw = JSON.stringify({}); + + var deleteRequestOptions = { + method: "PATCH", + headers: myDeleteHeaders, + body: deleteRaw, + redirect: "follow" + }; + + var url = "https://api.grdf.fr/adict/v1/droit_acces/" + accessRights; + + await fetch(url, deleteRequestOptions) + .then(async response => { + if (response.status !== 200) { + throw new Error(response.status + " - " + response.statusText); + } + return response.text(); + }) + .catch(error => { + log("debug", "Error from delete droits_access"); + throw error; + }); + + log("debug", "Active consent was successfully removed"); + } else { + log("debug", "No active consent"); + throw new Error("No active access right was found for given user"); + } + } catch (err) { + log( + "warn", + `Error while trying to remove grdf consent (for ${accountRev}): ${err.message}` + ); + } + } else { + throw new Error( + "No account revision was found, something went wrong during the deletion of said account" + ); + } +} + +const accountId = getAccountId(); +onDeleteAccount(accountId).then( + () => { + log( + "info", + `onDeleteAccount: Successfully retrieved grdf account from account doctype.` + ); + }, + err => { + log( + "error", + `onDeleteAccount: An error occured during getGrdfAccountInfos script: ${err.message}` + ); + } +); + +module.exports = { onDeleteAccount }; diff --git a/webpack.config.js b/webpack.config.js index df4df3ce23a39430ee93dd1d098618566a85b185..1507434ca3b411aa4852d173a81d7ad9d0045068 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,7 +4,7 @@ const webpack = require('webpack') const fs = require('fs') const SvgoInstance = require('svgo') -const entry = require('./package.json').main +const index = require('./package.json').main const readManifest = () => JSON.parse(fs.readFileSync(path.join(__dirname, './manifest.konnector'))) @@ -28,12 +28,15 @@ try { const appIconRX = iconName && new RegExp(`[^/]*/${iconName}`) module.exports = { - entry, + entry: { + index, + onDeleteAccount: './src/onDeleteAccount.js' + }, target: 'node', mode: 'none', output: { path: path.join(__dirname, 'build'), - filename: 'index.js' + filename: '[name].js' }, plugins: [ new CopyPlugin({ diff --git a/yarn.lock b/yarn.lock index 34934e91819ecefd73ce895e1b303c882bcccf2f..2ecb2ba91ee9df2889165cbe95b91bb76230139a 100755 --- a/yarn.lock +++ b/yarn.lock @@ -74,6 +74,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.9.2": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.0.tgz#b8d142fc0f7664fb3d9b5833fd40dcbab89276c0" + integrity sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -107,6 +114,24 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@cozy/minilog@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@cozy/minilog/-/minilog-1.0.0.tgz#1acc1aad849261e931e255a5f181b638315f7b84" + integrity sha512-IkDHF9CLh0kQeSEVsou59ar/VehvenpbEUjLfwhckJyOUqZnKAWmXy8qrBgMT5Loxr8Xjs2wmMnj0D67wP00eQ== + dependencies: + microee "0.0.6" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -228,11 +253,43 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^26.0.20": + version "26.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" + integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== + dependencies: + jest-diff "^26.0.0" + pretty-format "^26.0.0" + "@types/json-schema@^7.0.5": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/lodash@^4.14.170": + version "4.14.178" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" + integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== + "@types/node@*": version "14.11.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.1.tgz#56af902ad157e763f9ba63d671c39cda3193c835" @@ -248,6 +305,18 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -1445,6 +1514,32 @@ cozy-client@13.15.0: sift "^6.0.0" url-search-params-polyfill "^7.0.0" +cozy-client@23.22.0: + version "23.22.0" + resolved "https://registry.yarnpkg.com/cozy-client/-/cozy-client-23.22.0.tgz#2cc3c256635dcbbaef160bf37df7480a1938967c" + integrity sha512-zoKvEA83/4c0JU+T3ZoeLYoKnJsbz7V9nVJ89cAW0KJ8HESztZhumAjNJwo7lTJYh/lZkEhHF5QugP5NJTV0lg== + dependencies: + "@cozy/minilog" "1.0.0" + "@types/jest" "^26.0.20" + "@types/lodash" "^4.14.170" + btoa "^1.2.1" + cozy-device-helper "^1.12.0" + cozy-flags "2.7.1" + cozy-logger "^1.6.0" + cozy-stack-client "^23.19.0" + json-stable-stringify "^1.0.1" + lodash "^4.17.13" + microee "^0.0.6" + node-fetch "^2.6.1" + open "^7.0.2" + prop-types "^15.6.2" + react-redux "^7.2.0" + redux "3 || 4" + redux-thunk "^2.3.0" + server-destroy "^1.0.1" + sift "^6.0.0" + url-search-params-polyfill "^7.0.0" + cozy-client@^13.13.0: version "13.21.0" resolved "https://registry.yarnpkg.com/cozy-client/-/cozy-client-13.21.0.tgz#931e3056c933d0760567c734641e3c830381328d" @@ -1467,6 +1562,13 @@ cozy-client@^13.13.0: sift "^6.0.0" url-search-params-polyfill "^7.0.0" +cozy-device-helper@^1.12.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/cozy-device-helper/-/cozy-device-helper-1.17.0.tgz#fbce9737ea83c67969b2b173163b37299a36283c" + integrity sha512-G61i75dPe/JwLUxN0foWG34lnm+0iybMu05AjoXv/UU2fRsTPfNnsHH4ZRi5JS6OPK4ccuj+ffRmabdywo23TA== + dependencies: + lodash "^4.17.19" + cozy-device-helper@^1.7.3: version "1.10.2" resolved "https://registry.yarnpkg.com/cozy-device-helper/-/cozy-device-helper-1.10.2.tgz#f744ce65c76d1e5a95e30bf6c08bcc6d9d772f37" @@ -1486,6 +1588,13 @@ cozy-doctypes@^1.73.0: lodash "4.17.19" prop-types "^15.7.2" +cozy-flags@2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/cozy-flags/-/cozy-flags-2.7.1.tgz#f37251fee248ef9bef079a22bc52954f1a892dfc" + integrity sha512-TtVhuyMSRADRr4q5LSaRjq6u03S5m1zkZRc8n3q8bfad86FizqGC02m3e/Zh4kWTwnsO0pVW+mzeVSsBqDVT/g== + dependencies: + microee "^0.0.6" + cozy-jobs-cli@1.13.6: version "1.13.6" resolved "https://registry.yarnpkg.com/cozy-jobs-cli/-/cozy-jobs-cli-1.13.6.tgz#04f0e28d260da51ee02fccce1da6f9353a446f46" @@ -1550,6 +1659,16 @@ cozy-stack-client@^13.12.1, cozy-stack-client@^13.20.2: mime "^2.4.0" qs "^6.7.0" +cozy-stack-client@^23.19.0: + version "23.19.0" + resolved "https://registry.yarnpkg.com/cozy-stack-client/-/cozy-stack-client-23.19.0.tgz#2972c3dcc151b13c0f65749f341a6349170fe1d3" + integrity sha512-oq7/ERKy/Gg3jnxSi0rs3upvBccsGmmfdMiIa9hhJcw/Vxl7NMmjUM2itPnfmBNAMfBax6VlB8HWI1LY87fLuw== + dependencies: + cozy-flags "2.7.1" + detect-node "^2.0.4" + mime "^2.4.0" + qs "^6.7.0" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -1805,6 +1924,11 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3366,6 +3490,21 @@ isstream@0.1.x, isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +jest-diff@^26.0.0: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + js-beautify@^1.6.12: version "1.13.0" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.13.0.tgz#a056d5d3acfd4918549aae3ab039f9f3c51eebb2" @@ -3425,6 +3564,13 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + json-stringify-safe@5.0.1, json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -3451,6 +3597,11 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + jsonwebtoken@^8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" @@ -4094,6 +4245,13 @@ node-fetch@^2.0.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@^2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -4674,6 +4832,16 @@ prettier@1.18.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== +pretty-format@^26.0.0, pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + pretty@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5" @@ -4900,6 +5068,11 @@ react-is@^16.7.0, react-is@^16.8.1, react-is@^16.9.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-redux@^7.2.0: version "7.2.1" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985" @@ -4966,6 +5139,13 @@ redux-thunk@^2.3.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== +"redux@3 || 4": + version "4.1.2" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" + integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== + dependencies: + "@babel/runtime" "^7.9.2" + redux@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" @@ -5941,6 +6121,11 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + tslib@^1.9.0: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" @@ -6205,6 +6390,11 @@ watchpack@^1.7.4: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webpack-cli@3.3.12: version "3.3.12" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" @@ -6264,6 +6454,14 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"