diff --git a/api-js/package-lock.json b/api-js/package-lock.json index f5c8ebda9..b0818cd4c 100644 --- a/api-js/package-lock.json +++ b/api-js/package-lock.json @@ -4,49 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@apollo/protobufjs": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.5.tgz", - "integrity": "sha512-ZtyaBH1icCgqwIGb3zrtopV2D5Q8yxibkJzlaViM08eOhTQc7rACdYu0pfORFfhllvdMZ3aq69vifYHszY4gNA==", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.0", - "@types/node": "^10.1.0", - "long": "^4.0.0" - }, - "dependencies": { - "@types/node": { - "version": "10.17.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz", - "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw==" - } - } - }, - "@apollographql/apollo-tools": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.4.8.tgz", - "integrity": "sha512-W2+HB8Y7ifowcf3YyPHgDI05izyRtOeZ4MqIr7LbTArtmJ0ZHULWpn84SGMW7NAvTV1tFExpHlveHhnXuJfuGA==", - "requires": { - "apollo-env": "^0.6.5" - } - }, - "@apollographql/graphql-playground-html": { - "version": "1.6.26", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz", - "integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==", - "requires": { - "xss": "^1.0.6" - } - }, "@babel/cli": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.12.1.tgz", @@ -2520,60 +2477,6 @@ "fastq": "^1.6.0" } }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" - }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -2607,14 +2510,6 @@ "defer-to-connect": "^1.0.1" } }, - "@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "requires": { - "@types/node": "*" - } - }, "@types/babel__core": { "version": "7.1.10", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.10.tgz", @@ -2656,76 +2551,6 @@ "@babel/types": "^7.3.0" } }, - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", - "requires": { - "@types/node": "*" - } - }, - "@types/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==" - }, - "@types/cookies": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", - "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", - "requires": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "@types/cors": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.7.tgz", - "integrity": "sha512-sOdDRU3oRS7LBNTIqwDkPJyq0lpHYcbMTt0TrjzsXbk/e37hcLTH6eZX7CdbDeN0yJJvzw9hFBZkbtCSbk/jAQ==", - "requires": { - "@types/express": "*" - } - }, - "@types/express": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz", - "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.9", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz", - "integrity": "sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/fs-capacitor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", - "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", - "requires": { - "@types/node": "*" - } - }, "@types/graceful-fs": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz", @@ -2735,27 +2560,6 @@ "@types/node": "*" } }, - "@types/graphql-upload": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.4.tgz", - "integrity": "sha512-0TRyJD2o8vbkmJF8InppFcPVcXKk+Rvlg/xvpHBIndSJYpmDWfmtx/ZAtl4f3jR2vfarpTqYgj8MZuJssSoU7Q==", - "requires": { - "@types/express": "*", - "@types/fs-capacitor": "*", - "@types/koa": "*", - "graphql": "^15.3.0" - } - }, - "@types/http-assert": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", - "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==" - }, - "@types/http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==" - }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -2792,58 +2596,11 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" - }, - "@types/koa": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.4.tgz", - "integrity": "sha512-Etqs0kdqbuAsNr5k6mlZQelpZKVwMu9WPRHVVTLnceZlhr0pYmblRNJbCgoCMzKWWePldydU0AYEOX4Q9fnGUQ==", - "requires": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "requires": { - "@types/koa": "*" - } - }, - "@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "@types/mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" - }, "@types/node": { "version": "14.0.24", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.24.tgz", "integrity": "sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA==" }, - "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -2862,39 +2619,12 @@ "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ==", "dev": true }, - "@types/qs": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", - "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==" - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" - }, - "@types/serve-static": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz", - "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==", - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, "@types/stack-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", "dev": true }, - "@types/ws": { - "version": "7.2.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.7.tgz", - "integrity": "sha512-UUFC/xxqFLP17hTva8/lVT0SybLUrfSD9c+iapKb0fEiC8uoDbA+xuZ3pAN603eW+bY8ebSMLm9jXdIPnD0ZgA==", - "requires": { - "@types/node": "*" - } - }, "@types/yargs": { "version": "15.0.9", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz", @@ -2991,14 +2721,6 @@ } } }, - "@wry/equality": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz", - "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==", - "requires": { - "tslib": "^1.9.3" - } - }, "abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -3125,180 +2847,6 @@ "picomatch": "^2.0.4" } }, - "apollo-cache-control": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.3.tgz", - "integrity": "sha512-21GCeC9AIIa22uD0Vtqn/N0D5kOB4rY/Pa9aQhxVeLN+4f8Eu4nmteXhFypUD0LL1/58dmm8lS5embsfoIGjEA==", - "requires": { - "apollo-server-env": "^2.4.5", - "apollo-server-plugin-base": "^0.10.1" - } - }, - "apollo-datasource": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.2.tgz", - "integrity": "sha512-ibnW+s4BMp4K2AgzLEtvzkjg7dJgCaw9M5b5N0YKNmeRZRnl/I/qBTQae648FsRKgMwTbRQIvBhQ0URUFAqFOw==", - "requires": { - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5" - } - }, - "apollo-env": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.5.tgz", - "integrity": "sha512-jeBUVsGymeTHYWp3me0R2CZRZrFeuSZeICZHCeRflHTfnQtlmbSXdy5E0pOyRM9CU4JfQkKDC98S1YglQj7Bzg==", - "requires": { - "@types/node-fetch": "2.5.7", - "core-js": "^3.0.1", - "node-fetch": "^2.2.0", - "sha.js": "^2.4.11" - } - }, - "apollo-graphql": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.6.0.tgz", - "integrity": "sha512-BxTf5LOQe649e9BNTPdyCGItVv4Ll8wZ2BKnmiYpRAocYEXAVrQPWuSr3dO4iipqAU8X0gvle/Xu9mSqg5b7Qg==", - "requires": { - "apollo-env": "^0.6.5", - "lodash.sortby": "^4.7.0" - } - }, - "apollo-link": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz", - "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==", - "requires": { - "apollo-utilities": "^1.3.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.9.3", - "zen-observable-ts": "^0.8.21" - } - }, - "apollo-reporting-protobuf": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.0.tgz", - "integrity": "sha512-AFLQIuO0QhkoCF+41Be/B/YU0C33BZ0opfyXorIjM3MNNiEDSyjZqmUozlB3LqgfhT9mn2IR5RSsA+1b4VovDQ==", - "requires": { - "@apollo/protobufjs": "^1.0.3" - } - }, - "apollo-server-caching": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz", - "integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==", - "requires": { - "lru-cache": "^5.0.0" - } - }, - "apollo-server-core": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.18.2.tgz", - "integrity": "sha512-phz57BFBukMa3Ta7ZVW7pj1pdUne9KYLbcBdEcITr+I0+nbhy+YM8gcgpOnjrokWYiEZgIe52XeM3m4BMLw5dg==", - "requires": { - "@apollographql/apollo-tools": "^0.4.3", - "@apollographql/graphql-playground-html": "1.6.26", - "@types/graphql-upload": "^8.0.0", - "@types/ws": "^7.0.0", - "apollo-cache-control": "^0.11.3", - "apollo-datasource": "^0.7.2", - "apollo-graphql": "^0.6.0", - "apollo-reporting-protobuf": "^0.6.0", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5", - "apollo-server-errors": "^2.4.2", - "apollo-server-plugin-base": "^0.10.1", - "apollo-server-types": "^0.6.0", - "apollo-tracing": "^0.11.4", - "async-retry": "^1.2.1", - "fast-json-stable-stringify": "^2.0.0", - "graphql-extensions": "^0.12.5", - "graphql-tag": "^2.9.2", - "graphql-tools": "^4.0.0", - "graphql-upload": "^8.0.2", - "loglevel": "^1.6.7", - "lru-cache": "^5.0.0", - "sha.js": "^2.4.11", - "subscriptions-transport-ws": "^0.9.11", - "uuid": "^8.0.0", - "ws": "^6.0.0" - } - }, - "apollo-server-env": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz", - "integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==", - "requires": { - "node-fetch": "^2.1.2", - "util.promisify": "^1.0.0" - } - }, - "apollo-server-errors": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.2.tgz", - "integrity": "sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ==" - }, - "apollo-server-express": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.18.2.tgz", - "integrity": "sha512-9P5YOSE2amcNdkXqxqU3oulp+lpwoIBdwS2vOP69kl6ix+n7vEWHde4ulHwwl4xLdtZ88yyxgdKJEIkhaepiNw==", - "requires": { - "@apollographql/graphql-playground-html": "1.6.26", - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.0", - "@types/cors": "2.8.7", - "@types/express": "4.17.7", - "@types/express-serve-static-core": "4.17.9", - "accepts": "^1.3.5", - "apollo-server-core": "^2.18.2", - "apollo-server-types": "^0.6.0", - "body-parser": "^1.18.3", - "cors": "^2.8.4", - "express": "^4.17.1", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.0", - "parseurl": "^1.3.2", - "subscriptions-transport-ws": "^0.9.16", - "type-is": "^1.6.16" - } - }, - "apollo-server-plugin-base": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.10.1.tgz", - "integrity": "sha512-XChCBDNyfByWqVXptsjPwrwrCj5cxMmNbchZZi8KXjtJ0hN2C/9BMNlInJd6bVGXvUbkRJYUakfKCfO5dZmwIg==", - "requires": { - "apollo-server-types": "^0.6.0" - } - }, - "apollo-server-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.0.tgz", - "integrity": "sha512-usqXaz81bHxD2IZvKEQNnLpSbf2Z/BmobXZAjEefJEQv1ItNn+lJNUmSSEfGejHvHlg2A7WuAJKJWyDWcJrNnA==", - "requires": { - "apollo-reporting-protobuf": "^0.6.0", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5" - } - }, - "apollo-tracing": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.4.tgz", - "integrity": "sha512-zBu/SwQlXfbdpcKLzWARGVjrEkIZUW3W9Mb4CCIzv07HbBQ8IQpmf9w7HIJJefC7rBiBJYg6JBGyuro3N2lxCA==", - "requires": { - "apollo-server-env": "^2.4.5", - "apollo-server-plugin-base": "^0.10.1" - } - }, - "apollo-utilities": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz", - "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==", - "requires": { - "@wry/equality": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0" - } - }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -3497,18 +3045,11 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, - "async-retry": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.1.tgz", - "integrity": "sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==", - "requires": { - "retry": "0.12.0" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "atob": { "version": "2.1.2", @@ -4021,14 +3562,6 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "requires": { - "dicer": "0.3.0" - } - }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4339,12 +3872,6 @@ "mimic-response": "^1.0.0" } }, - "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", - "optional": true - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4397,6 +3924,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -4510,7 +4038,8 @@ "core-js": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "dev": true }, "core-js-compat": { "version": "3.6.5", @@ -4741,6 +4270,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -4789,28 +4319,19 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, - "deprecated-decorator": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", - "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=" - }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", @@ -4836,14 +4357,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "requires": { - "streamsearch": "0.1.2" - } - }, "diff-sequences": { "version": "26.5.0", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz", @@ -5009,6 +4522,7 @@ "version": "1.17.7", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -5027,6 +4541,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -5860,7 +5375,8 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -6110,6 +5626,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -6141,11 +5658,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "fs-capacitor": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", - "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==" - }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -6175,7 +5687,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", @@ -6386,16 +5899,6 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz", "integrity": "sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==" }, - "graphql-extensions": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.5.tgz", - "integrity": "sha512-mGyGaktGpK3TVBtM0ZoyPX6Xk0mN9GYX9DRyFzDU4k4A2w93nLX7Ebcp+9/O5nHRmgrc0WziYYSmoWq2WNIoUQ==", - "requires": { - "@apollographql/apollo-tools": "^0.4.3", - "apollo-server-env": "^2.4.5", - "apollo-server-types": "^0.6.0" - } - }, "graphql-playground-html": { "version": "1.6.29", "resolved": "https://registry.npmjs.org/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", @@ -6412,15 +5915,6 @@ "graphql-playground-html": "^1.6.29" } }, - "graphql-redis-subscriptions": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/graphql-redis-subscriptions/-/graphql-redis-subscriptions-2.3.1.tgz", - "integrity": "sha512-ztS3ZXBSoPJ8Q0/o7PG2iLO6QWq2tlJrukiBJCjgMccRv1I3lt3HmLjiH2CbDjPhpoINttZNoytQbxE0OE/UpA==", - "requires": { - "ioredis": "^4.17.3", - "iterall": "^1.3.0" - } - }, "graphql-relay": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.6.0.tgz", @@ -6449,30 +5943,6 @@ "iterall": "^1.2.1" } }, - "graphql-tag": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.11.0.tgz", - "integrity": "sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA==" - }, - "graphql-tools": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.8.tgz", - "integrity": "sha512-MW+ioleBrwhRjalKjYaLQbr+920pHBgy9vM/n47sswtns8+96sRn5M/G+J1eu7IMeKWiN/9p6tmwCHU7552VJg==", - "requires": { - "apollo-link": "^1.2.14", - "apollo-utilities": "^1.0.1", - "deprecated-decorator": "^0.1.6", - "iterall": "^1.1.3", - "uuid": "^3.1.0" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, "graphql-transport-ws": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/graphql-transport-ws/-/graphql-transport-ws-1.9.0.tgz", @@ -6488,17 +5958,6 @@ } } }, - "graphql-upload": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.1.0.tgz", - "integrity": "sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q==", - "requires": { - "busboy": "^0.3.1", - "fs-capacitor": "^2.0.4", - "http-errors": "^1.7.3", - "object-path": "^0.11.4" - } - }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", @@ -6526,6 +5985,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -6539,7 +5999,8 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -6899,35 +6360,6 @@ } } }, - "ioredis": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.19.2.tgz", - "integrity": "sha512-SZSIwMrbd96b7rJvJwyTWSP6XQ0m1kAIIqBnwglJKrIJ6na7TeY4F2EV2vDY0xm/fLrUY8cEg81dR7kVFt2sKA==", - "optional": true, - "requires": { - "cluster-key-slot": "^1.1.0", - "debug": "^4.1.1", - "denque": "^1.1.0", - "lodash.defaults": "^4.2.0", - "lodash.flatten": "^4.4.0", - "p-map": "^2.1.0", - "redis-commands": "1.6.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.0.1" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "optional": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, "ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", @@ -6999,7 +6431,8 @@ "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true }, "is-ci": { "version": "2.0.0", @@ -7042,7 +6475,8 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-decimal": { "version": "1.0.4", @@ -7138,7 +6572,8 @@ "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true }, "is-npm": { "version": "4.0.0", @@ -7183,6 +6618,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -7203,6 +6639,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -8242,18 +7679,6 @@ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "optional": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "optional": true - }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -8292,7 +7717,8 @@ "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true }, "log-symbols": { "version": "2.2.0", @@ -8340,30 +7766,12 @@ } } }, - "loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", - "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==" - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -8913,17 +8321,14 @@ "object-inspect": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-path": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.5.tgz", - "integrity": "sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -8938,6 +8343,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.18.0-next.0", @@ -8949,6 +8355,7 @@ "version": "1.18.0-next.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -8970,6 +8377,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" @@ -9141,12 +8549,6 @@ "p-limit": "^1.1.0" } }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "optional": true - }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", @@ -9650,35 +9052,6 @@ "picomatch": "^2.2.1" } }, - "redis": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz", - "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==", - "requires": { - "denque": "^1.4.1", - "redis-commands": "^1.5.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - } - }, - "redis-commands": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.6.0.tgz", - "integrity": "sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ==" - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "requires": { - "redis-errors": "^1.0.0" - } - }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -9993,11 +9366,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10338,15 +9706,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -10672,12 +10031,6 @@ } } }, - "standard-as-callback": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", - "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==", - "optional": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -10710,11 +10063,6 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, "string-length": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz", @@ -10757,6 +10105,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -10766,6 +10115,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -11135,14 +10485,6 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "ts-invariant": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", - "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", - "requires": { - "tslib": "^1.9.3" - } - }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -11158,7 +10500,8 @@ "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true }, "tsutils": { "version": "3.17.1", @@ -11451,17 +10794,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -11470,7 +10802,9 @@ "uuid": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "dev": true, + "optional": true }, "v8-compile-cache": { "version": "2.1.1", @@ -11789,14 +11123,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "requires": { - "async-limiter": "~1.0.0" - } - }, "x3-linkedlist": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/x3-linkedlist/-/x3-linkedlist-1.0.0.tgz", @@ -11979,20 +11305,6 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } - }, - "zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" - }, - "zen-observable-ts": { - "version": "0.8.21", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz", - "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==", - "requires": { - "tslib": "^1.9.3", - "zen-observable": "^0.8.0" - } } } } diff --git a/api-js/src/__tests__/load-user-affiliations-by-key.test.js b/api-js/src/__tests__/load-user-affiliations-by-key.test.js new file mode 100644 index 000000000..67efcdb1f --- /dev/null +++ b/api-js/src/__tests__/load-user-affiliations-by-key.test.js @@ -0,0 +1,333 @@ +const dotenv = require('dotenv-safe') +dotenv.config() +const { DB_PASS: rootPass, DB_URL: url } = process.env + +const { ArangoTools, dbNameFromFile } = require('arango-tools') +const { makeMigrations } = require('../../migrations') +const { affiliationLoaderByKey } = require('../loaders') +const { setupI18n } = require('@lingui/core') + +const englishMessages = require('../locale/en/messages') +const frenchMessages = require('../locale/fr/messages') + +describe('given a affiliationLoaderByKey dataloader', () => { + let query, + drop, + truncate, + migrate, + collections, + orgOne, + orgTwo, + affOne, + user, + i18n + + let consoleOutput = [] + const mockedError = (output) => consoleOutput.push(output) + beforeAll(async () => { + console.error = mockedError + }) + + beforeEach(async () => { + ;({ migrate } = await ArangoTools({ rootPass, url })) + ;({ query, drop, truncate, collections } = await migrate( + makeMigrations({ databaseName: dbNameFromFile(__filename), rootPass }), + )) + await truncate() + user = await collections.users.save({ + userName: 'test.account@istio.actually.exists', + displayName: 'Test Account', + preferredLang: 'french', + tfaValidated: false, + emailValidated: false, + }) + orgOne = await collections.organizations.save({ + orgDetails: { + en: { + slug: 'treasury-board-secretariat', + acronym: 'TBS', + name: 'Treasury Board of Canada Secretariat', + zone: 'FED', + sector: 'TBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + fr: { + slug: 'secretariat-conseil-tresor', + acronym: 'SCT', + name: 'Secrétariat du Conseil Trésor du Canada', + zone: 'FED', + sector: 'TBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + }, + }) + orgTwo = await collections.organizations.save({ + orgDetails: { + en: { + slug: 'not-treasury-board-secretariat', + acronym: 'NTBS', + name: 'Not Treasury Board of Canada Secretariat', + zone: 'NFED', + sector: 'NTBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + fr: { + slug: 'ne-pas-secretariat-conseil-tresor', + acronym: 'NPSCT', + name: 'Ne Pas Secrétariat du Conseil Trésor du Canada', + zone: 'NPFED', + sector: 'NPTBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + }, + }) + affOne = await collections.affiliations.save({ + _from: orgOne._id, + _to: user._id, + permission: 'user', + }) + await collections.affiliations.save({ + _from: orgTwo._id, + _to: user._id, + permission: 'user', + }) + consoleOutput = [] + }) + + afterEach(async () => { + await drop() + }) + + describe('language is set to english', () => { + beforeAll(() => { + i18n = setupI18n({ + language: 'en', + locales: ['en', 'fr'], + missing: 'Traduction manquante', + catalogs: { + en: englishMessages, + fr: frenchMessages, + }, + }) + }) + describe('given a single id', () => { + it('returns a single user affiliation', async () => { + // Get affiliation From db + const expectedCursor = await query` + FOR affiliation IN affiliations + FILTER affiliation._id == ${affOne._id} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + const expectedAffiliation = await expectedCursor.next() + + const loader = affiliationLoaderByKey(query, i18n) + const affiliation = await loader.load(expectedAffiliation._key) + + expect(affiliation).toEqual(expectedAffiliation) + }) + }) + describe('provided a list of ids', () => { + it('returns a list of user affiliations', async () => { + const affiliationIds = [] + const expectedAffiliations = [] + const expectedCursor = await query` + FOR affiliation IN affiliations + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + + while (expectedCursor.hasNext()) { + const tempAff = await expectedCursor.next() + affiliationIds.push(tempAff._key) + expectedAffiliations.push(tempAff) + } + + const loader = affiliationLoaderByKey(query, i18n) + const affiliations = await loader.loadMany(affiliationIds) + expect(affiliations).toEqual(expectedAffiliations) + }) + }) + describe('database error is raised', () => { + it('throws an error', async () => { + const expectedCursor = await query` + FOR affiliation IN affiliations + FILTER affiliation._id == ${affOne._id} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + const expectedAffiliation = await expectedCursor.next() + + query = jest + .fn() + .mockRejectedValue(new Error('Database error occurred.')) + const loader = affiliationLoaderByKey(query, i18n) + + try { + await loader.load(expectedAffiliation._key) + } catch (err) { + expect(err).toEqual( + new Error('Unable to find user affiliation(s). Please try again.'), + ) + } + + expect(consoleOutput).toEqual([ + `Database error occurred when running affiliationLoaderByKey: Error: Database error occurred.`, + ]) + }) + }) + describe('cursor error is raised', () => { + it('throws an error', async () => { + const expectedCursor = await query` + FOR affiliation IN affiliations + FILTER affiliation._id == ${affOne._id} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + const expectedAffiliation = await expectedCursor.next() + + const cursor = { + each() { + throw new Error('Cursor error occurred.') + }, + } + query = jest.fn().mockReturnValue(cursor) + const loader = affiliationLoaderByKey(query, i18n) + + try { + await loader.load(expectedAffiliation._key) + } catch (err) { + expect(err).toEqual( + new Error('Unable to find user affiliation(s). Please try again.'), + ) + } + + expect(consoleOutput).toEqual([ + `Cursor error occurred during affiliationLoaderByKey: Error: Cursor error occurred.`, + ]) + }) + }) + }) + describe('language is set to french', () => { + beforeAll(() => { + i18n = setupI18n({ + language: 'fr', + locales: ['en', 'fr'], + missing: 'Traduction manquante', + catalogs: { + en: englishMessages, + fr: frenchMessages, + }, + }) + }) + describe('given a single id', () => { + it('returns a single user affiliation', async () => { + // Get affiliation From db + const expectedCursor = await query` + FOR affiliation IN affiliations + FILTER affiliation._id == ${affOne._id} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + const expectedAffiliation = await expectedCursor.next() + + const loader = affiliationLoaderByKey(query, i18n) + const affiliation = await loader.load(expectedAffiliation._key) + + expect(affiliation).toEqual(expectedAffiliation) + }) + }) + describe('provided a list of ids', () => { + it('returns a list of user affiliations', async () => { + const affiliationIds = [] + const expectedAffiliations = [] + const expectedCursor = await query` + FOR affiliation IN affiliations + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + + while (expectedCursor.hasNext()) { + const tempAff = await expectedCursor.next() + affiliationIds.push(tempAff._key) + expectedAffiliations.push(tempAff) + } + + const loader = affiliationLoaderByKey(query, i18n) + const affiliations = await loader.loadMany(affiliationIds) + expect(affiliations).toEqual(expectedAffiliations) + }) + }) + describe('database error is raised', () => { + it('throws an error', async () => { + const expectedCursor = await query` + FOR affiliation IN affiliations + FILTER affiliation._id == ${affOne._id} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + const expectedAffiliation = await expectedCursor.next() + + query = jest + .fn() + .mockRejectedValue(new Error('Database error occurred.')) + const loader = affiliationLoaderByKey(query, i18n) + + try { + await loader.load(expectedAffiliation._key) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `Database error occurred when running affiliationLoaderByKey: Error: Database error occurred.`, + ]) + }) + }) + describe('cursor error is raised', () => { + it('throws an error', async () => { + const expectedCursor = await query` + FOR affiliation IN affiliations + FILTER affiliation._id == ${affOne._id} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + const expectedAffiliation = await expectedCursor.next() + + const cursor = { + each() { + throw new Error('Cursor error occurred.') + }, + } + query = jest.fn().mockReturnValue(cursor) + const loader = affiliationLoaderByKey(query, i18n) + + try { + await loader.load(expectedAffiliation._key) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `Cursor error occurred during affiliationLoaderByKey: Error: Cursor error occurred.`, + ]) + }) + }) + }) +}) diff --git a/api-js/src/__tests__/load-user-affiliations-by-org-id.test.js b/api-js/src/__tests__/load-user-affiliations-by-org-id.test.js new file mode 100644 index 000000000..b8f166b9c --- /dev/null +++ b/api-js/src/__tests__/load-user-affiliations-by-org-id.test.js @@ -0,0 +1,1084 @@ +const dotenv = require('dotenv-safe') +dotenv.config() +const { DB_PASS: rootPass, DB_URL: url } = process.env + +const { stringify } = require('jest-matcher-utils') +const { ArangoTools, dbNameFromFile } = require('arango-tools') +const { toGlobalId } = require('graphql-relay') +const { setupI18n } = require('@lingui/core') + +const englishMessages = require('../locale/en/messages') +const frenchMessages = require('../locale/fr/messages') +const { makeMigrations } = require('../../migrations') +const { cleanseInput } = require('../validators') +const { + affiliationLoaderByOrgId, + affiliationLoaderByKey, +} = require('../loaders') + +describe('given the load user affiliations by org id function', () => { + let query, drop, truncate, migrate, collections, user, org, userTwo, i18n + + const consoleOutput = [] + const mockedError = (output) => consoleOutput.push(output) + const mockedWarn = (output) => consoleOutput.push(output) + beforeAll(async () => { + console.error = mockedError + console.warn = mockedWarn + ;({ migrate } = await ArangoTools({ rootPass, url })) + ;({ query, drop, truncate, collections } = await migrate( + makeMigrations({ databaseName: dbNameFromFile(__filename), rootPass }), + )) + }) + + beforeEach(async () => { + await truncate() + user = await collections.users.save({ + userName: 'test.account@istio.actually.exists', + displayName: 'Test Account', + preferredLang: 'french', + tfaValidated: false, + emailValidated: false, + }) + userTwo = await collections.users.save({ + userName: 'test.accounttwo@istio.actually.exists', + displayName: 'Test Account Two', + preferredLang: 'french', + tfaValidated: false, + emailValidated: false, + }) + org = await collections.organizations.save({ + orgDetails: { + en: { + slug: 'treasury-board-secretariat', + acronym: 'TBS', + name: 'Treasury Board of Canada Secretariat', + zone: 'FED', + sector: 'TBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + fr: { + slug: 'secretariat-conseil-tresor', + acronym: 'SCT', + name: 'Secrétariat du Conseil Trésor du Canada', + zone: 'FED', + sector: 'TBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + }, + }) + + consoleOutput.length = 0 + }) + + afterAll(async () => { + await drop() + }) + + describe('users language is set to english', () => { + beforeAll(() => { + i18n = setupI18n({ + language: 'en', + locales: ['en', 'fr'], + missing: 'Traduction manquante', + catalogs: { + en: englishMessages, + fr: frenchMessages, + }, + }) + }) + describe('given a successful load', () => { + describe('given there are user affiliations to be returned', () => { + let affOne, affTwo + beforeEach(async () => { + affOne = await collections.affiliations.save({ + _from: org._id, + _to: user._id, + permission: 'user', + }) + affTwo = await collections.affiliations.save({ + _from: org._id, + _to: userTwo._id, + permission: 'user', + }) + }) + afterEach(async () => { + await query` + LET userEdges = (FOR v, e IN 1..1 ANY ${org._id} affiliations RETURN { edgeKey: e._key, userId: e._to }) + LET removeUserEdges = (FOR userEdge IN userEdges REMOVE userEdge.edgeKey IN affiliations) + RETURN true + ` + await query` + FOR affiliation IN affiliations + REMOVE affiliation IN affiliations + ` + }) + describe('using after cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + after: toGlobalId('affiliations', expectedAffiliations[0].id), + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using before cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + before: toGlobalId('affiliations', expectedAffiliations[1].id), + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only first limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 1, + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only last limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + last: 1, + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given there are no user affiliations to be returned', () => { + it('returns no affiliations', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given an unsuccessful load', () => { + describe('first and last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 1, + last: 1, + } + try { + await affiliationLoader({ orgId: org._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual( + new Error( + 'Passing both `first` and `last` to paginate the `affiliation` is not supported.', + ), + ) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` and \`last\` arguments set for: affiliationLoaderByOrgId.`, + ]) + }) + }) + describe('neither first nor last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = {} + try { + await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + `You must provide a \`first\` or \`last\` value to properly paginate the \`affiliation\`.`, + ), + ) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} did not have either \`first\` or \`last\` arguments set for: affiliationLoaderByOrgId.`, + ]) + }) + }) + describe('limits are set below minimum', () => { + describe('first is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: -1, + } + + try { + await connectionLoader({ + orgId: org._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + '`first` on the `affiliations` cannot be less than zero.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` set below zero for: affiliationLoaderByOrgId.`, + ]) + }) + }) + describe('last is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + last: -2, + } + + try { + await connectionLoader({ + orgId: org._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + '`last` on the `affiliations` cannot be less than zero.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`last\` set below zero for: affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + describe('limits are set above maximum', () => { + describe('first is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 1000, + } + + try { + await connectionLoader({ + orgId: org._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + 'Requesting `1000` records on the `affiliations` exceeds the `first` limit of 100 records.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` set to 1000 for: affiliationLoaderByOrgId.`, + ]) + }) + }) + describe('last is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + last: 200, + } + + try { + await connectionLoader({ + orgId: org._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + 'Requesting `200` records on the `affiliations` exceeds the `last` limit of 100 records.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`last\` set to 200 for: affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + describe('limits are not set to numbers', () => { + describe('first limit is set', () => { + ;['123', {}, [], null, true].forEach((invalidInput) => { + it(`returns an error when first set to ${stringify( + invalidInput, + )}`, async () => { + const connectionLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: invalidInput, + } + + try { + await connectionLoader({ + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + `\`first\` must be of type \`number\` not \`${typeof invalidInput}\`.`, + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${ + user._key + } attempted to have \`first\` set as a ${typeof invalidInput} for: affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + describe('last limit is set', () => { + ;['123', {}, [], null, true].forEach((invalidInput) => { + it(`returns an error when last set to ${stringify( + invalidInput, + )}`, async () => { + const connectionLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + last: invalidInput, + } + + try { + await connectionLoader({ + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + `\`last\` must be of type \`number\` not \`${typeof invalidInput}\`.`, + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${ + user._key + } attempted to have \`last\` set as a ${typeof invalidInput} for: affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + }) + }) + describe('given a database error', () => { + describe('while querying domains', () => { + it('returns an error message', async () => { + const query = jest + .fn() + .mockRejectedValue( + new Error('Unable to query organizations. Please try again.'), + ) + + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ orgId: org._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual( + new Error('Unable to query affiliations. Please try again.'), + ) + } + + expect(consoleOutput).toEqual([ + `Database error occurred while user: ${user._key} was trying to query affiliations in affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + describe('given a cursor error', () => { + describe('while gathering domains', () => { + it('returns an error message', async () => { + const cursor = { + next() { + throw new Error('Unable to load affiliations. Please try again.') + }, + } + const query = jest + .fn() + .mockReturnValueOnce([]) + .mockReturnValueOnce(cursor) + + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ orgId: org._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual( + new Error('Unable to load affiliations. Please try again.'), + ) + } + + expect(consoleOutput).toEqual([ + `Cursor error occurred while user: ${user._key} was trying to gather affiliations in affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + }) + describe('users language is set to french', () => { + beforeAll(() => { + i18n = setupI18n({ + language: 'fr', + locales: ['en', 'fr'], + missing: 'Traduction manquante', + catalogs: { + en: englishMessages, + fr: frenchMessages, + }, + }) + }) + describe('given a successful load', () => { + describe('given there are user affiliations to be returned', () => { + let affOne, affTwo + beforeEach(async () => { + affOne = await collections.affiliations.save({ + _from: org._id, + _to: user._id, + permission: 'user', + }) + affTwo = await collections.affiliations.save({ + _from: org._id, + _to: userTwo._id, + permission: 'user', + }) + }) + afterEach(async () => { + await query` + LET userEdges = (FOR v, e IN 1..1 ANY ${org._id} affiliations RETURN { edgeKey: e._key, userId: e._to }) + LET removeUserEdges = (FOR userEdge IN userEdges REMOVE userEdge.edgeKey IN affiliations) + RETURN true + ` + await query` + FOR affiliation IN affiliations + REMOVE affiliation IN affiliations + ` + }) + describe('using after cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + after: toGlobalId('affiliations', expectedAffiliations[0].id), + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using before cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + before: toGlobalId('affiliations', expectedAffiliations[1].id), + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only first limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 1, + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only last limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + last: 1, + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given there are no user affiliations to be returned', () => { + it('returns no affiliations', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + const affiliations = await affiliationLoader({ + orgId: org._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given an unsuccessful load', () => { + describe('first and last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 1, + last: 1, + } + try { + await affiliationLoader({ orgId: org._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` and \`last\` arguments set for: affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + describe('given a database error', () => { + describe('while querying domains', () => { + it('returns an error message', async () => { + const query = jest + .fn() + .mockRejectedValue( + new Error('Unable to query organizations. Please try again.'), + ) + + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ orgId: org._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `Database error occurred while user: ${user._key} was trying to query affiliations in affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + describe('given a cursor error', () => { + describe('while gathering domains', () => { + it('returns an error message', async () => { + const cursor = { + next() { + throw new Error('Unable to load affiliations. Please try again.') + }, + } + const query = jest + .fn() + .mockReturnValueOnce([]) + .mockReturnValueOnce(cursor) + + const affiliationLoader = affiliationLoaderByOrgId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ orgId: org._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `Cursor error occurred while user: ${user._key} was trying to gather affiliations in affiliationLoaderByOrgId.`, + ]) + }) + }) + }) + }) +}) diff --git a/api-js/src/__tests__/load-user-affiliations-by-user-id.test.js b/api-js/src/__tests__/load-user-affiliations-by-user-id.test.js new file mode 100644 index 000000000..d712d8d9f --- /dev/null +++ b/api-js/src/__tests__/load-user-affiliations-by-user-id.test.js @@ -0,0 +1,1148 @@ +const dotenv = require('dotenv-safe') +dotenv.config() +const { DB_PASS: rootPass, DB_URL: url } = process.env + +const { stringify } = require('jest-matcher-utils') +const { ArangoTools, dbNameFromFile } = require('arango-tools') +const { toGlobalId } = require('graphql-relay') +const { setupI18n } = require('@lingui/core') + +const englishMessages = require('../locale/en/messages') +const frenchMessages = require('../locale/fr/messages') +const { makeMigrations } = require('../../migrations') +const { cleanseInput } = require('../validators') +const { + affiliationLoaderByUserId, + affiliationLoaderByKey, +} = require('../loaders') + +describe('given the load user affiliations by user id function', () => { + let query, drop, truncate, migrate, collections, user, orgOne, orgTwo, i18n + + const consoleOutput = [] + const mockedError = (output) => consoleOutput.push(output) + const mockedWarn = (output) => consoleOutput.push(output) + beforeAll(async () => { + console.error = mockedError + console.warn = mockedWarn + ;({ migrate } = await ArangoTools({ rootPass, url })) + ;({ query, drop, truncate, collections } = await migrate( + makeMigrations({ databaseName: dbNameFromFile(__filename), rootPass }), + )) + }) + + beforeEach(async () => { + await truncate() + user = await collections.users.save({ + userName: 'test.account@istio.actually.exists', + displayName: 'Test Account', + preferredLang: 'french', + tfaValidated: false, + emailValidated: false, + }) + orgOne = await collections.organizations.save({ + orgDetails: { + en: { + slug: 'treasury-board-secretariat', + acronym: 'TBS', + name: 'Treasury Board of Canada Secretariat', + zone: 'FED', + sector: 'TBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + fr: { + slug: 'secretariat-conseil-tresor', + acronym: 'SCT', + name: 'Secrétariat du Conseil Trésor du Canada', + zone: 'FED', + sector: 'TBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + }, + }) + orgTwo = await collections.organizations.save({ + orgDetails: { + en: { + slug: 'not-treasury-board-secretariat', + acronym: 'NTBS', + name: 'Not Treasury Board of Canada Secretariat', + zone: 'NFED', + sector: 'NTBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + fr: { + slug: 'ne-pas-secretariat-conseil-tresor', + acronym: 'NPSCT', + name: 'Ne Pas Secrétariat du Conseil Trésor du Canada', + zone: 'NPFED', + sector: 'NPTBS', + country: 'Canada', + province: 'Ontario', + city: 'Ottawa', + }, + }, + }) + + consoleOutput.length = 0 + }) + + afterAll(async () => { + await drop() + }) + + describe('users language is set to english', () => { + beforeAll(() => { + i18n = setupI18n({ + language: 'en', + locales: ['en', 'fr'], + missing: 'Traduction manquante', + catalogs: { + en: englishMessages, + fr: frenchMessages, + }, + }) + }) + describe('given a successful load', () => { + describe('given there are user affiliations to be returned', () => { + let affOne, affTwo + beforeEach(async () => { + affOne = await collections.affiliations.save({ + _from: orgOne._id, + _to: user._id, + permission: 'user', + }) + affTwo = await collections.affiliations.save({ + _from: orgTwo._id, + _to: user._id, + permission: 'user', + }) + }) + afterEach(async () => { + await query` + LET userEdges = (FOR v, e IN 1..1 ANY ${orgOne._id} affiliations RETURN { edgeKey: e._key, userId: e._to }) + LET removeUserEdges = (FOR userEdge IN userEdges REMOVE userEdge.edgeKey IN affiliations) + RETURN true + ` + await query` + LET userEdges = (FOR v, e IN 1..1 ANY ${orgTwo._id} affiliations RETURN { edgeKey: e._key, userId: e._to }) + LET removeUserEdges = (FOR userEdge IN userEdges REMOVE userEdge.edgeKey IN affiliations) + RETURN true + ` + await query` + FOR affiliation IN affiliations + REMOVE affiliation IN affiliations + ` + }) + describe('using after cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + after: toGlobalId('affiliations', expectedAffiliations[0].id), + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using before cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + before: toGlobalId('affiliations', expectedAffiliations[1].id), + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only first limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 1, + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only last limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + last: 1, + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given there are no user affiliations to be returned', () => { + it('returns no affiliations', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given an unsuccessful load', () => { + describe('first and last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 1, + last: 1, + } + try { + await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + 'Passing both `first` and `last` to paginate the `affiliation` is not supported.', + ), + ) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` and \`last\` arguments set for: affiliationLoaderByUserId.`, + ]) + }) + }) + describe('neither first nor last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = {} + try { + await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + `You must provide a \`first\` or \`last\` value to properly paginate the \`affiliation\`.`, + ), + ) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} did not have either \`first\` or \`last\` arguments set for: affiliationLoaderByUserId.`, + ]) + }) + }) + describe('limits are set below minimum', () => { + describe('first is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: -1, + } + + try { + await connectionLoader({ + uId: user._id, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + '`first` on the `affiliations` cannot be less than zero.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` set below zero for: affiliationLoaderByUserId.`, + ]) + }) + }) + describe('last is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + last: -2, + } + + try { + await connectionLoader({ + uId: user._id, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + '`last` on the `affiliations` cannot be less than zero.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`last\` set below zero for: affiliationLoaderByUserId.`, + ]) + }) + }) + }) + describe('limits are set above maximum', () => { + describe('first is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 1000, + } + + try { + await connectionLoader({ + uId: user._id, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + 'Requesting `1000` records on the `affiliations` exceeds the `first` limit of 100 records.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` set to 1000 for: affiliationLoaderByUserId.`, + ]) + }) + }) + describe('last is set', () => { + it('returns an error message', async () => { + const connectionLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + last: 200, + } + + try { + await connectionLoader({ + uId: user._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + 'Requesting `200` records on the `affiliations` exceeds the `last` limit of 100 records.', + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`last\` set to 200 for: affiliationLoaderByUserId.`, + ]) + }) + }) + }) + describe('limits are not set to numbers', () => { + describe('first limit is set', () => { + ;['123', {}, [], null, true].forEach((invalidInput) => { + it(`returns an error when first set to ${stringify( + invalidInput, + )}`, async () => { + const connectionLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: invalidInput, + } + + try { + await connectionLoader({ + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + `\`first\` must be of type \`number\` not \`${typeof invalidInput}\`.`, + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${ + user._key + } attempted to have \`first\` set as a ${typeof invalidInput} for: affiliationLoaderByUserId.`, + ]) + }) + }) + }) + describe('last limit is set', () => { + ;['123', {}, [], null, true].forEach((invalidInput) => { + it(`returns an error when last set to ${stringify( + invalidInput, + )}`, async () => { + const connectionLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + last: invalidInput, + } + + try { + await connectionLoader({ + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + `\`last\` must be of type \`number\` not \`${typeof invalidInput}\`.`, + ), + ) + } + expect(consoleOutput).toEqual([ + `User: ${ + user._key + } attempted to have \`last\` set as a ${typeof invalidInput} for: affiliationLoaderByUserId.`, + ]) + }) + }) + }) + }) + }) + describe('given a database error', () => { + describe('while querying domains', () => { + it('returns an error message', async () => { + const query = jest + .fn() + .mockRejectedValue( + new Error('Unable to query organizations. Please try again.'), + ) + + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error('Unable to query affiliations. Please try again.'), + ) + } + + expect(consoleOutput).toEqual([ + `Database error occurred while user: ${user._key} was trying to query affiliations in affiliationLoaderByUserId.`, + ]) + }) + }) + }) + describe('given a cursor error', () => { + describe('while gathering domains', () => { + it('returns an error message', async () => { + const cursor = { + next() { + throw new Error('Unable to load affiliations. Please try again.') + }, + } + const query = jest + .fn() + .mockReturnValueOnce([]) + .mockReturnValueOnce(cursor) + + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error('Unable to load affiliations. Please try again.'), + ) + } + + expect(consoleOutput).toEqual([ + `Cursor error occurred while user: ${user._key} was trying to gather affiliations in affiliationLoaderByUserId.`, + ]) + }) + }) + }) + }) + describe('users language is set to french', () => { + beforeAll(() => { + i18n = setupI18n({ + language: 'fr', + locales: ['en', 'fr'], + missing: 'Traduction manquante', + catalogs: { + en: englishMessages, + fr: frenchMessages, + }, + }) + }) + describe('given a successful load', () => { + describe('given there are user affiliations to be returned', () => { + let affOne, affTwo + beforeEach(async () => { + affOne = await collections.affiliations.save({ + _from: orgOne._id, + _to: user._id, + permission: 'user', + }) + affTwo = await collections.affiliations.save({ + _from: orgTwo._id, + _to: user._id, + permission: 'user', + }) + }) + afterEach(async () => { + await query` + LET userEdges = (FOR v, e IN 1..1 ANY ${orgOne._id} affiliations RETURN { edgeKey: e._key, userId: e._to }) + LET removeUserEdges = (FOR userEdge IN userEdges REMOVE userEdge.edgeKey IN affiliations) + RETURN true + ` + await query` + LET userEdges = (FOR v, e IN 1..1 ANY ${orgTwo._id} affiliations RETURN { edgeKey: e._key, userId: e._to }) + LET removeUserEdges = (FOR userEdge IN userEdges REMOVE userEdge.edgeKey IN affiliations) + RETURN true + ` + await query` + FOR affiliation IN affiliations + REMOVE affiliation IN affiliations + ` + }) + describe('using after cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + after: toGlobalId('affiliations', expectedAffiliations[0].id), + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using before cursor', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 5, + before: toGlobalId('affiliations', expectedAffiliations[1].id), + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only first limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + first: 1, + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + node: { + ...expectedAffiliations[0], + }, + }, + ], + pageInfo: { + hasNextPage: true, + hasPreviousPage: false, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[0]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + describe('using only last limit', () => { + it('returns an affiliation', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const affLoader = affiliationLoaderByKey(query) + const expectedAffiliations = await affLoader.loadMany([ + affOne._key, + affTwo._key, + ]) + + expectedAffiliations[0].id = expectedAffiliations[0]._key + expectedAffiliations[1].id = expectedAffiliations[1]._key + + const connectionArgs = { + last: 1, + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [ + { + cursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + node: { + ...expectedAffiliations[1], + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: true, + startCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + endCursor: toGlobalId( + 'affiliations', + expectedAffiliations[1]._key, + ), + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given there are no user affiliations to be returned', () => { + it('returns no affiliations', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + const affiliations = await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + + const expectedStructure = { + edges: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', + }, + } + + expect(affiliations).toEqual(expectedStructure) + }) + }) + }) + describe('given an unsuccessful load', () => { + describe('first and last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 1, + last: 1, + } + try { + await affiliationLoader({ uId: user._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} attempted to have \`first\` and \`last\` arguments set for: affiliationLoaderByUserId.`, + ]) + }) + }) + describe('neither first nor last arguments are set', () => { + it('returns an error message', async () => { + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = {} + try { + await affiliationLoader({ + uId: user._key, + ...connectionArgs, + }) + } catch (err) { + expect(err).toEqual( + new Error( + 'todo', + ), + ) + } + + expect(consoleOutput).toEqual([ + `User: ${user._key} did not have either \`first\` or \`last\` arguments set for: affiliationLoaderByUserId.`, + ]) + }) + }) + }) + describe('given a database error', () => { + describe('while querying domains', () => { + it('returns an error message', async () => { + const query = jest + .fn() + .mockRejectedValue( + new Error('Unable to query organizations. Please try again.'), + ) + + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ uId: user._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `Database error occurred while user: ${user._key} was trying to query affiliations in affiliationLoaderByUserId.`, + ]) + }) + }) + }) + describe('given a cursor error', () => { + describe('while gathering domains', () => { + it('returns an error message', async () => { + const cursor = { + next() { + throw new Error('Unable to load affiliations. Please try again.') + }, + } + const query = jest + .fn() + .mockReturnValueOnce([]) + .mockReturnValueOnce(cursor) + + const affiliationLoader = affiliationLoaderByUserId( + query, + user._key, + cleanseInput, + i18n, + ) + + const connectionArgs = { + first: 5, + } + try { + await affiliationLoader({ uId: user._key, ...connectionArgs }) + } catch (err) { + expect(err).toEqual(new Error('todo')) + } + + expect(consoleOutput).toEqual([ + `Cursor error occurred while user: ${user._key} was trying to gather affiliations in affiliationLoaderByUserId.`, + ]) + }) + }) + }) + }) +}) diff --git a/api-js/src/loaders/index.js b/api-js/src/loaders/index.js index 71c462abc..4462b5095 100644 --- a/api-js/src/loaders/index.js +++ b/api-js/src/loaders/index.js @@ -4,6 +4,7 @@ const emailScanLoaders = require('./email-scan') const orgLoaders = require('./organizations') const userLoaders = require('./user') const webScanLoaders = require('./web-scan') +const userAffiliationLoaders = require('./user-affiliations') module.exports = { // Dmarc Report Loaders @@ -18,4 +19,6 @@ module.exports = { ...userLoaders, // Web Scan Loaders ...webScanLoaders, + // User Affiliation Loaders + ...userAffiliationLoaders, } diff --git a/api-js/src/loaders/user-affiliations/index.js b/api-js/src/loaders/user-affiliations/index.js new file mode 100644 index 000000000..9b41a8fa2 --- /dev/null +++ b/api-js/src/loaders/user-affiliations/index.js @@ -0,0 +1,9 @@ +const { affiliationLoaderByKey } = require('./load-user-affiliations-by-key') +const { affiliationLoaderByUserId } = require('./load-user-affiliations-by-user-id') +const { affiliationLoaderByOrgId } = require('./load-user-affiliations-by-org-id') + +module.exports = { + affiliationLoaderByKey, + affiliationLoaderByUserId, + affiliationLoaderByOrgId, +} diff --git a/api-js/src/loaders/user-affiliations/load-user-affiliations-by-key.js b/api-js/src/loaders/user-affiliations/load-user-affiliations-by-key.js new file mode 100644 index 000000000..72ad33d7d --- /dev/null +++ b/api-js/src/loaders/user-affiliations/load-user-affiliations-by-key.js @@ -0,0 +1,40 @@ +const DataLoader = require('dataloader') +const { t } = require('@lingui/macro') + +module.exports.affiliationLoaderByKey = (query, i18n) => + new DataLoader(async (ids) => { + let cursor + + try { + cursor = await query` + FOR affiliation IN affiliations + FILTER ${ids}[** FILTER CURRENT == affiliation._key] + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ` + } catch (err) { + console.error( + `Database error occurred when running affiliationLoaderByKey: ${err}`, + ) + throw new Error( + i18n._(t`Unable to find user affiliation(s). Please try again.`), + ) + } + + const affiliationMap = {} + try { + await cursor.each((affiliation) => { + affiliationMap[affiliation._key] = affiliation + }) + } catch (err) { + console.error( + `Cursor error occurred during affiliationLoaderByKey: ${err}`, + ) + throw new Error( + i18n._(t`Unable to find user affiliation(s). Please try again.`), + ) + } + + return ids.map((id) => affiliationMap[id]) + }) diff --git a/api-js/src/loaders/user-affiliations/load-user-affiliations-by-org-id.js b/api-js/src/loaders/user-affiliations/load-user-affiliations-by-org-id.js new file mode 100644 index 000000000..da2ed193a --- /dev/null +++ b/api-js/src/loaders/user-affiliations/load-user-affiliations-by-org-id.js @@ -0,0 +1,178 @@ +const { aql } = require('arangojs') +const { fromGlobalId, toGlobalId } = require('graphql-relay') +const { t } = require('@lingui/macro') + +const affiliationLoaderByOrgId = (query, userId, cleanseInput, i18n) => async ({ + orgId, + after, + before, + first, + last, +}) => { + let afterTemplate = aql`` + let beforeTemplate = aql`` + + const orgDBId = `organizations/${orgId}` + + let afterId + if (typeof after !== 'undefined') { + afterId = fromGlobalId(cleanseInput(after)).id + afterTemplate = aql`FILTER TO_NUMBER(affiliation._key) > TO_NUMBER(${afterId})` + } + + let beforeId + if (typeof before !== 'undefined') { + beforeId = fromGlobalId(cleanseInput(before)).id + beforeTemplate = aql`FILTER TO_NUMBER(affiliation._key) < TO_NUMBER(${beforeId})` + } + + let limitTemplate = aql`` + if (typeof first === 'undefined' && typeof last === 'undefined') { + console.warn( + `User: ${userId} did not have either \`first\` or \`last\` arguments set for: affiliationLoaderByOrgId.`, + ) + throw new Error( + i18n._( + t`You must provide a \`first\` or \`last\` value to properly paginate the \`affiliation\`.`, + ), + ) + } else if (typeof first !== 'undefined' && typeof last !== 'undefined') { + console.warn( + `User: ${userId} attempted to have \`first\` and \`last\` arguments set for: affiliationLoaderByOrgId.`, + ) + throw new Error( + i18n._( + t`Passing both \`first\` and \`last\` to paginate the \`affiliation\` is not supported.`, + ), + ) + } else if (typeof first === 'number' || typeof last === 'number') { + /* istanbul ignore else */ + if (first < 0 || last < 0) { + const argSet = typeof first !== 'undefined' ? 'first' : 'last' + console.warn( + `User: ${userId} attempted to have \`${argSet}\` set below zero for: affiliationLoaderByOrgId.`, + ) + throw new Error( + i18n._( + t`\`${argSet}\` on the \`affiliations\` cannot be less than zero.`, + ), + ) + } else if (first > 100 || last > 100) { + const argSet = typeof first !== 'undefined' ? 'first' : 'last' + const amount = typeof first !== 'undefined' ? first : last + console.warn( + `User: ${userId} attempted to have \`${argSet}\` set to ${amount} for: affiliationLoaderByOrgId.`, + ) + throw new Error( + i18n._( + t`Requesting \`${amount}\` records on the \`affiliations\` exceeds the \`${argSet}\` limit of 100 records.`, + ), + ) + } else if (typeof first !== 'undefined' && typeof last === 'undefined') { + limitTemplate = aql`SORT affiliation._key ASC LIMIT TO_NUMBER(${first})` + } else if (typeof first === 'undefined' && typeof last !== 'undefined') { + limitTemplate = aql`SORT affiliation._key DESC LIMIT TO_NUMBER(${last})` + } + } else { + const argSet = typeof first !== 'undefined' ? 'first' : 'last' + const typeSet = typeof first !== 'undefined' ? typeof first : typeof last + console.warn( + `User: ${userId} attempted to have \`${argSet}\` set as a ${typeSet} for: affiliationLoaderByOrgId.`, + ) + throw new Error( + i18n._(t`\`${argSet}\` must be of type \`number\` not \`${typeSet}\`.`), + ) + } + + let sortString + if (typeof last !== 'undefined') { + sortString = aql`DESC` + } else { + sortString = aql`ASC` + } + + let filteredAffiliationCursor + try { + filteredAffiliationCursor = await query` + LET affiliationKeys = (FOR v, e IN 1..1 ANY ${orgDBId} affiliations RETURN e._key) + LET retrievedAffiliations = ( + FOR affiliation IN affiliations + FILTER affiliation._key IN affiliationKeys + ${afterTemplate} + ${beforeTemplate} + ${limitTemplate} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ) + LET hasNextPage = (LENGTH( + FOR aff IN affiliations + FILTER aff._key IN affiliationKeys + FILTER TO_NUMBER(aff._key) > TO_NUMBER(LAST(retrievedAffiliations)._key) + SORT aff._key ${sortString} LIMIT 1 + ) > 0 ? true : false) + LET hasPreviousPage = (LENGTH( + FOR aff IN affiliations + FILTER aff._key IN affiliationKeys + FILTER TO_NUMBER(aff._key) < TO_NUMBER(FIRST(retrievedAffiliations)._key) + SORT aff._key ${sortString} LIMIT 1 + ) > 0 ? true : false) + RETURN { + "affiliations": retrievedAffiliations, + "hasNextPage": hasNextPage, + "hasPreviousPage": hasPreviousPage, + "startKey": FIRST(retrievedAffiliations)._key, + "endKey": LAST(retrievedAffiliations)._key + } + ` + } catch (err) { + console.error( + `Database error occurred while user: ${userId} was trying to query affiliations in affiliationLoaderByOrgId.`, + ) + throw new Error(i18n._(t`Unable to query affiliations. Please try again.`)) + } + + let filteredAffiliations + try { + filteredAffiliations = await filteredAffiliationCursor.next() + } catch (err) { + console.error( + `Cursor error occurred while user: ${userId} was trying to gather affiliations in affiliationLoaderByOrgId.`, + ) + throw new Error(i18n._(t`Unable to load affiliations. Please try again.`)) + } + + if (filteredAffiliations.affiliations.length === 0) { + return { + edges: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', + }, + } + } + + const edges = filteredAffiliations.affiliations.map((affiliation) => { + affiliation.id = affiliation._key + return { + cursor: toGlobalId('affiliations', affiliation._key), + node: affiliation, + } + }) + + return { + edges, + pageInfo: { + hasNextPage: filteredAffiliations.hasNextPage, + hasPreviousPage: filteredAffiliations.hasPreviousPage, + startCursor: toGlobalId('affiliations', filteredAffiliations.startKey), + endCursor: toGlobalId('affiliations', filteredAffiliations.endKey), + }, + } +} + +module.exports = { + affiliationLoaderByOrgId, +} diff --git a/api-js/src/loaders/user-affiliations/load-user-affiliations-by-user-id.js b/api-js/src/loaders/user-affiliations/load-user-affiliations-by-user-id.js new file mode 100644 index 000000000..4cecfb440 --- /dev/null +++ b/api-js/src/loaders/user-affiliations/load-user-affiliations-by-user-id.js @@ -0,0 +1,177 @@ +const { aql } = require('arangojs') +const { fromGlobalId, toGlobalId } = require('graphql-relay') +const { t } = require('@lingui/macro') + +const affiliationLoaderByUserId = ( + query, + userId, + cleanseInput, + i18n, +) => async ({ uId, after, before, first, last }) => { + let afterTemplate = aql`` + let beforeTemplate = aql`` + + const userDBId = `users/${uId}` + + let afterId + if (typeof after !== 'undefined') { + afterId = fromGlobalId(cleanseInput(after)).id + afterTemplate = aql`FILTER TO_NUMBER(affiliation._key) > TO_NUMBER(${afterId})` + } + + let beforeId + if (typeof before !== 'undefined') { + beforeId = fromGlobalId(cleanseInput(before)).id + beforeTemplate = aql`FILTER TO_NUMBER(affiliation._key) < TO_NUMBER(${beforeId})` + } + + let limitTemplate = aql`` + if (typeof first === 'undefined' && typeof last === 'undefined') { + console.warn( + `User: ${userId} did not have either \`first\` or \`last\` arguments set for: affiliationLoaderByUserId.`, + ) + throw new Error( + i18n._( + t`You must provide a \`first\` or \`last\` value to properly paginate the \`affiliation\`.`, + ), + ) + } else if (typeof first !== 'undefined' && typeof last !== 'undefined') { + console.warn( + `User: ${userId} attempted to have \`first\` and \`last\` arguments set for: affiliationLoaderByUserId.`, + ) + throw new Error( + i18n._( + t`Passing both \`first\` and \`last\` to paginate the \`affiliation\` is not supported.`, + ), + ) + } else if (typeof first === 'number' || typeof last === 'number') { + /* istanbul ignore else */ + if (first < 0 || last < 0) { + const argSet = typeof first !== 'undefined' ? 'first' : 'last' + console.warn( + `User: ${userId} attempted to have \`${argSet}\` set below zero for: affiliationLoaderByUserId.`, + ) + throw new Error( + i18n._( + t`\`${argSet}\` on the \`affiliations\` cannot be less than zero.`, + ), + ) + } else if (first > 100 || last > 100) { + const argSet = typeof first !== 'undefined' ? 'first' : 'last' + const amount = typeof first !== 'undefined' ? first : last + console.warn( + `User: ${userId} attempted to have \`${argSet}\` set to ${amount} for: affiliationLoaderByUserId.`, + ) + throw new Error( + i18n._( + t`Requesting \`${amount}\` records on the \`affiliations\` exceeds the \`${argSet}\` limit of 100 records.`, + ), + ) + } else if (typeof first !== 'undefined' && typeof last === 'undefined') { + limitTemplate = aql`SORT affiliation._key ASC LIMIT TO_NUMBER(${first})` + } else if (typeof first === 'undefined' && typeof last !== 'undefined') { + limitTemplate = aql`SORT affiliation._key DESC LIMIT TO_NUMBER(${last})` + } + } else { + const argSet = typeof first !== 'undefined' ? 'first' : 'last' + const typeSet = typeof first !== 'undefined' ? typeof first : typeof last + console.warn( + `User: ${userId} attempted to have \`${argSet}\` set as a ${typeSet} for: affiliationLoaderByUserId.`, + ) + throw new Error( + i18n._(t`\`${argSet}\` must be of type \`number\` not \`${typeSet}\`.`), + ) + } + + let sortString + if (typeof last !== 'undefined') { + sortString = aql`DESC` + } else { + sortString = aql`ASC` + } + + let filteredAffiliationCursor + try { + filteredAffiliationCursor = await query` + LET affiliationKeys = (FOR v, e IN 1..1 ANY ${userDBId} affiliations RETURN e._key) + LET retrievedAffiliations = ( + FOR affiliation IN affiliations + FILTER affiliation._key IN affiliationKeys + ${afterTemplate} + ${beforeTemplate} + ${limitTemplate} + LET orgKey = PARSE_IDENTIFIER(affiliation._from).key + LET userKey = PARSE_IDENTIFIER(affiliation._to).key + RETURN MERGE(affiliation, { orgKey: orgKey, userKey: userKey }) + ) + LET hasNextPage = (LENGTH( + FOR aff IN affiliations + FILTER aff._key IN affiliationKeys + FILTER TO_NUMBER(aff._key) > TO_NUMBER(LAST(retrievedAffiliations)._key) + SORT aff._key ${sortString} LIMIT 1 + ) > 0 ? true : false) + LET hasPreviousPage = (LENGTH( + FOR aff IN affiliations + FILTER aff._key IN affiliationKeys + FILTER TO_NUMBER(aff._key) < TO_NUMBER(FIRST(retrievedAffiliations)._key) + SORT aff._key ${sortString} LIMIT 1 + ) > 0 ? true : false) + RETURN { + "affiliations": retrievedAffiliations, + "hasNextPage": hasNextPage, + "hasPreviousPage": hasPreviousPage, + "startKey": FIRST(retrievedAffiliations)._key, + "endKey": LAST(retrievedAffiliations)._key + } + ` + } catch (err) { + console.error( + `Database error occurred while user: ${userId} was trying to query affiliations in affiliationLoaderByUserId.`, + ) + throw new Error(i18n._(t`Unable to query affiliations. Please try again.`)) + } + + let filteredAffiliations + try { + filteredAffiliations = await filteredAffiliationCursor.next() + } catch (err) { + console.error( + `Cursor error occurred while user: ${userId} was trying to gather affiliations in affiliationLoaderByUserId.`, + ) + throw new Error(i18n._(t`Unable to load affiliations. Please try again.`)) + } + + if (filteredAffiliations.affiliations.length === 0) { + return { + edges: [], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', + }, + } + } + + const edges = filteredAffiliations.affiliations.map((affiliation) => { + affiliation.id = affiliation._key + return { + cursor: toGlobalId('affiliations', affiliation._key), + node: affiliation, + } + }) + + return { + edges, + pageInfo: { + hasNextPage: filteredAffiliations.hasNextPage, + hasPreviousPage: filteredAffiliations.hasPreviousPage, + startCursor: toGlobalId('affiliations', filteredAffiliations.startKey), + endCursor: toGlobalId('affiliations', filteredAffiliations.endKey), + }, + } +} + +module.exports = { + affiliationLoaderByUserId, +} diff --git a/api-js/src/locale/en/messages.js b/api-js/src/locale/en/messages.js index e6465ae83..635170879 100644 --- a/api-js/src/locale/en/messages.js +++ b/api-js/src/locale/en/messages.js @@ -1,379 +1 @@ -/* eslint-disable */ module.exports = { - languageData: { - plurals: function (n, ord) { - var s = String(n).split('.'), - v0 = !s[1], - t0 = Number(s[0]) == n, - n10 = t0 && s[0].slice(-1), - n100 = t0 && s[0].slice(-2) - if (ord) - return n10 == 1 && n100 != 11 - ? 'one' - : n10 == 2 && n100 != 12 - ? 'two' - : n10 == 3 && n100 != 13 - ? 'few' - : 'other' - return n == 1 && v0 ? 'one' : 'other' - }, - }, - messages: { - 'Authentication error, please sign in again.': - 'Authentication error, please sign in again.', - 'Authentication error. Please sign in again.': - 'Authentication error. Please sign in again.', - 'Authentication error. Please sign in.': - 'Authentication error. Please sign in.', - 'Could not retrieve specified domain.': - 'Could not retrieve specified domain.', - 'Could not retrieve specified organization.': - 'Could not retrieve specified organization.', - 'Error when retrieving dmarc report information. Please try again.': - 'Error when retrieving dmarc report information. Please try again.', - 'If an account with this username is found, a password reset link will be found in your inbox.': - 'If an account with this username is found, a password reset link will be found in your inbox.', - 'If an account with this username is found, an email verification link will be found in your inbox.': - 'If an account with this username is found, an email verification link will be found in your inbox.', - 'Invalid token, please request a new one.': - 'Invalid token, please request a new one.', - 'New passwords do not match. Please try again.': - 'New passwords do not match. Please try again.', - 'No domain with the provided domain could be found.': - 'No domain with the provided domain could be found.', - 'No organization with the provided slug could be found.': - 'No organization with the provided slug could be found.', - 'Passing both `first` and `last` to paginate the `dkimResults` connection is not supported.': - 'Passing both `first` and `last` to paginate the `dkimResults` connection is not supported.', - 'Passing both `first` and `last` to paginate the `dkim` connection is not supported.': - 'Passing both `first` and `last` to paginate the `dkim` connection is not supported.', - 'Passing both `first` and `last` to paginate the `dmarc` connection is not supported.': - 'Passing both `first` and `last` to paginate the `dmarc` connection is not supported.', - 'Passing both `first` and `last` to paginate the `domain` connection is not supported.': - 'Passing both `first` and `last` to paginate the `domain` connection is not supported.', - 'Passing both `first` and `last` to paginate the `https` connection is not supported.': - 'Passing both `first` and `last` to paginate the `https` connection is not supported.', - 'Passing both `first` and `last` to paginate the `organization` connection is not supported.': - 'Passing both `first` and `last` to paginate the `organization` connection is not supported.', - 'Passing both `first` and `last` to paginate the `spf` connection is not supported.': - 'Passing both `first` and `last` to paginate the `spf` connection is not supported.', - 'Passing both `first` and `last` to paginate the `ssl` connection is not supported.': - 'Passing both `first` and `last` to paginate the `ssl` connection is not supported.', - 'Password is not strong enough. Please try again.': - 'Password is not strong enough. Please try again.', - 'Password is too short.': 'Password is too short.', - 'Password was successfully reset.': 'Password was successfully reset.', - 'Password was successfully updated.': 'Password was successfully updated.', - 'Passwords do not match.': 'Passwords do not match.', - 'Profile successfully updated.': 'Profile successfully updated.', - 'Requesting `{amount}` records on the `domain` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting `', - a('amount'), - '` records on the `domain` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting `{amount}` records on the `organization` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting `', - a('amount'), - '` records on the `organization` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting {amount} records on the `dkimResults` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting ', - a('amount'), - ' records on the `dkimResults` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting {amount} records on the `dkim` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting ', - a('amount'), - ' records on the `dkim` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting {amount} records on the `dmarc` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting ', - a('amount'), - ' records on the `dmarc` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting {amount} records on the `https` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting ', - a('amount'), - ' records on the `https` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting {amount} records on the `spf` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting ', - a('amount'), - ' records on the `spf` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records.': function ( - a, - ) { - return [ - 'Requesting ', - a('amount'), - ' records on the `ssl` connection exceeds the `', - a('argSet'), - '` limit of 100 records.', - ] - }, - 'Successfully invited user to organization, and sent notification email.': - 'Successfully invited user to organization, and sent notification email.', - 'Successfully removed domain: {0} from {1}.': function (a) { - return ['Successfully removed domain: ', a('0'), ' from ', a('1'), '.'] - }, - 'Successfully removed organization: {0}.': function (a) { - return ['Successfully removed organization: ', a('0'), '.'] - }, - 'Successfully sent invitation to service, and organization email.': - 'Successfully sent invitation to service, and organization email.', - 'Successfully two factor authenticated.': - 'Successfully two factor authenticated.', - 'Successfully verified account.': 'Successfully verified account.', - 'Too many failed login attempts, please reset your password, and try again.': - 'Too many failed login attempts, please reset your password, and try again.', - 'Two factor code has been successfully sent, you will receive a text message shortly.': - 'Two factor code has been successfully sent, you will receive a text message shortly.', - 'Unable to authenticate. Please try again.': - 'Unable to authenticate. Please try again.', - 'Unable to check permission. Please try again.': - 'Unable to check permission. Please try again.', - 'Unable to create domain. Please try again.': - 'Unable to create domain. Please try again.', - 'Unable to create organization. Please try again.': - 'Unable to create organization. Please try again.', - 'Unable to find dkim result. Please try again.': - 'Unable to find dkim result. Please try again.', - 'Unable to find dkim scan. Please try again.': - 'Unable to find dkim scan. Please try again.', - 'Unable to find dmarc scan. Please try again.': - 'Unable to find dmarc scan. Please try again.', - 'Unable to find domain. Please try again.': - 'Unable to find domain. Please try again.', - 'Unable to find https scan. Please try again.': - 'Unable to find https scan. Please try again.', - 'Unable to find organization. Please try again.': - 'Unable to find organization. Please try again.', - 'Unable to find spf scan. Please try again.': - 'Unable to find spf scan. Please try again.', - 'Unable to find ssl scan. Please try again.': - 'Unable to find ssl scan. Please try again.', - 'Unable to find user. Please try again.': - 'Unable to find user. Please try again.', - 'Unable to invite user. Please try again.': - 'Unable to invite user. Please try again.', - 'Unable to invite yourself to an org. Please try again.': - 'Unable to invite yourself to an org. Please try again.', - 'Unable to load dkim results. Please try again.': - 'Unable to load dkim results. Please try again.', - 'Unable to load dkim scans. Please try again.': - 'Unable to load dkim scans. Please try again.', - 'Unable to load dmarc scans. Please try again.': - 'Unable to load dmarc scans. Please try again.', - 'Unable to load domains. Please try again.': - 'Unable to load domains. Please try again.', - 'Unable to load https scans. Please try again.': - 'Unable to load https scans. Please try again.', - 'Unable to load organizations. Please try again.': - 'Unable to load organizations. Please try again.', - 'Unable to load spf scans. Please try again.': - 'Unable to load spf scans. Please try again.', - 'Unable to load ssl scans. Please try again.': - 'Unable to load ssl scans. Please try again.', - 'Unable to query domains. Please try again.': - 'Unable to query domains. Please try again.', - 'Unable to query organizations. Please try again.': - 'Unable to query organizations. Please try again.', - 'Unable to remove domain. Please try again.': - 'Unable to remove domain. Please try again.', - 'Unable to remove organization. Please try again.': - 'Unable to remove organization. Please try again.', - 'Unable to reset password. Please try again.': - 'Unable to reset password. Please try again.', - 'Unable to retrieve {0} for domain: {domain}.': function (a) { - return ['Unable to retrieve ', a('0'), ' for domain: ', a('domain'), '.'] - }, - 'Unable to send TFA code, please try again.': - 'Unable to send TFA code, please try again.', - 'Unable to send org invite email. Please try again.': - 'Unable to send org invite email. Please try again.', - 'Unable to send password reset email. Please try again.': - 'Unable to send password reset email. Please try again.', - 'Unable to send two factor authentication message. Please try again.': - 'Unable to send two factor authentication message. Please try again.', - 'Unable to send verification email. Please try again.': - 'Unable to send verification email. Please try again.', - 'Unable to sign in, please try again.': - 'Unable to sign in, please try again.', - 'Unable to sign up. Please try again.': - 'Unable to sign up. Please try again.', - 'Unable to two factor authenticate. Please try again.': - 'Unable to two factor authenticate. Please try again.', - 'Unable to update domain. Please try again.': - 'Unable to update domain. Please try again.', - 'Unable to update organization. Please try again.': - 'Unable to update organization. Please try again.', - 'Unable to update password, current password does not match. Please try again.': - 'Unable to update password, current password does not match. Please try again.', - 'Unable to update password, new passwords do not match. Please try again.': - 'Unable to update password, new passwords do not match. Please try again.', - 'Unable to update password, passwords are required to be 12 characters or longer. Please try again.': - 'Unable to update password, passwords are required to be 12 characters or longer. Please try again.', - 'Unable to update password. Please try again.': - 'Unable to update password. Please try again.', - 'Unable to update profile. Please try again.': - 'Unable to update profile. Please try again.', - 'Unable to update users role. Please invite user to the organization.': - 'Unable to update users role. Please invite user to the organization.', - 'Unable to update users role. Please try again.': - 'Unable to update users role. Please try again.', - 'Unable to update your own role. Please try again.': - 'Unable to update your own role. Please try again.', - 'Unable to verify account. Please request a new email.': - 'Unable to verify account. Please request a new email.', - 'Unable to verify account. Please try again.': - 'Unable to verify account. Please try again.', - 'Unable to verify if user is an admin, please try again.': - 'Unable to verify if user is an admin, please try again.', - 'User role was updated successfully.': - 'User role was updated successfully.', - 'Username already in use.': 'Username already in use.', - "We've sent you a text message with an authentication code to sign into Pulse.": - "We've sent you a text message with an authentication code to sign into Pulse.", - "We've sent you an email with an authentication code to sign into Pulse.": - "We've sent you an email with an authentication code to sign into Pulse.", - 'You must provide a `first` or `last` value to properly paginate the `dkimResults` connection.': - 'You must provide a `first` or `last` value to properly paginate the `dkimResults` connection.', - 'You must provide a `first` or `last` value to properly paginate the `dkim` connection.': - 'You must provide a `first` or `last` value to properly paginate the `dkim` connection.', - 'You must provide a `first` or `last` value to properly paginate the `dmarc` connection.': - 'You must provide a `first` or `last` value to properly paginate the `dmarc` connection.', - 'You must provide a `first` or `last` value to properly paginate the `domain` connection.': - 'You must provide a `first` or `last` value to properly paginate the `domain` connection.', - 'You must provide a `first` or `last` value to properly paginate the `https` connection.': - 'You must provide a `first` or `last` value to properly paginate the `https` connection.', - 'You must provide a `first` or `last` value to properly paginate the `organization` connection.': - 'You must provide a `first` or `last` value to properly paginate the `organization` connection.', - 'You must provide a `first` or `last` value to properly paginate the `spf` connection.': - 'You must provide a `first` or `last` value to properly paginate the `spf` connection.', - 'You must provide a `first` or `last` value to properly paginate the `ssl` connection.': - 'You must provide a `first` or `last` value to properly paginate the `ssl` connection.', - '`{argSet}` must be of type `number` not `{typeSet}`.': function (a) { - return [ - '`', - a('argSet'), - '` must be of type `number` not `', - a('typeSet'), - '`.', - ] - }, - '`{argSet}` on the `dkimResults` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `dkimResults` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `dkim` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `dkim` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `dmarc` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `dmarc` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `domain` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `domain` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `https` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `https` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `organization` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `organization` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `spf` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `spf` connection cannot be less than zero.', - ] - }, - '`{argSet}` on the `ssl` connection cannot be less than zero.': function ( - a, - ) { - return [ - '`', - a('argSet'), - '` on the `ssl` connection cannot be less than zero.', - ] - }, - }, -} +/* eslint-disable */module.exports={languageData:{"plurals":function(n,ord){var s=String(n).split("."),v0=!s[1],t0=Number(s[0])==n,n10=t0&&s[0].slice(-1),n100=t0&&s[0].slice(-2);if(ord)return n10==1&&n100!=11?"one":n10==2&&n100!=12?"two":n10==3&&n100!=13?"few":"other";return n==1&&v0?"one":"other"}},messages:{"Authentication error, please sign in again.":"Authentication error, please sign in again.","Authentication error. Please sign in again.":"Authentication error. Please sign in again.","Authentication error. Please sign in.":"Authentication error. Please sign in.","Could not retrieve specified domain.":"Could not retrieve specified domain.","Could not retrieve specified organization.":"Could not retrieve specified organization.","Error when retrieving dmarc report information. Please try again.":"Error when retrieving dmarc report information. Please try again.","If an account with this username is found, a password reset link will be found in your inbox.":"If an account with this username is found, a password reset link will be found in your inbox.","If an account with this username is found, an email verification link will be found in your inbox.":"If an account with this username is found, an email verification link will be found in your inbox.","Invalid token, please request a new one.":"Invalid token, please request a new one.","New passwords do not match. Please try again.":"New passwords do not match. Please try again.","No domain with the provided domain could be found.":"No domain with the provided domain could be found.","No organization with the provided slug could be found.":"No organization with the provided slug could be found.","Passing both `first` and `last` to paginate the `affiliation` is not supported.":"Passing both `first` and `last` to paginate the `affiliation` is not supported.","Passing both `first` and `last` to paginate the `dkimResults` connection is not supported.":"Passing both `first` and `last` to paginate the `dkimResults` connection is not supported.","Passing both `first` and `last` to paginate the `dkim` connection is not supported.":"Passing both `first` and `last` to paginate the `dkim` connection is not supported.","Passing both `first` and `last` to paginate the `dmarc` connection is not supported.":"Passing both `first` and `last` to paginate the `dmarc` connection is not supported.","Passing both `first` and `last` to paginate the `domain` connection is not supported.":"Passing both `first` and `last` to paginate the `domain` connection is not supported.","Passing both `first` and `last` to paginate the `https` connection is not supported.":"Passing both `first` and `last` to paginate the `https` connection is not supported.","Passing both `first` and `last` to paginate the `organization` connection is not supported.":"Passing both `first` and `last` to paginate the `organization` connection is not supported.","Passing both `first` and `last` to paginate the `spf` connection is not supported.":"Passing both `first` and `last` to paginate the `spf` connection is not supported.","Passing both `first` and `last` to paginate the `ssl` connection is not supported.":"Passing both `first` and `last` to paginate the `ssl` connection is not supported.","Password is not strong enough. Please try again.":"Password is not strong enough. Please try again.","Password is too short.":"Password is too short.","Password was successfully reset.":"Password was successfully reset.","Password was successfully updated.":"Password was successfully updated.","Passwords do not match.":"Passwords do not match.","Profile successfully updated.":"Profile successfully updated.","Requesting `{amount}` records on the `affiliations` exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting `",a("amount"),"` records on the `affiliations` exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting `{amount}` records on the `domain` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting `",a("amount"),"` records on the `domain` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting `{amount}` records on the `organization` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting `",a("amount"),"` records on the `organization` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting {amount} records on the `dkimResults` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting ",a("amount")," records on the `dkimResults` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting {amount} records on the `dkim` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting ",a("amount")," records on the `dkim` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting {amount} records on the `dmarc` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting ",a("amount")," records on the `dmarc` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting {amount} records on the `https` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting ",a("amount")," records on the `https` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting {amount} records on the `spf` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting ",a("amount")," records on the `spf` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records.":function(a){return["Requesting ",a("amount")," records on the `ssl` connection exceeds the `",a("argSet"),"` limit of 100 records."]},"Successfully invited user to organization, and sent notification email.":"Successfully invited user to organization, and sent notification email.","Successfully removed domain: {0} from {1}.":function(a){return["Successfully removed domain: ",a("0")," from ",a("1"),"."]},"Successfully removed organization: {0}.":function(a){return["Successfully removed organization: ",a("0"),"."]},"Successfully sent invitation to service, and organization email.":"Successfully sent invitation to service, and organization email.","Successfully two factor authenticated.":"Successfully two factor authenticated.","Successfully verified account.":"Successfully verified account.","Too many failed login attempts, please reset your password, and try again.":"Too many failed login attempts, please reset your password, and try again.","Two factor code has been successfully sent, you will receive a text message shortly.":"Two factor code has been successfully sent, you will receive a text message shortly.","Unable to authenticate. Please try again.":"Unable to authenticate. Please try again.","Unable to check permission. Please try again.":"Unable to check permission. Please try again.","Unable to create domain. Please try again.":"Unable to create domain. Please try again.","Unable to create organization. Please try again.":"Unable to create organization. Please try again.","Unable to find dkim result. Please try again.":"Unable to find dkim result. Please try again.","Unable to find dkim scan. Please try again.":"Unable to find dkim scan. Please try again.","Unable to find dmarc scan. Please try again.":"Unable to find dmarc scan. Please try again.","Unable to find domain. Please try again.":"Unable to find domain. Please try again.","Unable to find https scan. Please try again.":"Unable to find https scan. Please try again.","Unable to find organization. Please try again.":"Unable to find organization. Please try again.","Unable to find spf scan. Please try again.":"Unable to find spf scan. Please try again.","Unable to find ssl scan. Please try again.":"Unable to find ssl scan. Please try again.","Unable to find user affiliation(s). Please try again.":"Unable to find user affiliation(s). Please try again.","Unable to find user. Please try again.":"Unable to find user. Please try again.","Unable to invite user. Please try again.":"Unable to invite user. Please try again.","Unable to invite yourself to an org. Please try again.":"Unable to invite yourself to an org. Please try again.","Unable to load affiliations. Please try again.":"Unable to load affiliations. Please try again.","Unable to load dkim results. Please try again.":"Unable to load dkim results. Please try again.","Unable to load dkim scans. Please try again.":"Unable to load dkim scans. Please try again.","Unable to load dmarc scans. Please try again.":"Unable to load dmarc scans. Please try again.","Unable to load domains. Please try again.":"Unable to load domains. Please try again.","Unable to load https scans. Please try again.":"Unable to load https scans. Please try again.","Unable to load organizations. Please try again.":"Unable to load organizations. Please try again.","Unable to load spf scans. Please try again.":"Unable to load spf scans. Please try again.","Unable to load ssl scans. Please try again.":"Unable to load ssl scans. Please try again.","Unable to query affiliations. Please try again.":"Unable to query affiliations. Please try again.","Unable to query domains. Please try again.":"Unable to query domains. Please try again.","Unable to query organizations. Please try again.":"Unable to query organizations. Please try again.","Unable to remove domain. Please try again.":"Unable to remove domain. Please try again.","Unable to remove organization. Please try again.":"Unable to remove organization. Please try again.","Unable to reset password. Please try again.":"Unable to reset password. Please try again.","Unable to retrieve {0} for domain: {domain}.":function(a){return["Unable to retrieve ",a("0")," for domain: ",a("domain"),"."]},"Unable to send TFA code, please try again.":"Unable to send TFA code, please try again.","Unable to send org invite email. Please try again.":"Unable to send org invite email. Please try again.","Unable to send password reset email. Please try again.":"Unable to send password reset email. Please try again.","Unable to send two factor authentication message. Please try again.":"Unable to send two factor authentication message. Please try again.","Unable to send verification email. Please try again.":"Unable to send verification email. Please try again.","Unable to sign in, please try again.":"Unable to sign in, please try again.","Unable to sign up. Please try again.":"Unable to sign up. Please try again.","Unable to two factor authenticate. Please try again.":"Unable to two factor authenticate. Please try again.","Unable to update domain. Please try again.":"Unable to update domain. Please try again.","Unable to update organization. Please try again.":"Unable to update organization. Please try again.","Unable to update password, current password does not match. Please try again.":"Unable to update password, current password does not match. Please try again.","Unable to update password, new passwords do not match. Please try again.":"Unable to update password, new passwords do not match. Please try again.","Unable to update password, passwords are required to be 12 characters or longer. Please try again.":"Unable to update password, passwords are required to be 12 characters or longer. Please try again.","Unable to update password. Please try again.":"Unable to update password. Please try again.","Unable to update profile. Please try again.":"Unable to update profile. Please try again.","Unable to update users role. Please invite user to the organization.":"Unable to update users role. Please invite user to the organization.","Unable to update users role. Please try again.":"Unable to update users role. Please try again.","Unable to update your own role. Please try again.":"Unable to update your own role. Please try again.","Unable to verify account. Please request a new email.":"Unable to verify account. Please request a new email.","Unable to verify account. Please try again.":"Unable to verify account. Please try again.","Unable to verify if user is an admin, please try again.":"Unable to verify if user is an admin, please try again.","User role was updated successfully.":"User role was updated successfully.","Username already in use.":"Username already in use.","We've sent you a text message with an authentication code to sign into Pulse.":"We've sent you a text message with an authentication code to sign into Pulse.","We've sent you an email with an authentication code to sign into Pulse.":"We've sent you an email with an authentication code to sign into Pulse.","You must provide a `first` or `last` value to properly paginate the `affiliation`.":"You must provide a `first` or `last` value to properly paginate the `affiliation`.","You must provide a `first` or `last` value to properly paginate the `dkimResults` connection.":"You must provide a `first` or `last` value to properly paginate the `dkimResults` connection.","You must provide a `first` or `last` value to properly paginate the `dkim` connection.":"You must provide a `first` or `last` value to properly paginate the `dkim` connection.","You must provide a `first` or `last` value to properly paginate the `dmarc` connection.":"You must provide a `first` or `last` value to properly paginate the `dmarc` connection.","You must provide a `first` or `last` value to properly paginate the `domain` connection.":"You must provide a `first` or `last` value to properly paginate the `domain` connection.","You must provide a `first` or `last` value to properly paginate the `https` connection.":"You must provide a `first` or `last` value to properly paginate the `https` connection.","You must provide a `first` or `last` value to properly paginate the `organization` connection.":"You must provide a `first` or `last` value to properly paginate the `organization` connection.","You must provide a `first` or `last` value to properly paginate the `spf` connection.":"You must provide a `first` or `last` value to properly paginate the `spf` connection.","You must provide a `first` or `last` value to properly paginate the `ssl` connection.":"You must provide a `first` or `last` value to properly paginate the `ssl` connection.","`{argSet}` must be of type `number` not `{typeSet}`.":function(a){return["`",a("argSet"),"` must be of type `number` not `",a("typeSet"),"`."]},"`{argSet}` on the `affiliations` cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `affiliations` cannot be less than zero."]},"`{argSet}` on the `dkimResults` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `dkimResults` connection cannot be less than zero."]},"`{argSet}` on the `dkim` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `dkim` connection cannot be less than zero."]},"`{argSet}` on the `dmarc` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `dmarc` connection cannot be less than zero."]},"`{argSet}` on the `domain` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `domain` connection cannot be less than zero."]},"`{argSet}` on the `https` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `https` connection cannot be less than zero."]},"`{argSet}` on the `organization` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `organization` connection cannot be less than zero."]},"`{argSet}` on the `spf` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `spf` connection cannot be less than zero."]},"`{argSet}` on the `ssl` connection cannot be less than zero.":function(a){return["`",a("argSet"),"` on the `ssl` connection cannot be less than zero."]}}}; \ No newline at end of file diff --git a/api-js/src/locale/en/messages.po b/api-js/src/locale/en/messages.po index c7a5579ce..0f7ee57f0 100644 --- a/api-js/src/locale/en/messages.po +++ b/api-js/src/locale/en/messages.po @@ -38,8 +38,8 @@ msgstr "Could not retrieve specified domain." msgid "Could not retrieve specified organization." msgstr "Could not retrieve specified organization." -#: src/auth/check-domain-ownership.js:19 -#: src/auth/check-domain-ownership.js:30 +#: src/auth/check-domain-ownership.js:22 +#: src/auth/check-domain-ownership.js:35 msgid "Error when retrieving dmarc report information. Please try again." msgstr "Error when retrieving dmarc report information. Please try again." @@ -51,7 +51,7 @@ msgstr "If an account with this username is found, a password reset link will be msgid "If an account with this username is found, an email verification link will be found in your inbox." msgstr "If an account with this username is found, an email verification link will be found in your inbox." -#: src/auth/verify-jwt.js:12 +#: src/auth/verify-jwt.js:15 msgid "Invalid token, please request a new one." msgstr "Invalid token, please request a new one." @@ -67,6 +67,11 @@ msgstr "No domain with the provided domain could be found." msgid "No organization with the provided slug could be found." msgstr "No organization with the provided slug could be found." +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:45 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:44 +msgid "Passing both `first` and `last` to paginate the `affiliation` is not supported." +msgstr "Passing both `first` and `last` to paginate the `affiliation` is not supported." + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:39 msgid "Passing both `first` and `last` to paginate the `dkimResults` connection is not supported." msgstr "Passing both `first` and `last` to paginate the `dkimResults` connection is not supported." @@ -126,6 +131,11 @@ msgstr "Passwords do not match." msgid "Profile successfully updated." msgstr "Profile successfully updated." +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:68 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:67 +msgid "Requesting `{amount}` records on the `affiliations` exceeds the `{argSet}` limit of 100 records." +msgstr "Requesting `{amount}` records on the `affiliations` exceeds the `{argSet}` limit of 100 records." + #: src/loaders/domains/load-domain-connections-by-organizations-id.js:67 #: src/loaders/domains/load-domain-connections-by-user-id.js:65 msgid "Requesting `{amount}` records on the `domain` connection exceeds the `{argSet}` limit of 100 records." @@ -160,7 +170,7 @@ msgstr "Requesting {amount} records on the `spf` connection exceeds the `{argSet msgid "Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records." msgstr "Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records." -#: src/mutations/user-affiliations/invite-user-to-org.js:183 +#: src/mutations/user-affiliations/invite-user-to-org.js:186 msgid "Successfully invited user to organization, and sent notification email." msgstr "Successfully invited user to organization, and sent notification email." @@ -172,7 +182,7 @@ msgstr "Successfully removed domain: {0} from {1}." msgid "Successfully removed organization: {0}." msgstr "Successfully removed organization: {0}." -#: src/mutations/user-affiliations/invite-user-to-org.js:125 +#: src/mutations/user-affiliations/invite-user-to-org.js:127 msgid "Successfully sent invitation to service, and organization email." msgstr "Successfully sent invitation to service, and organization email." @@ -202,7 +212,7 @@ msgid "Unable to authenticate. Please try again." msgstr "Unable to authenticate. Please try again." #: src/auth/check-permission.js:27 -#: src/auth/check-permission.js:51 +#: src/auth/check-permission.js:53 msgid "Unable to check permission. Please try again." msgstr "Unable to check permission. Please try again." @@ -266,6 +276,11 @@ msgstr "Unable to find spf scan. Please try again." msgid "Unable to find ssl scan. Please try again." msgstr "Unable to find ssl scan. Please try again." +#: src/loaders/user-affiliations/load-user-affiliations-by-key.js:19 +#: src/loaders/user-affiliations/load-user-affiliations-by-key.js:33 +msgid "Unable to find user affiliation(s). Please try again." +msgstr "Unable to find user affiliation(s). Please try again." + #: src/loaders/user/load-user-by-key.js:18 #: src/loaders/user/load-user-by-key.js:28 #: src/loaders/user/load-user-by-username.js:18 @@ -273,17 +288,22 @@ msgstr "Unable to find ssl scan. Please try again." msgid "Unable to find user. Please try again." msgstr "Unable to find user. Please try again." -#: src/mutations/user-affiliations/invite-user-to-org.js:77 -#: src/mutations/user-affiliations/invite-user-to-org.js:90 -#: src/mutations/user-affiliations/invite-user-to-org.js:152 -#: src/mutations/user-affiliations/invite-user-to-org.js:174 +#: src/mutations/user-affiliations/invite-user-to-org.js:79 +#: src/mutations/user-affiliations/invite-user-to-org.js:92 +#: src/mutations/user-affiliations/invite-user-to-org.js:155 +#: src/mutations/user-affiliations/invite-user-to-org.js:177 msgid "Unable to invite user. Please try again." msgstr "Unable to invite user. Please try again." -#: src/mutations/user-affiliations/invite-user-to-org.js:67 +#: src/mutations/user-affiliations/invite-user-to-org.js:68 msgid "Unable to invite yourself to an org. Please try again." msgstr "Unable to invite yourself to an org. Please try again." +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:142 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:141 +msgid "Unable to load affiliations. Please try again." +msgstr "Unable to load affiliations. Please try again." + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:130 #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:140 msgid "Unable to load dkim results. Please try again." @@ -302,7 +322,7 @@ msgstr "Unable to load dmarc scans. Please try again." #: src/loaders/domains/load-domain-connections-by-organizations-id.js:148 #: src/loaders/domains/load-domain-connections-by-organizations-id.js:158 #: src/loaders/domains/load-domain-connections-by-user-id.js:148 -#: src/queries/domains/find-my-domains.js:25 +#: src/queries/domains/find-my-domains.js:24 msgid "Unable to load domains. Please try again." msgstr "Unable to load domains. Please try again." @@ -314,7 +334,7 @@ msgstr "Unable to load https scans. Please try again." #: src/loaders/organizations/load-organization-connections-by-domain-id.js:140 #: src/loaders/organizations/load-organization-connections-by-domain-id.js:150 #: src/loaders/organizations/load-organization-connections-by-user-id.js:145 -#: src/queries/organizations/find-my-organizations.js:24 +#: src/queries/organizations/find-my-organizations.js:25 msgid "Unable to load organizations. Please try again." msgstr "Unable to load organizations. Please try again." @@ -328,6 +348,11 @@ msgstr "Unable to load spf scans. Please try again." msgid "Unable to load ssl scans. Please try again." msgstr "Unable to load ssl scans. Please try again." +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:132 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:131 +msgid "Unable to query affiliations. Please try again." +msgstr "Unable to query affiliations. Please try again." + #: src/loaders/domains/load-domain-connections-by-user-id.js:138 msgid "Unable to query domains. Please try again." msgstr "Unable to query domains. Please try again." @@ -482,7 +507,7 @@ msgstr "Unable to verify account. Please request a new email." msgid "Unable to verify account. Please try again." msgstr "Unable to verify account. Please try again." -#: src/queries/user/is-user-admin.js:32 +#: src/queries/user/is-user-admin.js:23 msgid "Unable to verify if user is an admin, please try again." msgstr "Unable to verify if user is an admin, please try again." @@ -502,6 +527,11 @@ msgstr "We've sent you a text message with an authentication code to sign into P msgid "We've sent you an email with an authentication code to sign into Pulse." msgstr "We've sent you an email with an authentication code to sign into Pulse." +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:36 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:35 +msgid "You must provide a `first` or `last` value to properly paginate the `affiliation`." +msgstr "You must provide a `first` or `last` value to properly paginate the `affiliation`." + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:30 msgid "You must provide a `first` or `last` value to properly paginate the `dkimResults` connection." msgstr "You must provide a `first` or `last` value to properly paginate the `dkimResults` connection." @@ -544,11 +574,18 @@ msgstr "You must provide a `first` or `last` value to properly paginate the `ssl #: src/loaders/email-scan/load-spf-connections-by-domain-id.js:87 #: src/loaders/organizations/load-organization-connections-by-domain-id.js:81 #: src/loaders/organizations/load-organization-connections-by-user-id.js:81 +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:83 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:82 #: src/loaders/web-scan/load-https-connections-by-domain-id.js:87 #: src/loaders/web-scan/load-ssl-connections-by-domain-id.js:87 msgid "`{argSet}` must be of type `number` not `{typeSet}`." msgstr "`{argSet}` must be of type `number` not `{typeSet}`." +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:57 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:56 +msgid "`{argSet}` on the `affiliations` cannot be less than zero." +msgstr "`{argSet}` on the `affiliations` cannot be less than zero." + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:51 msgid "`{argSet}` on the `dkimResults` connection cannot be less than zero." msgstr "`{argSet}` on the `dkimResults` connection cannot be less than zero." diff --git a/api-js/src/locale/fr/messages.js b/api-js/src/locale/fr/messages.js index af3a67195..0665912f5 100644 --- a/api-js/src/locale/fr/messages.js +++ b/api-js/src/locale/fr/messages.js @@ -1,161 +1 @@ -/* eslint-disable */ module.exports = { - languageData: { - plurals: function (n, ord) { - if (ord) return n == 1 ? 'one' : 'other' - return n >= 0 && n < 2 ? 'one' : 'other' - }, - }, - messages: { - 'Authentication error, please sign in again.': 'todo', - 'Authentication error. Please sign in again.': 'todo', - 'Authentication error. Please sign in.': 'todo', - 'Could not retrieve specified domain.': 'todo', - 'Could not retrieve specified organization.': 'todo', - 'Error when retrieving dmarc report information. Please try again.': 'todo', - 'If an account with this username is found, a password reset link will be found in your inbox.': - 'todo', - 'If an account with this username is found, an email verification link will be found in your inbox.': - 'todo', - 'Invalid token, please request a new one.': 'todo', - 'New passwords do not match. Please try again.': 'todo', - 'No domain with the provided domain could be found.': 'todo', - 'No organization with the provided slug could be found.': 'todo', - 'Passing both `first` and `last` to paginate the `dkimResults` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `dkim` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `dmarc` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `domain` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `https` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `organization` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `spf` connection is not supported.': - 'todo', - 'Passing both `first` and `last` to paginate the `ssl` connection is not supported.': - 'todo', - 'Password is not strong enough. Please try again.': 'todo', - 'Password is too short.': 'todo', - 'Password was successfully reset.': 'todo', - 'Password was successfully updated.': 'todo', - 'Passwords do not match.': 'todo', - 'Profile successfully updated.': 'todo', - 'Requesting `{amount}` records on the `domain` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting `{amount}` records on the `organization` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting {amount} records on the `dkimResults` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting {amount} records on the `dkim` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting {amount} records on the `dmarc` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting {amount} records on the `https` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting {amount} records on the `spf` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records.': - 'todo', - 'Successfully invited user to organization, and sent notification email.': - 'todo', - 'Successfully removed domain: {0} from {1}.': 'todo', - 'Successfully removed organization: {0}.': 'todo', - 'Successfully sent invitation to service, and organization email.': 'todo', - 'Successfully two factor authenticated.': 'todo', - 'Successfully verified account.': 'todo', - 'Too many failed login attempts, please reset your password, and try again.': - 'todo', - 'Two factor code has been successfully sent, you will receive a text message shortly.': - 'todo', - 'Unable to authenticate. Please try again.': 'todo', - 'Unable to check permission. Please try again.': 'todo', - 'Unable to create domain. Please try again.': 'todo', - 'Unable to create organization. Please try again.': 'todo', - 'Unable to find dkim result. Please try again.': 'todo', - 'Unable to find dkim scan. Please try again.': 'todo', - 'Unable to find dmarc scan. Please try again.': 'todo', - 'Unable to find domain. Please try again.': 'todo', - 'Unable to find https scan. Please try again.': 'todo', - 'Unable to find organization. Please try again.': 'todo', - 'Unable to find spf scan. Please try again.': 'todo', - 'Unable to find ssl scan. Please try again.': 'todo', - 'Unable to find user. Please try again.': 'todo', - 'Unable to invite user. Please try again.': 'todo', - 'Unable to invite yourself to an org. Please try again.': 'todo', - 'Unable to load dkim results. Please try again.': 'todo', - 'Unable to load dkim scans. Please try again.': 'todo', - 'Unable to load dmarc scans. Please try again.': 'todo', - 'Unable to load domains. Please try again.': 'todo', - 'Unable to load https scans. Please try again.': 'todo', - 'Unable to load organizations. Please try again.': 'todo', - 'Unable to load spf scans. Please try again.': 'todo', - 'Unable to load ssl scans. Please try again.': 'todo', - 'Unable to query domains. Please try again.': 'todo', - 'Unable to query organizations. Please try again.': 'todo', - 'Unable to remove domain. Please try again.': 'todo', - 'Unable to remove organization. Please try again.': 'todo', - 'Unable to reset password. Please try again.': 'todo', - 'Unable to retrieve {0} for domain: {domain}.': 'todo', - 'Unable to send TFA code, please try again.': 'todo', - 'Unable to send org invite email. Please try again.': 'todo', - 'Unable to send password reset email. Please try again.': 'todo', - 'Unable to send two factor authentication message. Please try again.': - 'todo', - 'Unable to send verification email. Please try again.': 'todo', - 'Unable to sign in, please try again.': 'todo', - 'Unable to sign up. Please try again.': 'todo', - 'Unable to two factor authenticate. Please try again.': 'todo', - 'Unable to update domain. Please try again.': 'todo', - 'Unable to update organization. Please try again.': 'todo', - 'Unable to update password, current password does not match. Please try again.': - 'todo', - 'Unable to update password, new passwords do not match. Please try again.': - 'todo', - 'Unable to update password, passwords are required to be 12 characters or longer. Please try again.': - 'todo', - 'Unable to update password. Please try again.': 'todo', - 'Unable to update profile. Please try again.': 'todo', - 'Unable to update users role. Please invite user to the organization.': - 'todo', - 'Unable to update users role. Please try again.': 'todo', - 'Unable to update your own role. Please try again.': 'todo', - 'Unable to verify account. Please request a new email.': 'todo', - 'Unable to verify account. Please try again.': 'todo', - 'Unable to verify if user is an admin, please try again.': 'todo', - 'User role was updated successfully.': 'todo', - 'Username already in use.': 'todo', - "We've sent you a text message with an authentication code to sign into Pulse.": - 'todo', - "We've sent you an email with an authentication code to sign into Pulse.": - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `dkimResults` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `dkim` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `dmarc` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `domain` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `https` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `organization` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `spf` connection.': - 'todo', - 'You must provide a `first` or `last` value to properly paginate the `ssl` connection.': - 'todo', - '`{argSet}` must be of type `number` not `{typeSet}`.': 'todo', - '`{argSet}` on the `dkimResults` connection cannot be less than zero.': - 'todo', - '`{argSet}` on the `dkim` connection cannot be less than zero.': 'todo', - '`{argSet}` on the `dmarc` connection cannot be less than zero.': 'todo', - '`{argSet}` on the `domain` connection cannot be less than zero.': 'todo', - '`{argSet}` on the `https` connection cannot be less than zero.': 'todo', - '`{argSet}` on the `organization` connection cannot be less than zero.': - 'todo', - '`{argSet}` on the `spf` connection cannot be less than zero.': 'todo', - '`{argSet}` on the `ssl` connection cannot be less than zero.': 'todo', - }, -} +/* eslint-disable */module.exports={languageData:{"plurals":function(n,ord){if(ord)return n==1?"one":"other";return n>=0&&n<2?"one":"other"}},messages:{"Authentication error, please sign in again.":"todo","Authentication error. Please sign in again.":"todo","Authentication error. Please sign in.":"todo","Could not retrieve specified domain.":"todo","Could not retrieve specified organization.":"todo","Error when retrieving dmarc report information. Please try again.":"todo","If an account with this username is found, a password reset link will be found in your inbox.":"todo","If an account with this username is found, an email verification link will be found in your inbox.":"todo","Invalid token, please request a new one.":"todo","New passwords do not match. Please try again.":"todo","No domain with the provided domain could be found.":"todo","No organization with the provided slug could be found.":"todo","Passing both `first` and `last` to paginate the `affiliation` is not supported.":"todo","Passing both `first` and `last` to paginate the `dkimResults` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `dkim` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `dmarc` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `domain` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `https` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `organization` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `spf` connection is not supported.":"todo","Passing both `first` and `last` to paginate the `ssl` connection is not supported.":"todo","Password is not strong enough. Please try again.":"todo","Password is too short.":"todo","Password was successfully reset.":"todo","Password was successfully updated.":"todo","Passwords do not match.":"todo","Profile successfully updated.":"todo","Requesting `{amount}` records on the `affiliations` exceeds the `{argSet}` limit of 100 records.":"todo","Requesting `{amount}` records on the `domain` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting `{amount}` records on the `organization` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting {amount} records on the `dkimResults` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting {amount} records on the `dkim` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting {amount} records on the `dmarc` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting {amount} records on the `https` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting {amount} records on the `spf` connection exceeds the `{argSet}` limit of 100 records.":"todo","Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records.":"todo","Successfully invited user to organization, and sent notification email.":"todo","Successfully removed domain: {0} from {1}.":"todo","Successfully removed organization: {0}.":"todo","Successfully sent invitation to service, and organization email.":"todo","Successfully two factor authenticated.":"todo","Successfully verified account.":"todo","Too many failed login attempts, please reset your password, and try again.":"todo","Two factor code has been successfully sent, you will receive a text message shortly.":"todo","Unable to authenticate. Please try again.":"todo","Unable to check permission. Please try again.":"todo","Unable to create domain. Please try again.":"todo","Unable to create organization. Please try again.":"todo","Unable to find dkim result. Please try again.":"todo","Unable to find dkim scan. Please try again.":"todo","Unable to find dmarc scan. Please try again.":"todo","Unable to find domain. Please try again.":"todo","Unable to find https scan. Please try again.":"todo","Unable to find organization. Please try again.":"todo","Unable to find spf scan. Please try again.":"todo","Unable to find ssl scan. Please try again.":"todo","Unable to find user affiliation(s). Please try again.":"todo","Unable to find user. Please try again.":"todo","Unable to invite user. Please try again.":"todo","Unable to invite yourself to an org. Please try again.":"todo","Unable to load affiliations. Please try again.":"todo","Unable to load dkim results. Please try again.":"todo","Unable to load dkim scans. Please try again.":"todo","Unable to load dmarc scans. Please try again.":"todo","Unable to load domains. Please try again.":"todo","Unable to load https scans. Please try again.":"todo","Unable to load organizations. Please try again.":"todo","Unable to load spf scans. Please try again.":"todo","Unable to load ssl scans. Please try again.":"todo","Unable to query affiliations. Please try again.":"todo","Unable to query domains. Please try again.":"todo","Unable to query organizations. Please try again.":"todo","Unable to remove domain. Please try again.":"todo","Unable to remove organization. Please try again.":"todo","Unable to reset password. Please try again.":"todo","Unable to retrieve {0} for domain: {domain}.":"todo","Unable to send TFA code, please try again.":"todo","Unable to send org invite email. Please try again.":"todo","Unable to send password reset email. Please try again.":"todo","Unable to send two factor authentication message. Please try again.":"todo","Unable to send verification email. Please try again.":"todo","Unable to sign in, please try again.":"todo","Unable to sign up. Please try again.":"todo","Unable to two factor authenticate. Please try again.":"todo","Unable to update domain. Please try again.":"todo","Unable to update organization. Please try again.":"todo","Unable to update password, current password does not match. Please try again.":"todo","Unable to update password, new passwords do not match. Please try again.":"todo","Unable to update password, passwords are required to be 12 characters or longer. Please try again.":"todo","Unable to update password. Please try again.":"todo","Unable to update profile. Please try again.":"todo","Unable to update users role. Please invite user to the organization.":"todo","Unable to update users role. Please try again.":"todo","Unable to update your own role. Please try again.":"todo","Unable to verify account. Please request a new email.":"todo","Unable to verify account. Please try again.":"todo","Unable to verify if user is an admin, please try again.":"todo","User role was updated successfully.":"todo","Username already in use.":"todo","We've sent you a text message with an authentication code to sign into Pulse.":"todo","We've sent you an email with an authentication code to sign into Pulse.":"todo","You must provide a `first` or `last` value to properly paginate the `affiliation`.":"todo","You must provide a `first` or `last` value to properly paginate the `dkimResults` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `dkim` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `dmarc` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `domain` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `https` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `organization` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `spf` connection.":"todo","You must provide a `first` or `last` value to properly paginate the `ssl` connection.":"todo","`{argSet}` must be of type `number` not `{typeSet}`.":"todo","`{argSet}` on the `affiliations` cannot be less than zero.":"todo","`{argSet}` on the `dkimResults` connection cannot be less than zero.":"todo","`{argSet}` on the `dkim` connection cannot be less than zero.":"todo","`{argSet}` on the `dmarc` connection cannot be less than zero.":"todo","`{argSet}` on the `domain` connection cannot be less than zero.":"todo","`{argSet}` on the `https` connection cannot be less than zero.":"todo","`{argSet}` on the `organization` connection cannot be less than zero.":"todo","`{argSet}` on the `spf` connection cannot be less than zero.":"todo","`{argSet}` on the `ssl` connection cannot be less than zero.":"todo"}}; \ No newline at end of file diff --git a/api-js/src/locale/fr/messages.po b/api-js/src/locale/fr/messages.po index 5c1ed86c7..5ad34a469 100644 --- a/api-js/src/locale/fr/messages.po +++ b/api-js/src/locale/fr/messages.po @@ -38,8 +38,8 @@ msgstr "todo" msgid "Could not retrieve specified organization." msgstr "todo" -#: src/auth/check-domain-ownership.js:19 -#: src/auth/check-domain-ownership.js:30 +#: src/auth/check-domain-ownership.js:22 +#: src/auth/check-domain-ownership.js:35 msgid "Error when retrieving dmarc report information. Please try again." msgstr "todo" @@ -51,7 +51,7 @@ msgstr "todo" msgid "If an account with this username is found, an email verification link will be found in your inbox." msgstr "todo" -#: src/auth/verify-jwt.js:12 +#: src/auth/verify-jwt.js:15 msgid "Invalid token, please request a new one." msgstr "todo" @@ -67,6 +67,11 @@ msgstr "todo" msgid "No organization with the provided slug could be found." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:45 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:44 +msgid "Passing both `first` and `last` to paginate the `affiliation` is not supported." +msgstr "todo" + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:39 msgid "Passing both `first` and `last` to paginate the `dkimResults` connection is not supported." msgstr "todo" @@ -126,6 +131,11 @@ msgstr "todo" msgid "Profile successfully updated." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:68 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:67 +msgid "Requesting `{amount}` records on the `affiliations` exceeds the `{argSet}` limit of 100 records." +msgstr "todo" + #: src/loaders/domains/load-domain-connections-by-organizations-id.js:67 #: src/loaders/domains/load-domain-connections-by-user-id.js:65 msgid "Requesting `{amount}` records on the `domain` connection exceeds the `{argSet}` limit of 100 records." @@ -160,7 +170,7 @@ msgstr "todo" msgid "Requesting {amount} records on the `ssl` connection exceeds the `{argSet}` limit of 100 records." msgstr "todo" -#: src/mutations/user-affiliations/invite-user-to-org.js:183 +#: src/mutations/user-affiliations/invite-user-to-org.js:186 msgid "Successfully invited user to organization, and sent notification email." msgstr "todo" @@ -172,7 +182,7 @@ msgstr "todo" msgid "Successfully removed organization: {0}." msgstr "todo" -#: src/mutations/user-affiliations/invite-user-to-org.js:125 +#: src/mutations/user-affiliations/invite-user-to-org.js:127 msgid "Successfully sent invitation to service, and organization email." msgstr "todo" @@ -202,7 +212,7 @@ msgid "Unable to authenticate. Please try again." msgstr "todo" #: src/auth/check-permission.js:27 -#: src/auth/check-permission.js:51 +#: src/auth/check-permission.js:53 msgid "Unable to check permission. Please try again." msgstr "todo" @@ -266,6 +276,11 @@ msgstr "todo" msgid "Unable to find ssl scan. Please try again." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-key.js:19 +#: src/loaders/user-affiliations/load-user-affiliations-by-key.js:33 +msgid "Unable to find user affiliation(s). Please try again." +msgstr "todo" + #: src/loaders/user/load-user-by-key.js:18 #: src/loaders/user/load-user-by-key.js:28 #: src/loaders/user/load-user-by-username.js:18 @@ -273,17 +288,22 @@ msgstr "todo" msgid "Unable to find user. Please try again." msgstr "todo" -#: src/mutations/user-affiliations/invite-user-to-org.js:77 -#: src/mutations/user-affiliations/invite-user-to-org.js:90 -#: src/mutations/user-affiliations/invite-user-to-org.js:152 -#: src/mutations/user-affiliations/invite-user-to-org.js:174 +#: src/mutations/user-affiliations/invite-user-to-org.js:79 +#: src/mutations/user-affiliations/invite-user-to-org.js:92 +#: src/mutations/user-affiliations/invite-user-to-org.js:155 +#: src/mutations/user-affiliations/invite-user-to-org.js:177 msgid "Unable to invite user. Please try again." msgstr "todo" -#: src/mutations/user-affiliations/invite-user-to-org.js:67 +#: src/mutations/user-affiliations/invite-user-to-org.js:68 msgid "Unable to invite yourself to an org. Please try again." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:142 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:141 +msgid "Unable to load affiliations. Please try again." +msgstr "todo" + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:130 #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:140 msgid "Unable to load dkim results. Please try again." @@ -302,7 +322,7 @@ msgstr "todo" #: src/loaders/domains/load-domain-connections-by-organizations-id.js:148 #: src/loaders/domains/load-domain-connections-by-organizations-id.js:158 #: src/loaders/domains/load-domain-connections-by-user-id.js:148 -#: src/queries/domains/find-my-domains.js:25 +#: src/queries/domains/find-my-domains.js:24 msgid "Unable to load domains. Please try again." msgstr "todo" @@ -314,7 +334,7 @@ msgstr "todo" #: src/loaders/organizations/load-organization-connections-by-domain-id.js:140 #: src/loaders/organizations/load-organization-connections-by-domain-id.js:150 #: src/loaders/organizations/load-organization-connections-by-user-id.js:145 -#: src/queries/organizations/find-my-organizations.js:24 +#: src/queries/organizations/find-my-organizations.js:25 msgid "Unable to load organizations. Please try again." msgstr "todo" @@ -328,6 +348,11 @@ msgstr "todo" msgid "Unable to load ssl scans. Please try again." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:132 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:131 +msgid "Unable to query affiliations. Please try again." +msgstr "todo" + #: src/loaders/domains/load-domain-connections-by-user-id.js:138 msgid "Unable to query domains. Please try again." msgstr "todo" @@ -482,7 +507,7 @@ msgstr "todo" msgid "Unable to verify account. Please try again." msgstr "todo" -#: src/queries/user/is-user-admin.js:32 +#: src/queries/user/is-user-admin.js:23 msgid "Unable to verify if user is an admin, please try again." msgstr "todo" @@ -502,6 +527,11 @@ msgstr "todo" msgid "We've sent you an email with an authentication code to sign into Pulse." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:36 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:35 +msgid "You must provide a `first` or `last` value to properly paginate the `affiliation`." +msgstr "todo" + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:30 msgid "You must provide a `first` or `last` value to properly paginate the `dkimResults` connection." msgstr "todo" @@ -544,11 +574,18 @@ msgstr "todo" #: src/loaders/email-scan/load-spf-connections-by-domain-id.js:87 #: src/loaders/organizations/load-organization-connections-by-domain-id.js:81 #: src/loaders/organizations/load-organization-connections-by-user-id.js:81 +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:83 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:82 #: src/loaders/web-scan/load-https-connections-by-domain-id.js:87 #: src/loaders/web-scan/load-ssl-connections-by-domain-id.js:87 msgid "`{argSet}` must be of type `number` not `{typeSet}`." msgstr "todo" +#: src/loaders/user-affiliations/load-user-affiliations-by-org-id.js:57 +#: src/loaders/user-affiliations/load-user-affiliations-by-user-id.js:56 +msgid "`{argSet}` on the `affiliations` cannot be less than zero." +msgstr "todo" + #: src/loaders/email-scan/load-dkim-results-connections-by-dkim-id.js:51 msgid "`{argSet}` on the `dkimResults` connection cannot be less than zero." msgstr "todo" diff --git a/api-js/src/server.js b/api-js/src/server.js index 28d756681..f807e8df3 100644 --- a/api-js/src/server.js +++ b/api-js/src/server.js @@ -61,6 +61,9 @@ const { httpsLoaderConnectionsByDomainId, sslLoaderByKey, sslLoaderConnectionsByDomainId, + affiliationLoaderByKey, + affiliationLoaderByUserId, + affiliationLoaderByOrgId, } = require('./loaders') const createSchema = ({ language }) => new GraphQLSchema({ @@ -201,6 +204,19 @@ const createContext = ({context, request, response}) => { ), userLoaderByUserName: userLoaderByUserName(query, i18n), userLoaderByKey: userLoaderByKey(query, i18n), + affiliationLoaderByKey: affiliationLoaderByKey(query), + affiliationLoaderByUserId: affiliationLoaderByUserId( + query, + userId, + cleanseInput, + i18n, + ), + affiliationLoaderByOrgId: affiliationLoaderByOrgId( + query, + userId, + cleanseInput, + i18n, + ), }, } }