diff --git a/CHANGELOG.md b/CHANGELOG.md index 664c6cbe0..bcf2da9c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,123 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [v0.4.2](https://github.com/Human-Connection/Human-Connection/compare/v0.4.1...v0.4.2) + +> 12 March 2020 + +- build(deps): bump @sentry/node from 5.13.1 to 5.14.0 in /backend [`#3260`](https://github.com/Human-Connection/Human-Connection/pull/3260) +- build(deps): bump graphql-shield from 7.0.14 to 7.1.0 in /backend [`#3259`](https://github.com/Human-Connection/Human-Connection/pull/3259) +- feat: more prominent output of ./scripts/translations/sort.sh and hint to --fix feature of the script on errors [`#3251`](https://github.com/Human-Connection/Human-Connection/pull/3251) +- build(deps): bump nodemailer from 6.4.4 to 6.4.5 in /backend [`#3254`](https://github.com/Human-Connection/Human-Connection/pull/3254) +- build(deps-dev): bump @vue/test-utils from 1.0.0-beta.31 to 1.0.0-beta.32 in /webapp [`#3248`](https://github.com/Human-Connection/Human-Connection/pull/3248) +- build(deps-dev): bump async-validator from 3.2.3 to 3.2.4 in /webapp [`#3255`](https://github.com/Human-Connection/Human-Connection/pull/3255) +- build(deps-dev): bump eslint-plugin-jest from 23.8.1 to 23.8.2 in /backend [`#3253`](https://github.com/Human-Connection/Human-Connection/pull/3253) +- feature: Delete_user_as_admin_through_API_only [`#3063`](https://github.com/Human-Connection/Human-Connection/pull/3063) +- feat: zero bell to all notifications page [2823] [`#3219`](https://github.com/Human-Connection/Human-Connection/pull/3219) +- fix: layout shift [2607] [`#3218`](https://github.com/Human-Connection/Human-Connection/pull/3218) +- feat: Documentation for locales script [`#3242`](https://github.com/Human-Connection/Human-Connection/pull/3242) +- build(deps): bump metascraper-audio from 5.11.1 to 5.11.6 in /backend [`#3235`](https://github.com/Human-Connection/Human-Connection/pull/3235) +- build(deps): bump metascraper-video from 5.11.1 to 5.11.6 in /backend [`#3247`](https://github.com/Human-Connection/Human-Connection/pull/3247) +- build(deps): bump metascraper-soundcloud from 5.11.5 to 5.11.6 in /backend [`#3246`](https://github.com/Human-Connection/Human-Connection/pull/3246) +- build(deps): bump metascraper-lang from 5.11.1 to 5.11.6 in /backend [`#3234`](https://github.com/Human-Connection/Human-Connection/pull/3234) +- build(deps): bump metascraper-description from 5.11.1 to 5.11.6 in /backend [`#3233`](https://github.com/Human-Connection/Human-Connection/pull/3233) +- build(deps): bump cross-env from 7.0.1 to 7.0.2 in /backend [`#3245`](https://github.com/Human-Connection/Human-Connection/pull/3245) +- build(deps): bump metascraper-title from 5.11.1 to 5.11.6 in /backend [`#3244`](https://github.com/Human-Connection/Human-Connection/pull/3244) +- chore: Update to v0.4.1 [`#3243`](https://github.com/Human-Connection/Human-Connection/pull/3243) +- DRY user.spec.js [`da16590`](https://github.com/Human-Connection/Human-Connection/commit/da165906e2ed12baddd902b43064103ab3adfa06) +- test deleteuser as admin, moderator, another user and as I myself, fix lint [`3983612`](https://github.com/Human-Connection/Human-Connection/commit/3983612c56ac92473a192a318959e4c691a3e7b8) +- feature: test delete user as admin [`84c1547`](https://github.com/Human-Connection/Human-Connection/commit/84c154798efac0cec4c13dfefae18a6a9542058a) + +#### [v0.4.1](https://github.com/Human-Connection/Human-Connection/compare/v0.4.0...v0.4.1) + +> 9 March 2020 + +- build(deps): bump metascraper-publisher from 5.11.1 to 5.11.6 in /backend [`#3226`](https://github.com/Human-Connection/Human-Connection/pull/3226) +- build(deps-dev): bump eslint-plugin-vue from 6.2.1 to 6.2.2 in /webapp [`#3238`](https://github.com/Human-Connection/Human-Connection/pull/3238) +- build(deps): bump metascraper-date from 5.11.1 to 5.11.6 in /backend [`#3236`](https://github.com/Human-Connection/Human-Connection/pull/3236) +- build(deps): bump metascraper-image from 5.11.1 to 5.11.6 in /backend [`#3224`](https://github.com/Human-Connection/Human-Connection/pull/3224) +- build(deps): bump uuid from 7.0.1 to 7.0.2 in /backend [`#3214`](https://github.com/Human-Connection/Human-Connection/pull/3214) +- build(deps-dev): bump cypress from 4.0.2 to 4.1.0 [`#3190`](https://github.com/Human-Connection/Human-Connection/pull/3190) +- build(deps): bump cross-env from 7.0.1 to 7.0.2 in /webapp [`#3230`](https://github.com/Human-Connection/Human-Connection/pull/3230) +- build(deps): bump vue-infinite-loading from 2.4.4 to 2.4.5 in /webapp [`#3227`](https://github.com/Human-Connection/Human-Connection/pull/3227) +- build(deps): bump metascraper-youtube from 5.11.1 to 5.11.6 in /backend [`#3225`](https://github.com/Human-Connection/Human-Connection/pull/3225) +- build(deps): bump metascraper-url from 5.11.1 to 5.11.6 in /backend [`#3223`](https://github.com/Human-Connection/Human-Connection/pull/3223) +- build(deps): bump metascraper-author from 5.11.1 to 5.11.6 in /backend [`#3222`](https://github.com/Human-Connection/Human-Connection/pull/3222) +- build(deps): bump metascraper-logo from 5.11.1 to 5.11.6 in /backend [`#3221`](https://github.com/Human-Connection/Human-Connection/pull/3221) +- build(deps): bump metascraper from 5.11.4 to 5.11.6 in /backend [`#3220`](https://github.com/Human-Connection/Human-Connection/pull/3220) +- build(deps-dev): bump @storybook/addon-a11y from 5.3.13 to 5.3.14 in /webapp [`#3167`](https://github.com/Human-Connection/Human-Connection/pull/3167) +- build(deps-dev): bump @babel/core from 7.8.6 to 7.8.7 in /backend [`#3213`](https://github.com/Human-Connection/Human-Connection/pull/3213) +- build(deps): bump metascraper-soundcloud from 5.11.4 to 5.11.5 in /backend [`#3189`](https://github.com/Human-Connection/Human-Connection/pull/3189) +- build(deps-dev): bump @babel/preset-env from 7.8.6 to 7.8.7 in /backend [`#3211`](https://github.com/Human-Connection/Human-Connection/pull/3211) +- build(deps-dev): bump @babel/core from 7.8.6 to 7.8.7 [`#3210`](https://github.com/Human-Connection/Human-Connection/pull/3210) +- build(deps-dev): bump @babel/core from 7.8.6 to 7.8.7 in /webapp [`#3216`](https://github.com/Human-Connection/Human-Connection/pull/3216) +- build(deps-dev): bump @babel/node from 7.8.4 to 7.8.7 in /backend [`#3212`](https://github.com/Human-Connection/Human-Connection/pull/3212) +- build(deps-dev): bump @babel/preset-env from 7.8.6 to 7.8.7 [`#3209`](https://github.com/Human-Connection/Human-Connection/pull/3209) +- perf(neo4j): Improve currentUser read performance [`#3207`](https://github.com/Human-Connection/Human-Connection/pull/3207) +- build(deps-dev): bump apollo-server-testing from 2.10.1 to 2.11.0 in /backend [`#3205`](https://github.com/Human-Connection/Human-Connection/pull/3205) +- build(deps): bump apollo-server from 2.10.1 to 2.11.0 in /backend [`#3201`](https://github.com/Human-Connection/Human-Connection/pull/3201) +- build(deps): bump cross-env from 7.0.0 to 7.0.1 in /webapp [`#3206`](https://github.com/Human-Connection/Human-Connection/pull/3206) +- build(deps): bump apollo-server-express from 2.10.1 to 2.11.0 in /backend [`#3202`](https://github.com/Human-Connection/Human-Connection/pull/3202) +- build(deps): bump graphql-redis-subscriptions from 2.1.2 to 2.2.1 in /backend [`#3203`](https://github.com/Human-Connection/Human-Connection/pull/3203) +- build(deps): bump cross-env from 7.0.0 to 7.0.1 in /backend [`#3204`](https://github.com/Human-Connection/Human-Connection/pull/3204) +- build(deps-dev): bump @babel/preset-env from 7.8.4 to 7.8.6 [`#3175`](https://github.com/Human-Connection/Human-Connection/pull/3175) +- feat: Russian Translations Update By Ewald Arnold [`#3198`](https://github.com/Human-Connection/Human-Connection/pull/3198) +- feat: Translations update [`#3111`](https://github.com/Human-Connection/Human-Connection/pull/3111) +- build(deps-dev): bump @babel/core from 7.8.4 to 7.8.6 in /backend [`#3172`](https://github.com/Human-Connection/Human-Connection/pull/3172) +- build(deps-dev): bump @babel/core from 7.8.4 to 7.8.6 [`#3173`](https://github.com/Human-Connection/Human-Connection/pull/3173) +- fix: Update user.updatedAt when password is reset [`#3197`](https://github.com/Human-Connection/Human-Connection/pull/3197) +- build(deps-dev): bump @babel/register from 7.8.3 to 7.8.6 in /backend [`#3174`](https://github.com/Human-Connection/Human-Connection/pull/3174) +- build(deps-dev): bump @babel/preset-env from 7.8.4 to 7.8.6 in /webapp [`#3183`](https://github.com/Human-Connection/Human-Connection/pull/3183) +- build(deps-dev): bump eslint-plugin-jest from 23.8.0 to 23.8.1 in /backend [`#3191`](https://github.com/Human-Connection/Human-Connection/pull/3191) +- build(deps): bump wait-on from 4.0.0 to 4.0.1 in /backend [`#3176`](https://github.com/Human-Connection/Human-Connection/pull/3176) +- build(deps-dev): bump @babel/register from 7.8.3 to 7.8.6 [`#3179`](https://github.com/Human-Connection/Human-Connection/pull/3179) +- build(deps-dev): bump @babel/preset-env from 7.8.4 to 7.8.6 in /backend [`#3181`](https://github.com/Human-Connection/Human-Connection/pull/3181) +- build(deps-dev): bump @babel/core from 7.8.4 to 7.8.6 in /webapp [`#3182`](https://github.com/Human-Connection/Human-Connection/pull/3182) +- build(deps-dev): bump @vue/cli-shared-utils from 4.2.2 to 4.2.3 in /webapp [`#3184`](https://github.com/Human-Connection/Human-Connection/pull/3184) +- build(deps): bump @sentry/node from 5.12.4 to 5.13.1 in /backend [`#3192`](https://github.com/Human-Connection/Human-Connection/pull/3192) +- build(deps): bump nodemailer from 6.4.3 to 6.4.4 in /backend [`#3193`](https://github.com/Human-Connection/Human-Connection/pull/3193) +- build(deps-dev): bump eslint-plugin-jest from 23.8.0 to 23.8.1 in /webapp [`#3195`](https://github.com/Human-Connection/Human-Connection/pull/3195) +- build(deps): bump date-fns from 2.9.0 to 2.10.0 in /backend [`#3159`](https://github.com/Human-Connection/Human-Connection/pull/3159) +- build(deps-dev): bump @storybook/vue from 5.3.13 to 5.3.14 in /webapp [`#3165`](https://github.com/Human-Connection/Human-Connection/pull/3165) +- build(deps-dev): bump babel-eslint from 10.0.3 to 10.1.0 in /webapp [`#3168`](https://github.com/Human-Connection/Human-Connection/pull/3168) +- build(deps-dev): bump @storybook/addon-actions from 5.3.13 to 5.3.14 in /webapp [`#3166`](https://github.com/Human-Connection/Human-Connection/pull/3166) +- build(deps-dev): bump date-fns from 2.9.0 to 2.10.0 [`#3160`](https://github.com/Human-Connection/Human-Connection/pull/3160) +- build(deps-dev): bump @storybook/addon-notes from 5.3.13 to 5.3.14 in /webapp [`#3164`](https://github.com/Human-Connection/Human-Connection/pull/3164) +- build(deps): bump date-fns from 2.9.0 to 2.10.0 in /webapp [`#3163`](https://github.com/Human-Connection/Human-Connection/pull/3163) +- build(deps-dev): bump babel-eslint from 10.0.3 to 10.1.0 in /backend [`#3162`](https://github.com/Human-Connection/Human-Connection/pull/3162) +- build(deps): bump uuid from 7.0.0 to 7.0.1 in /backend [`#3161`](https://github.com/Human-Connection/Human-Connection/pull/3161) +- build(deps): bump xregexp from 4.2.4 to 4.3.0 in /backend [`#3044`](https://github.com/Human-Connection/Human-Connection/pull/3044) +- build(deps): bump metascraper-url from 5.10.7 to 5.11.1 in /backend [`#3147`](https://github.com/Human-Connection/Human-Connection/pull/3147) +- chore(build): Fix uuid deprecations [`#3156`](https://github.com/Human-Connection/Human-Connection/pull/3156) +- build(deps): bump graphql-shield from 7.0.13 to 7.0.14 in /backend [`#3153`](https://github.com/Human-Connection/Human-Connection/pull/3153) +- build(deps): bump metascraper-title from 5.10.7 to 5.11.1 in /backend [`#3148`](https://github.com/Human-Connection/Human-Connection/pull/3148) +- build(deps): bump helmet from 3.21.2 to 3.21.3 in /backend [`#3154`](https://github.com/Human-Connection/Human-Connection/pull/3154) +- build(deps): bump uuid from 3.4.0 to 7.0.0 in /backend [`#3155`](https://github.com/Human-Connection/Human-Connection/pull/3155) +- build(deps-dev): bump eslint-plugin-jest from 23.7.0 to 23.8.0 in /webapp [`#3150`](https://github.com/Human-Connection/Human-Connection/pull/3150) +- fix(webapp): remove ribbon z-index [`#3152`](https://github.com/Human-Connection/Human-Connection/pull/3152) +- build(deps): bump metascraper-description from 5.11.0 to 5.11.1 in /backend [`#3149`](https://github.com/Human-Connection/Human-Connection/pull/3149) +- build(deps-dev): bump eslint-plugin-jest from 23.7.0 to 23.8.0 in /backend [`#3146`](https://github.com/Human-Connection/Human-Connection/pull/3146) +- build(deps): bump sanitize-html from 1.21.1 to 1.22.0 in /backend [`#3145`](https://github.com/Human-Connection/Human-Connection/pull/3145) +- build(deps): bump nodemailer from 6.4.2 to 6.4.3 in /backend [`#3144`](https://github.com/Human-Connection/Human-Connection/pull/3144) +- build(deps): bump metascraper-video from 5.10.7 to 5.11.1 in /backend [`#3143`](https://github.com/Human-Connection/Human-Connection/pull/3143) +- feat: the point -no political use - added [`#3138`](https://github.com/Human-Connection/Human-Connection/pull/3138) +- build(deps): bump metascraper-lang from 5.10.7 to 5.11.1 in /backend [`#3071`](https://github.com/Human-Connection/Human-Connection/pull/3071) +- build(deps): bump metascraper from 5.11.0 to 5.11.4 in /backend [`#3136`](https://github.com/Human-Connection/Human-Connection/pull/3136) +- build(deps): bump metascraper-soundcloud from 5.10.7 to 5.11.4 in /backend [`#3137`](https://github.com/Human-Connection/Human-Connection/pull/3137) +- chore: Update to v0.4.0 [`#3132`](https://github.com/Human-Connection/Human-Connection/pull/3132) +- build(deps): bump metascraper-logo from 5.10.7 to 5.11.1 in /backend [`#3126`](https://github.com/Human-Connection/Human-Connection/pull/3126) +- chore(cypress): Favor firefox in cypress [`#3121`](https://github.com/Human-Connection/Human-Connection/pull/3121) +- build(deps): bump graphql-shield from 7.0.11 to 7.0.13 in /backend [`#3127`](https://github.com/Human-Connection/Human-Connection/pull/3127) +- build(deps): bump ioredis from 4.14.1 to 4.16.0 in /backend [`#3128`](https://github.com/Human-Connection/Human-Connection/pull/3128) +- build(deps-dev): bump @storybook/addon-notes in /webapp [`5ef2b25`](https://github.com/Human-Connection/Human-Connection/commit/5ef2b25ee6a3402a2ebe2f3f55dd65a6e0a1111e) +- build(deps-dev): bump @storybook/addon-a11y in /webapp [`f209436`](https://github.com/Human-Connection/Human-Connection/commit/f209436147fbf9afacfbd6edb6135847e6c4faed) +- build(deps): bump apollo-server-express in /backend [`3b35487`](https://github.com/Human-Connection/Human-Connection/commit/3b35487f0671490dee1e636fb938c408722bfd45) + #### [v0.4.0](https://github.com/Human-Connection/Human-Connection/compare/v0.3.1...v0.4.0) > 21 February 2020 +- build(deps): bump apollo-server from 2.10.0 to 2.10.1 in /backend [`#3125`](https://github.com/Human-Connection/Human-Connection/pull/3125) - fix: Favor Cypress.Promise over async/await in e2e tests [`#3115`](https://github.com/Human-Connection/Human-Connection/pull/3115) - docs(setup): Fix links in tests [`#3120`](https://github.com/Human-Connection/Human-Connection/pull/3120) - feat: 🍰 Expose sensitive report type to moderators only [`#3075`](https://github.com/Human-Connection/Human-Connection/pull/3075) diff --git a/backend/package.json b/backend/package.json index 1fdca3a28..83e98b1c9 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "human-connection-backend", - "version": "0.4.0", + "version": "0.4.2", "description": "GraphQL Backend for Human Connection", "main": "src/index.js", "scripts": { @@ -38,7 +38,7 @@ }, "dependencies": { "@hapi/joi": "^17.1.0", - "@sentry/node": "^5.13.1", + "@sentry/node": "^5.14.1", "apollo-cache-inmemory": "~1.6.5", "apollo-client": "~2.6.8", "apollo-link-context": "~1.0.19", @@ -49,7 +49,7 @@ "bcryptjs": "~2.4.3", "cheerio": "~1.0.0-rc.3", "cors": "~2.8.5", - "cross-env": "~7.0.1", + "cross-env": "~7.0.2", "date-fns": "2.10.0", "debug": "~4.1.1", "dotenv": "~8.2.0", @@ -61,7 +61,7 @@ "graphql-middleware": "~4.0.2", "graphql-middleware-sentry": "^3.2.1", "graphql-redis-subscriptions": "^2.2.1", - "graphql-shield": "~7.0.14", + "graphql-shield": "~7.2.0", "graphql-tag": "~2.10.3", "helmet": "~3.21.3", "ioredis": "^4.16.0", @@ -70,20 +70,20 @@ "lodash": "~4.17.14", "merge-graphql-schemas": "^1.7.6", "metascraper": "^5.11.6", - "metascraper-audio": "^5.11.1", + "metascraper-audio": "^5.11.6", "metascraper-author": "^5.11.6", "metascraper-clearbit-logo": "^5.3.0", - "metascraper-date": "^5.11.1", - "metascraper-description": "^5.11.1", - "metascraper-image": "^5.11.1", - "metascraper-lang": "^5.11.1", + "metascraper-date": "^5.11.6", + "metascraper-description": "^5.11.6", + "metascraper-image": "^5.11.6", + "metascraper-lang": "^5.11.6", "metascraper-lang-detector": "^4.10.2", "metascraper-logo": "^5.11.6", - "metascraper-publisher": "^5.11.1", - "metascraper-soundcloud": "^5.11.5", - "metascraper-title": "^5.11.1", + "metascraper-publisher": "^5.11.6", + "metascraper-soundcloud": "^5.11.6", + "metascraper-title": "^5.11.6", "metascraper-url": "^5.11.6", - "metascraper-video": "^5.11.1", + "metascraper-video": "^5.11.6", "metascraper-youtube": "^5.11.6", "migrate": "^1.6.2", "minimatch": "^3.0.4", @@ -92,15 +92,15 @@ "neo4j-graphql-js": "^2.11.5", "neode": "^0.3.7", "node-fetch": "~2.6.0", - "nodemailer": "^6.4.4", + "nodemailer": "^6.4.5", "nodemailer-html-to-text": "^3.1.0", "npm-run-all": "~4.1.5", "request": "~2.88.2", - "sanitize-html": "~1.22.0", + "sanitize-html": "~1.22.1", "slug": "~2.1.1", "subscriptions-transport-ws": "^0.9.16", "trunc-html": "~1.1.2", - "uuid": "~7.0.1", + "uuid": "~7.0.2", "validator": "^12.2.0", "wait-on": "~4.0.1", "xregexp": "^4.3.0" @@ -122,7 +122,7 @@ "eslint-config-prettier": "~6.10.0", "eslint-config-standard": "~14.1.0", "eslint-plugin-import": "~2.20.1", - "eslint-plugin-jest": "~23.8.1", + "eslint-plugin-jest": "~23.8.2", "eslint-plugin-node": "~11.0.0", "eslint-plugin-prettier": "~3.1.2", "eslint-plugin-promise": "~4.2.1", diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 10dc98845..fa88d9348 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -133,7 +133,7 @@ export default shield( CreateComment: isAuthenticated, UpdateComment: isAuthor, DeleteComment: isAuthor, - DeleteUser: isDeletingOwnAccount, + DeleteUser: or(isDeletingOwnAccount, isAdmin), requestPasswordReset: allow, resetPassword: allow, AddPostEmotions: isAuthenticated, diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index a1b68e20d..c29b021be 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -175,6 +175,7 @@ export default { DeleteUser: async (object, params, context, resolveInfo) => { const { resource } = params const session = context.driver.session() + const { id: userId } = params try { if (resource && resource.length) { await session.writeTransaction(transaction => { @@ -190,7 +191,7 @@ export default { RETURN author `, { - userId: context.user.id, + userId, }, ) }) @@ -212,7 +213,7 @@ export default { DETACH DELETE socialMedia RETURN user `, - { userId: context.user.id }, + { userId }, ) log(deleteUserTransactionResponse) return deleteUserTransactionResponse.records.map(record => record.get('user').properties) diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index 9e24b8082..892d2b4b4 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -273,189 +273,142 @@ describe('DeleteUser', () => { } } ` - beforeEach(async () => { - variables = { id: ' u343', resource: [] } + describe('as another user', () => { + beforeEach(async () => { + variables = { id: ' u343', resource: [] } - user = await Factory.build('user', { - name: 'My name should be deleted', - about: 'along with my about', - id: 'u343', + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', + }) }) - await Factory.build( - 'user', - { - id: 'not-my-account', - }, - { - email: 'friends-account@example.org', - }, - ) - }) - describe('unauthenticated', () => { - it('throws authorization error', async () => { + beforeEach(async () => { + const anotherUser = await Factory.build( + 'user', + { + role: 'user', + }, + { + email: 'user@example.org', + password: '1234', + }, + ) + + authenticatedUser = await anotherUser.toJson() + }) + + it("an ordinary user has no authorization to delete another user's account", async () => { const { errors } = await mutate({ mutation: deleteUserMutation, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('authenticated', () => { + describe('as moderator', () => { beforeEach(async () => { - authenticatedUser = await user.toJson() - }) + variables = { id: ' u343', resource: [] } - describe("attempting to delete another user's account", () => { - beforeEach(() => { - variables = { ...variables, id: 'not-my-account' } - }) - - it('throws an authorization error', async () => { - const { errors } = await mutate({ mutation: deleteUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', }) }) - describe('attempting to delete my own account', () => { - beforeEach(() => { - variables = { ...variables, id: 'u343' } + beforeEach(async () => { + const moderator = await Factory.build( + 'user', + { + role: 'moderator', + }, + { + email: 'moderator@example.org', + password: '1234', + }, + ) + + authenticatedUser = await moderator.toJson() + }) + + it('moderator is not allowed to delete other user accounts', async () => { + const { errors } = await mutate({ mutation: deleteUserMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('as admin', () => { + beforeEach(async () => { + variables = { id: ' u343', resource: [] } + + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', + }) + }) + + describe('authenticated as Admin', () => { + beforeEach(async () => { + const admin = await Factory.build( + 'user', + { + role: 'admin', + }, + { + email: 'admin@example.org', + password: '1234', + }, + ) + authenticatedUser = await admin.toJson() }) - describe('given posts and comments', () => { - beforeEach(async () => { - await Factory.build('category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', - }) - await Factory.build( - 'post', - { - id: 'p139', - content: 'Post by user u343', - }, - { - author: user, - categoryIds, - }, - ) - await Factory.build( - 'comment', - { - id: 'c155', - content: 'Comment by user u343', - }, - { - author: user, - }, - ) - await Factory.build( - 'comment', - { - id: 'c156', - content: "A comment by someone else on user u343's post", - }, - { - postId: 'p139', - }, - ) + describe('deleting a user account', () => { + beforeEach(() => { + variables = { ...variables, id: 'u343' } }) - it("deletes my account, but doesn't delete posts or comments by default", async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'Post by user u343', - contentExcerpt: 'Post by user u343', - deleted: false, - comments: [ - { - id: 'c156', - content: "A comment by someone else on user u343's post", - contentExcerpt: "A comment by someone else on user u343's post", - deleted: false, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'Comment by user u343', - contentExcerpt: 'Comment by user u343', - deleted: false, - }, - ], - }, - }, - errors: undefined, - } - await expect(mutate({ mutation: deleteUserMutation, variables })).resolves.toMatchObject( - expectedResponse, - ) - }) - - describe('deletion of all post requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Post'] } - }) - - describe("marks user's posts as deleted", () => { - it('posts on request', async () => { - const expectedResponse = { - data: { - DeleteUser: { - id: 'u343', - name: 'UNAVAILABLE', - about: 'UNAVAILABLE', - deleted: true, - contributions: [ - { - id: 'p139', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - comments: [ - { - id: 'c156', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, - }, - ], - }, - ], - comments: [ - { - id: 'c155', - content: 'Comment by user u343', - contentExcerpt: 'Comment by user u343', - deleted: false, - }, - ], - }, - }, - errors: undefined, - } - await expect( - mutate({ mutation: deleteUserMutation, variables }), - ).resolves.toMatchObject(expectedResponse) + describe('given posts and comments', () => { + beforeEach(async () => { + await Factory.build('category', { + id: 'cat9', + name: 'Democracy & Politics', + icon: 'university', }) - }) - }) - - describe('deletion of all comments requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Comment'] } + await Factory.build( + 'post', + { + id: 'p139', + content: 'Post by user u343', + }, + { + author: user, + categoryIds, + }, + ) + await Factory.build( + 'comment', + { + id: 'c155', + content: 'Comment by user u343', + }, + { + author: user, + }, + ) + await Factory.build( + 'comment', + { + id: 'c156', + content: "A comment by someone else on user u343's post", + }, + { + postId: 'p139', + }, + ) }) - it('marks comments as deleted', async () => { + it("deletes account, but doesn't delete posts or comments by default", async () => { const expectedResponse = { data: { DeleteUser: { @@ -482,9 +435,9 @@ describe('DeleteUser', () => { comments: [ { id: 'c155', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, + content: 'Comment by user u343', + contentExcerpt: 'Comment by user u343', + deleted: false, }, ], }, @@ -495,14 +448,257 @@ describe('DeleteUser', () => { mutate({ mutation: deleteUserMutation, variables }), ).resolves.toMatchObject(expectedResponse) }) - }) - describe('deletion of all post and comments requested', () => { - beforeEach(() => { - variables = { ...variables, resource: ['Post', 'Comment'] } + describe('deletion of all post requested', () => { + beforeEach(() => { + variables = { ...variables, resource: ['Post'] } + }) + + describe("marks user's posts as deleted", () => { + it('on request', async () => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [ + { + id: 'p139', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + comments: [ + { + id: 'c156', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + ], + comments: [ + { + id: 'c155', + content: 'Comment by user u343', + contentExcerpt: 'Comment by user u343', + deleted: false, + }, + ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) }) - it('marks posts and comments as deleted', async () => { + describe('deletion of all comments requested', () => { + beforeEach(() => { + variables = { ...variables, resource: ['Comment'] } + }) + + it('marks comments as deleted', async () => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [ + { + id: 'p139', + content: 'Post by user u343', + contentExcerpt: 'Post by user u343', + deleted: false, + comments: [ + { + id: 'c156', + content: "A comment by someone else on user u343's post", + contentExcerpt: "A comment by someone else on user u343's post", + deleted: false, + }, + ], + }, + ], + comments: [ + { + id: 'c155', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) + + describe('deletion of all posts and comments requested', () => { + beforeEach(() => { + variables = { ...variables, resource: ['Post', 'Comment'] } + }) + + it('marks posts and comments as deleted', async () => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [ + { + id: 'p139', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + comments: [ + { + id: 'c156', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + ], + comments: [ + { + id: 'c155', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) + }) + + describe('connected `EmailAddress` nodes', () => { + it('will be removed completely', async () => { + await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) + await mutate({ mutation: deleteUserMutation, variables }) + await expect(neode.all('EmailAddress')).resolves.toHaveLength(1) + }) + }) + + describe('connected `SocialMedia` nodes', () => { + beforeEach(async () => { + const socialMedia = await Factory.build('socialMedia') + await socialMedia.relateTo(user, 'ownedBy') + }) + + it('will be removed completely', async () => { + await expect(neode.all('SocialMedia')).resolves.toHaveLength(1) + await mutate({ mutation: deleteUserMutation, variables }) + await expect(neode.all('SocialMedia')).resolves.toHaveLength(0) + }) + }) + }) + }) + }) + + describe('user deletes his own account', () => { + beforeEach(async () => { + variables = { id: 'u343', resource: [] } + + user = await Factory.build('user', { + name: 'My name should be deleted', + about: 'along with my about', + id: 'u343', + }) + await Factory.build( + 'user', + { + id: 'not-my-account', + }, + { + email: 'friends-account@example.org', + }, + ) + }) + + describe('authenticated', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + describe("attempting to delete another user's account", () => { + beforeEach(() => { + variables = { ...variables, id: 'not-my-account' } + }) + + it('throws an authorization error', async () => { + const { errors } = await mutate({ mutation: deleteUserMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('attempting to delete my own account', () => { + beforeEach(() => { + variables = { ...variables, id: 'u343' } + }) + + describe('given posts and comments', () => { + beforeEach(async () => { + await Factory.build('category', { + id: 'cat9', + name: 'Democracy & Politics', + icon: 'university', + }) + await Factory.build( + 'post', + { + id: 'p139', + content: 'Post by user u343', + }, + { + author: user, + categoryIds, + }, + ) + await Factory.build( + 'comment', + { + id: 'c155', + content: 'Comment by user u343', + }, + { + author: user, + }, + ) + await Factory.build( + 'comment', + { + id: 'c156', + content: "A comment by someone else on user u343's post", + }, + { + postId: 'p139', + }, + ) + }) + + it("deletes my account, but doesn't delete posts or comments by default", async () => { const expectedResponse = { data: { DeleteUser: { @@ -513,15 +709,15 @@ describe('DeleteUser', () => { contributions: [ { id: 'p139', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, + content: 'Post by user u343', + contentExcerpt: 'Post by user u343', + deleted: false, comments: [ { id: 'c156', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, + content: "A comment by someone else on user u343's post", + contentExcerpt: "A comment by someone else on user u343's post", + deleted: false, }, ], }, @@ -529,9 +725,9 @@ describe('DeleteUser', () => { comments: [ { id: 'c155', - content: 'UNAVAILABLE', - contentExcerpt: 'UNAVAILABLE', - deleted: true, + content: 'Comment by user u343', + contentExcerpt: 'Comment by user u343', + deleted: false, }, ], }, @@ -542,27 +738,170 @@ describe('DeleteUser', () => { mutate({ mutation: deleteUserMutation, variables }), ).resolves.toMatchObject(expectedResponse) }) - }) - }) - describe('connected `EmailAddress` nodes', () => { - it('will be removed completely', async () => { - await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('EmailAddress')).resolves.toHaveLength(1) - }) - }) + describe('deletion of all post requested', () => { + beforeEach(() => { + variables = { ...variables, resource: ['Post'] } + }) - describe('connected `SocialMedia` nodes', () => { - beforeEach(async () => { - const socialMedia = await Factory.build('socialMedia') - await socialMedia.relateTo(user, 'ownedBy') + describe("marks user's posts as deleted", () => { + it('posts on request', async () => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [ + { + id: 'p139', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + comments: [ + { + id: 'c156', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + ], + comments: [ + { + id: 'c155', + content: 'Comment by user u343', + contentExcerpt: 'Comment by user u343', + deleted: false, + }, + ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) + }) + + describe('deletion of all comments requested', () => { + beforeEach(() => { + variables = { ...variables, resource: ['Comment'] } + }) + + it('marks comments as deleted', async () => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [ + { + id: 'p139', + content: 'Post by user u343', + contentExcerpt: 'Post by user u343', + deleted: false, + comments: [ + { + id: 'c156', + content: "A comment by someone else on user u343's post", + contentExcerpt: "A comment by someone else on user u343's post", + deleted: false, + }, + ], + }, + ], + comments: [ + { + id: 'c155', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) + + describe('deletion of all post and comments requested', () => { + beforeEach(() => { + variables = { ...variables, resource: ['Post', 'Comment'] } + }) + + it('marks posts and comments as deleted', async () => { + const expectedResponse = { + data: { + DeleteUser: { + id: 'u343', + name: 'UNAVAILABLE', + about: 'UNAVAILABLE', + deleted: true, + contributions: [ + { + id: 'p139', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + comments: [ + { + id: 'c156', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + ], + comments: [ + { + id: 'c155', + content: 'UNAVAILABLE', + contentExcerpt: 'UNAVAILABLE', + deleted: true, + }, + ], + }, + }, + errors: undefined, + } + await expect( + mutate({ mutation: deleteUserMutation, variables }), + ).resolves.toMatchObject(expectedResponse) + }) + }) }) - it('will be removed completely', async () => { - await expect(neode.all('SocialMedia')).resolves.toHaveLength(1) - await mutate({ mutation: deleteUserMutation, variables }) - await expect(neode.all('SocialMedia')).resolves.toHaveLength(0) + describe('connected `EmailAddress` nodes', () => { + it('will be removed completely', async () => { + await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) + await mutate({ mutation: deleteUserMutation, variables }) + await expect(neode.all('EmailAddress')).resolves.toHaveLength(1) + }) + }) + + describe('connected `SocialMedia` nodes', () => { + beforeEach(async () => { + const socialMedia = await Factory.build('socialMedia') + await socialMedia.relateTo(user, 'ownedBy') + }) + + it('will be removed completely', async () => { + await expect(neode.all('SocialMedia')).resolves.toHaveLength(1) + await mutate({ mutation: deleteUserMutation, variables }) + await expect(neode.all('SocialMedia')).resolves.toHaveLength(0) + }) }) }) }) diff --git a/backend/yarn.lock b/backend/yarn.lock index d9ae7c5c6..3abbd461d 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -795,14 +795,14 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.5.5": +"@babel/runtime@^7.5.5": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.2.tgz#c3d6e41b304ef10dcf13777a33e7694ec4a9a6dd" integrity sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg== dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.8.4": +"@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d" integrity sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg== @@ -1162,7 +1162,7 @@ url-regex "~4.1.1" video-extensions "~1.1.0" -"@metascraper/helpers@^5.11.1", "@metascraper/helpers@^5.11.6": +"@metascraper/helpers@^5.11.6": version "5.11.6" resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.11.6.tgz#2fef2f420f06f4f8903cc6f699ccb79195950a60" integrity sha512-DKCJMz5Q4wrBPZVfJdeNarmW2WHm3Y7D6M78KKA/D0mcXPikKLoiBxjyPtjc5tEE/5er+PYFijDBmyTT60M2bg== @@ -1262,83 +1262,83 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@sentry/apm@5.13.1": - version "5.13.1" - resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.13.1.tgz#152a7a54b06f344112477cb376e8554860a6af86" - integrity sha512-be6M8/TOA/K7jQNZEm1YC0Y9+LdM0jyX5LMwy9NWwhneE6Iq8xvsU/pYZByj6+AAs0tIpiFd9QFxFKNUtKIRUQ== +"@sentry/apm@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.14.1.tgz#99605c4cf933962aeda4a1b03e99256213e51d7d" + integrity sha512-vm5Ee0VPAZ5TmO3iKwLFwTAtDj0ZVJvawJCfBjUe5sn58GL60XapN5AsXICdsh4fbgtNJVZEtsawcL2JNVJvuQ== dependencies: - "@sentry/browser" "5.13.0" - "@sentry/hub" "5.13.0" - "@sentry/minimal" "5.13.0" - "@sentry/types" "5.12.4" - "@sentry/utils" "5.13.0" + "@sentry/browser" "5.14.1" + "@sentry/hub" "5.14.1" + "@sentry/minimal" "5.14.1" + "@sentry/types" "5.14.1" + "@sentry/utils" "5.14.1" tslib "^1.9.3" -"@sentry/browser@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.13.0.tgz#399b0a09d6603726d787b746bcc70659010bc50c" - integrity sha512-adiW9gG/gCrl6FQAA6Fk8osXMHxP3pYltszRK0mr55O7GcTC8RQNI3mEW/YuQV9IySUL8dFWQ0v8n0lfssHf/A== +"@sentry/browser@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.14.1.tgz#ccd806d77b4eff1ae6ca1ec3a0839b9bbb5dd241" + integrity sha512-PiadrPcsPcCjHrfT8nxzVFi0WiekLYh2unGnkSFoIvS8dGv+fjIX0gqYPy7UHhCZZUsLCCiuWpoaSDWymkZGTA== dependencies: - "@sentry/core" "5.13.0" - "@sentry/types" "5.12.4" - "@sentry/utils" "5.13.0" + "@sentry/core" "5.14.1" + "@sentry/types" "5.14.1" + "@sentry/utils" "5.14.1" tslib "^1.9.3" -"@sentry/core@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.13.0.tgz#144beb2d48b53244774a7fd809f9b5b672920971" - integrity sha512-e0olbaHBmANO1RIBc7xynSkBZ6BsK7drycz0TawLUnx+0H3aEau3K9U2QVdbjwLNPdydcIS+UgYfTBtXfe0E+A== +"@sentry/core@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.14.1.tgz#21a7c14ca08b0f228023f9c6f399db1e35cd6438" + integrity sha512-UPwnS7P4xdjlC60ybzKZ/o1kYkVCublD0OUW9JfLJpIyiu3QEA3QUHjbambzvU47WHOSy9b4RYtQll44WMtdaw== dependencies: - "@sentry/hub" "5.13.0" - "@sentry/minimal" "5.13.0" - "@sentry/types" "5.12.4" - "@sentry/utils" "5.13.0" + "@sentry/hub" "5.14.1" + "@sentry/minimal" "5.14.1" + "@sentry/types" "5.14.1" + "@sentry/utils" "5.14.1" tslib "^1.9.3" -"@sentry/hub@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.13.0.tgz#f48e3e4e273f40316391cd6190e22ea69cb20c7e" - integrity sha512-MeytooJ5g91zxq4/LU1LHj7KxpggAEn1dybEsWG31QVy67J4a40zIGfYgGGIVAFSv0WVlk5Ei5C159LhgW59/w== +"@sentry/hub@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.14.1.tgz#1a4515558705b2680a6e9f3cb8092555ed31324a" + integrity sha512-FTqeLcOWbww18WRQ8F3Z0DryQwD5DeuapXlinez7Y+HDZZAOm7HdPDEY5xjrUzi4V0n9BtgfJDp27UKJENWtYA== dependencies: - "@sentry/types" "5.12.4" - "@sentry/utils" "5.13.0" + "@sentry/types" "5.14.1" + "@sentry/utils" "5.14.1" tslib "^1.9.3" -"@sentry/minimal@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.13.0.tgz#ee906191e3c2a1f7d0925fbfa0a4e96261013764" - integrity sha512-6D2Mu4TrmJmGlvb+z1Pp6yI2fUmdY1RvwK0MqmBP+QJdrd0as7cpGuwFSXgUs6CLUflDzlpn3n6WcgGV8oEDYA== +"@sentry/minimal@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.14.1.tgz#3ec74503cd72772de56188f010a35d9bc956dc94" + integrity sha512-TC+i37rGBomu74xcSdPA4xeqSeWEvTHP5dx+LIJunntk4/mDi5/aC3HSMxRy3ifoJiUwZO+gyJJ7I/UMzvOMEw== dependencies: - "@sentry/hub" "5.13.0" - "@sentry/types" "5.12.4" + "@sentry/hub" "5.14.1" + "@sentry/types" "5.14.1" tslib "^1.9.3" -"@sentry/node@^5.13.1": - version "5.13.1" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.13.1.tgz#41d2eec02bc718a0f5aa59698635242d585470f2" - integrity sha512-6/HaewN2kX0za3LncYwp6nlvm/6i0S0/D/HO7VDHMSpc8z/8/Em6xTZy7hLV3phosMoLIa5P3CRXvLVybBTrpg== +"@sentry/node@^5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.14.1.tgz#ebac38bd5036d7feefa0b44569e731b59441ce27" + integrity sha512-bkOp6RRynt0C8J2yRF6RII9/dn03WFo5Yk/di7753VW1CUgjUOjtozirs0PYewlfXfaVHveixjN61Mcy4XwJ+g== dependencies: - "@sentry/apm" "5.13.1" - "@sentry/core" "5.13.0" - "@sentry/hub" "5.13.0" - "@sentry/types" "5.12.4" - "@sentry/utils" "5.13.0" + "@sentry/apm" "5.14.1" + "@sentry/core" "5.14.1" + "@sentry/hub" "5.14.1" + "@sentry/types" "5.14.1" + "@sentry/utils" "5.14.1" cookie "^0.3.1" https-proxy-agent "^4.0.0" lru_map "^0.3.3" tslib "^1.9.3" -"@sentry/types@5.12.4": - version "5.12.4" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.12.4.tgz#6e52639bc3b4e136e9a0da5385890f8f78bb7697" - integrity sha512-JoN3YIp7Z+uxUZArj2B6NcEoXFQDhd0kqO0QpfiHZyg4Dhx2/E2aHuVx0H6Fndk+60iEZSECaCBXe2MOPo4fqA== +"@sentry/types@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.14.1.tgz#564f9b703c06c2a97e756f60a3c873b977b2bbd2" + integrity sha512-Eht+qI68BxELKQRnaV6q1PxS9/E+YatUHjG80ov9/azLbIJElQhWUDzyyJCefDD/fEI37VQ2SrsQsVqS9W7ZOQ== -"@sentry/utils@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.13.0.tgz#6463e53b6178dbbd3b90e671517cbca82744b055" - integrity sha512-BcmNQN+IfFbVWGnEwXHku69zqJc97sjBRYVxpStKMaO/4aLVIQcOJCMWxVJtVoSVAHQaigBZmFutWH7EJMRJxg== +"@sentry/utils@5.14.1": + version "5.14.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.14.1.tgz#577a9dd7b5f4b3436e8e2847d058547eab2ed5c4" + integrity sha512-iCN5p+ArPVMkt09bRfYuldtKSTQEqRfNuoCxPFJKDfMyLO9YetIwRCwHluIRoJoEIFE4JTM2F4HfmTsxoTqw4g== dependencies: - "@sentry/types" "5.12.4" + "@sentry/types" "5.14.1" tslib "^1.9.3" "@sindresorhus/is@^0.14.0": @@ -2979,10 +2979,10 @@ create-error-class@^3.0.0: dependencies: capture-stack-trace "^1.0.0" -cross-env@~7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.1.tgz#c8e03412ea0e1370fe3f0066929a70b8e1e90c39" - integrity sha512-1+DmLosu38kC4s1H4HzNkcolwdANifu9+5bE6uKQCV4L6jvVdV9qdRAk8vV3GoWRe0x4z+K2fFhgoDMqwNsPqQ== +cross-env@~7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.2.tgz#bd5ed31339a93a3418ac4f3ca9ca3403082ae5f9" + integrity sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw== dependencies: cross-spawn "^7.0.1" @@ -3664,10 +3664,10 @@ eslint-plugin-import@~2.20.1: read-pkg-up "^2.0.0" resolve "^1.12.0" -eslint-plugin-jest@~23.8.1: - version "23.8.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.1.tgz#247025e8a51b3a25a4cc41166369b0bfb4db83b7" - integrity sha512-OycLNqPo/2EfO6kTqnmsu1khz1gTIOxGl3ThIVwL5/oycDF4pm5uNDyvFelNLdpr4COUuM8PVi3963NEG1Efpw== +eslint-plugin-jest@~23.8.2: + version "23.8.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz#6f28b41c67ef635f803ebd9e168f6b73858eb8d4" + integrity sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg== dependencies: "@typescript-eslint/experimental-utils" "^2.5.0" @@ -4155,10 +4155,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== -fn-name@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" - integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= +fn-name@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c" + integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA== for-in@^1.0.2: version "1.0.2" @@ -4505,14 +4505,14 @@ graphql-redis-subscriptions@^2.2.1: optionalDependencies: ioredis "^4.6.3" -graphql-shield@~7.0.14: - version "7.0.14" - resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.0.14.tgz#3cbbf2722f2e3393fed7f47d866a1324bc3ce76a" - integrity sha512-YVedaL+4pITisSGRqMVeGX8ydOLSTQlHQN6o0Jly7z2cSy1wOzGJIRpfofETJtGLhBnPHHy1otINzuAyjGJO/g== +graphql-shield@~7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.2.0.tgz#81b26794370608ad78dfe3833473789fb471fbd8" + integrity sha512-eLdD+gUIKYu77XRcuHs5ewZhiBuRFeWFGxPnJa+g9AkxB7Yi5RSEjEJEx0Drg9GuNvDYpHeW7nPff4v35AT2aQ== dependencies: "@types/yup" "0.26.32" object-hash "^2.0.3" - yup "^0.28.1" + yup "^0.28.3" graphql-subscriptions@^1.0.0: version "1.1.0" @@ -6064,7 +6064,7 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= -lodash.mergewith@^4.6.1: +lodash.mergewith@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== @@ -6223,12 +6223,12 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== -metascraper-audio@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.11.1.tgz#46a45fc8d9c4ccc1c24340d46a8c25dc3685d7b9" - integrity sha512-L5eGfw5cOww4/f3ppMa/k+bix3LdICKcKJ2WVTLgz1QkKTWt5IQrgdW+kRfwUdaUTH6w0Tco+nOO7yUCaWytAQ== +metascraper-audio@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.11.6.tgz#392b4b84309ac017bce4b4d0d52948f3a17d7ecc" + integrity sha512-X1nEPP+bgTUStXmWuy/s/h5dix2Smuphx8VdH47/uqXRkifGByQ4nHt9Rd+rg3BNOI15bCib/Nc56awtUOG+3Q== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" metascraper-author@^5.11.6: version "5.11.6" @@ -6245,26 +6245,26 @@ metascraper-clearbit-logo@^5.3.0: dependencies: got "~9.6.0" -metascraper-date@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-date/-/metascraper-date-5.11.1.tgz#30aee414aca075fb671069abc3423b39e5972af3" - integrity sha512-lIvUPFaLkW0A7LTuoaaz3sVxk7SYvt8+sDWGxiRAOiN2nJJJkg2H7xN6SFDiFafBFjipeOglveGAhe8Ktc//qg== +metascraper-date@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-date/-/metascraper-date-5.11.6.tgz#81e3bbf6dbdca5b0cc315631ccc6011ac31a758a" + integrity sha512-3AZBTrnb6krZ6z1jcwl3K9H3/hkpRD3O59YEA079GEpyiQE97tPGh3afncYBwahrMfBnT+znebTpfGP0gL+Ueg== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" -metascraper-description@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-description/-/metascraper-description-5.11.1.tgz#55a90f165e73dae9289fb922e5269f902cc57d6b" - integrity sha512-xClk2kxYYeAY5yHgrUXQXiSz8I6qa3JNPietWIk4dtUQ+DxHyUOBo6B6pQmlbfX/BjCLh35m0srAqzZ7+r1s2g== +metascraper-description@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-description/-/metascraper-description-5.11.6.tgz#515368b5ca88cb5fa1fd92c0946458795b03960f" + integrity sha512-rGD6hEWLHPlZ/091htCoFAJGft2oRDAaAoDcnafMdTBcuukBIpZ3QNOR3rYpliWHbpS8cwiX2Q9IawyqB4iK0g== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" -metascraper-image@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-image/-/metascraper-image-5.11.1.tgz#e63e9ff045441783f9aa8c684e04927cac289e44" - integrity sha512-Nz2ZTecj2V0KgK2QE390dOSedppaG2PtUBrTz/oaFLMZEReBtMVrcygYm9VuuTpa6XwkubvuBaouCRah12zdfg== +metascraper-image@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-image/-/metascraper-image-5.11.6.tgz#94ce5cab960ab82d319b9b3034b24084de066297" + integrity sha512-2GB16BhWc2ZX7fK4z8mYmRNxwHZmnHcsb0cjJisJm6lxVexW1mvstqXKxiNCv+yoDtssnXaE7psBsHRP8hAR1Q== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" metascraper-lang-detector@^4.10.2: version "4.10.2" @@ -6275,12 +6275,12 @@ metascraper-lang-detector@^4.10.2: franc "~4.0.0" iso-639-3 "~1.1.0" -metascraper-lang@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-lang/-/metascraper-lang-5.11.1.tgz#494d080f30c76bfe2d10ce2c50a55f64bd534e1d" - integrity sha512-g0XjUFbaMwKa5ws09/gJj5WOM6FsB2v0P9gWLIj2bYo9+QXXGZqn9MusYXGMHiCNELkesPyFXQY8oTjJ7z2hMA== +metascraper-lang@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-lang/-/metascraper-lang-5.11.6.tgz#bf8b38c220c472bf46fb1adb78e36b4d2a223cfe" + integrity sha512-gIHrmR6YE1+W2FUmYMggiD8NU7oCuQUYG8fYE0zKxdoAseM2qQcmZ+aGgYAFL4RlgMQwm+9zxhcLX+Te4oMRDw== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" metascraper-logo@^5.11.6: version "5.11.6" @@ -6289,27 +6289,27 @@ metascraper-logo@^5.11.6: dependencies: "@metascraper/helpers" "^5.11.6" -metascraper-publisher@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-publisher/-/metascraper-publisher-5.11.1.tgz#997ffca0efb27f616cbab1c065bf5912037f1980" - integrity sha512-NaZQtdwDT6s5eZyD7p+L/9JcEBMH6bqrKOzJEChGK+cz0ZCdrj1az4lecB9T9FeQsD6PD1h40K0xuTYgn81Iuw== +metascraper-publisher@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-publisher/-/metascraper-publisher-5.11.6.tgz#60b4e6f9d130ee754df5ab07301e57ad6617ef21" + integrity sha512-kXV5pVu4a9gCCpiP878mr3IiBRbgFnoSbpTM1mMOQDuOnb7QQjvXQ72IYd77znN3wAh1heGm8BxQm49PLEATLg== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" -metascraper-soundcloud@^5.11.5: - version "5.11.5" - resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.11.5.tgz#989665c8d4177e0b687e12de3d951b79d69704bc" - integrity sha512-SbDtLkp/Uyg+gykNdmF+6Hy15TbNBnBWuVbRk99x+9XDoLbsK98kp1pJm0lU//RlRJAPfeWXPyMjhBMbDbeE/A== +metascraper-soundcloud@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.11.6.tgz#01699553a37d5e02f73cd5b15792986f761e94e9" + integrity sha512-KR/KNK5pWthgwuixqyfL13uSwr+mUanzhC6LEYSL7kHYTtYl0mwG7P64Ab+OdloLMwRkekITK6EaD3T8Omj2tw== dependencies: - "@metascraper/helpers" "^5.11.1" - tldts "~5.6.9" + "@metascraper/helpers" "^5.11.6" + tldts "~5.6.10" -metascraper-title@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-title/-/metascraper-title-5.11.1.tgz#fb32da17e71b2c64dc45d12c3602ca9330ab4bd5" - integrity sha512-fZ8qjf+d5ntwz/75X2r3BYD8X+tioZS1s+k9G3gfc+6ByJvrL9/ey6YzlDlU4zYqX73Vdx7+zUyy2ct0aJqWFA== +metascraper-title@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-title/-/metascraper-title-5.11.6.tgz#286d6b0e4a9ee51c54524ea441be50629d4e91f3" + integrity sha512-oIVEo+erZZ1s/3E4VGh1Dk9AGeunHQaR0bslkBT3OuwO0hqf94n5pA0fMmbhmv/Pdon+ZTTL6JV+uEYQnV6EKw== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" lodash "~4.17.15" metascraper-url@^5.11.6: @@ -6319,12 +6319,12 @@ metascraper-url@^5.11.6: dependencies: "@metascraper/helpers" "^5.11.6" -metascraper-video@^5.11.1: - version "5.11.1" - resolved "https://registry.yarnpkg.com/metascraper-video/-/metascraper-video-5.11.1.tgz#4018a635d816f3123c7ba97fe7669e4d61af2196" - integrity sha512-g8x6R4ntX7pt7ntuRCzL1+xIRd0JFAp/LoVPYFvdwn/D78u9GMJi+JvrNuLIEcrmtb6re6rE9MIOy8qMo1g3qA== +metascraper-video@^5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/metascraper-video/-/metascraper-video-5.11.6.tgz#da8a2f81f07891391b1245346750a5450a3ae8c6" + integrity sha512-jxcLqSTvkPku1OMz/x8epDs6mnN3/IgBbcffC2TIzM7yJxcHpzxOGfVcUZ4igwKlz70lk8P8V5gIHMYAFDNdrQ== dependencies: - "@metascraper/helpers" "^5.11.1" + "@metascraper/helpers" "^5.11.6" lodash "~4.17.15" metascraper-youtube@^5.11.6: @@ -6691,10 +6691,10 @@ nodemailer-html-to-text@^3.1.0: dependencies: html-to-text "^5.1.1" -nodemailer@^6.4.4: - version "6.4.4" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.4.tgz#f4bb26a833786e8908b3ac8afbf2d0382ac24feb" - integrity sha512-2GqGu5o3FBmDibczU3+LZh9lCEiKmNx7LvHl512p8Kj+Kn5FQVOICZv85MDFz/erK0BDd5EJp3nqQLpWCZD1Gg== +nodemailer@^6.4.5: + version "6.4.5" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.5.tgz#45614c6454d1a947242105eeddae03df87e29916" + integrity sha512-NH7aNVQyZLAvGr2+EOto7znvz+qJ02Cb/xpou98ApUt5tEAUSVUxhvHvgV/8I5dhjKTYqUw0nasoKzLNBJKrDQ== nodemon@~2.0.2: version "2.0.2" @@ -7367,10 +7367,10 @@ prop-types@^15.6.2: object-assign "^4.1.1" react-is "^16.8.1" -property-expr@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" - integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== +property-expr@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.2.tgz#fff2a43919135553a3bc2fdd94bdb841965b2330" + integrity sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g== proxy-addr@~2.0.5: version "2.0.5" @@ -7895,10 +7895,10 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sanitize-html@~1.22.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.22.0.tgz#9df779c53cf5755adb2322943c21c1c1dffca7bf" - integrity sha512-3RPo65mbTKpOAdAYWU496MSty1YbB3Y5bjwL5OclgaSSMtv65xvM7RW/EHRumzaZ1UddEJowCbSdK0xl5sAu0A== +sanitize-html@~1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.22.1.tgz#5b36c92ab27917ddd2775396815c2bc1a6268310" + integrity sha512-++IMC00KfMQc45UWZJlhWOlS9eMrME38sFG9GXfR+k6oBo9JXSYQgTOZCl9j3v/smFTRNT9XNwz5DseFdMY+2Q== dependencies: chalk "^2.4.1" htmlparser2 "^4.1.0" @@ -7906,7 +7906,7 @@ sanitize-html@~1.22.0: lodash.escaperegexp "^4.1.2" lodash.isplainobject "^4.0.6" lodash.isstring "^4.0.1" - lodash.mergewith "^4.6.1" + lodash.mergewith "^4.6.2" postcss "^7.0.27" srcset "^2.0.1" xtend "^4.0.1" @@ -8548,10 +8548,10 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -synchronous-promise@^2.0.6: - version "2.0.9" - resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.9.tgz#b83db98e9e7ae826bf9c8261fd8ac859126c780a" - integrity sha512-LO95GIW16x69LuND1nuuwM4pjgFGupg7pZ/4lU86AmchPKrhk0o2tpMU2unXRrqo81iAFe1YJ0nAGEVwsrZAgg== +synchronous-promise@^2.0.10: + version "2.0.10" + resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.10.tgz#e64c6fd3afd25f423963353043f4a68ebd397fd8" + integrity sha512-6PC+JRGmNjiG3kJ56ZMNWDPL8hjyghF5cMXIFOKg+NiwwEZZIvxTWd0pinWKyD227odg9ygF8xVhhz7gb8Uq7A== table@^5.2.3: version "5.4.6" @@ -8667,17 +8667,17 @@ tlds@^1.187.0, tlds@^1.203.0: resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.203.1.tgz#4dc9b02f53de3315bc98b80665e13de3edfc1dfc" integrity sha512-7MUlYyGJ6rSitEZ3r1Q1QNV8uSIzapS8SmmhSusBuIc7uIxPPwsKllEP0GRp1NS6Ik6F+fRZvnjDWm3ecv2hDw== -tldts-core@^5.6.9: - version "5.6.9" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-5.6.9.tgz#70e9b1d944b3b93008e0b31ffd8d1de6ce690bc9" - integrity sha512-MOvSUUxUyNmNK7R7cJKBvWys1rufuobWpPaVcGJd8EEsIyJzSVOlA5Y9l9V1Z0FdzlPMBAYPcpKuoQkvH7pfRg== +tldts-core@^5.6.10: + version "5.6.10" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-5.6.10.tgz#509a93c2bfd79da5a456f06ef099a19fa00bc2c9" + integrity sha512-bbz6I/200adIZgrUcnCD2RiOWkOeyDSuRSyueYN6XFs/Jwoser30nQwEqFaXeKCRsUl4IobnOGWbvUC5ihcxCA== -tldts@~5.6.9: - version "5.6.9" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-5.6.9.tgz#6fb3a10161aae568b1a862e4c96101a79adb557f" - integrity sha512-Dt5c+gD6tC3hvcUZEI/yMvru1gbnFzx95s7Di+GWZUrfEjI6vQg+vthje2Apduv9RHXXPEr5BLA51OsAwPvhWQ== +tldts@~5.6.10: + version "5.6.10" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-5.6.10.tgz#b9a07d7ed14c7a2b7bcf48ac1f6908d5b06d28e1" + integrity sha512-YM/3+cMeulrAqGQE8EhU7Ugmw5PAqTUJJq51XTVzsh0S9VxEwFZRkJSn7B4OY/tgQIMu8GXzPMd9fIoiOxsRYA== dependencies: - tldts-core "^5.6.9" + tldts-core "^5.6.10" tmp@^0.0.33: version "0.0.33" @@ -9076,10 +9076,10 @@ uuid@^3.1.0, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@~7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.1.tgz#95ed6ff3d8c881cbf85f0f05cc3915ef994818ef" - integrity sha512-yqjRXZzSJm9Dbl84H2VDHpM3zMjzSJQ+hn6C4zqd5ilW+7P4ZmLEEqwho9LjP+tGuZlF4xrHQXT0h9QZUS/pWA== +uuid@~7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.2.tgz#7ff5c203467e91f5e0d85cfcbaaf7d2ebbca9be6" + integrity sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw== v8-compile-cache@^2.0.3: version "2.1.0" @@ -9385,17 +9385,17 @@ yargs@^15.0.0: y18n "^4.0.0" yargs-parser "^16.1.0" -yup@^0.28.1: - version "0.28.1" - resolved "https://registry.yarnpkg.com/yup/-/yup-0.28.1.tgz#60c0725be7057ed7a9ae61561333809332a63d47" - integrity sha512-xSHMZA7UyecSG/CCTDCtnYZMjBrYDR/C7hu0fMsZ6UcS/ngko4qCVFbw+CAmNtHlbItKkvQ3YXITODeTj/dUkw== +yup@^0.28.3: + version "0.28.3" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.28.3.tgz#1ca607405a8adf24a5ac51f54bd09d527555f0ba" + integrity sha512-amVkCgFWe5bGjrrUiODkbIzrSwtB8JpZrQYSrfj2YsbRdrV+tn9LquWdZDlfOx2HXyfEA8FGnlwidE/bFDxO7Q== dependencies: - "@babel/runtime" "^7.0.0" - fn-name "~2.0.1" - lodash "^4.17.11" + "@babel/runtime" "^7.8.7" + fn-name "~3.0.0" + lodash "^4.17.15" lodash-es "^4.17.11" - property-expr "^1.5.0" - synchronous-promise "^2.0.6" + property-expr "^2.0.0" + synchronous-promise "^2.0.10" toposort "^2.0.2" zen-observable-ts@^0.8.20: diff --git a/cypress/integration/common/steps.js b/cypress/integration/common/steps.js index 550649524..9d0c4b03a 100644 --- a/cypress/integration/common/steps.js +++ b/cypress/integration/common/steps.js @@ -423,14 +423,13 @@ When("mention {string} in the text", mention => { .click(); }); -Then("the notification gets marked as read", () => { - cy.get(".notifications-menu-popover .notification") - .first() - .should("have.class", "--read"); +Then("the unread counter is removed", () => { + cy.get('.notifications-menu .counter-icon').should('not.exist'); }); -Then("there are no notifications in the top menu", () => { - cy.get(".notifications-menu").should("contain", "0"); +Then("the notification menu button links to the all notifications page", () => { + cy.get(".notifications-menu").click(); + cy.location("pathname").should("contain", "/notifications"); }); Given("there is an annoying user called {string}", name => { diff --git a/cypress/integration/notifications/Mentions.feature b/cypress/integration/notifications/Mentions.feature index 08eddcacd..1cf265624 100644 --- a/cypress/integration/notifications/Mentions.feature +++ b/cypress/integration/notifications/Mentions.feature @@ -24,6 +24,6 @@ Feature: Notification for a mention And see 1 unread notifications in the top menu And open the notification menu and click on the first item Then I get to the post page of ".../hey-matt" - And the notification gets marked as read - But when I refresh the page - Then there are no notifications in the top menu + And the unread counter is removed + And the notification menu button links to the all notifications page + diff --git a/package.json b/package.json index 21f87ef64..8695f5fc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "human-connection", - "version": "0.4.0", + "version": "0.4.2", "description": "Fullstack and API tests with cypress and cucumber for Human Connection", "author": "Human Connection gGmbh", "license": "MIT", @@ -34,7 +34,7 @@ "codecov": "^3.6.5", "cross-env": "^6.0.3", "cucumber": "^6.0.5", - "cypress": "^4.0.0", + "cypress": "^4.1.0", "cypress-cucumber-preprocessor": "^2.0.1", "cypress-file-upload": "^3.5.3", "cypress-plugin-retries": "^1.5.2", diff --git a/scripts/translations/sort.sh b/scripts/translations/sort.sh index 35496f27e..aa5737de8 100755 --- a/scripts/translations/sort.sh +++ b/scripts/translations/sort.sh @@ -3,6 +3,12 @@ ROOT_DIR=$(dirname "$0")/../.. tmp=$(mktemp) exit_code=0 +errors=0 + +TEXT_RED="\e[31m" +TEXT_BLUE="\e[34m" +TEXT_RESET="\e[0m" +TEXT_BOLD="\e[1m" for locale_file in $ROOT_DIR/webapp/locales/*.json do @@ -16,9 +22,13 @@ do : # all good else exit_code=$? - echo "$(basename -- $locale_file) is not sorted by keys" + echo -e "${TEXT_BOLD}${TEXT_RED}>>> $(basename -- $locale_file) is not sorted by keys <<<${TEXT_RESET}" + errors=1 fi fi done +[ "$errors" = 1 ] && echo -e "${TEXT_BOLD}${TEXT_BLUE}Please run $0 --fix to sort your locale definitions!${TEXT_RESET}"; + + exit $exit_code diff --git a/webapp/README.md b/webapp/README.md index 897bb56ca..7a9d578e1 100644 --- a/webapp/README.md +++ b/webapp/README.md @@ -72,7 +72,7 @@ You can then visit the Storybook playground on `http://localhost:3002` After starting the application following the above guidelines, open new terminal windows and navigate to the `/webapp` directory for each of these commands: ```bash -# run eslint in /webapp +# run eslint in /webapp (use option --fix to normalize the files) $ yarn lint ``` @@ -81,6 +81,11 @@ $ yarn lint $ yarn test ``` +```bash +# run locales in /webapp (use option --fix to sort the locales) +$ yarn locales +``` + ```bash # start storybook in /webapp $ yarn storybook diff --git a/webapp/components/Dropdown.vue b/webapp/components/Dropdown.vue index 6743529e8..be1157961 100644 --- a/webapp/components/Dropdown.vue +++ b/webapp/components/Dropdown.vue @@ -48,11 +48,23 @@ export default { if (isOpen) { this.$nextTick(() => { setTimeout(() => { - document.getElementsByTagName('body')[0].classList.add('dropdown-open') + const paddingRightStyle = `${window.innerWidth - + document.documentElement.clientWidth}px` + const navigationElement = document.querySelector('.main-navigation') + document.body.style.paddingRight = paddingRightStyle + document.body.classList.add('dropdown-open') + if (navigationElement) { + navigationElement.style.paddingRight = paddingRightStyle + } }, 20) }) } else { - document.getElementsByTagName('body')[0].classList.remove('dropdown-open') + const navigationElement = document.querySelector('.main-navigation') + document.body.style.paddingRight = null + document.body.classList.remove('dropdown-open') + if (navigationElement) { + navigationElement.style.paddingRight = null + } } } catch (err) {} }, diff --git a/webapp/components/NotificationMenu/NotificationMenu.spec.js b/webapp/components/NotificationMenu/NotificationMenu.spec.js index 8020c8bb4..a44d7a94d 100644 --- a/webapp/components/NotificationMenu/NotificationMenu.spec.js +++ b/webapp/components/NotificationMenu/NotificationMenu.spec.js @@ -1,4 +1,4 @@ -import { config, mount } from '@vue/test-utils' +import { config, mount, RouterLinkStub } from '@vue/test-utils' import NotificationMenu from './NotificationMenu' const localVue = global.localVue @@ -11,6 +11,7 @@ describe('NotificationMenu.vue', () => { let wrapper let mocks let data + let stubs beforeEach(() => { mocks = { $t: jest.fn(), @@ -20,6 +21,9 @@ describe('NotificationMenu.vue', () => { notifications: [], } } + stubs = { + NuxtLink: RouterLinkStub, + } }) describe('mount', () => { @@ -28,12 +32,14 @@ describe('NotificationMenu.vue', () => { data, mocks, localVue, + stubs, }) } - it('counter displays 0', () => { + it('renders as link without counter', () => { wrapper = Wrapper() - expect(wrapper.find('.count').text()).toEqual('0') + expect(wrapper.is('a.notifications-menu')).toBe(true) + expect(() => wrapper.get('.count')).toThrow() }) it('no dropdown is rendered', () => { @@ -41,7 +47,7 @@ describe('NotificationMenu.vue', () => { expect(wrapper.contains('.dropdown')).toBe(false) }) - describe('given only unread notifications', () => { + describe('given only read notifications', () => { beforeEach(() => { data = () => { return { @@ -65,14 +71,15 @@ describe('NotificationMenu.vue', () => { } }) - it('counter displays 0', () => { + it('renders as link without counter', () => { wrapper = Wrapper() - expect(wrapper.find('.count').text()).toEqual('0') + expect(wrapper.is('a.notifications-menu')).toBe(true) + expect(() => wrapper.get('.count')).toThrow() }) - it('counter is not colored', () => { + it('no dropdown is rendered', () => { wrapper = Wrapper() - expect(wrapper.find('.count').classes()).toContain('--inactive') + expect(wrapper.contains('.dropdown')).toBe(false) }) }) diff --git a/webapp/components/NotificationMenu/NotificationMenu.vue b/webapp/components/NotificationMenu/NotificationMenu.vue index d00ab2837..fb047a0c3 100644 --- a/webapp/components/NotificationMenu/NotificationMenu.vue +++ b/webapp/components/NotificationMenu/NotificationMenu.vue @@ -1,7 +1,11 @@