From d2f6590e057d94e1d2e7678069b027608efb6564 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Aug 2022 04:25:39 +0000 Subject: [PATCH 01/67] Bump vue-sweetalert-icons from 4.3.0 to 4.3.1 in /webapp Bumps [vue-sweetalert-icons](https://github.com/JorgenVatle/vue-sweetalert-icons) from 4.3.0 to 4.3.1. - [Release notes](https://github.com/JorgenVatle/vue-sweetalert-icons/releases) - [Commits](https://github.com/JorgenVatle/vue-sweetalert-icons/compare/v4.3.0...v4.3.1) --- updated-dependencies: - dependency-name: vue-sweetalert-icons dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- webapp/package.json | 2 +- webapp/yarn.lock | 325 +++----------------------------------------- 2 files changed, 21 insertions(+), 306 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index 234149521..5b6b381a0 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -99,7 +99,7 @@ "vue-izitoast": "^1.2.1", "vue-observe-visibility": "^1.0.0", "vue-scrollto": "^2.20.0", - "vue-sweetalert-icons": "~4.3.0", + "vue-sweetalert-icons": "~4.3.1", "vuex-i18n": "~1.13.1", "xregexp": "^4.3.0", "zxcvbn": "^4.4.2" diff --git a/webapp/yarn.lock b/webapp/yarn.lock index ef71a2a53..0b7dcf028 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -5538,11 +5538,6 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -6223,11 +6218,6 @@ array-filter@~0.0.0: resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -6392,11 +6382,6 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -7016,13 +7001,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - bluebird@^3.1.1, bluebird@^3.5.1: version "3.5.4" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714" @@ -7450,19 +7428,6 @@ camelcase-css@2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -7567,7 +7532,7 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3. escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -8568,14 +8533,6 @@ cross-spawn@7.0.3: shebang-command "^2.0.0" which "^2.0.1" -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -8915,13 +8872,6 @@ cuint@^0.2.2: resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -9000,7 +8950,7 @@ debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.2.6: dependencies: ms "^2.1.1" -decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.1.1, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -10805,16 +10755,6 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -fstream@^1.0.0, fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -10859,7 +10799,7 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -gaze@1.1.3, gaze@^1.0.0: +gaze@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== @@ -10911,11 +10851,6 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.1" -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" @@ -11046,7 +10981,7 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -11995,18 +11930,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - indent-string@^3.0.0, indent-string@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" @@ -12035,7 +11958,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -12359,13 +12282,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -13215,11 +13131,6 @@ jimp-compact@^0.8.0: resolved "https://registry.yarnpkg.com/jimp-compact/-/jimp-compact-0.8.4.tgz#0878a0c30f22d2d4f8b33e96722eb09d20770627" integrity sha512-9mvZ7/TJ28bWtdx0RxmfiOTzSom4zuRniFTLtJHfNL6HxQdnRtjmX8XIRjmofgVXj2TW/GgSuZKB3dSZ5hNhKg== -js-base64@^2.1.8: - version "2.5.1" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" - integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== - js-beautify@^1.6.12: version "1.10.2" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" @@ -13754,7 +13665,7 @@ loader-utils@^0.2.16: json5 "^0.5.0" object-assign "^4.0.1" -loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.0.4, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.0.2, loader-utils@^1.0.4, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -13913,7 +13824,7 @@ lodash.xorby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.xorby/-/lodash.xorby-4.7.0.tgz#9c19a6f9f063a6eb53dd03c1b6871799801463d7" integrity sha1-nBmm+fBjputT3QPBtocXmYAUY9c= -lodash@4.x, lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: +lodash@4.x, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -13958,14 +13869,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - lower-case-first@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" @@ -14102,11 +14005,6 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - map-or-similar@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" @@ -14229,22 +14127,6 @@ mensch@0.3.4: resolved "https://registry.yarnpkg.com/mensch/-/mensch-0.3.4.tgz#770f91b46cb16ea5b204ee735768c3f0c491fecd" integrity sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g== -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -14420,7 +14302,7 @@ minimist@^0.1.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4= -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: +minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= @@ -14512,7 +14394,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: version "0.5.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== @@ -14566,7 +14448,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== @@ -14685,24 +14567,6 @@ node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -14816,29 +14680,6 @@ node-res@^5.0.1: on-finished "^2.3.0" vary "^1.1.2" -node-sass@^4.12.0: - version "4.13.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.1.tgz#9db5689696bb2eec2c32b98bfea4c7a2e992d0a3" - integrity sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw== - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash "^4.17.15" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.13.2" - node-gyp "^3.8.0" - npmlog "^4.0.0" - request "^2.88.0" - sass-graph "^2.2.4" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - nodemon@^1.19.4: version "1.19.4" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.4.tgz#56db5c607408e0fdf8920d2b444819af1aae0971" @@ -14855,13 +14696,6 @@ nodemon@^1.19.4: undefsafe "^2.0.2" update-notifier "^2.5.0" -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - nopt@^4.0.1, nopt@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -14877,7 +14711,7 @@ nopt@~1.0.10: dependencies: abbrev "1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -14953,7 +14787,7 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -15273,7 +15107,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0, osenv@^0.1.4: +osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -17627,14 +17461,6 @@ recursive-readdir@2.2.2: dependencies: minimatch "3.0.4" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - redeyed@~2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b" @@ -17887,13 +17713,6 @@ repeat-string@^1.5.4, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-promise-core@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" @@ -17910,7 +17729,7 @@ request-promise-native@^1.0.5, request-promise-native@^1.0.8: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -"request@>=2.76.0 <3.0.0", request@^2.87.0, request@^2.88.0, request@^2.88.2: +"request@>=2.76.0 <3.0.0", request@^2.87.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -18062,7 +17881,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@~2.6.2: +rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -18183,27 +18002,6 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^7.0.0" - -sass-loader@^7.1.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.3.1.tgz#a5bf68a04bcea1c13ff842d747150f7ab7d0d23f" - integrity sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA== - dependencies: - clone-deep "^4.0.1" - loader-utils "^1.0.1" - neo-async "^2.5.0" - pify "^4.0.1" - semver "^6.3.0" - sass-loader@~10.1.1: version "10.1.1" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.1.1.tgz#4ddd5a3d7638e7949065dd6e9c7c04037f7e663d" @@ -18296,14 +18094,6 @@ schema-utils@^3.0.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - select@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" @@ -18345,11 +18135,6 @@ semver@^7.3.4: dependencies: lru-cache "^6.0.0" -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -18739,13 +18524,6 @@ source-map@0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= -source-map@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" - source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -18905,13 +18683,6 @@ std-env@^2.2.1: dependencies: ci-info "^1.6.0" -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -19212,13 +18983,6 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -19420,15 +19184,6 @@ tapable@^1.0.0, tapable@^1.0.0-beta.5, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== - dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" - tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" @@ -19888,11 +19643,6 @@ treeify@^1.1.0: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" @@ -19908,13 +19658,6 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" - trunc-html@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/trunc-html/-/trunc-html-1.1.2.tgz#1e97d51f67d470b67662b1a670e6d0ea7a8edafe" @@ -20878,14 +20621,12 @@ vue-svg-loader@~0.16.0: loader-utils "^1.2.3" svg-to-vue "^0.7.0" -vue-sweetalert-icons@~4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/vue-sweetalert-icons/-/vue-sweetalert-icons-4.3.0.tgz#0808632cb6bfa67bf07afab1ae683352c038af7d" - integrity sha512-8SgzgyqppIj/gQt6Y5JLXPnqt1pEq50w6TeQ1B3aVd1mWm3gHTeWHWujiycjouo8too1fgtWkn3mi16vumKSJw== +vue-sweetalert-icons@~4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/vue-sweetalert-icons/-/vue-sweetalert-icons-4.3.1.tgz#dad763abb5084b015ba3e209dd28dcf1371b030c" + integrity sha512-FqKcMB8Ebgb32UyzvhIBzj23U0NRP91cTXovDYfYwNHpJ1TAFBEHoemgyu01h2Wp+UJhytvQ+13GL+GAs8QkWw== dependencies: color "^3.1.2" - node-sass "^4.12.0" - sass-loader "^7.1.0" validate-color "^2.1.0" vue-template-compiler@^2.6.11: @@ -21228,7 +20969,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.2.9, which@^1.3.1: +which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -21515,13 +21256,6 @@ yargs-parser@^4.2.0: dependencies: camelcase "^3.0.0" -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - dependencies: - camelcase "^3.0.0" - yargs@6.6.0: version "6.6.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" @@ -21558,25 +21292,6 @@ yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" - yargs@~1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b" From dd876c52fab328eabccb1379923f2dbf6ba9891d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 15 Aug 2022 10:52:31 +0200 Subject: [PATCH 02/67] increas max-old-space-size for jest, handle some asyncs, test validation for caregories only if categories are active --- backend/package.json | 2 +- backend/src/middleware/excerptMiddleware.js | 15 ++++-------- .../src/middleware/slugifyMiddleware.spec.js | 24 +++++++++---------- backend/src/schema/resolvers/groups.js | 6 ++--- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/backend/package.json b/backend/package.json index 9651cbb95..9aa7f539f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -15,7 +15,7 @@ "dev": "nodemon --exec babel-node src/ -e js,gql", "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", "lint": "eslint src --config .eslintrc.js", - "test": "cross-env NODE_ENV=test jest --forceExit --detectOpenHandles --runInBand --coverage", + "test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --forceExit --detectOpenHandles --runInBand --coverage", "db:clean": "babel-node src/db/clean.js", "db:reset": "yarn run db:clean", "db:seed": "babel-node src/db/seed.js", diff --git a/backend/src/middleware/excerptMiddleware.js b/backend/src/middleware/excerptMiddleware.js index cfaf7f1b0..ca061609a 100644 --- a/backend/src/middleware/excerptMiddleware.js +++ b/backend/src/middleware/excerptMiddleware.js @@ -4,28 +4,23 @@ export default { Mutation: { CreateGroup: async (resolve, root, args, context, info) => { args.descriptionExcerpt = trunc(args.description, 120).html - const result = await resolve(root, args, context, info) - return result + return resolve(root, args, context, info) }, CreatePost: async (resolve, root, args, context, info) => { args.contentExcerpt = trunc(args.content, 120).html - const result = await resolve(root, args, context, info) - return result + return resolve(root, args, context, info) }, UpdatePost: async (resolve, root, args, context, info) => { args.contentExcerpt = trunc(args.content, 120).html - const result = await resolve(root, args, context, info) - return result + return resolve(root, args, context, info) }, CreateComment: async (resolve, root, args, context, info) => { args.contentExcerpt = trunc(args.content, 180).html - const result = await resolve(root, args, context, info) - return result + return resolve(root, args, context, info) }, UpdateComment: async (resolve, root, args, context, info) => { args.contentExcerpt = trunc(args.content, 180).html - const result = await resolve(root, args, context, info) - return result + return resolve(root, args, context, info) }, }, } diff --git a/backend/src/middleware/slugifyMiddleware.spec.js b/backend/src/middleware/slugifyMiddleware.spec.js index 9605aada9..3fea526ee 100644 --- a/backend/src/middleware/slugifyMiddleware.spec.js +++ b/backend/src/middleware/slugifyMiddleware.spec.js @@ -6,7 +6,6 @@ import { createGroupMutation } from '../db/graphql/groups' import { createPostMutation } from '../db/graphql/posts' import { signupVerificationMutation } from '../db/graphql/authentications' -let mutate let authenticatedUser let variables @@ -15,19 +14,20 @@ const neode = getNeode() const descriptionAdditional100 = ' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789' +const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + } + }, +}) + +const { mutate } = createTestClient(server) + beforeAll(async () => { await cleanDatabase() - - const { server } = createServer({ - context: () => { - return { - driver, - neode, - user: authenticatedUser, - } - }, - }) - mutate = createTestClient(server).mutate }) afterAll(async () => { diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index d1af98513..5737f5505 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -51,10 +51,10 @@ export default { CreateGroup: async (_parent, params, context, _resolveInfo) => { const { categoryIds } = params delete params.categoryIds - if (!categoryIds || categoryIds.length < CATEGORIES_MIN) { + if (CONFIG.CATEGORIES_ACTIVE && (!categoryIds || categoryIds.length < CATEGORIES_MIN)) { throw new UserInputError('Too view categories!') } - if (categoryIds && categoryIds.length > CATEGORIES_MAX) { + if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length > CATEGORIES_MAX) { throw new UserInputError('Too many categories!') } if ( @@ -94,7 +94,7 @@ export default { `, { userId: context.user.id, categoryIds, params }, ) - const [group] = ownerCreateGroupTransactionResponse.records.map((record) => + const [group] = await ownerCreateGroupTransactionResponse.records.map((record) => record.get('group'), ) return group From beacad4a17b33ececa908b6fe655626f1487f949 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 15 Aug 2022 11:07:45 +0200 Subject: [PATCH 03/67] set CONFIG in specs --- backend/src/schema/resolvers/groups.spec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index b3327d44a..707558a06 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -3,6 +3,7 @@ import Factory, { cleanDatabase } from '../../db/factories' import { createGroupMutation, groupQuery } from '../../db/graphql/groups' import { getNeode, getDriver } from '../../db/neo4j' import createServer from '../../server' +import CONFIG from '../../config' const driver = getDriver() const neode = getNeode() @@ -291,6 +292,10 @@ describe('CreateGroup', () => { }) describe('categories', () => { + beforeEach(() => { + CONFIG.CATEGORIES_ACTIVE = true + }) + describe('not even one', () => { it('throws error: "Too view categories!"', async () => { const { errors } = await mutate({ From 2d0ba9982bc1ce7db6d96af878aa2bd9e11a14ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 15 Aug 2022 12:17:16 +0200 Subject: [PATCH 04/67] Add '--logHeapUsage' to jest test call --- backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 62188a650..e619874af 100644 --- a/backend/package.json +++ b/backend/package.json @@ -15,7 +15,7 @@ "dev": "nodemon --exec babel-node src/ -e js,gql", "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", "lint": "eslint src --config .eslintrc.js", - "test": "cross-env NODE_ENV=test jest --forceExit --detectOpenHandles --runInBand --coverage", + "test": "cross-env NODE_ENV=test jest --forceExit --detectOpenHandles --runInBand --coverage --logHeapUsage", "db:clean": "babel-node src/db/clean.js", "db:reset": "yarn run db:clean", "db:seed": "babel-node src/db/seed.js", From 916dfbb46ed08cb7e786b9b16b723ca78c0ccf7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 15 Aug 2022 14:00:36 +0200 Subject: [PATCH 05/67] Move or use GQL mutations in seeding to or from separate files --- backend/src/db/graphql/comments.js | 15 +++++++++++++++ backend/src/db/graphql/posts.js | 5 +++-- backend/src/db/seed.js | 18 +++--------------- 3 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 backend/src/db/graphql/comments.js diff --git a/backend/src/db/graphql/comments.js b/backend/src/db/graphql/comments.js new file mode 100644 index 000000000..b408c5e95 --- /dev/null +++ b/backend/src/db/graphql/comments.js @@ -0,0 +1,15 @@ +import gql from 'graphql-tag' + +// ------ mutations + +export const createCommentMutation = gql` + mutation ($id: ID, $postId: ID!, $content: String!) { + CreateComment(id: $id, postId: $postId, content: $content) { + id + } + } +` + +// ------ queries + +// fill queries in here diff --git a/backend/src/db/graphql/posts.js b/backend/src/db/graphql/posts.js index 3277af820..237446d41 100644 --- a/backend/src/db/graphql/posts.js +++ b/backend/src/db/graphql/posts.js @@ -3,8 +3,9 @@ import gql from 'graphql-tag' // ------ mutations export const createPostMutation = gql` - mutation ($title: String!, $content: String!, $categoryIds: [ID]!, $slug: String) { - CreatePost(title: $title, content: $content, categoryIds: $categoryIds, slug: $slug) { + mutation ($id: ID, $title: String!, $slug: String, $content: String!, $categoryIds: [ID]!) { + CreatePost(id: $id, title: $title, slug: $slug, content: $content, categoryIds: $categoryIds) { + id slug } } diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 46c5870e0..0a0926f06 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -5,7 +5,9 @@ import createServer from '../server' import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' -import { gql } from '../helpers/jest' +// import { createGroupMutation } from './graphql/groups' +import { createPostMutation } from './graphql/posts' +import { createCommentMutation } from './graphql/comments' if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) { throw new Error(`You cannot seed the database in a non-staging and real production environment!`) @@ -558,13 +560,6 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] 'See #NaturphilosophieYoga, it can really help you!' const hashtagAndMention1 = 'The new physics of #QuantenFlussTheorie can explain #QuantumGravity! @peter-lustig got that already. ;-)' - const createPostMutation = gql` - mutation ($id: ID, $title: String!, $content: String!, $categoryIds: [ID]) { - CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) { - id - } - } - ` await Promise.all([ mutate({ @@ -615,13 +610,6 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] 'I heard @jenny-rostock has practiced it for 3 years now.' const mentionInComment2 = 'Did @peter-lustig tell you?' - const createCommentMutation = gql` - mutation ($id: ID, $postId: ID!, $content: String!) { - CreateComment(id: $id, postId: $postId, content: $content) { - id - } - } - ` await Promise.all([ mutate({ mutation: createCommentMutation, From 0f8abe770a1856629efefcbeacb6e6c2eb376fda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 15 Aug 2022 15:01:26 +0200 Subject: [PATCH 06/67] Move GQL mutation 'loginMutation' in 'user_management.spec.js' into a separate file --- backend/src/db/graphql/userManagement.js | 13 +++++++++++++ .../src/schema/resolvers/user_management.spec.js | 7 +------ 2 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 backend/src/db/graphql/userManagement.js diff --git a/backend/src/db/graphql/userManagement.js b/backend/src/db/graphql/userManagement.js new file mode 100644 index 000000000..3cb8a05f8 --- /dev/null +++ b/backend/src/db/graphql/userManagement.js @@ -0,0 +1,13 @@ +import gql from 'graphql-tag' + +// ------ mutations + +export const loginMutation = gql` + mutation ($email: String!, $password: String!) { + login(email: $email, password: $password) + } +` + +// ------ queries + +// fill queries in here diff --git a/backend/src/schema/resolvers/user_management.spec.js b/backend/src/schema/resolvers/user_management.spec.js index 2dcb14855..15b39e80d 100644 --- a/backend/src/schema/resolvers/user_management.spec.js +++ b/backend/src/schema/resolvers/user_management.spec.js @@ -2,6 +2,7 @@ import jwt from 'jsonwebtoken' import CONFIG from './../../config' import Factory, { cleanDatabase } from '../../db/factories' import { gql } from '../../helpers/jest' +import { loginMutation } from '../../db/graphql/userManagement' import { createTestClient } from 'apollo-server-testing' import createServer, { context } from '../../server' import encode from '../../jwt/encode' @@ -177,12 +178,6 @@ describe('currentUser', () => { }) describe('login', () => { - const loginMutation = gql` - mutation ($email: String!, $password: String!) { - login(email: $email, password: $password) - } - ` - const respondsWith = async (expected) => { await expect(mutate({ mutation: loginMutation, variables })).resolves.toMatchObject(expected) } From bbda8e6dd06bb39725d5c731041c36dd825c5d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 15 Aug 2022 15:22:49 +0200 Subject: [PATCH 07/67] Seed some groups --- backend/src/db/seed.js | 54 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 0a0926f06..64ee3c1dd 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -5,7 +5,7 @@ import createServer from '../server' import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' -// import { createGroupMutation } from './graphql/groups' +import { createGroupMutation } from './graphql/groups' import { createPostMutation } from './graphql/posts' import { createCommentMutation } from './graphql/comments' @@ -383,6 +383,58 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }), ]) + // Create Groups + + authenticatedUser = await peterLustig.toJson() + await Promise.all([ + mutate({ + mutation: createGroupMutation, + variables: { + id: 'g0', + name: 'Investigative Journalism', + about: 'Investigative journalists share ideas and insights and can collaborate.', + description: `

English:

This group is hidden.

What is our group for?

This group was created to allow investigative journalists to share and collaborate.

How does it work?

Here you can internally share posts and comments about them.


Deutsch:

Diese Gruppe ist verborgen.

Wofür ist unsere Gruppe?

Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.

Wie funktioniert das?

Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.

`, + groupType: 'hidden', + actionRadius: 'global', + categoryIds: ['cat3', 'cat13', 'cat16'], + }, + }), + ]) + + authenticatedUser = await jennyRostock.toJson() + await Promise.all([ + mutate({ + mutation: createGroupMutation, + variables: { + id: 'g1', + name: 'School For Citizens', + about: 'Our children shall receive education for life.', + description: `

English

Our goal

Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives.

Curiosity

For this we need a school that takes up the curiosity of the children, the people, and satisfies it through a lot of experience.


Deutsch

Unser Ziel

Nur wer Spaß am Lernen hat und seine Neugier nicht verliert, kann gute Bildung für's Leben erlangen und sein ganzes Leben mit Freude weiter lernen.

Neugier

Dazu benötigen wir eine Schule, die die Neugier der Kinder, der Menschen, aufnimmt und durch viel Erfahrung befriedigt.

`, + groupType: 'closed', + actionRadius: 'national', + categoryIds: ['cat3', 'cat13', 'cat16'], + }, + }), + ]) + + authenticatedUser = await bobDerBaumeister.toJson() + await Promise.all([ + mutate({ + mutation: createGroupMutation, + variables: { + id: 'g2', + name: 'Yoga Practice', + about: 'We do yoga around the clock.', + description: `

What Is yoga?

Yoga is not just about practicing asanas. It's about how we do it.

And practicing asanas doesn't have to be yoga, it can be more athletic than yogic.

What makes practicing asanas yogic?

The important thing is:

  • Use the exercises (consciously) for your personal development.

`, + groupType: 'public', + actionRadius: 'interplanetary', + categoryIds: ['cat3', 'cat13', 'cat16'], + }, + }), + ]) + + // Create Posts + const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([ Factory.build( 'post', From e2c987f3003f773dc36eb378124917f6fdbf3a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 15 Aug 2022 16:14:19 +0200 Subject: [PATCH 08/67] Refine categories of seeded groups --- backend/src/db/seed.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 64ee3c1dd..e41ef1abc 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -396,7 +396,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] description: `

English:

This group is hidden.

What is our group for?

This group was created to allow investigative journalists to share and collaborate.

How does it work?

Here you can internally share posts and comments about them.


Deutsch:

Diese Gruppe ist verborgen.

Wofür ist unsere Gruppe?

Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.

Wie funktioniert das?

Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.

`, groupType: 'hidden', actionRadius: 'global', - categoryIds: ['cat3', 'cat13', 'cat16'], + categoryIds: ['cat6', 'cat9', 'cat14'], }, }), ]) @@ -412,7 +412,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] description: `

English

Our goal

Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives.

Curiosity

For this we need a school that takes up the curiosity of the children, the people, and satisfies it through a lot of experience.


Deutsch

Unser Ziel

Nur wer Spaß am Lernen hat und seine Neugier nicht verliert, kann gute Bildung für's Leben erlangen und sein ganzes Leben mit Freude weiter lernen.

Neugier

Dazu benötigen wir eine Schule, die die Neugier der Kinder, der Menschen, aufnimmt und durch viel Erfahrung befriedigt.

`, groupType: 'closed', actionRadius: 'national', - categoryIds: ['cat3', 'cat13', 'cat16'], + categoryIds: ['cat7', 'cat9', 'cat16'], }, }), ]) From 73559242d6ec363419fd92bbf5871300f4ab8789 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Aug 2022 06:44:19 +0000 Subject: [PATCH 09/67] Bump cross-env from 7.0.2 to 7.0.3 in /webapp Bumps [cross-env](https://github.com/kentcdodds/cross-env) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/kentcdodds/cross-env/releases) - [Changelog](https://github.com/kentcdodds/cross-env/blob/master/CHANGELOG.md) - [Commits](https://github.com/kentcdodds/cross-env/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: cross-env dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- webapp/package.json | 2 +- webapp/yarn.lock | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index 234149521..deb8bfa79 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -75,7 +75,7 @@ "apollo-client": "~2.6.8", "cookie-universal-nuxt": "~2.1.5", "cropperjs": "^1.5.5", - "cross-env": "~7.0.2", + "cross-env": "~7.0.3", "date-fns": "2.22.1", "express": "~4.17.1", "graphql": "~14.7.0", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index ef71a2a53..a39404fdc 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -8544,10 +8544,10 @@ cropperjs@^1.5.5: resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.5.6.tgz#82faf432bec709d828f2f7a96d1179198edaf0e2" integrity sha512-eAgWf4j7sNJIG329qUHIFi17PSV0VtuWyAu9glZSgu/KlQSrfTQOC2zAz+jHGa5fAB+bJldEnQwvJEaJ8zRf5A== -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== +cross-env@~7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== dependencies: cross-spawn "^7.0.1" @@ -8559,7 +8559,7 @@ cross-fetch@^3.0.4: node-fetch "2.6.0" whatwg-fetch "3.0.0" -cross-spawn@7.0.3: +cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -8596,15 +8596,6 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" - integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" From 92f4b7b813db1a58acc24b2fb6043e438ad266dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 04:17:15 +0000 Subject: [PATCH 10/67] Bump slug from 5.1.0 to 6.0.0 Bumps [slug](https://github.com/Trott/slug) from 5.1.0 to 6.0.0. - [Release notes](https://github.com/Trott/slug/releases) - [Changelog](https://github.com/Trott/slug/blob/main/CHANGELOG.md) - [Commits](https://github.com/Trott/slug/compare/v5.1.0...v6.0.0) --- updated-dependencies: - dependency-name: slug dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7756ac8e6..a36063f04 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "neode": "^0.4.7", "npm-run-all": "^4.1.5", "rosie": "^2.1.0", - "slug": "^5.1.0" + "slug": "^6.0.0" }, "resolutions": { "set-value": "^2.0.1" diff --git a/yarn.lock b/yarn.lock index 4e2303801..7b1c5eb79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5426,10 +5426,10 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= -slug@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/slug/-/slug-5.1.0.tgz#8a7e30ca1c3a6dc40cf74e269750913a865edb0b" - integrity sha512-IS39jKR6m+puU8zWgH6ruwx1sfzFNJ6Ai5PKIlUqd0X8C3ca7PB49Cvm0uayqgEt1jgaojO2wWEsQJngnh7fDA== +slug@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/slug/-/slug-6.0.0.tgz#39637b32e5a873bc692812a630842880499ed6c9" + integrity sha512-0MpNLyCSUSf0G1nAZmp9gY1cvesPP35a1Live25vZ23gWQ5SAopF0N+0hk9KI4ytNuTebJrHGNrgTnxboofcSg== snapdragon-node@^2.0.1: version "2.1.1" From b7077d3b4b864734973792fb9df0d3fadd3c0cfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 04:50:20 +0000 Subject: [PATCH 11/67] Bump slug from 4.0.2 to 6.0.0 in /backend Bumps [slug](https://github.com/Trott/slug) from 4.0.2 to 6.0.0. - [Release notes](https://github.com/Trott/slug/releases) - [Changelog](https://github.com/Trott/slug/blob/main/CHANGELOG.md) - [Commits](https://github.com/Trott/slug/compare/v4.0.2...v6.0.0) --- updated-dependencies: - dependency-name: slug dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- backend/package.json | 2 +- backend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/package.json b/backend/package.json index e619874af..9c576db94 100644 --- a/backend/package.json +++ b/backend/package.json @@ -110,7 +110,7 @@ "npm-run-all": "~4.1.5", "request": "~2.88.2", "sanitize-html": "~1.22.0", - "slug": "~4.0.2", + "slug": "~6.0.0", "subscriptions-transport-ws": "^0.9.19", "trunc-html": "~1.1.2", "uuid": "~8.3.2", diff --git a/backend/yarn.lock b/backend/yarn.lock index 24bd00b3a..32eeb6b24 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -9262,10 +9262,10 @@ slug@^0.9.2: dependencies: unicode ">= 0.3.1" -slug@~4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/slug/-/slug-4.0.2.tgz#35a62b4e71582778ac08bb30a1bf439fd0a43ea7" - integrity sha512-c5XbWkwxHU13gAdSvBHQgnGy2sxv/REMz0ugcM0SOSBCO/N4wfU0TDBC3pgdOwVGjZwGnLBTRljXzdVYE+KYNw== +slug@~6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/slug/-/slug-6.0.0.tgz#39637b32e5a873bc692812a630842880499ed6c9" + integrity sha512-0MpNLyCSUSf0G1nAZmp9gY1cvesPP35a1Live25vZ23gWQ5SAopF0N+0hk9KI4ytNuTebJrHGNrgTnxboofcSg== smart-buffer@^4.1.0: version "4.1.0" From 27b74eb9e1ba5e41c43f4eea9c40db59e5cdb76e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 17 Aug 2022 12:11:52 +0200 Subject: [PATCH 12/67] Implement 'GroupMember' resolver, a first step --- .../src/middleware/permissionsMiddleware.js | 32 +++++ backend/src/schema/resolvers/groups.js | 22 ++++ backend/src/schema/resolvers/groups.spec.js | 122 ++++++++++++++++++ backend/src/schema/types/type/Group.gql | 8 ++ backend/src/schema/types/type/User.gql | 2 + 5 files changed, 186 insertions(+) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 99dcfc0cd..4c73624b0 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -52,6 +52,37 @@ const isMySocialMedia = rule({ return socialMedia.ownedBy.node.id === user.id }) +const isAllowSeeingMembersOfGroup = rule({ + cache: 'no_cache', +})(async (_parent, args, { user, driver }) => { + if (!user) return false + const { id: groupId } = args + const session = driver.session() + const readTxPromise = session.readTransaction(async (transaction) => { + const transactionResponse = await transaction.run( + ` + MATCH (group:Group {id: $groupId}) + OPTIONAL MATCH (admin {id:User $userId})-[membership:MEMBER_OF]->(group) + WHERE membership.role IN ['admin', 'owner'] + RETURN group, admin + `, + { groupId, userId: user.id }, + ) + return { + admin: transactionResponse.records.map((record) => record.get('admin')), + group: transactionResponse.records.map((record) => record.get('group')), + } + }) + try { + const [{ admin, group }] = await readTxPromise + return group.groupType === 'public' || !!admin + } catch (error) { + throw new Error(error) + } finally { + session.close() + } +}) + const isAuthor = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { @@ -115,6 +146,7 @@ export default shield( statistics: allow, currentUser: allow, Group: isAuthenticated, + GroupMember: isAllowSeeingMembersOfGroup, Post: allow, profilePagePosts: allow, Comment: allow, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 5737f5505..d27d9b5e4 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -46,6 +46,28 @@ export default { session.close() } }, + GroupMember: async (_object, params, context, _resolveInfo) => { + const { id: groupId } = params + const session = context.driver.session() + const readTxResultPromise = session.readTransaction(async (txc) => { + const groupMemberCypher = ` + MATCH (user:User {id: $userId})-[membership:MEMBER_OF]->(:Group {id: $groupId}) + RETURN user {.*, myRoleInGroup: membership.role} + ` + const result = await txc.run(groupMemberCypher, { + groupId, + userId: context.user.id, + }) + return result.records.map((record) => record.get('user')) + }) + try { + return await readTxResultPromise + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, }, Mutation: { CreateGroup: async (_parent, params, context, _resolveInfo) => { diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 707558a06..706e27748 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -207,6 +207,128 @@ describe('Group', () => { }) }) +describe('GroupMember', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await query({ query: groupQuery, variables: {} }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + let otherUser + + beforeEach(async () => { + otherUser = await Factory.build( + 'user', + { + id: 'other-user', + name: 'Other TestUser', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + authenticatedUser = await otherUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'others-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'my-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + }) + + describe('query group members', () => { + describe('by owner', () => { + it.only('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'my-group', + slug: 'the-best-group', + myRole: 'owner', + }), + // Wolle: expect.objectContaining({ + // id: 'others-group', + // slug: 'uninteresting-group', + // myRole: null, + // }), + ]), + }, + errors: undefined, + } + await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected) + }) + }) + + describe('isMember = true', () => { + it('finds only groups where user is member', async () => { + const expected = { + data: { + Group: [ + { + id: 'my-group', + slug: 'the-best-group', + myRole: 'owner', + }, + ], + }, + errors: undefined, + } + await expect( + query({ query: groupQuery, variables: { isMember: true } }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('isMember = false', () => { + it('finds only groups where user is not(!) member', async () => { + const expected = { + data: { + Group: expect.arrayContaining([ + expect.objectContaining({ + id: 'others-group', + slug: 'uninteresting-group', + myRole: null, + }), + ]), + }, + errors: undefined, + } + await expect( + query({ query: groupQuery, variables: { isMember: false } }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) +}) + describe('CreateGroup', () => { beforeEach(() => { variables = { diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index 3165b4a44..fd53d48b3 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -74,6 +74,14 @@ type Query { filter: _GroupFilter ): [Group] + GroupMember( + id: ID + first: Int + offset: Int + orderBy: [_GroupOrdering] + filter: _GroupFilter + ): [User] + AvailableGroupTypes: [GroupType]! AvailableGroupActionRadii: [GroupActionRadius]! diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index a25e51079..4219cd00e 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -114,6 +114,8 @@ type User { badgesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)") emotions: [EMOTED] + + myRoleInGroup: GroupMemberRole } From 25ed30dba168f901f4f09a6c3d03c27c2692d3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 18 Aug 2022 10:12:11 +0200 Subject: [PATCH 13/67] Implement 'EnterGroup' resolver --- backend/src/db/graphql/groups.js | 22 + .../src/middleware/permissionsMiddleware.js | 5 +- backend/src/schema/resolvers/groups.js | 34 +- backend/src/schema/resolvers/groups.spec.js | 479 +++++++++++++----- backend/src/schema/types/type/Group.gql | 12 +- 5 files changed, 423 insertions(+), 129 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index 2a611f324..b169e10fb 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -39,6 +39,17 @@ export const createGroupMutation = gql` } ` +export const enterGroupMutation = gql` + mutation ($id: ID!, $userId: ID!) { + EnterGroup(id: $id, userId: $userId) { + id + name + slug + myRoleInGroup + } + } +` + // ------ queries export const groupQuery = gql` @@ -93,3 +104,14 @@ export const groupQuery = gql` } } ` + +export const groupMemberQuery = gql` + query ($id: ID!, $first: Int, $offset: Int, $orderBy: [_UserOrdering], $filter: _UserFilter) { + GroupMember(id: $id, first: $first, offset: $offset, orderBy: $orderBy, filter: $filter) { + id + name + slug + myRoleInGroup + } + } +` diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 4c73624b0..9dcf35476 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -62,9 +62,9 @@ const isAllowSeeingMembersOfGroup = rule({ const transactionResponse = await transaction.run( ` MATCH (group:Group {id: $groupId}) - OPTIONAL MATCH (admin {id:User $userId})-[membership:MEMBER_OF]->(group) + OPTIONAL MATCH (admin:User {id: $userId})-[membership:MEMBER_OF]->(group) WHERE membership.role IN ['admin', 'owner'] - RETURN group, admin + RETURN group, admin {.*, myRoleInGroup: membership.role} `, { groupId, userId: user.id }, ) @@ -174,6 +174,7 @@ export default shield( SignupVerification: allow, UpdateUser: onlyYourself, CreateGroup: isAuthenticated, + EnterGroup: isAuthenticated, CreatePost: isAuthenticated, UpdatePost: isAuthor, DeletePost: isAuthor, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index d27d9b5e4..b64484d37 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -109,7 +109,7 @@ export default { MERGE (owner)-[:CREATED]->(group) MERGE (owner)-[membership:MEMBER_OF]->(group) SET membership.createdAt = toString(datetime()) - SET membership.updatedAt = toString(datetime()) + SET membership.updatedAt = membership.createdAt SET membership.role = 'owner' ${categoriesCypher} RETURN group {.*, myRole: membership.role} @@ -122,8 +122,7 @@ export default { return group }) try { - const group = await writeTxResultPromise - return group + return await writeTxResultPromise } catch (error) { if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed') throw new UserInputError('Group with this slug already exists!') @@ -132,6 +131,35 @@ export default { session.close() } }, + EnterGroup: async (_parent, params, context, _resolveInfo) => { + const { id: groupId, userId } = params + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const enterGroupCypher = ` + MATCH (member:User {id: $userId}), (group:Group {id: $groupId}) + MERGE (member)-[membership:MEMBER_OF]->(group) + ON CREATE SET + membership.createdAt = toString(datetime()), + membership.updatedAt = membership.createdAt, + membership.role = + CASE WHEN group.groupType = 'public' + THEN 'usual' + ELSE 'pending' + END + RETURN member {.*, myRoleInGroup: membership.role} + ` + const result = await transaction.run(enterGroupCypher, { groupId, userId }) + const [member] = await result.records.map((record) => record.get('member')) + return member + }) + try { + return await writeTxResultPromise + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, }, Group: { ...Resolver('Group', { diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 706e27748..81223a584 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -1,6 +1,11 @@ import { createTestClient } from 'apollo-server-testing' import Factory, { cleanDatabase } from '../../db/factories' -import { createGroupMutation, groupQuery } from '../../db/graphql/groups' +import { + createGroupMutation, + enterGroupMutation, + groupMemberQuery, + groupQuery, +} from '../../db/graphql/groups' import { getNeode, getDriver } from '../../db/neo4j' import createServer from '../../server' import CONFIG from '../../config' @@ -94,10 +99,6 @@ describe('Group', () => { }) describe('authenticated', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - let otherUser beforeEach(async () => { @@ -207,127 +208,127 @@ describe('Group', () => { }) }) -describe('GroupMember', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await query({ query: groupQuery, variables: {} }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) +// describe('GroupMember', () => { +// describe('unauthenticated', () => { +// it('throws authorization error', async () => { +// const { errors } = await query({ query: groupMemberQuery, variables: {} }) +// expect(errors[0]).toHaveProperty('message', 'Not Authorised!') +// }) +// }) - describe('authenticated', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) +// describe('authenticated', () => { +// beforeEach(async () => { +// authenticatedUser = await user.toJson() +// }) - let otherUser +// let otherUser - beforeEach(async () => { - otherUser = await Factory.build( - 'user', - { - id: 'other-user', - name: 'Other TestUser', - }, - { - email: 'test2@example.org', - password: '1234', - }, - ) - authenticatedUser = await otherUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'others-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'global', - categoryIds, - }, - }) - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'my-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) - }) +// beforeEach(async () => { +// otherUser = await Factory.build( +// 'user', +// { +// id: 'other-user', +// name: 'Other TestUser', +// }, +// { +// email: 'test2@example.org', +// password: '1234', +// }, +// ) +// authenticatedUser = await otherUser.toJson() +// await mutate({ +// mutation: createGroupMutation, +// variables: { +// id: 'others-group', +// name: 'Uninteresting Group', +// about: 'We will change nothing!', +// description: 'We love it like it is!?' + descriptionAdditional100, +// groupType: 'closed', +// actionRadius: 'global', +// categoryIds, +// }, +// }) +// authenticatedUser = await user.toJson() +// await mutate({ +// mutation: createGroupMutation, +// variables: { +// id: 'my-group', +// name: 'The Best Group', +// about: 'We will change the world!', +// description: 'Some description' + descriptionAdditional100, +// groupType: 'public', +// actionRadius: 'regional', +// categoryIds, +// }, +// }) +// }) - describe('query group members', () => { - describe('by owner', () => { - it.only('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'my-group', - slug: 'the-best-group', - myRole: 'owner', - }), - // Wolle: expect.objectContaining({ - // id: 'others-group', - // slug: 'uninteresting-group', - // myRole: null, - // }), - ]), - }, - errors: undefined, - } - await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected) - }) - }) +// describe('query group members', () => { +// describe('by owner', () => { +// it.only('finds all members', async () => { +// const expected = { +// data: { +// GroupMember: expect.arrayContaining([ +// expect.objectContaining({ +// id: 'my-group', +// slug: 'the-best-group', +// myRole: 'owner', +// }), +// // Wolle: expect.objectContaining({ +// // id: 'others-group', +// // slug: 'uninteresting-group', +// // myRole: null, +// // }), +// ]), +// }, +// errors: undefined, +// } +// await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected) +// }) +// }) - describe('isMember = true', () => { - it('finds only groups where user is member', async () => { - const expected = { - data: { - Group: [ - { - id: 'my-group', - slug: 'the-best-group', - myRole: 'owner', - }, - ], - }, - errors: undefined, - } - await expect( - query({ query: groupQuery, variables: { isMember: true } }), - ).resolves.toMatchObject(expected) - }) - }) +// describe('isMember = true', () => { +// it('finds only groups where user is member', async () => { +// const expected = { +// data: { +// Group: [ +// { +// id: 'my-group', +// slug: 'the-best-group', +// myRole: 'owner', +// }, +// ], +// }, +// errors: undefined, +// } +// await expect( +// query({ query: groupQuery, variables: { isMember: true } }), +// ).resolves.toMatchObject(expected) +// }) +// }) - describe('isMember = false', () => { - it('finds only groups where user is not(!) member', async () => { - const expected = { - data: { - Group: expect.arrayContaining([ - expect.objectContaining({ - id: 'others-group', - slug: 'uninteresting-group', - myRole: null, - }), - ]), - }, - errors: undefined, - } - await expect( - query({ query: groupQuery, variables: { isMember: false } }), - ).resolves.toMatchObject(expected) - }) - }) - }) - }) -}) +// describe('isMember = false', () => { +// it('finds only groups where user is not(!) member', async () => { +// const expected = { +// data: { +// Group: expect.arrayContaining([ +// expect.objectContaining({ +// id: 'others-group', +// slug: 'uninteresting-group', +// myRole: null, +// }), +// ]), +// }, +// errors: undefined, +// } +// await expect( +// query({ query: groupQuery, variables: { isMember: false } }), +// ).resolves.toMatchObject(expected) +// }) +// }) +// }) +// }) +// }) describe('CreateGroup', () => { beforeEach(() => { @@ -440,3 +441,241 @@ describe('CreateGroup', () => { }) }) }) + +describe('EnterGroup', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + userId: 'current-user', + } + const { errors } = await mutate({ mutation: enterGroupMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser + + beforeEach(async () => { + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + }) + + describe('public group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "usual" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'current-user', + } + const expected = { + data: { + EnterGroup: { + id: 'current-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('closed group', () => { + describe('entered by "current-user"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'current-user', + } + const expected = { + data: { + EnterGroup: { + id: 'current-user', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('hidden group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-hidden-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + }) +}) diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index fd53d48b3..cf44894db 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -71,15 +71,14 @@ type Query { first: Int offset: Int orderBy: [_GroupOrdering] - filter: _GroupFilter ): [Group] GroupMember( - id: ID + id: ID! first: Int offset: Int - orderBy: [_GroupOrdering] - filter: _GroupFilter + orderBy: [_UserOrdering] + filter: _UserFilter ): [User] AvailableGroupTypes: [GroupType]! @@ -114,4 +113,9 @@ type Mutation { ): Group DeleteGroup(id: ID!): Group + + EnterGroup( + id: ID! + userId: ID! + ): User } From 613f91b0371825a6b093e1fc0bb48c680709235a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 18 Aug 2022 11:47:27 +0200 Subject: [PATCH 14/67] Add seedings for group memberships --- backend/src/db/seed.js | 78 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index e41ef1abc..ebe8a6020 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -5,7 +5,7 @@ import createServer from '../server' import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' -import { createGroupMutation } from './graphql/groups' +import { createGroupMutation, enterGroupMutation } from './graphql/groups' import { createPostMutation } from './graphql/posts' import { createCommentMutation } from './graphql/comments' @@ -400,6 +400,22 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), ]) + await Promise.all([ + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g0', + userId: 'u2', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g0', + userId: 'u3', + }, + }), + ]) authenticatedUser = await jennyRostock.toJson() await Promise.all([ @@ -416,6 +432,36 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), ]) + await Promise.all([ + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g1', + userId: 'u1', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g1', + userId: 'u5', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g1', + userId: 'u6', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g1', + userId: 'u7', + }, + }), + ]) authenticatedUser = await bobDerBaumeister.toJson() await Promise.all([ @@ -432,6 +478,36 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), ]) + await Promise.all([ + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g2', + userId: 'u4', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g2', + userId: 'u5', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g2', + userId: 'u6', + }, + }), + mutate({ + mutation: enterGroupMutation, + variables: { + id: 'g2', + userId: 'u7', + }, + }), + ]) // Create Posts From d36f0eab57887569d439680e3770ba9ea0e41209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 18 Aug 2022 11:48:26 +0200 Subject: [PATCH 15/67] Add tests for 'GroupMember' resolver, a start --- .../src/middleware/permissionsMiddleware.js | 17 +- backend/src/schema/resolvers/groups.js | 4 +- backend/src/schema/resolvers/groups.spec.js | 412 +++++++++++++----- 3 files changed, 310 insertions(+), 123 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 9dcf35476..dc54d5a29 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -52,11 +52,13 @@ const isMySocialMedia = rule({ return socialMedia.ownedBy.node.id === user.id }) -const isAllowSeeingMembersOfGroup = rule({ +const isAllowedSeeingMembersOfGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { if (!user) return false const { id: groupId } = args + // Wolle: console.log('groupId: ', groupId) + // console.log('user.id: ', user.id) const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { const transactionResponse = await transaction.run( @@ -64,19 +66,22 @@ const isAllowSeeingMembersOfGroup = rule({ MATCH (group:Group {id: $groupId}) OPTIONAL MATCH (admin:User {id: $userId})-[membership:MEMBER_OF]->(group) WHERE membership.role IN ['admin', 'owner'] - RETURN group, admin {.*, myRoleInGroup: membership.role} + RETURN group {.*}, admin {.*, myRoleInGroup: membership.role} `, { groupId, userId: user.id }, ) return { - admin: transactionResponse.records.map((record) => record.get('admin')), - group: transactionResponse.records.map((record) => record.get('group')), + admin: transactionResponse.records.map((record) => record.get('admin'))[0], + group: transactionResponse.records.map((record) => record.get('group'))[0], } }) try { - const [{ admin, group }] = await readTxPromise + const { admin, group } = await readTxPromise + // Wolle: console.log('admin: ', admin) + // console.log('group: ', group) return group.groupType === 'public' || !!admin } catch (error) { + // Wolle: console.log('error: ', error) throw new Error(error) } finally { session.close() @@ -146,7 +151,7 @@ export default shield( statistics: allow, currentUser: allow, Group: isAuthenticated, - GroupMember: isAllowSeeingMembersOfGroup, + GroupMember: isAllowedSeeingMembersOfGroup, Post: allow, profilePagePosts: allow, Comment: allow, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index b64484d37..91135a1db 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -48,15 +48,15 @@ export default { }, GroupMember: async (_object, params, context, _resolveInfo) => { const { id: groupId } = params + // Wolle: console.log('groupId: ', groupId) const session = context.driver.session() const readTxResultPromise = session.readTransaction(async (txc) => { const groupMemberCypher = ` - MATCH (user:User {id: $userId})-[membership:MEMBER_OF]->(:Group {id: $groupId}) + MATCH (user:User)-[membership:MEMBER_OF]->(:Group {id: $groupId}) RETURN user {.*, myRoleInGroup: membership.role} ` const result = await txc.run(groupMemberCypher, { groupId, - userId: context.user.id, }) return result.records.map((record) => record.get('user')) }) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 81223a584..33aeaf2bd 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -208,127 +208,309 @@ describe('Group', () => { }) }) -// describe('GroupMember', () => { -// describe('unauthenticated', () => { -// it('throws authorization error', async () => { -// const { errors } = await query({ query: groupMemberQuery, variables: {} }) -// expect(errors[0]).toHaveProperty('message', 'Not Authorised!') -// }) -// }) +describe('GroupMember', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + } + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) -// describe('authenticated', () => { -// beforeEach(async () => { -// authenticatedUser = await user.toJson() -// }) + describe('authenticated', () => { + let otherUser + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser -// let otherUser + beforeEach(async () => { + // create users + otherUser = await Factory.build( + 'user', + { + id: 'other-user', + name: 'Other TestUser', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + // create groups + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + // create additional memberships + await mutate({ + mutation: enterGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-closed-group', + }, + }) + await mutate({ + mutation: enterGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-hidden-group', + }, + }) + await mutate({ + mutation: enterGroupMutation, + variables: { + id: 'closed-group', + userId: 'current-user', + }, + }) + await mutate({ + mutation: enterGroupMutation, + variables: { + id: 'hidden-group', + userId: 'owner-of-closed-group', + }, + }) + }) -// beforeEach(async () => { -// otherUser = await Factory.build( -// 'user', -// { -// id: 'other-user', -// name: 'Other TestUser', -// }, -// { -// email: 'test2@example.org', -// password: '1234', -// }, -// ) -// authenticatedUser = await otherUser.toJson() -// await mutate({ -// mutation: createGroupMutation, -// variables: { -// id: 'others-group', -// name: 'Uninteresting Group', -// about: 'We will change nothing!', -// description: 'We love it like it is!?' + descriptionAdditional100, -// groupType: 'closed', -// actionRadius: 'global', -// categoryIds, -// }, -// }) -// authenticatedUser = await user.toJson() -// await mutate({ -// mutation: createGroupMutation, -// variables: { -// id: 'my-group', -// name: 'The Best Group', -// about: 'We will change the world!', -// description: 'Some description' + descriptionAdditional100, -// groupType: 'public', -// actionRadius: 'regional', -// categoryIds, -// }, -// }) -// }) + describe('public group', () => { + beforeEach(async () => { + variables = { + id: 'public-group', + } + }) -// describe('query group members', () => { -// describe('by owner', () => { -// it.only('finds all members', async () => { -// const expected = { -// data: { -// GroupMember: expect.arrayContaining([ -// expect.objectContaining({ -// id: 'my-group', -// slug: 'the-best-group', -// myRole: 'owner', -// }), -// // Wolle: expect.objectContaining({ -// // id: 'others-group', -// // slug: 'uninteresting-group', -// // myRole: null, -// // }), -// ]), -// }, -// errors: undefined, -// } -// await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected) -// }) -// }) + describe('query group members', () => { + describe('by owner', () => { + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) -// describe('isMember = true', () => { -// it('finds only groups where user is member', async () => { -// const expected = { -// data: { -// Group: [ -// { -// id: 'my-group', -// slug: 'the-best-group', -// myRole: 'owner', -// }, -// ], -// }, -// errors: undefined, -// } -// await expect( -// query({ query: groupQuery, variables: { isMember: true } }), -// ).resolves.toMatchObject(expected) -// }) -// }) + describe('by "other-user"', () => { + it.only('throws authorization error', async () => { + authenticatedUser = await otherUser.toJson() + const result = await query({ query: groupMemberQuery, variables }) + console.log('result: ', result) + // Wolle: const { errors } = await query({ query: groupMemberQuery, variables }) + // expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) -// describe('isMember = false', () => { -// it('finds only groups where user is not(!) member', async () => { -// const expected = { -// data: { -// Group: expect.arrayContaining([ -// expect.objectContaining({ -// id: 'others-group', -// slug: 'uninteresting-group', -// myRole: null, -// }), -// ]), -// }, -// errors: undefined, -// } -// await expect( -// query({ query: groupQuery, variables: { isMember: false } }), -// ).resolves.toMatchObject(expected) -// }) -// }) -// }) -// }) -// }) + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'current-user', + } + const expected = { + data: { + EnterGroup: { + id: 'current-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('closed group', () => { + describe('entered by "current-user"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'current-user', + } + const expected = { + data: { + EnterGroup: { + id: 'current-user', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('hidden group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-hidden-group', + } + const expected = { + data: { + EnterGroup: { + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: enterGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + }) +}) describe('CreateGroup', () => { beforeEach(() => { From 14620b00eb1e63b23c3d83399de6a4e735307c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Fri, 19 Aug 2022 10:47:17 +0200 Subject: [PATCH 16/67] Add tests for 'JoinGroup' and 'GroupMember' resolver --- backend/src/db/graphql/groups.js | 4 +- backend/src/db/seed.js | 22 +- .../src/middleware/permissionsMiddleware.js | 20 +- backend/src/schema/resolvers/groups.js | 6 +- backend/src/schema/resolvers/groups.spec.js | 1022 +++++++++-------- backend/src/schema/types/type/Group.gql | 2 +- 6 files changed, 603 insertions(+), 473 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index b169e10fb..8486288ec 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -39,9 +39,9 @@ export const createGroupMutation = gql` } ` -export const enterGroupMutation = gql` +export const joinGroupMutation = gql` mutation ($id: ID!, $userId: ID!) { - EnterGroup(id: $id, userId: $userId) { + JoinGroup(id: $id, userId: $userId) { id name slug diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index ebe8a6020..f9b2d05da 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -5,7 +5,7 @@ import createServer from '../server' import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' -import { createGroupMutation, enterGroupMutation } from './graphql/groups' +import { createGroupMutation, joinGroupMutation } from './graphql/groups' import { createPostMutation } from './graphql/posts' import { createCommentMutation } from './graphql/comments' @@ -402,14 +402,14 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) await Promise.all([ mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g0', userId: 'u2', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g0', userId: 'u3', @@ -434,28 +434,28 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) await Promise.all([ mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g1', userId: 'u1', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g1', userId: 'u5', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g1', userId: 'u6', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g1', userId: 'u7', @@ -480,28 +480,28 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) await Promise.all([ mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g2', userId: 'u4', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g2', userId: 'u5', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g2', userId: 'u6', }, }), mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'g2', userId: 'u7', diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index dc54d5a29..afdc5501e 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -64,22 +64,26 @@ const isAllowedSeeingMembersOfGroup = rule({ const transactionResponse = await transaction.run( ` MATCH (group:Group {id: $groupId}) - OPTIONAL MATCH (admin:User {id: $userId})-[membership:MEMBER_OF]->(group) - WHERE membership.role IN ['admin', 'owner'] - RETURN group {.*}, admin {.*, myRoleInGroup: membership.role} + OPTIONAL MATCH (member:User {id: $userId})-[membership:MEMBER_OF]->(group) + RETURN group {.*}, member {.*, myRoleInGroup: membership.role} `, { groupId, userId: user.id }, ) return { - admin: transactionResponse.records.map((record) => record.get('admin'))[0], + member: transactionResponse.records.map((record) => record.get('member'))[0], group: transactionResponse.records.map((record) => record.get('group'))[0], } }) try { - const { admin, group } = await readTxPromise - // Wolle: console.log('admin: ', admin) + const { member, group } = await readTxPromise + // Wolle: console.log('member: ', member) // console.log('group: ', group) - return group.groupType === 'public' || !!admin + return ( + group.groupType === 'public' || + (['closed', 'hidden'].includes(group.groupType) && + !!member && + ['usual', 'admin', 'owner'].includes(member.myRoleInGroup)) + ) } catch (error) { // Wolle: console.log('error: ', error) throw new Error(error) @@ -179,7 +183,7 @@ export default shield( SignupVerification: allow, UpdateUser: onlyYourself, CreateGroup: isAuthenticated, - EnterGroup: isAuthenticated, + JoinGroup: isAuthenticated, CreatePost: isAuthenticated, UpdatePost: isAuthor, DeletePost: isAuthor, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 91135a1db..c9a31fdc3 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -131,11 +131,11 @@ export default { session.close() } }, - EnterGroup: async (_parent, params, context, _resolveInfo) => { + JoinGroup: async (_parent, params, context, _resolveInfo) => { const { id: groupId, userId } = params const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { - const enterGroupCypher = ` + const joinGroupCypher = ` MATCH (member:User {id: $userId}), (group:Group {id: $groupId}) MERGE (member)-[membership:MEMBER_OF]->(group) ON CREATE SET @@ -148,7 +148,7 @@ export default { END RETURN member {.*, myRoleInGroup: membership.role} ` - const result = await transaction.run(enterGroupCypher, { groupId, userId }) + const result = await transaction.run(joinGroupCypher, { groupId, userId }) const [member] = await result.records.map((record) => record.get('member')) return member }) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 33aeaf2bd..87eb02dc0 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -2,7 +2,7 @@ import { createTestClient } from 'apollo-server-testing' import Factory, { cleanDatabase } from '../../db/factories' import { createGroupMutation, - enterGroupMutation, + joinGroupMutation, groupMemberQuery, groupQuery, } from '../../db/graphql/groups' @@ -90,6 +90,118 @@ afterEach(async () => { await cleanDatabase() }) +describe('CreateGroup', () => { + beforeEach(() => { + variables = { + ...variables, + id: 'g589', + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + } + }) + + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: createGroupMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('creates a group', async () => { + const expected = { + data: { + CreateGroup: { + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + }, + }, + errors: undefined, + } + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + expected, + ) + }) + + it('assigns the authenticated user as owner', async () => { + const expected = { + data: { + CreateGroup: { + name: 'The Best Group', + myRole: 'owner', + }, + }, + errors: undefined, + } + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + expected, + ) + }) + + it('has "disabled" and "deleted" default to "false"', async () => { + const expected = { data: { CreateGroup: { disabled: false, deleted: false } } } + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + expected, + ) + }) + + describe('description', () => { + describe('length without HTML', () => { + describe('less then 100 chars', () => { + it('throws error: "Too view categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { + ...variables, + description: + '0123456789' + + '0123456789', + }, + }) + expect(errors[0]).toHaveProperty('message', 'Description too short!') + }) + }) + }) + }) + + describe('categories', () => { + beforeEach(() => { + CONFIG.CATEGORIES_ACTIVE = true + }) + + describe('not even one', () => { + it('throws error: "Too view categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { ...variables, categoryIds: null }, + }) + expect(errors[0]).toHaveProperty('message', 'Too view categories!') + }) + }) + + describe('four', () => { + it('throws error: "Too many categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, + }) + expect(errors[0]).toHaveProperty('message', 'Too many categories!') + }) + }) + }) + }) +}) + describe('Group', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { @@ -208,6 +320,244 @@ describe('Group', () => { }) }) +describe('JoinGroup', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + userId: 'current-user', + } + const { errors } = await mutate({ mutation: joinGroupMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser + + beforeEach(async () => { + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + }) + + describe('public group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "usual" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'current-user', + } + const expected = { + data: { + JoinGroup: { + id: 'current-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('closed group', () => { + describe('entered by "current-user"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'current-user', + } + const expected = { + data: { + JoinGroup: { + id: 'current-user', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('hidden group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-hidden-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + }) +}) + describe('GroupMember', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { @@ -301,28 +651,28 @@ describe('GroupMember', () => { }) // create additional memberships await mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'public-group', userId: 'owner-of-closed-group', }, }) await mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'public-group', userId: 'owner-of-hidden-group', }, }) await mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'closed-group', userId: 'current-user', }, }) await mutate({ - mutation: enterGroupMutation, + mutation: joinGroupMutation, variables: { id: 'hidden-group', userId: 'owner-of-closed-group', @@ -338,7 +688,11 @@ describe('GroupMember', () => { }) describe('query group members', () => { - describe('by owner', () => { + describe('by owner "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + it('finds all members', async () => { const expected = { data: { @@ -368,493 +722,265 @@ describe('GroupMember', () => { }) }) - describe('by "other-user"', () => { - it.only('throws authorization error', async () => { - authenticatedUser = await otherUser.toJson() - const result = await query({ query: groupMemberQuery, variables }) - console.log('result: ', result) - // Wolle: const { errors } = await query({ query: groupMemberQuery, variables }) - // expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + describe('by usual member "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() }) - }) - }) - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'current-user', - } + it('finds all members', async () => { const expected = { data: { - EnterGroup: { - id: 'current-user', - myRoleInGroup: 'owner', - }, + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), }, errors: undefined, } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - }) - }) - - describe('closed group', () => { - describe('entered by "current-user"', () => { - it('has "pending" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'current-user', - } - const expected = { - data: { - EnterGroup: { - id: 'current-user', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, + const result = await mutate({ + mutation: groupMemberQuery, variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - EnterGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - }) - }) - - describe('hidden group', () => { - describe('entered by "owner-of-closed-group"', () => { - it('has "pending" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - EnterGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-hidden-group', - } - const expected = { - data: { - EnterGroup: { - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - }) - }) - }) -}) - -describe('CreateGroup', () => { - beforeEach(() => { - variables = { - ...variables, - id: 'g589', - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - } - }) - - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await mutate({ mutation: createGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('creates a group', async () => { - const expected = { - data: { - CreateGroup: { - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', - }, - }, - errors: undefined, - } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) - }) - - it('assigns the authenticated user as owner', async () => { - const expected = { - data: { - CreateGroup: { - name: 'The Best Group', - myRole: 'owner', - }, - }, - errors: undefined, - } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) - }) - - it('has "disabled" and "deleted" default to "false"', async () => { - const expected = { data: { CreateGroup: { disabled: false, deleted: false } } } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) - }) - - describe('description', () => { - describe('length without HTML', () => { - describe('less then 100 chars', () => { - it('throws error: "Too view categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { - ...variables, - description: - '0123456789' + - '0123456789', - }, }) - expect(errors[0]).toHaveProperty('message', 'Description too short!') + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) }) }) - }) - }) - describe('categories', () => { - beforeEach(() => { - CONFIG.CATEGORIES_ACTIVE = true - }) - - describe('not even one', () => { - it('throws error: "Too view categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { ...variables, categoryIds: null }, + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() }) - expect(errors[0]).toHaveProperty('message', 'Too view categories!') - }) - }) - describe('four', () => { - it('throws error: "Too many categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, - }) - expect(errors[0]).toHaveProperty('message', 'Too many categories!') - }) - }) - }) - }) -}) - -describe('EnterGroup', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - userId: 'current-user', - } - const { errors } = await mutate({ mutation: enterGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - let ownerOfClosedGroupUser - let ownerOfHiddenGroupUser - - beforeEach(async () => { - ownerOfClosedGroupUser = await Factory.build( - 'user', - { - id: 'owner-of-closed-group', - name: 'Owner Of Closed Group', - }, - { - email: 'owner-of-closed-group@example.org', - password: '1234', - }, - ) - ownerOfHiddenGroupUser = await Factory.build( - 'user', - { - id: 'owner-of-hidden-group', - name: 'Owner Of Hidden Group', - }, - { - email: 'owner-of-hidden-group@example.org', - password: '1234', - }, - ) - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'public-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) - }) - - describe('public group', () => { - describe('entered by "owner-of-closed-group"', () => { - it('has "usual" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - EnterGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'current-user', - } + it('finds all members', async () => { const expected = { data: { - EnterGroup: { - id: 'current-user', - myRoleInGroup: 'owner', - }, + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), }, errors: undefined, } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) }) }) }) }) describe('closed group', () => { - describe('entered by "current-user"', () => { - it('has "pending" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'current-user', - } - const expected = { - data: { - EnterGroup: { - id: 'current-user', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) + beforeEach(async () => { + variables = { + id: 'closed-group', + } }) - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'owner-of-closed-group', - } + describe('query group members', () => { + describe('by owner "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { const expected = { data: { - EnterGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }, + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }), + ]), }, errors: undefined, } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(2) + }) + }) + + // needs 'SwitchGroupMemberRole' + describe.skip('by usual member "owner-of-hidden-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by pending member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) }) describe('hidden group', () => { - describe('entered by "owner-of-closed-group"', () => { - it('has "pending" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - EnterGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) + beforeEach(async () => { + variables = { + id: 'hidden-group', + } }) - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-hidden-group', - } + describe('query group members', () => { + describe('by owner "owner-of-hidden-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + }) + + it('finds all members', async () => { const expected = { data: { - EnterGroup: { - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }, + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), }, errors: undefined, } - await expect( - mutate({ - mutation: enterGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(2) + }) + }) + + // needs 'SwitchGroupMemberRole' + describe.skip('by usual member "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by pending member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index cf44894db..fad1b7e58 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -114,7 +114,7 @@ type Mutation { DeleteGroup(id: ID!): Group - EnterGroup( + JoinGroup( id: ID! userId: ID! ): User From 695a71bf2574c02ed0c8a5ed78503b375318eb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 20 Aug 2022 09:43:37 +0200 Subject: [PATCH 17/67] Implement 'SwitchGroupMemberRole' resolver and write the beginning to test it --- backend/src/db/graphql/groups.js | 11 + .../src/middleware/permissionsMiddleware.js | 85 +++- backend/src/schema/resolvers/groups.js | 27 ++ backend/src/schema/resolvers/groups.spec.js | 438 +++++++++++++++--- backend/src/schema/types/type/Group.gql | 6 + 5 files changed, 507 insertions(+), 60 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index 8486288ec..41780f7cd 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -50,6 +50,17 @@ export const joinGroupMutation = gql` } ` +export const switchGroupMemberRoleMutation = gql` + mutation ($id: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) { + SwitchGroupMemberRole(id: $id, userId: $userId, roleInGroup: $roleInGroup) { + id + name + slug + myRoleInGroup + } + } +` + // ------ queries export const groupQuery = gql` diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index afdc5501e..11ca956b6 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -79,10 +79,82 @@ const isAllowedSeeingMembersOfGroup = rule({ // Wolle: console.log('member: ', member) // console.log('group: ', group) return ( - group.groupType === 'public' || - (['closed', 'hidden'].includes(group.groupType) && - !!member && - ['usual', 'admin', 'owner'].includes(member.myRoleInGroup)) + !!group && + (group.groupType === 'public' || + (['closed', 'hidden'].includes(group.groupType) && + !!member && + ['usual', 'admin', 'owner'].includes(member.myRoleInGroup))) + ) + } catch (error) { + // Wolle: console.log('error: ', error) + throw new Error(error) + } finally { + session.close() + } +}) + +const isAllowedToSwitchGroupMemberRole = rule({ + cache: 'no_cache', +})(async (_parent, args, { user, driver }) => { + if (!user) return false + const adminId = user.id + const { id: groupId, userId, roleInGroup } = args + // Wolle: + // console.log('adminId: ', adminId) + // console.log('groupId: ', groupId) + // console.log('userId: ', userId) + // console.log('roleInGroup: ', roleInGroup) + const session = driver.session() + const readTxPromise = session.readTransaction(async (transaction) => { + const transactionResponse = await transaction.run( + ` + MATCH (admin:User {id: $adminId})-[adminMembership:MEMBER_OF]->(group:Group {id: $groupId})<-[userMembership:MEMBER_OF]-(member:User {id: $userId}) + RETURN group {.*}, admin {.*, myRoleInGroup: adminMembership.role}, member {.*, myRoleInGroup: userMembership.role} + `, + { groupId, adminId, userId }, + ) + // Wolle: + // console.log( + // 'transactionResponse: ', + // transactionResponse, + // ) + // console.log( + // 'transaction admins: ', + // transactionResponse.records.map((record) => record.get('admin')), + // ) + // console.log( + // 'transaction groups: ', + // transactionResponse.records.map((record) => record.get('group')), + // ) + // console.log( + // 'transaction members: ', + // transactionResponse.records.map((record) => record.get('member')), + // ) + return { + admin: transactionResponse.records.map((record) => record.get('admin'))[0], + group: transactionResponse.records.map((record) => record.get('group'))[0], + member: transactionResponse.records.map((record) => record.get('member'))[0], + } + }) + try { + // Wolle: + // console.log('enter try !!!') + const { admin, group, member } = await readTxPromise + // Wolle: + // console.log('after !!!') + // console.log('admin: ', admin) + // console.log('group: ', group) + // console.log('member: ', member) + return ( + !!group && + !!admin && + !!member && + adminId !== userId && + ((['admin'].includes(admin.myRoleInGroup) && + !['owner'].includes(member.myRoleInGroup) && + ['pending', 'usual', 'admin'].includes(roleInGroup)) || + (['owner'].includes(admin.myRoleInGroup) && + ['pending', 'usual', 'admin', 'owner'].includes(roleInGroup))) ) } catch (error) { // Wolle: console.log('error: ', error) @@ -118,7 +190,7 @@ const isAuthor = rule({ const isDeletingOwnAccount = rule({ cache: 'no_cache', -})(async (parent, args, context, info) => { +})(async (parent, args, context, _info) => { return context.user.id === args.id }) @@ -183,7 +255,8 @@ export default shield( SignupVerification: allow, UpdateUser: onlyYourself, CreateGroup: isAuthenticated, - JoinGroup: isAuthenticated, + JoinGroup: isAuthenticated, // Wolle: can not be correct + SwitchGroupMemberRole: isAllowedToSwitchGroupMemberRole, CreatePost: isAuthenticated, UpdatePost: isAuthor, DeletePost: isAuthor, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index c9a31fdc3..34959908d 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -160,6 +160,33 @@ export default { session.close() } }, + SwitchGroupMemberRole: async (_parent, params, context, _resolveInfo) => { + const { id: groupId, userId, roleInGroup } = params + // Wolle + // console.log('groupId: ', groupId) + // console.log('userId: ', groupId) + // console.log('roleInGroup: ', groupId) + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const joinGroupCypher = ` + MATCH (member:User {id: $userId})-[membership:MEMBER_OF]->(group:Group {id: $groupId}) + SET + membership.updatedAt = toString(datetime()), + membership.role = $roleInGroup + RETURN member {.*, myRoleInGroup: membership.role} + ` + const result = await transaction.run(joinGroupCypher, { groupId, userId, roleInGroup }) + const [member] = await result.records.map((record) => record.get('member')) + return member + }) + try { + return await writeTxResultPromise + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, }, Group: { ...Resolver('Group', { diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 87eb02dc0..e17e4827a 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -3,6 +3,7 @@ import Factory, { cleanDatabase } from '../../db/factories' import { createGroupMutation, joinGroupMutation, + switchGroupMemberRoleMutation, groupMemberQuery, groupQuery, } from '../../db/graphql/groups' @@ -13,8 +14,8 @@ import CONFIG from '../../config' const driver = getDriver() const neode = getNeode() -let query -let mutate +let isCleanDbAfterEach = true +let isSeedDb = true let authenticatedUser let user @@ -23,20 +24,20 @@ const descriptionAdditional100 = ' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789' let variables = {} +const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + } + }, +}) +const { query } = createTestClient(server) +const { mutate } = createTestClient(server) + beforeAll(async () => { await cleanDatabase() - - const { server } = createServer({ - context: () => { - return { - driver, - neode, - user: authenticatedUser, - } - }, - }) - query = createTestClient(server).query - mutate = createTestClient(server).mutate }) afterAll(async () => { @@ -44,50 +45,55 @@ afterAll(async () => { }) beforeEach(async () => { - variables = {} - user = await Factory.build( - 'user', - { - id: 'current-user', - name: 'TestUser', - }, - { - email: 'test@example.org', - password: '1234', - }, - ) - await Promise.all([ - neode.create('Category', { - id: 'cat9', - name: 'Democracy & Politics', - slug: 'democracy-politics', - icon: 'university', - }), - neode.create('Category', { - id: 'cat4', - name: 'Environment & Nature', - slug: 'environment-nature', - icon: 'tree', - }), - neode.create('Category', { - id: 'cat15', - name: 'Consumption & Sustainability', - slug: 'consumption-sustainability', - icon: 'shopping-cart', - }), - neode.create('Category', { - id: 'cat27', - name: 'Animal Protection', - slug: 'animal-protection', - icon: 'paw', - }), - ]) - authenticatedUser = null + // Wolle: find a better solution + if (isSeedDb) { + variables = {} + user = await Factory.build( + 'user', + { + id: 'current-user', + name: 'TestUser', + }, + { + email: 'test@example.org', + password: '1234', + }, + ) + await Promise.all([ + neode.create('Category', { + id: 'cat9', + name: 'Democracy & Politics', + slug: 'democracy-politics', + icon: 'university', + }), + neode.create('Category', { + id: 'cat4', + name: 'Environment & Nature', + slug: 'environment-nature', + icon: 'tree', + }), + neode.create('Category', { + id: 'cat15', + name: 'Consumption & Sustainability', + slug: 'consumption-sustainability', + icon: 'shopping-cart', + }), + neode.create('Category', { + id: 'cat27', + name: 'Animal Protection', + slug: 'animal-protection', + icon: 'paw', + }), + ]) + authenticatedUser = null + } }) // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 afterEach(async () => { - await cleanDatabase() + if (isCleanDbAfterEach) { + await cleanDatabase() + } }) describe('CreateGroup', () => { @@ -558,6 +564,330 @@ describe('JoinGroup', () => { }) }) +describe('SwitchGroupMemberRole', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + userId: 'current-user', + roleInGroup: 'pending', + } + const { errors } = await mutate({ mutation: switchGroupMemberRoleMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + describe('in building up mode', () => { + let usualMemberUser + let adminMemberUser + let ownerMemberUser + // let secondOwnerMemberUser + + beforeEach(async () => { + // Wolle: change this to beforeAll? + if (isSeedDb) { + // create users + usualMemberUser = await Factory.build( + 'user', + { + id: 'usual-member-user', + name: 'Usual Member TestUser', + }, + { + email: 'usual-member-user@example.org', + password: '1234', + }, + ) + adminMemberUser = await Factory.build( + 'user', + { + id: 'admin-member-user', + name: 'Admin Member TestUser', + }, + { + email: 'admin-member-user@example.org', + password: '1234', + }, + ) + ownerMemberUser = await Factory.build( + 'user', + { + id: 'owner-member-user', + name: 'Owner Member TestUser', + }, + { + email: 'owner-member-user@example.org', + password: '1234', + }, + ) + // secondOwnerMemberUser = + await Factory.build( + 'user', + { + id: 'second-owner-member-user', + name: 'Second Owner Member TestUser', + }, + { + email: 'second-owner-member-user@example.org', + password: '1234', + }, + ) + // create groups + authenticatedUser = await usualMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + authenticatedUser = await ownerMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + authenticatedUser = await adminMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + // create additional memberships + // public-group + authenticatedUser = await usualMemberUser.toJson() + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-closed-group', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-hidden-group', + }, + }) + // closed-group + authenticatedUser = await ownerMemberUser.toJson() + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'usual-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'admin-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'second-owner-member-user', + }, + }) + // hidden-group + authenticatedUser = await adminMemberUser.toJson() + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'admin-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'second-owner-member-user', + }, + }) + // Wolle + // function sleep(ms) { + // return new Promise(resolve => setTimeout(resolve, ms)); + // } + // await sleep(4 * 1000) + isCleanDbAfterEach = false + isSeedDb = false + } + }) + afterAll(async () => { + // Wolle: find a better solution + await cleanDatabase() + isCleanDbAfterEach = true + isSeedDb = true + }) + + describe('in all group types – here "closed-group" for example', () => { + beforeEach(async () => { + variables = { + id: 'closed-group', + } + }) + + describe('switch role', () => { + describe('of owner member "owner-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'owner-member-user', + } + }) + + describe('by owner themself "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + + describe('of prospective admin member "admin-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'admin-member-user', + } + }) + + describe('by owner "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('has role admin', async () => { + // Wolle: + // const groups = await query({ query: groupQuery, variables: {} }) + // console.log('groups.data.Group: ', groups.data.Group) + // const groupMemberOfClosedGroup = await mutate({ + // mutation: groupMemberQuery, + // variables: { + // id: 'closed-group', + // }, + // }) + // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'admin-member-user', + myRoleInGroup: 'admin', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + + describe('by still pending member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('degrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by none member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + describe('degrade to pending again', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + }) + }) + }) + }) +}) + describe('GroupMember', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index fad1b7e58..270f5c844 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -118,4 +118,10 @@ type Mutation { id: ID! userId: ID! ): User + + SwitchGroupMemberRole( + id: ID! + userId: ID! + roleInGroup: GroupMemberRole! + ): User } From 0fe609e29452a5f8e3634e3f8e08dbc0d9c6f8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 07:19:07 +0200 Subject: [PATCH 18/67] Add test for find all member of closed and hidden groups if you are usual member --- .../src/middleware/permissionsMiddleware.js | 2 + backend/src/schema/resolvers/groups.spec.js | 81 ++++++++++++++----- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 11ca956b6..728385902 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -55,6 +55,7 @@ const isMySocialMedia = rule({ const isAllowedSeeingMembersOfGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { + // Wolle: may have a look to 'isAuthenticated' if (!user) return false const { id: groupId } = args // Wolle: console.log('groupId: ', groupId) @@ -96,6 +97,7 @@ const isAllowedSeeingMembersOfGroup = rule({ const isAllowedToSwitchGroupMemberRole = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { + // Wolle: may have a look to 'isAuthenticated' if (!user) return false const adminId = user.id const { id: groupId, userId, roleInGroup } = args diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index e17e4827a..1721e3e00 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -940,6 +940,19 @@ describe('GroupMember', () => { }, ) // create groups + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) authenticatedUser = await ownerOfClosedGroupUser.toJson() await mutate({ mutation: createGroupMutation, @@ -966,20 +979,8 @@ describe('GroupMember', () => { categoryIds, }, }) - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'public-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) // create additional memberships + // public-group await mutate({ mutation: joinGroupMutation, variables: { @@ -994,6 +995,7 @@ describe('GroupMember', () => { userId: 'owner-of-hidden-group', }, }) + // closed-group await mutate({ mutation: joinGroupMutation, variables: { @@ -1001,6 +1003,21 @@ describe('GroupMember', () => { userId: 'current-user', }, }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'owner-of-hidden-group', + }, + }) + // hidden-group + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'current-user', + }, + }) await mutate({ mutation: joinGroupMutation, variables: { @@ -1008,6 +1025,8 @@ describe('GroupMember', () => { userId: 'owner-of-closed-group', }, }) + + authenticatedUser = await user.toJson() }) describe('public group', () => { @@ -1147,6 +1166,10 @@ describe('GroupMember', () => { id: 'owner-of-closed-group', myRoleInGroup: 'owner', }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'pending', + }), ]), }, errors: undefined, @@ -1156,13 +1179,21 @@ describe('GroupMember', () => { variables, }) expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(2) + expect(result.data.GroupMember.length).toBe(3) }) }) - // needs 'SwitchGroupMemberRole' - describe.skip('by usual member "owner-of-hidden-group"', () => { + describe('by usual member "owner-of-hidden-group"', () => { beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'closed-group', + userId: 'owner-of-hidden-group', + roleInGroup: 'usual', + }, + }) authenticatedUser = await ownerOfHiddenGroupUser.toJson() }) @@ -1236,6 +1267,10 @@ describe('GroupMember', () => { const expected = { data: { GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), expect.objectContaining({ id: 'owner-of-closed-group', myRoleInGroup: 'pending', @@ -1253,13 +1288,21 @@ describe('GroupMember', () => { variables, }) expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(2) + expect(result.data.GroupMember.length).toBe(3) }) }) - // needs 'SwitchGroupMemberRole' - describe.skip('by usual member "owner-of-closed-group"', () => { + describe('by usual member "owner-of-closed-group"', () => { beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'hidden-group', + userId: 'owner-of-closed-group', + roleInGroup: 'usual', + }, + }) authenticatedUser = await ownerOfClosedGroupUser.toJson() }) From 74589d4d3f0a71c50a35ed285429803e614626f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 07:27:46 +0200 Subject: [PATCH 19/67] Resort creation of groups and its connected joins of the groups --- backend/src/schema/resolvers/groups.spec.js | 113 ++++++++++---------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 1721e3e00..ea3904d0a 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -343,6 +343,7 @@ describe('JoinGroup', () => { let ownerOfHiddenGroupUser beforeEach(async () => { + // create users ownerOfClosedGroupUser = await Factory.build( 'user', { @@ -365,6 +366,8 @@ describe('JoinGroup', () => { password: '1234', }, ) + // create groups + // public-group authenticatedUser = await ownerOfClosedGroupUser.toJson() await mutate({ mutation: createGroupMutation, @@ -634,6 +637,7 @@ describe('SwitchGroupMemberRole', () => { }, ) // create groups + // public-group authenticatedUser = await usualMemberUser.toJson() await mutate({ mutation: createGroupMutation, @@ -647,35 +651,6 @@ describe('SwitchGroupMemberRole', () => { categoryIds, }, }) - authenticatedUser = await ownerMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - authenticatedUser = await adminMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - // create additional memberships - // public-group - authenticatedUser = await usualMemberUser.toJson() await mutate({ mutation: joinGroupMutation, variables: { @@ -692,6 +667,18 @@ describe('SwitchGroupMemberRole', () => { }) // closed-group authenticatedUser = await ownerMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) await mutate({ mutation: joinGroupMutation, variables: { @@ -715,6 +702,18 @@ describe('SwitchGroupMemberRole', () => { }) // hidden-group authenticatedUser = await adminMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) await mutate({ mutation: joinGroupMutation, variables: { @@ -729,6 +728,7 @@ describe('SwitchGroupMemberRole', () => { userId: 'second-owner-member-user', }, }) + // Wolle // function sleep(ms) { // return new Promise(resolve => setTimeout(resolve, ms)); @@ -940,6 +940,7 @@ describe('GroupMember', () => { }, ) // create groups + // public-group authenticatedUser = await user.toJson() await mutate({ mutation: createGroupMutation, @@ -953,34 +954,6 @@ describe('GroupMember', () => { categoryIds, }, }) - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - // create additional memberships - // public-group await mutate({ mutation: joinGroupMutation, variables: { @@ -996,6 +969,19 @@ describe('GroupMember', () => { }, }) // closed-group + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) await mutate({ mutation: joinGroupMutation, variables: { @@ -1011,6 +997,19 @@ describe('GroupMember', () => { }, }) // hidden-group + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) await mutate({ mutation: joinGroupMutation, variables: { From e91394948cda44717edeb1dac7e62fbedef391ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 10:08:58 +0200 Subject: [PATCH 20/67] Add tests for 'SwitchGroupMemberRole' resolver --- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/resolvers/groups.spec.js | 765 +++++++++++++++++- 2 files changed, 735 insertions(+), 31 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 728385902..e3e3b3eb0 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -152,6 +152,7 @@ const isAllowedToSwitchGroupMemberRole = rule({ !!admin && !!member && adminId !== userId && + // Wolle: member.myRoleInGroup === roleInGroup && ((['admin'].includes(admin.myRoleInGroup) && !['owner'].includes(member.myRoleInGroup) && ['pending', 'usual', 'admin'].includes(roleInGroup)) || diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index ea3904d0a..a06191baa 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -582,15 +582,27 @@ describe('SwitchGroupMemberRole', () => { describe('authenticated', () => { describe('in building up mode', () => { + let pendingMemberUser let usualMemberUser let adminMemberUser let ownerMemberUser - // let secondOwnerMemberUser + let secondOwnerMemberUser beforeEach(async () => { // Wolle: change this to beforeAll? if (isSeedDb) { // create users + pendingMemberUser = await Factory.build( + 'user', + { + id: 'pending-member-user', + name: 'Pending Member TestUser', + }, + { + email: 'pending-member-user@example.org', + password: '1234', + }, + ) usualMemberUser = await Factory.build( 'user', { @@ -624,8 +636,7 @@ describe('SwitchGroupMemberRole', () => { password: '1234', }, ) - // secondOwnerMemberUser = - await Factory.build( + secondOwnerMemberUser = await Factory.build( 'user', { id: 'second-owner-member-user', @@ -679,6 +690,13 @@ describe('SwitchGroupMemberRole', () => { categoryIds, }, }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'pending-member-user', + }, + }) await mutate({ mutation: joinGroupMutation, variables: { @@ -752,50 +770,54 @@ describe('SwitchGroupMemberRole', () => { } }) - describe('switch role', () => { - describe('of owner member "owner-member-user"', () => { + describe('give the members their prospective roles', () => { + describe('by owner "owner-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - userId: 'owner-member-user', - } + authenticatedUser = await ownerMemberUser.toJson() }) - describe('by owner themself "owner-member-user"', () => { + describe('switch role of "usual-member-user"', () => { beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() + variables = { + ...variables, + userId: 'usual-member-user', + } }) - describe('to admin', () => { + describe('to usual', () => { beforeEach(async () => { variables = { ...variables, - roleInGroup: 'admin', + roleInGroup: 'usual', } }) - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + it('has role usual', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'usual-member-user', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) }) }) }) - }) - describe('of prospective admin member "admin-member-user"', () => { - beforeEach(async () => { - variables = { - ...variables, - userId: 'admin-member-user', - } - }) - - describe('by owner "owner-member-user"', () => { + describe('switch role of "admin-member-user"', () => { beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() + variables = { + ...variables, + userId: 'admin-member-user', + } }) describe('to admin', () => { @@ -836,11 +858,348 @@ describe('SwitchGroupMemberRole', () => { }) }) - describe('by still pending member "usual-member-user"', () => { + describe('switch role of "second-owner-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'second-owner-member-user', + } + }) + + describe('to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('has role owner', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'second-owner-member-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + // Wolle: + // const groups = await query({ query: groupQuery, variables: {} }) + // console.log('groups.data.Group: ', groups.data.Group) + // const groupMemberOfClosedGroup = await mutate({ + // mutation: groupMemberQuery, + // variables: { + // id: 'closed-group', + // }, + // }) + // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) + }) + }) + }) + }) + }) + + describe('switch role', () => { + describe('of owner "owner-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'owner-member-user', + } + }) + + describe('by owner themself "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + // Wolle: shall this be possible for now? + // or shall only an owner who gave the second owner the owner role downgrade themself? + describe('by second owner "second-owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await secondOwnerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('has role admin', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'owner-member-user', + myRoleInGroup: 'admin', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('back to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('has role owner again', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'owner-member-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + + describe('by admin "admin-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await adminMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { beforeEach(async () => { authenticatedUser = await usualMemberUser.toJson() }) + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by still pending member "pending-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + + describe('of admin "admin-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'admin-member-user', + } + }) + + describe('by owner "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('has role owner', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'admin-member-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('back to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('has role admin again', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'admin-member-user', + myRoleInGroup: 'admin', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('upgrade to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by still pending member "pending-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingMemberUser.toJson() + }) + + describe('upgrade to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + describe('degrade to usual', () => { beforeEach(async () => { variables = { @@ -864,6 +1223,23 @@ describe('SwitchGroupMemberRole', () => { authenticatedUser = await user.toJson() }) + describe('upgrade to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + describe('degrade to pending again', () => { beforeEach(async () => { variables = { @@ -882,6 +1258,333 @@ describe('SwitchGroupMemberRole', () => { }) }) }) + + describe('of usual member "usual-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'usual-member-user', + } + }) + + describe('by owner "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('has role admin', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'usual-member-user', + myRoleInGroup: 'admin', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('back to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('has role usual again', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'usual-member-user', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('upgrade to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to pending', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by still pending member "pending-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingMemberUser.toJson() + }) + + describe('upgrade to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to pending', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by none member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + describe('upgrade to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to pending again', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + + describe('of still pending member "pending-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'pending-member-user', + } + }) + + describe('by owner "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('has role usual', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'pending-member-user', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('back to pending', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('has role usual again', async () => { + const expected = { + data: { + SwitchGroupMemberRole: { + id: 'pending-member-user', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('upgrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by still pending member "pending-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingMemberUser.toJson() + }) + + describe('upgrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by none member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + describe('upgrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: switchGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) }) }) }) From 29874e54a146e4174d17a09f6e2f4d451efe2954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 10:40:16 +0200 Subject: [PATCH 21/67] Add jest dev helper function for sleeping --- backend/src/helpers/jest.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/helpers/jest.js b/backend/src/helpers/jest.js index ecfc1a042..bb0ab9d7c 100644 --- a/backend/src/helpers/jest.js +++ b/backend/src/helpers/jest.js @@ -7,3 +7,11 @@ export function gql(strings) { return strings.join('') } + +// sometime we have to wait to check a db state by having a look into the db in a certain moment +// or we wait a bit to check if we missed to set an await somewhere +export function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} +// usage – 4 seconds for example +// await sleep(4 * 1000) From 41bf1f7d3977b40e9d5b33d7b72fa738ad43e2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 10:41:31 +0200 Subject: [PATCH 22/67] Refactor tests in 'groups.spec.js' to have modes 'clean db' and 'building up' --- backend/src/schema/resolvers/groups.spec.js | 2228 +++++++++---------- 1 file changed, 1105 insertions(+), 1123 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index a06191baa..1a1386118 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -14,8 +14,6 @@ import CONFIG from '../../config' const driver = getDriver() const neode = getNeode() -let isCleanDbAfterEach = true -let isSeedDb = true let authenticatedUser let user @@ -36,6 +34,48 @@ const { server } = createServer({ const { query } = createTestClient(server) const { mutate } = createTestClient(server) +const seedBasicsAndClearAuthentication = async () => { + variables = {} + user = await Factory.build( + 'user', + { + id: 'current-user', + name: 'TestUser', + }, + { + email: 'test@example.org', + password: '1234', + }, + ) + await Promise.all([ + neode.create('Category', { + id: 'cat9', + name: 'Democracy & Politics', + slug: 'democracy-politics', + icon: 'university', + }), + neode.create('Category', { + id: 'cat4', + name: 'Environment & Nature', + slug: 'environment-nature', + icon: 'tree', + }), + neode.create('Category', { + id: 'cat15', + name: 'Consumption & Sustainability', + slug: 'consumption-sustainability', + icon: 'shopping-cart', + }), + neode.create('Category', { + id: 'cat27', + name: 'Animal Protection', + slug: 'animal-protection', + icon: 'paw', + }), + ]) + authenticatedUser = null +} + beforeAll(async () => { await cleanDatabase() }) @@ -44,357 +84,1038 @@ afterAll(async () => { await cleanDatabase() }) -beforeEach(async () => { - // Wolle: find a better solution - if (isSeedDb) { - variables = {} - user = await Factory.build( - 'user', - { - id: 'current-user', - name: 'TestUser', - }, - { - email: 'test@example.org', - password: '1234', - }, - ) - await Promise.all([ - neode.create('Category', { - id: 'cat9', - name: 'Democracy & Politics', - slug: 'democracy-politics', - icon: 'university', - }), - neode.create('Category', { - id: 'cat4', - name: 'Environment & Nature', - slug: 'environment-nature', - icon: 'tree', - }), - neode.create('Category', { - id: 'cat15', - name: 'Consumption & Sustainability', - slug: 'consumption-sustainability', - icon: 'shopping-cart', - }), - neode.create('Category', { - id: 'cat27', - name: 'Animal Protection', - slug: 'animal-protection', - icon: 'paw', - }), - ]) - authenticatedUser = null - } -}) +describe('in mode: always clean db', () => { + beforeEach(async () => { + await seedBasicsAndClearAuthentication() + }) -// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 -afterEach(async () => { - if (isCleanDbAfterEach) { + // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 + afterEach(async () => { await cleanDatabase() - } -}) - -describe('CreateGroup', () => { - beforeEach(() => { - variables = { - ...variables, - id: 'g589', - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - } }) - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await mutate({ mutation: createGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('creates a group', async () => { - const expected = { - data: { - CreateGroup: { - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', - }, - }, - errors: undefined, + describe('CreateGroup', () => { + beforeEach(() => { + variables = { + ...variables, + id: 'g589', + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) }) - it('assigns the authenticated user as owner', async () => { - const expected = { - data: { - CreateGroup: { - name: 'The Best Group', - myRole: 'owner', + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: createGroupMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('creates a group', async () => { + const expected = { + data: { + CreateGroup: { + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + }, }, - }, - errors: undefined, - } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) - }) + errors: undefined, + } + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + expected, + ) + }) - it('has "disabled" and "deleted" default to "false"', async () => { - const expected = { data: { CreateGroup: { disabled: false, deleted: false } } } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) - }) + it('assigns the authenticated user as owner', async () => { + const expected = { + data: { + CreateGroup: { + name: 'The Best Group', + myRole: 'owner', + }, + }, + errors: undefined, + } + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + expected, + ) + }) - describe('description', () => { - describe('length without HTML', () => { - describe('less then 100 chars', () => { + it('has "disabled" and "deleted" default to "false"', async () => { + const expected = { data: { CreateGroup: { disabled: false, deleted: false } } } + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + expected, + ) + }) + + describe('description', () => { + describe('length without HTML', () => { + describe('less then 100 chars', () => { + it('throws error: "Too view categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { + ...variables, + description: + '0123456789' + + '0123456789', + }, + }) + expect(errors[0]).toHaveProperty('message', 'Description too short!') + }) + }) + }) + }) + + describe('categories', () => { + beforeEach(() => { + CONFIG.CATEGORIES_ACTIVE = true + }) + + describe('not even one', () => { it('throws error: "Too view categories!"', async () => { const { errors } = await mutate({ mutation: createGroupMutation, - variables: { - ...variables, - description: - '0123456789' + - '0123456789', - }, + variables: { ...variables, categoryIds: null }, }) - expect(errors[0]).toHaveProperty('message', 'Description too short!') + expect(errors[0]).toHaveProperty('message', 'Too view categories!') }) }) - }) - }) - describe('categories', () => { - beforeEach(() => { - CONFIG.CATEGORIES_ACTIVE = true - }) - - describe('not even one', () => { - it('throws error: "Too view categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { ...variables, categoryIds: null }, + describe('four', () => { + it('throws error: "Too many categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, + }) + expect(errors[0]).toHaveProperty('message', 'Too many categories!') }) - expect(errors[0]).toHaveProperty('message', 'Too view categories!') - }) - }) - - describe('four', () => { - it('throws error: "Too many categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, - }) - expect(errors[0]).toHaveProperty('message', 'Too many categories!') }) }) }) }) -}) -describe('Group', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await query({ query: groupQuery, variables: {} }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - let otherUser - - beforeEach(async () => { - otherUser = await Factory.build( - 'user', - { - id: 'other-user', - name: 'Other TestUser', - }, - { - email: 'test2@example.org', - password: '1234', - }, - ) - authenticatedUser = await otherUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'others-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'global', - categoryIds, - }, - }) - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'my-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, + describe('Group', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await query({ query: groupQuery, variables: {} }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('query groups', () => { - describe('without any filters', () => { - it('finds all groups', async () => { - const expected = { - data: { - Group: expect.arrayContaining([ - expect.objectContaining({ - id: 'my-group', - slug: 'the-best-group', - myRole: 'owner', - }), - expect.objectContaining({ - id: 'others-group', - slug: 'uninteresting-group', - myRole: null, - }), - ]), - }, - errors: undefined, - } - await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected) + describe('authenticated', () => { + let otherUser + + beforeEach(async () => { + otherUser = await Factory.build( + 'user', + { + id: 'other-user', + name: 'Other TestUser', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + authenticatedUser = await otherUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'others-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'my-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, }) }) - describe('isMember = true', () => { - it('finds only groups where user is member', async () => { - const expected = { - data: { - Group: [ - { - id: 'my-group', - slug: 'the-best-group', - myRole: 'owner', + describe('query groups', () => { + describe('without any filters', () => { + it('finds all groups', async () => { + const expected = { + data: { + Group: expect.arrayContaining([ + expect.objectContaining({ + id: 'my-group', + slug: 'the-best-group', + myRole: 'owner', + }), + expect.objectContaining({ + id: 'others-group', + slug: 'uninteresting-group', + myRole: null, + }), + ]), + }, + errors: undefined, + } + await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject( + expected, + ) + }) + }) + + describe('isMember = true', () => { + it('finds only groups where user is member', async () => { + const expected = { + data: { + Group: [ + { + id: 'my-group', + slug: 'the-best-group', + myRole: 'owner', + }, + ], + }, + errors: undefined, + } + await expect( + query({ query: groupQuery, variables: { isMember: true } }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('isMember = false', () => { + it('finds only groups where user is not(!) member', async () => { + const expected = { + data: { + Group: expect.arrayContaining([ + expect.objectContaining({ + id: 'others-group', + slug: 'uninteresting-group', + myRole: null, + }), + ]), + }, + errors: undefined, + } + await expect( + query({ query: groupQuery, variables: { isMember: false } }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + }) + + describe('JoinGroup', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + userId: 'current-user', + } + const { errors } = await mutate({ mutation: joinGroupMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser + + beforeEach(async () => { + // create users + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + // create groups + // public-group + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + }) + + describe('public group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "usual" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', }, - ], - }, - errors: undefined, - } - await expect( - query({ query: groupQuery, variables: { isMember: true } }), - ).resolves.toMatchObject(expected) + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'public-group', + userId: 'current-user', + } + const expected = { + data: { + JoinGroup: { + id: 'current-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) }) }) - describe('isMember = false', () => { - it('finds only groups where user is not(!) member', async () => { - const expected = { - data: { - Group: expect.arrayContaining([ - expect.objectContaining({ - id: 'others-group', - slug: 'uninteresting-group', - myRole: null, + describe('closed group', () => { + describe('entered by "current-user"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'current-user', + } + const expected = { + data: { + JoinGroup: { + id: 'current-user', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'closed-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, }), - ]), - }, - errors: undefined, + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + + describe('hidden group', () => { + describe('entered by "owner-of-closed-group"', () => { + it('has "pending" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-closed-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + + describe('entered by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + variables = { + id: 'hidden-group', + userId: 'owner-of-hidden-group', + } + const expected = { + data: { + JoinGroup: { + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + } + await expect( + mutate({ + mutation: joinGroupMutation, + variables, + }), + ).resolves.toMatchObject(expected) + }) + }) + }) + }) + }) + }) + + describe('GroupMember', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + } + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + let otherUser + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser + + beforeEach(async () => { + // create users + otherUser = await Factory.build( + 'user', + { + id: 'other-user', + name: 'Other TestUser', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + // create groups + // public-group + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-closed-group', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-hidden-group', + }, + }) + // closed-group + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'current-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'owner-of-hidden-group', + }, + }) + // hidden-group + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'current-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'owner-of-closed-group', + }, + }) + + authenticatedUser = await user.toJson() + }) + + describe('public group', () => { + beforeEach(async () => { + variables = { + id: 'public-group', } - await expect( - query({ query: groupQuery, variables: { isMember: false } }), - ).resolves.toMatchObject(expected) + }) + + describe('query group members', () => { + describe('by owner "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by usual member "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + }) + }) + + describe('closed group', () => { + beforeEach(async () => { + variables = { + id: 'closed-group', + } + }) + + describe('query group members', () => { + describe('by owner "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'pending', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by usual member "owner-of-hidden-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'closed-group', + userId: 'owner-of-hidden-group', + roleInGroup: 'usual', + }, + }) + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by pending member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + + describe('hidden group', () => { + beforeEach(async () => { + variables = { + id: 'hidden-group', + } + }) + + describe('query group members', () => { + describe('by owner "owner-of-hidden-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by usual member "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'hidden-group', + userId: 'owner-of-closed-group', + roleInGroup: 'usual', + }, + }) + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), + }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(3) + }) + }) + + describe('by pending member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) }) }) }) }) }) -describe('JoinGroup', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - userId: 'current-user', - } - const { errors } = await mutate({ mutation: joinGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) +describe('in mode: building up', () => { + beforeAll(async () => { + await seedBasicsAndClearAuthentication() }) - describe('authenticated', () => { - let ownerOfClosedGroupUser - let ownerOfHiddenGroupUser + afterAll(async () => { + await cleanDatabase() + }) - beforeEach(async () => { + describe('SwitchGroupMemberRole', () => { + let pendingMemberUser + let usualMemberUser + let adminMemberUser + let ownerMemberUser + let secondOwnerMemberUser + + beforeAll(async () => { // create users - ownerOfClosedGroupUser = await Factory.build( + pendingMemberUser = await Factory.build( 'user', { - id: 'owner-of-closed-group', - name: 'Owner Of Closed Group', + id: 'pending-member-user', + name: 'Pending Member TestUser', }, { - email: 'owner-of-closed-group@example.org', + email: 'pending-member-user@example.org', password: '1234', }, ) - ownerOfHiddenGroupUser = await Factory.build( + usualMemberUser = await Factory.build( 'user', { - id: 'owner-of-hidden-group', - name: 'Owner Of Hidden Group', + id: 'usual-member-user', + name: 'Usual Member TestUser', }, { - email: 'owner-of-hidden-group@example.org', + email: 'usual-member-user@example.org', + password: '1234', + }, + ) + adminMemberUser = await Factory.build( + 'user', + { + id: 'admin-member-user', + name: 'Admin Member TestUser', + }, + { + email: 'admin-member-user@example.org', + password: '1234', + }, + ) + ownerMemberUser = await Factory.build( + 'user', + { + id: 'owner-member-user', + name: 'Owner Member TestUser', + }, + { + email: 'owner-member-user@example.org', + password: '1234', + }, + ) + secondOwnerMemberUser = await Factory.build( + 'user', + { + id: 'second-owner-member-user', + name: 'Second Owner Member TestUser', + }, + { + email: 'second-owner-member-user@example.org', password: '1234', }, ) // create groups // public-group - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - authenticatedUser = await user.toJson() + authenticatedUser = await usualMemberUser.toJson() await mutate({ mutation: createGroupMutation, variables: { @@ -407,362 +1128,105 @@ describe('JoinGroup', () => { categoryIds, }, }) - }) - - describe('public group', () => { - describe('entered by "owner-of-closed-group"', () => { - it('has "usual" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - JoinGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-closed-group', + }, }) - - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'current-user', - } - const expected = { - data: { - JoinGroup: { - id: 'current-user', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-hidden-group', + }, + }) + // closed-group + authenticatedUser = await ownerMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'pending-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'usual-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'admin-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'second-owner-member-user', + }, + }) + // hidden-group + authenticatedUser = await adminMemberUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'admin-member-user', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'second-owner-member-user', + }, }) }) - describe('closed group', () => { - describe('entered by "current-user"', () => { - it('has "pending" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'current-user', - } - const expected = { - data: { - JoinGroup: { - id: 'current-user', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - JoinGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - }) - }) - - describe('hidden group', () => { - describe('entered by "owner-of-closed-group"', () => { - it('has "pending" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-closed-group', - } - const expected = { - data: { - JoinGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - - describe('entered by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-hidden-group', - } - const expected = { - data: { - JoinGroup: { - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) - }) - }) - }) - }) - }) -}) - -describe('SwitchGroupMemberRole', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - userId: 'current-user', - roleInGroup: 'pending', - } - const { errors } = await mutate({ mutation: switchGroupMemberRoleMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - describe('in building up mode', () => { - let pendingMemberUser - let usualMemberUser - let adminMemberUser - let ownerMemberUser - let secondOwnerMemberUser - - beforeEach(async () => { - // Wolle: change this to beforeAll? - if (isSeedDb) { - // create users - pendingMemberUser = await Factory.build( - 'user', - { - id: 'pending-member-user', - name: 'Pending Member TestUser', - }, - { - email: 'pending-member-user@example.org', - password: '1234', - }, - ) - usualMemberUser = await Factory.build( - 'user', - { - id: 'usual-member-user', - name: 'Usual Member TestUser', - }, - { - email: 'usual-member-user@example.org', - password: '1234', - }, - ) - adminMemberUser = await Factory.build( - 'user', - { - id: 'admin-member-user', - name: 'Admin Member TestUser', - }, - { - email: 'admin-member-user@example.org', - password: '1234', - }, - ) - ownerMemberUser = await Factory.build( - 'user', - { - id: 'owner-member-user', - name: 'Owner Member TestUser', - }, - { - email: 'owner-member-user@example.org', - password: '1234', - }, - ) - secondOwnerMemberUser = await Factory.build( - 'user', - { - id: 'second-owner-member-user', - name: 'Second Owner Member TestUser', - }, - { - email: 'second-owner-member-user@example.org', - password: '1234', - }, - ) - // create groups - // public-group - authenticatedUser = await usualMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'public-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'public-group', - userId: 'owner-of-closed-group', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'public-group', - userId: 'owner-of-hidden-group', - }, - }) - // closed-group - authenticatedUser = await ownerMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'pending-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'usual-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'admin-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'second-owner-member-user', - }, - }) - // hidden-group - authenticatedUser = await adminMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'hidden-group', - userId: 'admin-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'hidden-group', - userId: 'second-owner-member-user', - }, - }) - - // Wolle - // function sleep(ms) { - // return new Promise(resolve => setTimeout(resolve, ms)); - // } - // await sleep(4 * 1000) - isCleanDbAfterEach = false - isSeedDb = false + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + userId: 'current-user', + roleInGroup: 'pending', } + const { errors } = await mutate({ mutation: switchGroupMemberRoleMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) - afterAll(async () => { - // Wolle: find a better solution - await cleanDatabase() - isCleanDbAfterEach = true - isSeedDb = true - }) + }) + describe('authenticated', () => { describe('in all group types – here "closed-group" for example', () => { beforeEach(async () => { variables = { @@ -890,16 +1354,6 @@ describe('SwitchGroupMemberRole', () => { variables, }), ).resolves.toMatchObject(expected) - // Wolle: - // const groups = await query({ query: groupQuery, variables: {} }) - // console.log('groups.data.Group: ', groups.data.Group) - // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMemberQuery, - // variables: { - // id: 'closed-group', - // }, - // }) - // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) }) }) }) @@ -1590,475 +2044,3 @@ describe('SwitchGroupMemberRole', () => { }) }) }) - -describe('GroupMember', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - } - const { errors } = await query({ query: groupMemberQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - let otherUser - let ownerOfClosedGroupUser - let ownerOfHiddenGroupUser - - beforeEach(async () => { - // create users - otherUser = await Factory.build( - 'user', - { - id: 'other-user', - name: 'Other TestUser', - }, - { - email: 'test2@example.org', - password: '1234', - }, - ) - ownerOfClosedGroupUser = await Factory.build( - 'user', - { - id: 'owner-of-closed-group', - name: 'Owner Of Closed Group', - }, - { - email: 'owner-of-closed-group@example.org', - password: '1234', - }, - ) - ownerOfHiddenGroupUser = await Factory.build( - 'user', - { - id: 'owner-of-hidden-group', - name: 'Owner Of Hidden Group', - }, - { - email: 'owner-of-hidden-group@example.org', - password: '1234', - }, - ) - // create groups - // public-group - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'public-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'public-group', - userId: 'owner-of-closed-group', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'public-group', - userId: 'owner-of-hidden-group', - }, - }) - // closed-group - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'current-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'owner-of-hidden-group', - }, - }) - // hidden-group - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'hidden-group', - userId: 'current-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'hidden-group', - userId: 'owner-of-closed-group', - }, - }) - - authenticatedUser = await user.toJson() - }) - - describe('public group', () => { - beforeEach(async () => { - variables = { - id: 'public-group', - } - }) - - describe('query group members', () => { - describe('by owner "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - - describe('by usual member "owner-of-closed-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - - describe('by none member "other-user"', () => { - beforeEach(async () => { - authenticatedUser = await otherUser.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - }) - }) - - describe('closed group', () => { - beforeEach(async () => { - variables = { - id: 'closed-group', - } - }) - - describe('query group members', () => { - describe('by owner "owner-of-closed-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'pending', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - - describe('by usual member "owner-of-hidden-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: switchGroupMemberRoleMutation, - variables: { - id: 'closed-group', - userId: 'owner-of-hidden-group', - roleInGroup: 'usual', - }, - }) - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - - describe('by pending member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('by none member "other-user"', () => { - beforeEach(async () => { - authenticatedUser = await otherUser.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - - describe('hidden group', () => { - beforeEach(async () => { - variables = { - id: 'hidden-group', - } - }) - - describe('query group members', () => { - describe('by owner "owner-of-hidden-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - - describe('by usual member "owner-of-closed-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: switchGroupMemberRoleMutation, - variables: { - id: 'hidden-group', - userId: 'owner-of-closed-group', - roleInGroup: 'usual', - }, - }) - authenticatedUser = await ownerOfClosedGroupUser.toJson() - }) - - it('finds all members', async () => { - const expected = { - data: { - GroupMember: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }), - ]), - }, - errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, - }) - expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) - }) - }) - - describe('by pending member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('by none member "other-user"', () => { - beforeEach(async () => { - authenticatedUser = await otherUser.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - }) -}) From f9c8c9b4be2165f1e1187d0b4b2f87e2a73424a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 11:27:18 +0200 Subject: [PATCH 23/67] Add different group member roles to seeding --- backend/src/db/seed.js | 113 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index f9b2d05da..a2be78553 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -5,7 +5,11 @@ import createServer from '../server' import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' -import { createGroupMutation, joinGroupMutation } from './graphql/groups' +import { + createGroupMutation, + joinGroupMutation, + switchGroupMemberRoleMutation, +} from './graphql/groups' import { createPostMutation } from './graphql/posts' import { createCommentMutation } from './graphql/comments' @@ -415,6 +419,46 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] userId: 'u3', }, }), + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'g0', + userId: 'u4', + }, + }), + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'g0', + userId: 'u6', + }, + }), + ]) + await Promise.all([ + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u2', + roleInGroup: 'usual', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u4', + roleInGroup: 'admin', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u3', + roleInGroup: 'owner', + }, + }), ]) authenticatedUser = await jennyRostock.toJson() @@ -440,6 +484,13 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] userId: 'u1', }, }), + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'g1', + userId: 'u2', + }, + }), mutate({ mutation: joinGroupMutation, variables: { @@ -462,6 +513,40 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), ]) + await Promise.all([ + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u1', + roleInGroup: 'usual', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u2', + roleInGroup: 'usual', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u5', + roleInGroup: 'admin', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u6', + roleInGroup: 'owner', + }, + }), + ]) authenticatedUser = await bobDerBaumeister.toJson() await Promise.all([ @@ -508,6 +593,32 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), ]) + await Promise.all([ + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u4', + roleInGroup: 'usual', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u5', + roleInGroup: 'usual', + }, + }), + mutate({ + mutation: switchGroupMemberRoleMutation, + variables: { + id: 'g0', + userId: 'u6', + roleInGroup: 'usual', + }, + }), + ]) // Create Posts From b3c179011a05d30fab24bd925c0f56c5796e0a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 11:45:51 +0200 Subject: [PATCH 24/67] Add URL comment for sleep --- backend/src/helpers/jest.js | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/helpers/jest.js b/backend/src/helpers/jest.js index bb0ab9d7c..e3f6a3c84 100644 --- a/backend/src/helpers/jest.js +++ b/backend/src/helpers/jest.js @@ -10,6 +10,7 @@ export function gql(strings) { // sometime we have to wait to check a db state by having a look into the db in a certain moment // or we wait a bit to check if we missed to set an await somewhere +// see: https://www.sitepoint.com/delay-sleep-pause-wait/ export function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)) } From dee20c25a9c2a4765173ecba8336cca9603fa920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 11:46:41 +0200 Subject: [PATCH 25/67] Add test todo for 'has "updatedAt" newer as "createdAt"' --- backend/src/schema/resolvers/groups.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 1a1386118..22bac6da7 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -1273,6 +1273,9 @@ describe('in mode: building up', () => { }), ).resolves.toMatchObject(expected) }) + + // the GQL mutation needs this fields in the result for testing + it.todo('has "updatedAt" newer as "createdAt"') }) }) From 9312e66b154b60e41da6ad8cf867b0d3ae0c6cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 22 Aug 2022 12:53:27 +0200 Subject: [PATCH 26/67] Add bigger JS heap size to backend tests --- backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index e619874af..c19019ca1 100644 --- a/backend/package.json +++ b/backend/package.json @@ -15,7 +15,7 @@ "dev": "nodemon --exec babel-node src/ -e js,gql", "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", "lint": "eslint src --config .eslintrc.js", - "test": "cross-env NODE_ENV=test jest --forceExit --detectOpenHandles --runInBand --coverage --logHeapUsage", + "test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --forceExit --detectOpenHandles --runInBand --coverage --logHeapUsage", "db:clean": "babel-node src/db/clean.js", "db:reset": "yarn run db:clean", "db:seed": "babel-node src/db/seed.js", From a22023174d4b9c7afc24530331daf6c7c85fb3fc Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 18:33:12 +0200 Subject: [PATCH 27/67] feat: Show Categories Filter when Categories are Active --- webapp/components/FilterMenu/FilterMenu.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webapp/components/FilterMenu/FilterMenu.vue b/webapp/components/FilterMenu/FilterMenu.vue index 9e211ccf9..84c7c1f67 100644 --- a/webapp/components/FilterMenu/FilterMenu.vue +++ b/webapp/components/FilterMenu/FilterMenu.vue @@ -14,6 +14,7 @@

{{ $t('filter-menu.filter-by') }}

+

{{ $t('filter-menu.order-by') }}

@@ -28,17 +29,24 @@ import Dropdown from '~/components/Dropdown' import { mapGetters } from 'vuex' import FollowingFilter from './FollowingFilter' import OrderByFilter from './OrderByFilter' +import CategoriesFilter from './CategoriesFilter' export default { components: { Dropdown, FollowingFilter, + CategoriesFilter, OrderByFilter, }, props: { placement: { type: String }, offset: { type: [String, Number] }, }, + data() { + return { + categoriesActive: this.$env.CATEGORIES_ACTIVE, + } + }, computed: { ...mapGetters({ filterActive: 'posts/isActive', From eddaa96d367e2be279eb5dfcbf3b0560b35357cb Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 18:52:42 +0200 Subject: [PATCH 28/67] add movement icon --- webapp/assets/_new/icons/svgs/movement.svg | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 webapp/assets/_new/icons/svgs/movement.svg diff --git a/webapp/assets/_new/icons/svgs/movement.svg b/webapp/assets/_new/icons/svgs/movement.svg new file mode 100644 index 000000000..ac5cd9cc0 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/movement.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + From c1f1408f6c7670f9305643b7440e5c9af0b17beb Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 19:17:50 +0200 Subject: [PATCH 29/67] add yunite categories --- backend/src/constants/categories.js | 98 +++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 backend/src/constants/categories.js diff --git a/backend/src/constants/categories.js b/backend/src/constants/categories.js new file mode 100644 index 000000000..d38f64b1a --- /dev/null +++ b/backend/src/constants/categories.js @@ -0,0 +1,98 @@ +export const categories = [ + { + icon: 'users', + name: 'networking', + description: 'Kooperation, Aktionsbündnisse, Solidarität, Hilfe', + }, + { + icon: 'home', + name: 'home', + description: 'Bauen, Lebensgemeinschaften, Tiny Houses, Gemüsegarten', + }, + { + icon: 'lightbulb', + name: 'energy', + description: 'Öl, Gas, Kohle, Wind, Wasserkraft, Biogas, Atomenergie, ...', + }, + { + icon: 'smile', + name: 'psyche', + description: 'Seele, Gefühle, Glück', + }, + { + icon: 'movement', + name: 'body-and-excercise', + description: 'Sport, Yoga, Massage, Tanzen, Entspannung', + }, + { + icon: 'balance-scale', + name: 'law', + description: 'Menschenrechte, Gesetze, Verordnungen', + }, + { + icon: 'money', + name: 'finance', + description: 'Geld, Finanzsystem, Alternativwährungen, ...', + }, + { + icon: 'child', + name: 'children', + description: 'Familie, Pädagogik, Schule, Prägung', + }, + { + icon: 'suitcase', + name: 'mobility', + description: 'Reise, Verkehr, Elektromobilität', + }, + { + icon: 'shopping-cart', + name: 'economy', + description: 'Handel, Konsum, Marketing, Lebensmittel, Lieferketten, ...', + }, + { + icon: 'angellist', + name: 'peace', + description: 'Krieg, Militär, soziale Verteidigung, Waffen, Cyberattacken', + }, + { + icon: 'university', + name: 'politics', + description: 'Demokratie, Mitbestimmung, Wahlen, Korruption, Parteien', + }, + { + icon: 'tree', + name: 'nature', + description: 'Tiere, Pflanzen, Landwirtschaft, Ökologie, Artenvielfalt', + }, + { + icon: 'graduation-cap', + name: 'science', + description: 'Bildung, Hochschule, Publikationen, ...', + }, + { + icon: 'medkit', + name: 'health', + description: 'Medizin, Ernährung, WHO, Impfungen, Schadstoffe, ...', + }, + { + icon: 'desktop', + name: 'IT-and-media', + description: + 'Nachrichten, Manipulation, Datenschutz, Überwachung, Datenkraken, AI, Software, Apps', + }, + { + icon: 'heart-o', + name: 'spirituality', + description: 'Religion, Werte, Ethik', + }, + { + icon: 'music', + name: 'culture', + description: 'Kunst, Theater, Musik, Fotografie, Film', + }, + { + icon: 'ellipsis-h', + name: 'miscellaneous', + description: '', + }, +] From 6425e5d172fa06020f46d1c3a9d1fcf5266c9cf2 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 19:44:20 +0200 Subject: [PATCH 30/67] seed categories on db:migrate init --- backend/src/db/migrate/store.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index 377caf0b0..0361e874b 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -1,6 +1,8 @@ import { getDriver, getNeode } from '../../db/neo4j' import { hashSync } from 'bcryptjs' import { v4 as uuid } from 'uuid' +import { categories } from '../../constants/categories' +import CONFIG from '../../config' const defaultAdmin = { email: 'admin@example.org', @@ -10,6 +12,27 @@ const defaultAdmin = { slug: 'admin', } +const createCategories = async (session) => { + const createCategoriesTxResultPromise = session.writeTransaction(async (txc) => { + categories.forEach(({ icon, name }, index) => { + const id = `cat${index + 1}` + txc.run( + `MERGE (c:Category { + icon: "${icon}", + slug: "${name}", + id: "${id}", + createdAt: toString(datetime()) + })`, + ) + }) + }) + try { + await createCategoriesTxResultPromise + } catch (error) { + console.log(`Error creating categories: ${error}`) // eslint-disable-line no-console + } +} + const createDefaultAdminUser = async (session) => { const readTxResultPromise = session.readTransaction(async (txc) => { const result = await txc.run('MATCH (user:User) RETURN count(user) AS userCount') @@ -58,6 +81,7 @@ class Store { const { driver } = neode const session = driver.session() await createDefaultAdminUser(session) + if (CONFIG.CATEGORIES_ACTIVE) await createCategories(session) const writeTxResultPromise = session.writeTransaction(async (txc) => { await txc.run('CALL apoc.schema.assert({},{},true)') // drop all indices return Promise.all( From 5b7bdc02913e7b3aad12dced5725441010e34045 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 19:56:35 +0200 Subject: [PATCH 31/67] seed Yunite categories --- backend/src/db/factories.js | 1 - backend/src/db/seed.js | 106 +++------------------------------ backend/src/models/Category.js | 4 +- 3 files changed, 10 insertions(+), 101 deletions(-) diff --git a/backend/src/db/factories.js b/backend/src/db/factories.js index 3e164d51b..f46ac10ee 100644 --- a/backend/src/db/factories.js +++ b/backend/src/db/factories.js @@ -35,7 +35,6 @@ export const cleanDatabase = async (options = {}) => { Factory.define('category') .attr('id', uuid) .attr('icon', 'globe') - .attr('name', 'Global Peace & Nonviolence') .after((buildObject, options) => { return neode.create('Category', buildObject) }) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 46c5870e0..eb79d5aa2 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -6,6 +6,7 @@ import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' import { gql } from '../helpers/jest' +import { categories } from '../constants/categories' if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) { throw new Error(`You cannot seed the database in a non-staging and real production environment!`) @@ -267,104 +268,15 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] dagobert.relateTo(louie, 'blocked'), ]) - await Promise.all([ - Factory.build('category', { - id: 'cat1', - name: 'Just For Fun', - slug: 'just-for-fun', - icon: 'smile', + await Promise.all( + categories.map(({ icon, name }, index) => { + Factory.build('category', { + id: `cat${index + 1}`, + slug: name, + icon, + }) }), - Factory.build('category', { - id: 'cat2', - name: 'Happiness & Values', - slug: 'happiness-values', - icon: 'heart-o', - }), - Factory.build('category', { - id: 'cat3', - name: 'Health & Wellbeing', - slug: 'health-wellbeing', - icon: 'medkit', - }), - Factory.build('category', { - id: 'cat4', - name: 'Environment & Nature', - slug: 'environment-nature', - icon: 'tree', - }), - Factory.build('category', { - id: 'cat5', - name: 'Animal Protection', - slug: 'animal-protection', - icon: 'paw', - }), - Factory.build('category', { - id: 'cat6', - name: 'Human Rights & Justice', - slug: 'human-rights-justice', - icon: 'balance-scale', - }), - Factory.build('category', { - id: 'cat7', - name: 'Education & Sciences', - slug: 'education-sciences', - icon: 'graduation-cap', - }), - Factory.build('category', { - id: 'cat8', - name: 'Cooperation & Development', - slug: 'cooperation-development', - icon: 'users', - }), - Factory.build('category', { - id: 'cat9', - name: 'Democracy & Politics', - slug: 'democracy-politics', - icon: 'university', - }), - Factory.build('category', { - id: 'cat10', - name: 'Economy & Finances', - slug: 'economy-finances', - icon: 'money', - }), - Factory.build('category', { - id: 'cat11', - name: 'Energy & Technology', - slug: 'energy-technology', - icon: 'flash', - }), - Factory.build('category', { - id: 'cat12', - name: 'IT, Internet & Data Privacy', - slug: 'it-internet-data-privacy', - icon: 'mouse-pointer', - }), - Factory.build('category', { - id: 'cat13', - name: 'Art, Culture & Sport', - slug: 'art-culture-sport', - icon: 'paint-brush', - }), - Factory.build('category', { - id: 'cat14', - name: 'Freedom of Speech', - slug: 'freedom-of-speech', - icon: 'bullhorn', - }), - Factory.build('category', { - id: 'cat15', - name: 'Consumption & Sustainability', - slug: 'consumption-sustainability', - icon: 'shopping-cart', - }), - Factory.build('category', { - id: 'cat16', - name: 'Global Peace & Nonviolence', - slug: 'global-peace-nonviolence', - icon: 'angellist', - }), - ]) + ) const [environment, nature, democracy, freedom] = await Promise.all([ Factory.build('tag', { diff --git a/backend/src/models/Category.js b/backend/src/models/Category.js index ea617adc8..8d87ac0e2 100644 --- a/backend/src/models/Category.js +++ b/backend/src/models/Category.js @@ -2,15 +2,13 @@ import { v4 as uuid } from 'uuid' export default { id: { type: 'string', primary: true, default: uuid }, - name: { type: 'string', required: true, default: false }, slug: { type: 'string', unique: 'true' }, icon: { type: 'string', required: true, default: false }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, updatedAt: { type: 'string', isoDate: true, - required: true, - default: () => new Date().toISOString(), + required: false, }, post: { type: 'relationship', From 25c8fe275f61c886f7634e68565fd7aa87875343 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 20:11:21 +0200 Subject: [PATCH 32/67] add locales for yunite categories --- backend/src/constants/categories.js | 2 +- webapp/locales/de.json | 35 ++++++++++++++++------------- webapp/locales/en.json | 35 ++++++++++++++++------------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/backend/src/constants/categories.js b/backend/src/constants/categories.js index d38f64b1a..146131453 100644 --- a/backend/src/constants/categories.js +++ b/backend/src/constants/categories.js @@ -76,7 +76,7 @@ export const categories = [ }, { icon: 'desktop', - name: 'IT-and-media', + name: 'it-and-media', description: 'Nachrichten, Manipulation, Datenschutz, Überwachung, Datenkraken, AI, Software, Apps', }, diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 297daa511..dee8d086a 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -218,22 +218,25 @@ }, "category": { "name": { - "animal-protection": "Schutz der Tiere", - "art-culture-sport": "Kunst, Kultur & Sport", - "consumption-sustainability": "Verbrauch & Nachhaltigkeit", - "cooperation-development": "Zusammenarbeit & Entwicklung", - "democracy-politics": "Demokratie & Politik", - "economy-finances": "Wirtschaft & Finanzen", - "education-sciences": "Bildung & Wissenschaft", - "energy-technology": "Energie & Technologie", - "environment-nature": "Umwelt & Natur", - "freedom-of-speech": "Redefreiheit", - "global-peace-nonviolence": "Globaler Frieden & Gewaltlosigkeit", - "happiness-values": "Glück & Werte", - "health-wellbeing": "Gesundheit & Wohlbefinden", - "human-rights-justice": "Menschenrechte & Gerechtigkeit", - "it-internet-data-privacy": "IT, Internet & Datenschutz", - "just-for-fun": "Nur zum Spaß" + "body-and-excercise": "Körper & Bewegung", + "children": "Kinder", + "culture": "Kultur", + "economy": "Wirtschaft", + "energy": "Energie", + "finance": "Finanzen", + "health": "Gesundheit", + "home": "Wohnen", + "it-and-media": "IT & Medien", + "law": "Recht", + "miscellaneous": "Sonstiges", + "mobility": "Mobilität", + "nature": "Natur", + "networking": "Vernetzung", + "peace": "Frieden", + "politics": "Politik", + "psyche": "Psyche", + "science": "Wissenschaft", + "spirituality": "Spiritualität" } }, "emotions-label": { diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 8499b0290..d6172c257 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -218,22 +218,25 @@ }, "category": { "name": { - "animal-protection": "Animal Protection", - "art-culture-sport": "Art, Culture, & Sport", - "consumption-sustainability": "Consumption & Sustainability", - "cooperation-development": "Cooperation & Development", - "democracy-politics": "Democracy & Politics", - "economy-finances": "Economy & Finances", - "education-sciences": "Education & Sciences", - "energy-technology": "Energy & Technology", - "environment-nature": "Environment & Nature", - "freedom-of-speech": "Freedom of Speech", - "global-peace-nonviolence": "Global Peace & Nonviolence", - "happiness-values": "Happiness & Values", - "health-wellbeing": "Health & Wellbeing", - "human-rights-justice": "Human Rights & Justice", - "it-internet-data-privacy": "IT, Internet & Data Privacy", - "just-for-fun": "Just for Fun" + "body-and-excercise": "Body & Excercise", + "children": "Children", + "culture": "Culture", + "economy": "Economy", + "energy": "Energy", + "finance": "Finance", + "health": "Health", + "home": "Home", + "it-and-media": "IT & Media", + "law": "Law", + "miscellaneous": "Miscellaneous", + "mobility": "Mobility", + "nature": "Nature", + "networking": "Networking", + "peace": "Peace", + "politics": "Politics", + "psyche": "Psyche", + "science": "Science", + "spirituality": "Spirituality" } }, "emotions-label": { From ad4497786ce9b26171846a9fa9881dc67aa9f371 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 20:29:04 +0200 Subject: [PATCH 33/67] add missing items for categories --- webapp/assets/_new/icons/svgs/child.svg | 5 +++++ webapp/assets/_new/icons/svgs/desktop.svg | 5 +++++ webapp/assets/_new/icons/svgs/ellipsis-h.svg | 5 +++++ webapp/assets/_new/icons/svgs/home.svg | 5 +++++ webapp/assets/_new/icons/svgs/lightbulb.svg | 5 +++++ webapp/assets/_new/icons/svgs/music.svg | 5 +++++ webapp/assets/_new/icons/svgs/suitcase.svg | 5 +++++ 7 files changed, 35 insertions(+) create mode 100644 webapp/assets/_new/icons/svgs/child.svg create mode 100644 webapp/assets/_new/icons/svgs/desktop.svg create mode 100644 webapp/assets/_new/icons/svgs/ellipsis-h.svg create mode 100644 webapp/assets/_new/icons/svgs/home.svg create mode 100644 webapp/assets/_new/icons/svgs/lightbulb.svg create mode 100644 webapp/assets/_new/icons/svgs/music.svg create mode 100644 webapp/assets/_new/icons/svgs/suitcase.svg diff --git a/webapp/assets/_new/icons/svgs/child.svg b/webapp/assets/_new/icons/svgs/child.svg new file mode 100644 index 000000000..fcb5651f0 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/child.svg @@ -0,0 +1,5 @@ + + +child + + diff --git a/webapp/assets/_new/icons/svgs/desktop.svg b/webapp/assets/_new/icons/svgs/desktop.svg new file mode 100644 index 000000000..ba1ef8431 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/desktop.svg @@ -0,0 +1,5 @@ + + +desktop + + diff --git a/webapp/assets/_new/icons/svgs/ellipsis-h.svg b/webapp/assets/_new/icons/svgs/ellipsis-h.svg new file mode 100644 index 000000000..eb7deeab0 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/ellipsis-h.svg @@ -0,0 +1,5 @@ + + +ellipsis-h + + diff --git a/webapp/assets/_new/icons/svgs/home.svg b/webapp/assets/_new/icons/svgs/home.svg new file mode 100644 index 000000000..b1a13b06f --- /dev/null +++ b/webapp/assets/_new/icons/svgs/home.svg @@ -0,0 +1,5 @@ + + +home + + diff --git a/webapp/assets/_new/icons/svgs/lightbulb.svg b/webapp/assets/_new/icons/svgs/lightbulb.svg new file mode 100644 index 000000000..1c19c81b1 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/lightbulb.svg @@ -0,0 +1,5 @@ + + +lightbulb-o + + diff --git a/webapp/assets/_new/icons/svgs/music.svg b/webapp/assets/_new/icons/svgs/music.svg new file mode 100644 index 000000000..b84b87800 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/music.svg @@ -0,0 +1,5 @@ + + +music + + diff --git a/webapp/assets/_new/icons/svgs/suitcase.svg b/webapp/assets/_new/icons/svgs/suitcase.svg new file mode 100644 index 000000000..ceca5cbad --- /dev/null +++ b/webapp/assets/_new/icons/svgs/suitcase.svg @@ -0,0 +1,5 @@ + + +suitcase + + From d948067f44a1d6caf492dde222d97564d824940c Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 22 Aug 2022 20:47:37 +0200 Subject: [PATCH 34/67] add category name again to seed and init to avoid conflicts with graphql model --- backend/src/db/factories.js | 1 + backend/src/db/migrate/store.js | 1 + backend/src/db/seed.js | 1 + backend/src/models/Category.js | 1 + backend/src/schema/resolvers/posts.js | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/db/factories.js b/backend/src/db/factories.js index f46ac10ee..3e164d51b 100644 --- a/backend/src/db/factories.js +++ b/backend/src/db/factories.js @@ -35,6 +35,7 @@ export const cleanDatabase = async (options = {}) => { Factory.define('category') .attr('id', uuid) .attr('icon', 'globe') + .attr('name', 'Global Peace & Nonviolence') .after((buildObject, options) => { return neode.create('Category', buildObject) }) diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index 0361e874b..61d591cb7 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -20,6 +20,7 @@ const createCategories = async (session) => { `MERGE (c:Category { icon: "${icon}", slug: "${name}", + name: "${name}", id: "${id}", createdAt: toString(datetime()) })`, diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index eb79d5aa2..482517e69 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -273,6 +273,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] Factory.build('category', { id: `cat${index + 1}`, slug: name, + name, icon, }) }), diff --git a/backend/src/models/Category.js b/backend/src/models/Category.js index 8d87ac0e2..9a3f47fd0 100644 --- a/backend/src/models/Category.js +++ b/backend/src/models/Category.js @@ -2,6 +2,7 @@ import { v4 as uuid } from 'uuid' export default { id: { type: 'string', primary: true, default: uuid }, + name: { type: 'string', required: true, default: false }, slug: { type: 'string', unique: 'true' }, icon: { type: 'string', required: true, default: false }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, diff --git a/backend/src/schema/resolvers/posts.js b/backend/src/schema/resolvers/posts.js index b09bb3edd..d9a04732c 100644 --- a/backend/src/schema/resolvers/posts.js +++ b/backend/src/schema/resolvers/posts.js @@ -358,7 +358,7 @@ export default { undefinedToNull: ['activityId', 'objectId', 'language', 'pinnedAt', 'pinned'], hasMany: { tags: '-[:TAGGED]->(related:Tag)', - // categories: '-[:CATEGORIZED]->(related:Category)', + categories: '-[:CATEGORIZED]->(related:Category)', comments: '<-[:COMMENTS]-(related:Comment)', shoutedBy: '<-[:SHOUTED]-(related:User)', emotions: '<-[related:EMOTED]', From e3549d3aa99cefbb21b4e3e5d919613d9a7d56a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 05:11:10 +0200 Subject: [PATCH 35/67] Rename resolver `SwitchGroupMemberRole` to `ChangeGroupMemberRole` Co-Authored-By: Mogge --- backend/src/db/graphql/groups.js | 4 +- backend/src/db/seed.js | 22 ++--- .../src/middleware/permissionsMiddleware.js | 2 +- backend/src/schema/resolvers/groups.js | 2 +- backend/src/schema/resolvers/groups.spec.js | 92 +++++++++---------- backend/src/schema/types/type/Group.gql | 2 +- 6 files changed, 62 insertions(+), 62 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index 41780f7cd..2a9647860 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -50,9 +50,9 @@ export const joinGroupMutation = gql` } ` -export const switchGroupMemberRoleMutation = gql` +export const changeGroupMemberRoleMutation = gql` mutation ($id: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) { - SwitchGroupMemberRole(id: $id, userId: $userId, roleInGroup: $roleInGroup) { + ChangeGroupMemberRole(id: $id, userId: $userId, roleInGroup: $roleInGroup) { id name slug diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index a2be78553..0010b09ef 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -8,7 +8,7 @@ import { getNeode, getDriver } from '../db/neo4j' import { createGroupMutation, joinGroupMutation, - switchGroupMemberRoleMutation, + changeGroupMemberRoleMutation, } from './graphql/groups' import { createPostMutation } from './graphql/posts' import { createCommentMutation } from './graphql/comments' @@ -436,7 +436,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) await Promise.all([ mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u2', @@ -444,7 +444,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u4', @@ -452,7 +452,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u3', @@ -515,7 +515,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) await Promise.all([ mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u1', @@ -523,7 +523,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u2', @@ -531,7 +531,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u5', @@ -539,7 +539,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u6', @@ -595,7 +595,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) await Promise.all([ mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u4', @@ -603,7 +603,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u5', @@ -611,7 +611,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, }), mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'g0', userId: 'u6', diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index e3e3b3eb0..a3935872e 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -259,7 +259,7 @@ export default shield( UpdateUser: onlyYourself, CreateGroup: isAuthenticated, JoinGroup: isAuthenticated, // Wolle: can not be correct - SwitchGroupMemberRole: isAllowedToSwitchGroupMemberRole, + ChangeGroupMemberRole: isAllowedToSwitchGroupMemberRole, CreatePost: isAuthenticated, UpdatePost: isAuthor, DeletePost: isAuthor, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 34959908d..ca24ef55f 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -160,7 +160,7 @@ export default { session.close() } }, - SwitchGroupMemberRole: async (_parent, params, context, _resolveInfo) => { + ChangeGroupMemberRole: async (_parent, params, context, _resolveInfo) => { const { id: groupId, userId, roleInGroup } = params // Wolle // console.log('groupId: ', groupId) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 22bac6da7..23fc5646e 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -3,7 +3,7 @@ import Factory, { cleanDatabase } from '../../db/factories' import { createGroupMutation, joinGroupMutation, - switchGroupMemberRoleMutation, + changeGroupMemberRoleMutation, groupMemberQuery, groupQuery, } from '../../db/graphql/groups' @@ -865,7 +865,7 @@ describe('in mode: always clean db', () => { beforeEach(async () => { authenticatedUser = await ownerOfClosedGroupUser.toJson() await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'closed-group', userId: 'owner-of-hidden-group', @@ -974,7 +974,7 @@ describe('in mode: always clean db', () => { beforeEach(async () => { authenticatedUser = await ownerOfHiddenGroupUser.toJson() await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'hidden-group', userId: 'owner-of-closed-group', @@ -1049,7 +1049,7 @@ describe('in mode: building up', () => { await cleanDatabase() }) - describe('SwitchGroupMemberRole', () => { + describe('ChangeGroupMemberRole', () => { let pendingMemberUser let usualMemberUser let adminMemberUser @@ -1221,7 +1221,7 @@ describe('in mode: building up', () => { userId: 'current-user', roleInGroup: 'pending', } - const { errors } = await mutate({ mutation: switchGroupMemberRoleMutation, variables }) + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -1259,7 +1259,7 @@ describe('in mode: building up', () => { it('has role usual', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'usual-member-user', myRoleInGroup: 'usual', }, @@ -1268,7 +1268,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1308,7 +1308,7 @@ describe('in mode: building up', () => { // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'admin-member-user', myRoleInGroup: 'admin', }, @@ -1317,7 +1317,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1344,7 +1344,7 @@ describe('in mode: building up', () => { it('has role owner', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'second-owner-member-user', myRoleInGroup: 'owner', }, @@ -1353,7 +1353,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1387,7 +1387,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1413,7 +1413,7 @@ describe('in mode: building up', () => { it('has role admin', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'owner-member-user', myRoleInGroup: 'admin', }, @@ -1422,7 +1422,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1440,7 +1440,7 @@ describe('in mode: building up', () => { it('has role owner again', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'owner-member-user', myRoleInGroup: 'owner', }, @@ -1449,7 +1449,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1472,7 +1472,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1495,7 +1495,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1518,7 +1518,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1551,7 +1551,7 @@ describe('in mode: building up', () => { it('has role owner', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'admin-member-user', myRoleInGroup: 'owner', }, @@ -1560,7 +1560,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1578,7 +1578,7 @@ describe('in mode: building up', () => { it('has role admin again', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'admin-member-user', myRoleInGroup: 'admin', }, @@ -1587,7 +1587,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1610,7 +1610,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1627,7 +1627,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1650,7 +1650,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1667,7 +1667,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1690,7 +1690,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1707,7 +1707,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1740,7 +1740,7 @@ describe('in mode: building up', () => { it('has role admin', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'usual-member-user', myRoleInGroup: 'admin', }, @@ -1749,7 +1749,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1767,7 +1767,7 @@ describe('in mode: building up', () => { it('has role usual again', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'usual-member-user', myRoleInGroup: 'usual', }, @@ -1776,7 +1776,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1799,7 +1799,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1816,7 +1816,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1839,7 +1839,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1856,7 +1856,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1879,7 +1879,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1896,7 +1896,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -1929,7 +1929,7 @@ describe('in mode: building up', () => { it('has role usual', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'pending-member-user', myRoleInGroup: 'usual', }, @@ -1938,7 +1938,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1956,7 +1956,7 @@ describe('in mode: building up', () => { it('has role usual again', async () => { const expected = { data: { - SwitchGroupMemberRole: { + ChangeGroupMemberRole: { id: 'pending-member-user', myRoleInGroup: 'pending', }, @@ -1965,7 +1965,7 @@ describe('in mode: building up', () => { } await expect( mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }), ).resolves.toMatchObject(expected) @@ -1988,7 +1988,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -2011,7 +2011,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') @@ -2034,7 +2034,7 @@ describe('in mode: building up', () => { it('throws authorization error', async () => { const { errors } = await mutate({ - mutation: switchGroupMemberRoleMutation, + mutation: changeGroupMemberRoleMutation, variables, }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index 270f5c844..f12b98c07 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -119,7 +119,7 @@ type Mutation { userId: ID! ): User - SwitchGroupMemberRole( + ChangeGroupMemberRole( id: ID! userId: ID! roleInGroup: GroupMemberRole! From 3ab33a44f19d17940ec09f9d2a40a1d493100ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 05:21:53 +0200 Subject: [PATCH 36/67] Check permission not given for resolver `ChangeGroupMemberRole` if admin will change their own member role in group already at the beginning of 'isAllowedToChangeGroupMemberRole' Co-Authored-By: Mogge --- backend/src/middleware/permissionsMiddleware.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index a3935872e..a92aacbba 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -55,8 +55,7 @@ const isMySocialMedia = rule({ const isAllowedSeeingMembersOfGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - // Wolle: may have a look to 'isAuthenticated' - if (!user) return false + if (!(user && user.id)) return false const { id: groupId } = args // Wolle: console.log('groupId: ', groupId) // console.log('user.id: ', user.id) @@ -94,13 +93,13 @@ const isAllowedSeeingMembersOfGroup = rule({ } }) -const isAllowedToSwitchGroupMemberRole = rule({ +const isAllowedToChangeGroupMemberRole = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { - // Wolle: may have a look to 'isAuthenticated' - if (!user) return false + if (!(user && user.id)) return false const adminId = user.id const { id: groupId, userId, roleInGroup } = args + if (adminId === userId) return false // Wolle: // console.log('adminId: ', adminId) // console.log('groupId: ', groupId) @@ -151,7 +150,6 @@ const isAllowedToSwitchGroupMemberRole = rule({ !!group && !!admin && !!member && - adminId !== userId && // Wolle: member.myRoleInGroup === roleInGroup && ((['admin'].includes(admin.myRoleInGroup) && !['owner'].includes(member.myRoleInGroup) && @@ -259,7 +257,7 @@ export default shield( UpdateUser: onlyYourself, CreateGroup: isAuthenticated, JoinGroup: isAuthenticated, // Wolle: can not be correct - ChangeGroupMemberRole: isAllowedToSwitchGroupMemberRole, + ChangeGroupMemberRole: isAllowedToChangeGroupMemberRole, CreatePost: isAuthenticated, UpdatePost: isAuthor, DeletePost: isAuthor, From 95cebd577d9793a75aef18906516a0ab669c5998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 10:18:00 +0200 Subject: [PATCH 37/67] Refactor to group joining by `ChangeGroupMemberRole` and that `JoinGroup` is not possible for hidden groups Co-Authored-By: Mogge --- .../src/middleware/permissionsMiddleware.js | 68 ++++- backend/src/schema/resolvers/groups.js | 16 +- backend/src/schema/resolvers/groups.spec.js | 288 ++++++++++-------- 3 files changed, 237 insertions(+), 135 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index a92aacbba..f0ddd04ca 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -101,6 +101,7 @@ const isAllowedToChangeGroupMemberRole = rule({ const { id: groupId, userId, roleInGroup } = args if (adminId === userId) return false // Wolle: + // console.log('isAllowedToChangeGroupMemberRole !!!') // console.log('adminId: ', adminId) // console.log('groupId: ', groupId) // console.log('userId: ', userId) @@ -109,7 +110,8 @@ const isAllowedToChangeGroupMemberRole = rule({ const readTxPromise = session.readTransaction(async (transaction) => { const transactionResponse = await transaction.run( ` - MATCH (admin:User {id: $adminId})-[adminMembership:MEMBER_OF]->(group:Group {id: $groupId})<-[userMembership:MEMBER_OF]-(member:User {id: $userId}) + MATCH (admin:User {id: $adminId})-[adminMembership:MEMBER_OF]->(group:Group {id: $groupId}) + OPTIONAL MATCH (group)<-[userMembership:MEMBER_OF]-(member:User {id: $userId}) RETURN group {.*}, admin {.*, myRoleInGroup: adminMembership.role}, member {.*, myRoleInGroup: userMembership.role} `, { groupId, adminId, userId }, @@ -149,14 +151,70 @@ const isAllowedToChangeGroupMemberRole = rule({ return ( !!group && !!admin && - !!member && - // Wolle: member.myRoleInGroup === roleInGroup && + (!member || + (!!member && + (member.myRoleInGroup === roleInGroup || !['owner'].includes(member.myRoleInGroup)))) && ((['admin'].includes(admin.myRoleInGroup) && - !['owner'].includes(member.myRoleInGroup) && ['pending', 'usual', 'admin'].includes(roleInGroup)) || (['owner'].includes(admin.myRoleInGroup) && ['pending', 'usual', 'admin', 'owner'].includes(roleInGroup))) ) + } catch (error) { + // Wolle: + // console.log('error: ', error) + throw new Error(error) + } finally { + session.close() + } +}) + +const isAllowedToJoinGroup = rule({ + cache: 'no_cache', +})(async (_parent, args, { user, driver }) => { + if (!(user && user.id)) return false + const { id: groupId, userId } = args + // Wolle: + // console.log('adminId: ', adminId) + // console.log('groupId: ', groupId) + // console.log('userId: ', userId) + // console.log('roleInGroup: ', roleInGroup) + const session = driver.session() + const readTxPromise = session.readTransaction(async (transaction) => { + const transactionResponse = await transaction.run( + ` + MATCH (group:Group {id: $groupId}) + OPTIONAL MATCH (group)<-[membership:MEMBER_OF]-(member:User {id: $userId}) + RETURN group {.*}, member {.*, myRoleInGroup: membership.role} + `, + { groupId, userId }, + ) + // Wolle: + // console.log( + // 'transactionResponse: ', + // transactionResponse, + // ) + // console.log( + // 'transaction groups: ', + // transactionResponse.records.map((record) => record.get('group')), + // ) + // console.log( + // 'transaction members: ', + // transactionResponse.records.map((record) => record.get('member')), + // ) + return { + group: transactionResponse.records.map((record) => record.get('group'))[0], + member: transactionResponse.records.map((record) => record.get('member'))[0], + } + }) + try { + // Wolle: + // console.log('enter try !!!') + const { group, member } = await readTxPromise + // Wolle: + // console.log('after !!!') + // console.log('group: ', group) + // console.log('member: ', member) + return !!group && (group.groupType !== 'hidden' || (!!member && !!member.myRoleInGroup)) } catch (error) { // Wolle: console.log('error: ', error) throw new Error(error) @@ -256,7 +314,7 @@ export default shield( SignupVerification: allow, UpdateUser: onlyYourself, CreateGroup: isAuthenticated, - JoinGroup: isAuthenticated, // Wolle: can not be correct + JoinGroup: isAllowedToJoinGroup, ChangeGroupMemberRole: isAllowedToChangeGroupMemberRole, CreatePost: isAuthenticated, UpdatePost: isAuthor, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index ca24ef55f..89c136dc5 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -163,20 +163,28 @@ export default { ChangeGroupMemberRole: async (_parent, params, context, _resolveInfo) => { const { id: groupId, userId, roleInGroup } = params // Wolle + // console.log('ChangeGroupMemberRole !!!') // console.log('groupId: ', groupId) - // console.log('userId: ', groupId) - // console.log('roleInGroup: ', groupId) + // console.log('userId: ', userId) + // console.log('roleInGroup: ', roleInGroup) const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { const joinGroupCypher = ` - MATCH (member:User {id: $userId})-[membership:MEMBER_OF]->(group:Group {id: $groupId}) - SET + MATCH (member:User {id: $userId}), (group:Group {id: $groupId}) + MERGE (member)-[membership:MEMBER_OF]->(group) + ON CREATE SET + membership.createdAt = toString(datetime()), + membership.updatedAt = membership.createdAt, + membership.role = $roleInGroup + ON MATCH SET membership.updatedAt = toString(datetime()), membership.role = $roleInGroup RETURN member {.*, myRoleInGroup: membership.role} ` const result = await transaction.run(joinGroupCypher, { groupId, userId, roleInGroup }) const [member] = await result.records.map((record) => record.get('member')) + // Wolle + // console.log('member: ', member) return member }) try { diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 23fc5646e..d9c2f22e3 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -410,7 +410,7 @@ describe('in mode: always clean db', () => { }) describe('public group', () => { - describe('entered by "owner-of-closed-group"', () => { + describe('joined by "owner-of-closed-group"', () => { it('has "usual" as membership role', async () => { variables = { id: 'public-group', @@ -434,7 +434,7 @@ describe('in mode: always clean db', () => { }) }) - describe('entered by its owner', () => { + describe('joined by its owner', () => { describe('does not create additional "MEMBER_OF" relation and therefore', () => { it('has still "owner" as membership role', async () => { variables = { @@ -462,7 +462,7 @@ describe('in mode: always clean db', () => { }) describe('closed group', () => { - describe('entered by "current-user"', () => { + describe('joined by "current-user"', () => { it('has "pending" as membership role', async () => { variables = { id: 'closed-group', @@ -486,7 +486,7 @@ describe('in mode: always clean db', () => { }) }) - describe('entered by its owner', () => { + describe('joined by its owner', () => { describe('does not create additional "MEMBER_OF" relation and therefore', () => { it('has still "owner" as membership role', async () => { variables = { @@ -514,31 +514,18 @@ describe('in mode: always clean db', () => { }) describe('hidden group', () => { - describe('entered by "owner-of-closed-group"', () => { - it('has "pending" as membership role', async () => { + describe('joined by "owner-of-closed-group"', () => { + it('throws authorization error', async () => { variables = { id: 'hidden-group', userId: 'owner-of-closed-group', } - const expected = { - data: { - JoinGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + const { errors } = await query({ query: groupMemberQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('entered by its owner', () => { + describe('joined by its owner', () => { describe('does not create additional "MEMBER_OF" relation and therefore', () => { it('has still "owner" as membership role', async () => { variables = { @@ -566,8 +553,18 @@ describe('in mode: always clean db', () => { }) }) }) +}) +describe('in mode: building up – separate for each resolver', () => { describe('GroupMember', () => { + beforeAll(async () => { + await seedBasicsAndClearAuthentication() + }) + + afterAll(async () => { + await cleanDatabase() + }) + describe('unauthenticated', () => { it('throws authorization error', async () => { variables = { @@ -580,10 +577,11 @@ describe('in mode: always clean db', () => { describe('authenticated', () => { let otherUser + let pendingUser let ownerOfClosedGroupUser let ownerOfHiddenGroupUser - beforeEach(async () => { + beforeAll(async () => { // create users otherUser = await Factory.build( 'user', @@ -592,7 +590,18 @@ describe('in mode: always clean db', () => { name: 'Other TestUser', }, { - email: 'test2@example.org', + email: 'other-user@example.org', + password: '1234', + }, + ) + pendingUser = await Factory.build( + 'user', + { + id: 'pending-user', + name: 'Pending TestUser', + }, + { + email: 'pending@example.org', password: '1234', }, ) @@ -689,22 +698,43 @@ describe('in mode: always clean db', () => { categoryIds, }, }) + // 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner await mutate({ - mutation: joinGroupMutation, + mutation: changeGroupMemberRoleMutation, + variables: { + id: 'hidden-group', + userId: 'pending-user', + roleInGroup: 'pending', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, variables: { id: 'hidden-group', userId: 'current-user', + roleInGroup: 'usual', }, }) await mutate({ - mutation: joinGroupMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'hidden-group', userId: 'owner-of-closed-group', + roleInGroup: 'admin', }, }) + // Wolle: + // const groups = await query({ query: groupQuery, variables: {} }) + // console.log('groups.data.Group: ', groups.data.Group) + // const groupMemberOfClosedGroup = await mutate({ + // mutation: groupMemberQuery, + // variables: { + // id: 'hidden-group', + // }, + // }) + // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) - authenticatedUser = await user.toJson() + authenticatedUser = null }) describe('public group', () => { @@ -946,12 +976,16 @@ describe('in mode: always clean db', () => { data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ - id: 'current-user', + id: 'pending-user', myRoleInGroup: 'pending', }), + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'usual', + }), expect.objectContaining({ id: 'owner-of-closed-group', - myRoleInGroup: 'pending', + myRoleInGroup: 'admin', }), expect.objectContaining({ id: 'owner-of-hidden-group', @@ -966,21 +1000,50 @@ describe('in mode: always clean db', () => { variables, }) expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMember.length).toBe(4) }) }) - describe('by usual member "owner-of-closed-group"', () => { + describe('by usual member "current-user"', () => { beforeEach(async () => { - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - id: 'hidden-group', - userId: 'owner-of-closed-group', - roleInGroup: 'usual', + authenticatedUser = await user.toJson() + }) + + it('finds all members', async () => { + const expected = { + data: { + GroupMember: expect.arrayContaining([ + expect.objectContaining({ + id: 'pending-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'admin', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), }, + errors: undefined, + } + const result = await mutate({ + mutation: groupMemberQuery, + variables, }) + expect(result).toMatchObject(expected) + expect(result.data.GroupMember.length).toBe(4) + }) + }) + + describe('by admin member "owner-of-closed-group"', () => { + beforeEach(async () => { authenticatedUser = await ownerOfClosedGroupUser.toJson() }) @@ -989,13 +1052,17 @@ describe('in mode: always clean db', () => { data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ - id: 'current-user', + id: 'pending-user', myRoleInGroup: 'pending', }), expect.objectContaining({ - id: 'owner-of-closed-group', + id: 'current-user', myRoleInGroup: 'usual', }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'admin', + }), expect.objectContaining({ id: 'owner-of-hidden-group', myRoleInGroup: 'owner', @@ -1009,13 +1076,13 @@ describe('in mode: always clean db', () => { variables, }) expect(result).toMatchObject(expected) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMember.length).toBe(4) }) }) - describe('by pending member "current-user"', () => { + describe('by pending member "pending-user"', () => { beforeEach(async () => { - authenticatedUser = await user.toJson() + authenticatedUser = await pendingUser.toJson() }) it('throws authorization error', async () => { @@ -1038,16 +1105,6 @@ describe('in mode: always clean db', () => { }) }) }) -}) - -describe('in mode: building up', () => { - beforeAll(async () => { - await seedBasicsAndClearAuthentication() - }) - - afterAll(async () => { - await cleanDatabase() - }) describe('ChangeGroupMemberRole', () => { let pendingMemberUser @@ -1057,6 +1114,7 @@ describe('in mode: building up', () => { let secondOwnerMemberUser beforeAll(async () => { + await seedBasicsAndClearAuthentication() // create users pendingMemberUser = await Factory.build( 'user', @@ -1156,34 +1214,6 @@ describe('in mode: building up', () => { categoryIds, }, }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'pending-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'usual-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'admin-member-user', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - id: 'closed-group', - userId: 'second-owner-member-user', - }, - }) // hidden-group authenticatedUser = await adminMemberUser.toJson() await mutate({ @@ -1198,20 +1228,45 @@ describe('in mode: building up', () => { categoryIds, }, }) + // 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner await mutate({ - mutation: joinGroupMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'hidden-group', userId: 'admin-member-user', + roleInGroup: 'usual', }, }) await mutate({ - mutation: joinGroupMutation, + mutation: changeGroupMemberRoleMutation, variables: { id: 'hidden-group', userId: 'second-owner-member-user', + roleInGroup: 'usual', }, }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + id: 'hidden-group', + userId: 'admin-member-user', + roleInGroup: 'usual', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + id: 'hidden-group', + userId: 'second-owner-member-user', + roleInGroup: 'usual', + }, + }) + + authenticatedUser = null + }) + + afterAll(async () => { + await cleanDatabase() }) describe('unauthenticated', () => { @@ -1234,13 +1289,13 @@ describe('in mode: building up', () => { } }) - describe('give the members their prospective roles', () => { + describe('join the members and give them their prospective roles', () => { describe('by owner "owner-member-user"', () => { beforeEach(async () => { authenticatedUser = await ownerMemberUser.toJson() }) - describe('switch role of "usual-member-user"', () => { + describe('for "usual-member-user"', () => { beforeEach(async () => { variables = { ...variables, @@ -1248,7 +1303,7 @@ describe('in mode: building up', () => { } }) - describe('to usual', () => { + describe('as usual', () => { beforeEach(async () => { variables = { ...variables, @@ -1279,7 +1334,7 @@ describe('in mode: building up', () => { }) }) - describe('switch role of "admin-member-user"', () => { + describe('for "admin-member-user"', () => { beforeEach(async () => { variables = { ...variables, @@ -1287,7 +1342,7 @@ describe('in mode: building up', () => { } }) - describe('to admin', () => { + describe('as admin', () => { beforeEach(async () => { variables = { ...variables, @@ -1325,7 +1380,7 @@ describe('in mode: building up', () => { }) }) - describe('switch role of "second-owner-member-user"', () => { + describe('for "second-owner-member-user"', () => { beforeEach(async () => { variables = { ...variables, @@ -1333,7 +1388,7 @@ describe('in mode: building up', () => { } }) - describe('to owner', () => { + describe('as owner', () => { beforeEach(async () => { variables = { ...variables, @@ -1395,8 +1450,9 @@ describe('in mode: building up', () => { }) }) - // Wolle: shall this be possible for now? - // or shall only an owner who gave the second owner the owner role downgrade themself? + // shall this be possible in the future? + // or shall only an owner who gave the second owner the owner role downgrade themself for savety? + // otherwise the first owner who downgrades the other one has the victory over the group! describe('by second owner "second-owner-member-user"', () => { beforeEach(async () => { authenticatedUser = await secondOwnerMemberUser.toJson() @@ -1410,26 +1466,16 @@ describe('in mode: building up', () => { } }) - it('has role admin', async () => { - const expected = { - data: { - ChangeGroupMemberRole: { - id: 'owner-member-user', - myRoleInGroup: 'admin', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('back to owner', () => { + describe('to same role owner', () => { beforeEach(async () => { variables = { ...variables, @@ -1437,7 +1483,7 @@ describe('in mode: building up', () => { } }) - it('has role owner again', async () => { + it('has role owner still', async () => { const expected = { data: { ChangeGroupMemberRole: { @@ -1575,22 +1621,12 @@ describe('in mode: building up', () => { } }) - it('has role admin again', async () => { - const expected = { - data: { - ChangeGroupMemberRole: { - id: 'admin-member-user', - myRoleInGroup: 'admin', - }, - }, - errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) From 9dd819f8d23bbed03d1d797a98b465190741a7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 10:25:39 +0200 Subject: [PATCH 38/67] Set not 'membership.updatedAt' on relation creation Co-Authored-By: Mogge --- backend/src/schema/resolvers/groups.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 89c136dc5..04ef6d704 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -109,7 +109,6 @@ export default { MERGE (owner)-[:CREATED]->(group) MERGE (owner)-[membership:MEMBER_OF]->(group) SET membership.createdAt = toString(datetime()) - SET membership.updatedAt = membership.createdAt SET membership.role = 'owner' ${categoriesCypher} RETURN group {.*, myRole: membership.role} @@ -140,7 +139,6 @@ export default { MERGE (member)-[membership:MEMBER_OF]->(group) ON CREATE SET membership.createdAt = toString(datetime()), - membership.updatedAt = membership.createdAt, membership.role = CASE WHEN group.groupType = 'public' THEN 'usual' @@ -174,7 +172,6 @@ export default { MERGE (member)-[membership:MEMBER_OF]->(group) ON CREATE SET membership.createdAt = toString(datetime()), - membership.updatedAt = membership.createdAt, membership.role = $roleInGroup ON MATCH SET membership.updatedAt = toString(datetime()), From 356fac9d948642379dfecce2b0163bb198ba1983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 10:36:37 +0200 Subject: [PATCH 39/67] Destruction of 'mutate' and 'query' in 'groups.spec.js' in one line now Co-Authored-By: Mogge --- backend/src/schema/resolvers/groups.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index d9c2f22e3..6787e866e 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -31,8 +31,7 @@ const { server } = createServer({ } }, }) -const { query } = createTestClient(server) -const { mutate } = createTestClient(server) +const { mutate, query } = createTestClient(server) const seedBasicsAndClearAuthentication = async () => { variables = {} From b703621eb7a8db37cbd4de1aab0be955aea6c462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 10:52:15 +0200 Subject: [PATCH 40/67] Remove local variables 'expected' and some 'variable' and put the values directly in the 'expect' calls in 'groups.spec.js' Co-Authored-By: Mogge --- backend/src/schema/resolvers/groups.spec.js | 379 +++++++++----------- 1 file changed, 170 insertions(+), 209 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 6787e866e..df4c5388b 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -121,7 +121,7 @@ describe('in mode: always clean db', () => { }) it('creates a group', async () => { - const expected = { + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ data: { CreateGroup: { name: 'The Best Group', @@ -130,14 +130,11 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) + }) }) it('assigns the authenticated user as owner', async () => { - const expected = { + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ data: { CreateGroup: { name: 'The Best Group', @@ -145,17 +142,13 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) + }) }) it('has "disabled" and "deleted" default to "false"', async () => { - const expected = { data: { CreateGroup: { disabled: false, deleted: false } } } - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( - expected, - ) + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ + data: { CreateGroup: { disabled: false, deleted: false } }, + }) }) describe('description', () => { @@ -259,7 +252,7 @@ describe('in mode: always clean db', () => { describe('query groups', () => { describe('without any filters', () => { it('finds all groups', async () => { - const expected = { + await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({ data: { Group: expect.arrayContaining([ expect.objectContaining({ @@ -275,16 +268,15 @@ describe('in mode: always clean db', () => { ]), }, errors: undefined, - } - await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject( - expected, - ) + }) }) }) describe('isMember = true', () => { it('finds only groups where user is member', async () => { - const expected = { + await expect( + query({ query: groupQuery, variables: { isMember: true } }), + ).resolves.toMatchObject({ data: { Group: [ { @@ -295,16 +287,15 @@ describe('in mode: always clean db', () => { ], }, errors: undefined, - } - await expect( - query({ query: groupQuery, variables: { isMember: true } }), - ).resolves.toMatchObject(expected) + }) }) }) describe('isMember = false', () => { it('finds only groups where user is not(!) member', async () => { - const expected = { + await expect( + query({ query: groupQuery, variables: { isMember: false } }), + ).resolves.toMatchObject({ data: { Group: expect.arrayContaining([ expect.objectContaining({ @@ -315,10 +306,7 @@ describe('in mode: always clean db', () => { ]), }, errors: undefined, - } - await expect( - query({ query: groupQuery, variables: { isMember: false } }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -411,11 +399,15 @@ describe('in mode: always clean db', () => { describe('public group', () => { describe('joined by "owner-of-closed-group"', () => { it('has "usual" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'owner-of-closed-group', - } - const expected = { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'owner-of-closed-group', + }, + }), + ).resolves.toMatchObject({ data: { JoinGroup: { id: 'owner-of-closed-group', @@ -423,24 +415,22 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) describe('joined by its owner', () => { describe('does not create additional "MEMBER_OF" relation and therefore', () => { it('has still "owner" as membership role', async () => { - variables = { - id: 'public-group', - userId: 'current-user', - } - const expected = { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'public-group', + userId: 'current-user', + }, + }), + ).resolves.toMatchObject({ data: { JoinGroup: { id: 'current-user', @@ -448,13 +438,7 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -463,11 +447,15 @@ describe('in mode: always clean db', () => { describe('closed group', () => { describe('joined by "current-user"', () => { it('has "pending" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'current-user', - } - const expected = { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'current-user', + }, + }), + ).resolves.toMatchObject({ data: { JoinGroup: { id: 'current-user', @@ -475,24 +463,22 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) describe('joined by its owner', () => { describe('does not create additional "MEMBER_OF" relation and therefore', () => { it('has still "owner" as membership role', async () => { - variables = { - id: 'closed-group', - userId: 'owner-of-closed-group', - } - const expected = { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'closed-group', + userId: 'owner-of-closed-group', + }, + }), + ).resolves.toMatchObject({ data: { JoinGroup: { id: 'owner-of-closed-group', @@ -500,13 +486,7 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -527,11 +507,15 @@ describe('in mode: always clean db', () => { describe('joined by its owner', () => { describe('does not create additional "MEMBER_OF" relation and therefore', () => { it('has still "owner" as membership role', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-hidden-group', - } - const expected = { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + id: 'hidden-group', + userId: 'owner-of-hidden-group', + }, + }), + ).resolves.toMatchObject({ data: { JoinGroup: { id: 'owner-of-hidden-group', @@ -539,13 +523,7 @@ describe('in mode: always clean db', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: joinGroupMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -750,7 +728,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -768,12 +750,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(3) }) }) @@ -784,7 +761,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -802,12 +783,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(3) }) }) @@ -818,7 +794,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -836,12 +816,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(3) }) }) @@ -862,7 +837,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -880,12 +859,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(3) }) }) @@ -905,7 +879,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -923,12 +901,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(3) }) }) @@ -971,7 +944,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -993,12 +970,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(4) }) }) @@ -1009,7 +981,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -1031,12 +1007,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(4) }) }) @@ -1047,7 +1018,11 @@ describe('in mode: building up – separate for each resolver', () => { }) it('finds all members', async () => { - const expected = { + const result = await mutate({ + mutation: groupMemberQuery, + variables, + }) + expect(result).toMatchObject({ data: { GroupMember: expect.arrayContaining([ expect.objectContaining({ @@ -1069,12 +1044,7 @@ describe('in mode: building up – separate for each resolver', () => { ]), }, errors: undefined, - } - const result = await mutate({ - mutation: groupMemberQuery, - variables, }) - expect(result).toMatchObject(expected) expect(result.data.GroupMember.length).toBe(4) }) }) @@ -1311,7 +1281,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role usual', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'usual-member-user', @@ -1319,13 +1294,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) // the GQL mutation needs this fields in the result for testing @@ -1360,7 +1329,12 @@ describe('in mode: building up – separate for each resolver', () => { // }, // }) // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'admin-member-user', @@ -1368,13 +1342,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -1396,7 +1364,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role owner', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'second-owner-member-user', @@ -1404,13 +1377,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -1483,7 +1450,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role owner still', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'owner-member-user', @@ -1491,13 +1463,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -1594,7 +1560,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role owner', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'admin-member-user', @@ -1602,13 +1573,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) @@ -1773,7 +1738,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role admin', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'usual-member-user', @@ -1781,13 +1751,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) @@ -1800,7 +1764,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role usual again', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'usual-member-user', @@ -1808,13 +1777,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) @@ -1962,7 +1925,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role usual', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'pending-member-user', @@ -1970,13 +1938,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) @@ -1989,7 +1951,12 @@ describe('in mode: building up – separate for each resolver', () => { }) it('has role usual again', async () => { - const expected = { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ data: { ChangeGroupMemberRole: { id: 'pending-member-user', @@ -1997,13 +1964,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }, errors: undefined, - } - await expect( - mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }), - ).resolves.toMatchObject(expected) + }) }) }) }) From 826cf5a8e0364845f4c92b7d870e389f02f5a700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 11:03:47 +0200 Subject: [PATCH 41/67] Renamed 'GroupMember' to 'GroupMembers' Co-Authored-By: Mogge --- backend/src/db/graphql/groups.js | 4 +- .../src/middleware/permissionsMiddleware.js | 2 +- backend/src/schema/resolvers/groups.js | 2 +- backend/src/schema/resolvers/groups.spec.js | 72 +++++++++---------- backend/src/schema/types/type/Group.gql | 2 +- 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index 2a9647860..3a7f047d2 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -116,9 +116,9 @@ export const groupQuery = gql` } ` -export const groupMemberQuery = gql` +export const groupMembersQuery = gql` query ($id: ID!, $first: Int, $offset: Int, $orderBy: [_UserOrdering], $filter: _UserFilter) { - GroupMember(id: $id, first: $first, offset: $offset, orderBy: $orderBy, filter: $filter) { + GroupMembers(id: $id, first: $first, offset: $offset, orderBy: $orderBy, filter: $filter) { id name slug diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index f0ddd04ca..c8f97cd17 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -286,7 +286,7 @@ export default shield( statistics: allow, currentUser: allow, Group: isAuthenticated, - GroupMember: isAllowedSeeingMembersOfGroup, + GroupMembers: isAllowedSeeingMembersOfGroup, Post: allow, profilePagePosts: allow, Comment: allow, diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 04ef6d704..5e401c28e 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -46,7 +46,7 @@ export default { session.close() } }, - GroupMember: async (_object, params, context, _resolveInfo) => { + GroupMembers: async (_object, params, context, _resolveInfo) => { const { id: groupId } = params // Wolle: console.log('groupId: ', groupId) const session = context.driver.session() diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index df4c5388b..c81f976be 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -4,7 +4,7 @@ import { createGroupMutation, joinGroupMutation, changeGroupMemberRoleMutation, - groupMemberQuery, + groupMembersQuery, groupQuery, } from '../../db/graphql/groups' import { getNeode, getDriver } from '../../db/neo4j' @@ -499,7 +499,7 @@ describe('in mode: always clean db', () => { id: 'hidden-group', userId: 'owner-of-closed-group', } - const { errors } = await query({ query: groupMemberQuery, variables }) + const { errors } = await query({ query: groupMembersQuery, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -533,7 +533,7 @@ describe('in mode: always clean db', () => { }) describe('in mode: building up – separate for each resolver', () => { - describe('GroupMember', () => { + describe('GroupMembers', () => { beforeAll(async () => { await seedBasicsAndClearAuthentication() }) @@ -547,7 +547,7 @@ describe('in mode: building up – separate for each resolver', () => { variables = { id: 'not-existing-group', } - const { errors } = await query({ query: groupMemberQuery, variables }) + const { errors } = await query({ query: groupMembersQuery, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -704,12 +704,12 @@ describe('in mode: building up – separate for each resolver', () => { // const groups = await query({ query: groupQuery, variables: {} }) // console.log('groups.data.Group: ', groups.data.Group) // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMemberQuery, + // mutation: groupMembersQuery, // variables: { // id: 'hidden-group', // }, // }) - // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) + // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) authenticatedUser = null }) @@ -729,12 +729,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'current-user', myRoleInGroup: 'owner', @@ -751,7 +751,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMembers.length).toBe(3) }) }) @@ -762,12 +762,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'current-user', myRoleInGroup: 'owner', @@ -784,7 +784,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMembers.length).toBe(3) }) }) @@ -795,12 +795,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'current-user', myRoleInGroup: 'owner', @@ -817,7 +817,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMembers.length).toBe(3) }) }) }) @@ -838,12 +838,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'current-user', myRoleInGroup: 'pending', @@ -860,7 +860,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMembers.length).toBe(3) }) }) @@ -880,12 +880,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'current-user', myRoleInGroup: 'pending', @@ -902,7 +902,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(3) + expect(result.data.GroupMembers.length).toBe(3) }) }) @@ -912,7 +912,7 @@ describe('in mode: building up – separate for each resolver', () => { }) it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) + const { errors } = await query({ query: groupMembersQuery, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -923,7 +923,7 @@ describe('in mode: building up – separate for each resolver', () => { }) it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) + const { errors } = await query({ query: groupMembersQuery, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -945,12 +945,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'pending-user', myRoleInGroup: 'pending', @@ -971,7 +971,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(4) + expect(result.data.GroupMembers.length).toBe(4) }) }) @@ -982,12 +982,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'pending-user', myRoleInGroup: 'pending', @@ -1008,7 +1008,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(4) + expect(result.data.GroupMembers.length).toBe(4) }) }) @@ -1019,12 +1019,12 @@ describe('in mode: building up – separate for each resolver', () => { it('finds all members', async () => { const result = await mutate({ - mutation: groupMemberQuery, + mutation: groupMembersQuery, variables, }) expect(result).toMatchObject({ data: { - GroupMember: expect.arrayContaining([ + GroupMembers: expect.arrayContaining([ expect.objectContaining({ id: 'pending-user', myRoleInGroup: 'pending', @@ -1045,7 +1045,7 @@ describe('in mode: building up – separate for each resolver', () => { }, errors: undefined, }) - expect(result.data.GroupMember.length).toBe(4) + expect(result.data.GroupMembers.length).toBe(4) }) }) @@ -1055,7 +1055,7 @@ describe('in mode: building up – separate for each resolver', () => { }) it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) + const { errors } = await query({ query: groupMembersQuery, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -1066,7 +1066,7 @@ describe('in mode: building up – separate for each resolver', () => { }) it('throws authorization error', async () => { - const { errors } = await query({ query: groupMemberQuery, variables }) + const { errors } = await query({ query: groupMembersQuery, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -1323,12 +1323,12 @@ describe('in mode: building up – separate for each resolver', () => { // const groups = await query({ query: groupQuery, variables: {} }) // console.log('groups.data.Group: ', groups.data.Group) // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMemberQuery, + // mutation: groupMembersQuery, // variables: { // id: 'closed-group', // }, // }) - // console.log('groupMemberOfClosedGroup.data.GroupMember: ', groupMemberOfClosedGroup.data.GroupMember) + // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) await expect( mutate({ mutation: changeGroupMemberRoleMutation, diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index f12b98c07..1f59d7cc4 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -73,7 +73,7 @@ type Query { orderBy: [_GroupOrdering] ): [Group] - GroupMember( + GroupMembers( id: ID! first: Int offset: Int From 813c072dc7d0ba9983c780c194ebfacd90185671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 11:32:22 +0200 Subject: [PATCH 42/67] Change GQL parameter for 'JoinGroup' from 'id' to 'groupId' Co-Authored-By: Mogge --- backend/src/db/graphql/groups.js | 4 +- backend/src/db/seed.js | 26 +++++------ .../src/middleware/permissionsMiddleware.js | 2 +- backend/src/schema/resolvers/groups.js | 2 +- backend/src/schema/resolvers/groups.spec.js | 46 ++++++++++--------- backend/src/schema/types/type/Group.gql | 2 +- 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index 3a7f047d2..a0aef97b2 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -40,8 +40,8 @@ export const createGroupMutation = gql` ` export const joinGroupMutation = gql` - mutation ($id: ID!, $userId: ID!) { - JoinGroup(id: $id, userId: $userId) { + mutation ($groupId: ID!, $userId: ID!) { + JoinGroup(groupId: $groupId, userId: $userId) { id name slug diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 0010b09ef..1bd535456 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -408,28 +408,28 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: joinGroupMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u2', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u3', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u4', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u6', }, }), @@ -480,35 +480,35 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: joinGroupMutation, variables: { - id: 'g1', + groupId: 'g1', userId: 'u1', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g1', + groupId: 'g1', userId: 'u2', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g1', + groupId: 'g1', userId: 'u5', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g1', + groupId: 'g1', userId: 'u6', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g1', + groupId: 'g1', userId: 'u7', }, }), @@ -567,28 +567,28 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: joinGroupMutation, variables: { - id: 'g2', + groupId: 'g2', userId: 'u4', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g2', + groupId: 'g2', userId: 'u5', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g2', + groupId: 'g2', userId: 'u6', }, }), mutate({ mutation: joinGroupMutation, variables: { - id: 'g2', + groupId: 'g2', userId: 'u7', }, }), diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index c8f97cd17..bbaff67d9 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -172,7 +172,7 @@ const isAllowedToJoinGroup = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { if (!(user && user.id)) return false - const { id: groupId, userId } = args + const { groupId, userId } = args // Wolle: // console.log('adminId: ', adminId) // console.log('groupId: ', groupId) diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 5e401c28e..d34d62eb7 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -131,7 +131,7 @@ export default { } }, JoinGroup: async (_parent, params, context, _resolveInfo) => { - const { id: groupId, userId } = params + const { groupId, userId } = params const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { const joinGroupCypher = ` diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index c81f976be..74f806b7b 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -316,11 +316,13 @@ describe('in mode: always clean db', () => { describe('JoinGroup', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - userId: 'current-user', - } - const { errors } = await mutate({ mutation: joinGroupMutation, variables }) + const { errors } = await mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'not-existing-group', + userId: 'current-user', + }, + }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -403,7 +405,7 @@ describe('in mode: always clean db', () => { mutate({ mutation: joinGroupMutation, variables: { - id: 'public-group', + groupId: 'public-group', userId: 'owner-of-closed-group', }, }), @@ -426,7 +428,7 @@ describe('in mode: always clean db', () => { mutate({ mutation: joinGroupMutation, variables: { - id: 'public-group', + groupId: 'public-group', userId: 'current-user', }, }), @@ -451,7 +453,7 @@ describe('in mode: always clean db', () => { mutate({ mutation: joinGroupMutation, variables: { - id: 'closed-group', + groupId: 'closed-group', userId: 'current-user', }, }), @@ -474,7 +476,7 @@ describe('in mode: always clean db', () => { mutate({ mutation: joinGroupMutation, variables: { - id: 'closed-group', + groupId: 'closed-group', userId: 'owner-of-closed-group', }, }), @@ -495,11 +497,13 @@ describe('in mode: always clean db', () => { describe('hidden group', () => { describe('joined by "owner-of-closed-group"', () => { it('throws authorization error', async () => { - variables = { - id: 'hidden-group', - userId: 'owner-of-closed-group', - } - const { errors } = await query({ query: groupMembersQuery, variables }) + const { errors } = await query({ + query: joinGroupMutation, + variables: { + groupId: 'hidden-group', + userId: 'owner-of-closed-group', + }, + }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -511,7 +515,7 @@ describe('in mode: always clean db', () => { mutate({ mutation: joinGroupMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'owner-of-hidden-group', }, }), @@ -622,14 +626,14 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: joinGroupMutation, variables: { - id: 'public-group', + groupId: 'public-group', userId: 'owner-of-closed-group', }, }) await mutate({ mutation: joinGroupMutation, variables: { - id: 'public-group', + groupId: 'public-group', userId: 'owner-of-hidden-group', }, }) @@ -650,14 +654,14 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: joinGroupMutation, variables: { - id: 'closed-group', + groupId: 'closed-group', userId: 'current-user', }, }) await mutate({ mutation: joinGroupMutation, variables: { - id: 'closed-group', + groupId: 'closed-group', userId: 'owner-of-hidden-group', }, }) @@ -1158,14 +1162,14 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: joinGroupMutation, variables: { - id: 'public-group', + groupId: 'public-group', userId: 'owner-of-closed-group', }, }) await mutate({ mutation: joinGroupMutation, variables: { - id: 'public-group', + groupId: 'public-group', userId: 'owner-of-hidden-group', }, }) diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index 1f59d7cc4..9d2210a1a 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -115,7 +115,7 @@ type Mutation { DeleteGroup(id: ID!): Group JoinGroup( - id: ID! + groupId: ID! userId: ID! ): User From fd497a03aae62b0296c7f1ffc5129c2facf25c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 11:58:23 +0200 Subject: [PATCH 43/67] Change GQL parameter for 'ChangeGroupMemberRole' from 'id' to 'groupId' Co-Authored-By: Mogge --- backend/src/db/graphql/groups.js | 4 +- backend/src/db/seed.js | 20 ++++----- .../src/middleware/permissionsMiddleware.js | 2 +- backend/src/schema/resolvers/groups.js | 2 +- backend/src/schema/resolvers/groups.spec.js | 44 ++++++++----------- backend/src/schema/types/type/Group.gql | 2 +- 6 files changed, 34 insertions(+), 40 deletions(-) diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js index a0aef97b2..c6f110ed1 100644 --- a/backend/src/db/graphql/groups.js +++ b/backend/src/db/graphql/groups.js @@ -51,8 +51,8 @@ export const joinGroupMutation = gql` ` export const changeGroupMemberRoleMutation = gql` - mutation ($id: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) { - ChangeGroupMemberRole(id: $id, userId: $userId, roleInGroup: $roleInGroup) { + mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) { + ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) { id name slug diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 1bd535456..a71b11131 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -438,7 +438,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u2', roleInGroup: 'usual', }, @@ -446,7 +446,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u4', roleInGroup: 'admin', }, @@ -454,7 +454,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u3', roleInGroup: 'owner', }, @@ -517,7 +517,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u1', roleInGroup: 'usual', }, @@ -525,7 +525,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u2', roleInGroup: 'usual', }, @@ -533,7 +533,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u5', roleInGroup: 'admin', }, @@ -541,7 +541,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u6', roleInGroup: 'owner', }, @@ -597,7 +597,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u4', roleInGroup: 'usual', }, @@ -605,7 +605,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u5', roleInGroup: 'usual', }, @@ -613,7 +613,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'g0', + groupId: 'g0', userId: 'u6', roleInGroup: 'usual', }, diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index bbaff67d9..926f824e4 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -98,7 +98,7 @@ const isAllowedToChangeGroupMemberRole = rule({ })(async (_parent, args, { user, driver }) => { if (!(user && user.id)) return false const adminId = user.id - const { id: groupId, userId, roleInGroup } = args + const { groupId, userId, roleInGroup } = args if (adminId === userId) return false // Wolle: // console.log('isAllowedToChangeGroupMemberRole !!!') diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index d34d62eb7..6ca09d72a 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -159,7 +159,7 @@ export default { } }, ChangeGroupMemberRole: async (_parent, params, context, _resolveInfo) => { - const { id: groupId, userId, roleInGroup } = params + const { groupId, userId, roleInGroup } = params // Wolle // console.log('ChangeGroupMemberRole !!!') // console.log('groupId: ', groupId) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 74f806b7b..a660f6ce8 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -659,10 +659,11 @@ describe('in mode: building up – separate for each resolver', () => { }, }) await mutate({ - mutation: joinGroupMutation, + mutation: changeGroupMemberRoleMutation, variables: { groupId: 'closed-group', userId: 'owner-of-hidden-group', + roleInGroup: 'usual', }, }) // hidden-group @@ -683,7 +684,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'pending-user', roleInGroup: 'pending', }, @@ -691,7 +692,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'current-user', roleInGroup: 'usual', }, @@ -699,7 +700,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'owner-of-closed-group', roleInGroup: 'admin', }, @@ -858,7 +859,7 @@ describe('in mode: building up – separate for each resolver', () => { }), expect.objectContaining({ id: 'owner-of-hidden-group', - myRoleInGroup: 'pending', + myRoleInGroup: 'usual', }), ]), }, @@ -870,15 +871,6 @@ describe('in mode: building up – separate for each resolver', () => { describe('by usual member "owner-of-hidden-group"', () => { beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - id: 'closed-group', - userId: 'owner-of-hidden-group', - roleInGroup: 'usual', - }, - }) authenticatedUser = await ownerOfHiddenGroupUser.toJson() }) @@ -1205,7 +1197,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'admin-member-user', roleInGroup: 'usual', }, @@ -1213,7 +1205,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'second-owner-member-user', roleInGroup: 'usual', }, @@ -1221,7 +1213,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'admin-member-user', roleInGroup: 'usual', }, @@ -1229,7 +1221,7 @@ describe('in mode: building up – separate for each resolver', () => { await mutate({ mutation: changeGroupMemberRoleMutation, variables: { - id: 'hidden-group', + groupId: 'hidden-group', userId: 'second-owner-member-user', roleInGroup: 'usual', }, @@ -1244,12 +1236,14 @@ describe('in mode: building up – separate for each resolver', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - userId: 'current-user', - roleInGroup: 'pending', - } - const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables }) + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'not-existing-group', + userId: 'current-user', + roleInGroup: 'pending', + }, + }) expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) @@ -1258,7 +1252,7 @@ describe('in mode: building up – separate for each resolver', () => { describe('in all group types – here "closed-group" for example', () => { beforeEach(async () => { variables = { - id: 'closed-group', + groupId: 'closed-group', } }) diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index 9d2210a1a..5c98e49e8 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -120,7 +120,7 @@ type Mutation { ): User ChangeGroupMemberRole( - id: ID! + groupId: ID! userId: ID! roleInGroup: GroupMemberRole! ): User From c7c2ebdeb7544078a3a6bf4441965e775294640d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 12:20:27 +0200 Subject: [PATCH 44/67] Refine clean db mode in 'groups.spec.js' --- backend/src/schema/resolvers/groups.spec.js | 3264 ++++++++++--------- 1 file changed, 1633 insertions(+), 1631 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index a660f6ce8..054e3abb0 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -83,361 +83,228 @@ afterAll(async () => { await cleanDatabase() }) -describe('in mode: always clean db', () => { - beforeEach(async () => { - await seedBasicsAndClearAuthentication() - }) - - // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 - afterEach(async () => { - await cleanDatabase() - }) - - describe('CreateGroup', () => { - beforeEach(() => { - variables = { - ...variables, - id: 'g589', - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - } +describe('in mode', () => { + describe('clean db after each single test', () => { + beforeEach(async () => { + await seedBasicsAndClearAuthentication() }) - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await mutate({ mutation: createGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) + // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 + afterEach(async () => { + await cleanDatabase() }) - describe('authenticated', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() + describe('CreateGroup', () => { + beforeEach(() => { + variables = { + ...variables, + id: 'g589', + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + } }) - it('creates a group', async () => { - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ - data: { - CreateGroup: { - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: createGroupMutation, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('creates a group', async () => { + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ + data: { + CreateGroup: { + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + }, }, - }, - errors: undefined, + errors: undefined, + }) }) - }) - it('assigns the authenticated user as owner', async () => { - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ - data: { - CreateGroup: { - name: 'The Best Group', - myRole: 'owner', + it('assigns the authenticated user as owner', async () => { + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ + data: { + CreateGroup: { + name: 'The Best Group', + myRole: 'owner', + }, }, - }, - errors: undefined, + errors: undefined, + }) }) - }) - it('has "disabled" and "deleted" default to "false"', async () => { - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ - data: { CreateGroup: { disabled: false, deleted: false } }, + it('has "disabled" and "deleted" default to "false"', async () => { + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ + data: { CreateGroup: { disabled: false, deleted: false } }, + }) }) - }) - describe('description', () => { - describe('length without HTML', () => { - describe('less then 100 chars', () => { + describe('description', () => { + describe('length without HTML', () => { + describe('less then 100 chars', () => { + it('throws error: "Too view categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { + ...variables, + description: + '0123456789' + + '0123456789', + }, + }) + expect(errors[0]).toHaveProperty('message', 'Description too short!') + }) + }) + }) + }) + + describe('categories', () => { + beforeEach(() => { + CONFIG.CATEGORIES_ACTIVE = true + }) + + describe('not even one', () => { it('throws error: "Too view categories!"', async () => { const { errors } = await mutate({ mutation: createGroupMutation, - variables: { - ...variables, - description: - '0123456789' + - '0123456789', - }, + variables: { ...variables, categoryIds: null }, }) - expect(errors[0]).toHaveProperty('message', 'Description too short!') + expect(errors[0]).toHaveProperty('message', 'Too view categories!') }) }) - }) - }) - describe('categories', () => { - beforeEach(() => { - CONFIG.CATEGORIES_ACTIVE = true - }) - - describe('not even one', () => { - it('throws error: "Too view categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { ...variables, categoryIds: null }, - }) - expect(errors[0]).toHaveProperty('message', 'Too view categories!') - }) - }) - - describe('four', () => { - it('throws error: "Too many categories!"', async () => { - const { errors } = await mutate({ - mutation: createGroupMutation, - variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, - }) - expect(errors[0]).toHaveProperty('message', 'Too many categories!') - }) - }) - }) - }) - }) - - describe('Group', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await query({ query: groupQuery, variables: {} }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - let otherUser - - beforeEach(async () => { - otherUser = await Factory.build( - 'user', - { - id: 'other-user', - name: 'Other TestUser', - }, - { - email: 'test2@example.org', - password: '1234', - }, - ) - authenticatedUser = await otherUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'others-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'global', - categoryIds, - }, - }) - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'my-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) - }) - - describe('query groups', () => { - describe('without any filters', () => { - it('finds all groups', async () => { - await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({ - data: { - Group: expect.arrayContaining([ - expect.objectContaining({ - id: 'my-group', - slug: 'the-best-group', - myRole: 'owner', - }), - expect.objectContaining({ - id: 'others-group', - slug: 'uninteresting-group', - myRole: null, - }), - ]), - }, - errors: undefined, - }) - }) - }) - - describe('isMember = true', () => { - it('finds only groups where user is member', async () => { - await expect( - query({ query: groupQuery, variables: { isMember: true } }), - ).resolves.toMatchObject({ - data: { - Group: [ - { - id: 'my-group', - slug: 'the-best-group', - myRole: 'owner', - }, - ], - }, - errors: undefined, - }) - }) - }) - - describe('isMember = false', () => { - it('finds only groups where user is not(!) member', async () => { - await expect( - query({ query: groupQuery, variables: { isMember: false } }), - ).resolves.toMatchObject({ - data: { - Group: expect.arrayContaining([ - expect.objectContaining({ - id: 'others-group', - slug: 'uninteresting-group', - myRole: null, - }), - ]), - }, - errors: undefined, + describe('four', () => { + it('throws error: "Too many categories!"', async () => { + const { errors } = await mutate({ + mutation: createGroupMutation, + variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, + }) + expect(errors[0]).toHaveProperty('message', 'Too many categories!') }) }) }) }) }) - }) - describe('JoinGroup', () => { - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'not-existing-group', - userId: 'current-user', - }, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - let ownerOfClosedGroupUser - let ownerOfHiddenGroupUser - - beforeEach(async () => { - // create users - ownerOfClosedGroupUser = await Factory.build( - 'user', - { - id: 'owner-of-closed-group', - name: 'Owner Of Closed Group', - }, - { - email: 'owner-of-closed-group@example.org', - password: '1234', - }, - ) - ownerOfHiddenGroupUser = await Factory.build( - 'user', - { - id: 'owner-of-hidden-group', - name: 'Owner Of Hidden Group', - }, - { - email: 'owner-of-hidden-group@example.org', - password: '1234', - }, - ) - // create groups - // public-group - authenticatedUser = await ownerOfClosedGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - authenticatedUser = await user.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'public-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, + describe('Group', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await query({ query: groupQuery, variables: {} }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('public group', () => { - describe('joined by "owner-of-closed-group"', () => { - it('has "usual" as membership role', async () => { - await expect( - mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'public-group', - userId: 'owner-of-closed-group', + describe('authenticated', () => { + let otherUser + + beforeEach(async () => { + otherUser = await Factory.build( + 'user', + { + id: 'other-user', + name: 'Other TestUser', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + authenticatedUser = await otherUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'others-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'my-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + }) + + describe('query groups', () => { + describe('without any filters', () => { + it('finds all groups', async () => { + await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({ + data: { + Group: expect.arrayContaining([ + expect.objectContaining({ + id: 'my-group', + slug: 'the-best-group', + myRole: 'owner', + }), + expect.objectContaining({ + id: 'others-group', + slug: 'uninteresting-group', + myRole: null, + }), + ]), }, - }), - ).resolves.toMatchObject({ - data: { - JoinGroup: { - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }, - }, - errors: undefined, + errors: undefined, + }) }) }) - }) - describe('joined by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { + describe('isMember = true', () => { + it('finds only groups where user is member', async () => { await expect( - mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'public-group', - userId: 'current-user', - }, - }), + query({ query: groupQuery, variables: { isMember: true } }), ).resolves.toMatchObject({ data: { - JoinGroup: { - id: 'current-user', - myRoleInGroup: 'owner', - }, + Group: [ + { + id: 'my-group', + slug: 'the-best-group', + myRole: 'owner', + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('isMember = false', () => { + it('finds only groups where user is not(!) member', async () => { + await expect( + query({ query: groupQuery, variables: { isMember: false } }), + ).resolves.toMatchObject({ + data: { + Group: expect.arrayContaining([ + expect.objectContaining({ + id: 'others-group', + slug: 'uninteresting-group', + myRole: null, + }), + ]), }, errors: undefined, }) @@ -445,38 +312,101 @@ describe('in mode: always clean db', () => { }) }) }) + }) - describe('closed group', () => { - describe('joined by "current-user"', () => { - it('has "pending" as membership role', async () => { - await expect( - mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'closed-group', - userId: 'current-user', - }, - }), - ).resolves.toMatchObject({ - data: { - JoinGroup: { - id: 'current-user', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, - }) + describe('JoinGroup', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'not-existing-group', + userId: 'current-user', + }, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser + + beforeEach(async () => { + // create users + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + // create groups + // public-group + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, }) }) - describe('joined by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { + describe('public group', () => { + describe('joined by "owner-of-closed-group"', () => { + it('has "usual" as membership role', async () => { await expect( mutate({ mutation: joinGroupMutation, variables: { - groupId: 'closed-group', + groupId: 'public-group', userId: 'owner-of-closed-group', }, }), @@ -484,133 +414,732 @@ describe('in mode: always clean db', () => { data: { JoinGroup: { id: 'owner-of-closed-group', - myRoleInGroup: 'owner', + myRoleInGroup: 'usual', }, }, errors: undefined, }) }) }) - }) - }) - describe('hidden group', () => { - describe('joined by "owner-of-closed-group"', () => { - it('throws authorization error', async () => { - const { errors } = await query({ - query: joinGroupMutation, - variables: { - groupId: 'hidden-group', - userId: 'owner-of-closed-group', - }, + describe('joined by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'public-group', + userId: 'current-user', + }, + }), + ).resolves.toMatchObject({ + data: { + JoinGroup: { + id: 'current-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + }) + }) }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('joined by its owner', () => { - describe('does not create additional "MEMBER_OF" relation and therefore', () => { - it('has still "owner" as membership role', async () => { + describe('closed group', () => { + describe('joined by "current-user"', () => { + it('has "pending" as membership role', async () => { await expect( mutate({ mutation: joinGroupMutation, variables: { - groupId: 'hidden-group', - userId: 'owner-of-hidden-group', + groupId: 'closed-group', + userId: 'current-user', }, }), ).resolves.toMatchObject({ data: { JoinGroup: { - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', + id: 'current-user', + myRoleInGroup: 'pending', }, }, errors: undefined, }) }) }) + + describe('joined by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'closed-group', + userId: 'owner-of-closed-group', + }, + }), + ).resolves.toMatchObject({ + data: { + JoinGroup: { + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + }) + }) + }) + }) + }) + + describe('hidden group', () => { + describe('joined by "owner-of-closed-group"', () => { + it('throws authorization error', async () => { + const { errors } = await query({ + query: joinGroupMutation, + variables: { + groupId: 'hidden-group', + userId: 'owner-of-closed-group', + }, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('joined by its owner', () => { + describe('does not create additional "MEMBER_OF" relation and therefore', () => { + it('has still "owner" as membership role', async () => { + await expect( + mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'hidden-group', + userId: 'owner-of-hidden-group', + }, + }), + ).resolves.toMatchObject({ + data: { + JoinGroup: { + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + }) + }) + }) + }) }) }) }) }) -}) -describe('in mode: building up – separate for each resolver', () => { - describe('GroupMembers', () => { - beforeAll(async () => { - await seedBasicsAndClearAuthentication() - }) + describe('building up – clean db after each resolver', () => { + describe('GroupMembers', () => { + beforeAll(async () => { + await seedBasicsAndClearAuthentication() + }) - afterAll(async () => { - await cleanDatabase() - }) + afterAll(async () => { + await cleanDatabase() + }) - describe('unauthenticated', () => { - it('throws authorization error', async () => { - variables = { - id: 'not-existing-group', - } - const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'not-existing-group', + } + const { errors } = await query({ query: groupMembersQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('authenticated', () => { + let otherUser + let pendingUser + let ownerOfClosedGroupUser + let ownerOfHiddenGroupUser + + beforeAll(async () => { + // create users + otherUser = await Factory.build( + 'user', + { + id: 'other-user', + name: 'Other TestUser', + }, + { + email: 'other-user@example.org', + password: '1234', + }, + ) + pendingUser = await Factory.build( + 'user', + { + id: 'pending-user', + name: 'Pending TestUser', + }, + { + email: 'pending@example.org', + password: '1234', + }, + ) + ownerOfClosedGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-closed-group', + name: 'Owner Of Closed Group', + }, + { + email: 'owner-of-closed-group@example.org', + password: '1234', + }, + ) + ownerOfHiddenGroupUser = await Factory.build( + 'user', + { + id: 'owner-of-hidden-group', + name: 'Owner Of Hidden Group', + }, + { + email: 'owner-of-hidden-group@example.org', + password: '1234', + }, + ) + // create groups + // public-group + authenticatedUser = await user.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'public-group', + name: 'The Best Group', + about: 'We will change the world!', + description: 'Some description' + descriptionAdditional100, + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'public-group', + userId: 'owner-of-closed-group', + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'public-group', + userId: 'owner-of-hidden-group', + }, + }) + // closed-group + authenticatedUser = await ownerOfClosedGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'closed-group', + name: 'Uninteresting Group', + about: 'We will change nothing!', + description: 'We love it like it is!?' + descriptionAdditional100, + groupType: 'closed', + actionRadius: 'national', + categoryIds, + }, + }) + await mutate({ + mutation: joinGroupMutation, + variables: { + groupId: 'closed-group', + userId: 'current-user', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'closed-group', + userId: 'owner-of-hidden-group', + roleInGroup: 'usual', + }, + }) + // hidden-group + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + await mutate({ + mutation: createGroupMutation, + variables: { + id: 'hidden-group', + name: 'Investigative Journalism Group', + about: 'We will change all.', + description: 'We research …' + descriptionAdditional100, + groupType: 'hidden', + actionRadius: 'global', + categoryIds, + }, + }) + // 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'hidden-group', + userId: 'pending-user', + roleInGroup: 'pending', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'hidden-group', + userId: 'current-user', + roleInGroup: 'usual', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'hidden-group', + userId: 'owner-of-closed-group', + roleInGroup: 'admin', + }, + }) + // Wolle: + // const groups = await query({ query: groupQuery, variables: {} }) + // console.log('groups.data.Group: ', groups.data.Group) + // const groupMemberOfClosedGroup = await mutate({ + // mutation: groupMembersQuery, + // variables: { + // id: 'hidden-group', + // }, + // }) + // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) + + authenticatedUser = null + }) + + describe('public group', () => { + beforeEach(async () => { + variables = { + id: 'public-group', + } + }) + + describe('query group members', () => { + describe('by owner "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(3) + }) + }) + + describe('by usual member "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(3) + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(3) + }) + }) + }) + }) + + describe('closed group', () => { + beforeEach(async () => { + variables = { + id: 'closed-group', + } + }) + + describe('query group members', () => { + describe('by owner "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(3) + }) + }) + + describe('by usual member "owner-of-hidden-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'owner', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'usual', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(3) + }) + }) + + describe('by pending member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMembersQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMembersQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + + describe('hidden group', () => { + beforeEach(async () => { + variables = { + id: 'hidden-group', + } + }) + + describe('query group members', () => { + describe('by owner "owner-of-hidden-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfHiddenGroupUser.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'pending-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'admin', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(4) + }) + }) + + describe('by usual member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'pending-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'admin', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(4) + }) + }) + + describe('by admin member "owner-of-closed-group"', () => { + beforeEach(async () => { + authenticatedUser = await ownerOfClosedGroupUser.toJson() + }) + + it('finds all members', async () => { + const result = await mutate({ + mutation: groupMembersQuery, + variables, + }) + expect(result).toMatchObject({ + data: { + GroupMembers: expect.arrayContaining([ + expect.objectContaining({ + id: 'pending-user', + myRoleInGroup: 'pending', + }), + expect.objectContaining({ + id: 'current-user', + myRoleInGroup: 'usual', + }), + expect.objectContaining({ + id: 'owner-of-closed-group', + myRoleInGroup: 'admin', + }), + expect.objectContaining({ + id: 'owner-of-hidden-group', + myRoleInGroup: 'owner', + }), + ]), + }, + errors: undefined, + }) + expect(result.data.GroupMembers.length).toBe(4) + }) + }) + + describe('by pending member "pending-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMembersQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('by none member "other-user"', () => { + beforeEach(async () => { + authenticatedUser = await otherUser.toJson() + }) + + it('throws authorization error', async () => { + const { errors } = await query({ query: groupMembersQuery, variables }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) }) }) - describe('authenticated', () => { - let otherUser - let pendingUser - let ownerOfClosedGroupUser - let ownerOfHiddenGroupUser + describe('ChangeGroupMemberRole', () => { + let pendingMemberUser + let usualMemberUser + let adminMemberUser + let ownerMemberUser + let secondOwnerMemberUser beforeAll(async () => { + await seedBasicsAndClearAuthentication() // create users - otherUser = await Factory.build( + pendingMemberUser = await Factory.build( 'user', { - id: 'other-user', - name: 'Other TestUser', + id: 'pending-member-user', + name: 'Pending Member TestUser', }, { - email: 'other-user@example.org', + email: 'pending-member-user@example.org', password: '1234', }, ) - pendingUser = await Factory.build( + usualMemberUser = await Factory.build( 'user', { - id: 'pending-user', - name: 'Pending TestUser', + id: 'usual-member-user', + name: 'Usual Member TestUser', }, { - email: 'pending@example.org', + email: 'usual-member-user@example.org', password: '1234', }, ) - ownerOfClosedGroupUser = await Factory.build( + adminMemberUser = await Factory.build( 'user', { - id: 'owner-of-closed-group', - name: 'Owner Of Closed Group', + id: 'admin-member-user', + name: 'Admin Member TestUser', }, { - email: 'owner-of-closed-group@example.org', + email: 'admin-member-user@example.org', password: '1234', }, ) - ownerOfHiddenGroupUser = await Factory.build( + ownerMemberUser = await Factory.build( 'user', { - id: 'owner-of-hidden-group', - name: 'Owner Of Hidden Group', + id: 'owner-member-user', + name: 'Owner Member TestUser', }, { - email: 'owner-of-hidden-group@example.org', + email: 'owner-member-user@example.org', + password: '1234', + }, + ) + secondOwnerMemberUser = await Factory.build( + 'user', + { + id: 'second-owner-member-user', + name: 'Second Owner Member TestUser', + }, + { + email: 'second-owner-member-user@example.org', password: '1234', }, ) // create groups // public-group - authenticatedUser = await user.toJson() + authenticatedUser = await usualMemberUser.toJson() await mutate({ mutation: createGroupMutation, variables: { @@ -638,7 +1167,7 @@ describe('in mode: building up – separate for each resolver', () => { }, }) // closed-group - authenticatedUser = await ownerOfClosedGroupUser.toJson() + authenticatedUser = await ownerMemberUser.toJson() await mutate({ mutation: createGroupMutation, variables: { @@ -651,23 +1180,8 @@ describe('in mode: building up – separate for each resolver', () => { categoryIds, }, }) - await mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'closed-group', - userId: 'current-user', - }, - }) - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'closed-group', - userId: 'owner-of-hidden-group', - roleInGroup: 'usual', - }, - }) // hidden-group - authenticatedUser = await ownerOfHiddenGroupUser.toJson() + authenticatedUser = await adminMemberUser.toJson() await mutate({ mutation: createGroupMutation, variables: { @@ -685,15 +1199,7 @@ describe('in mode: building up – separate for each resolver', () => { mutation: changeGroupMemberRoleMutation, variables: { groupId: 'hidden-group', - userId: 'pending-user', - roleInGroup: 'pending', - }, - }) - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'hidden-group', - userId: 'current-user', + userId: 'admin-member-user', roleInGroup: 'usual', }, }) @@ -701,606 +1207,337 @@ describe('in mode: building up – separate for each resolver', () => { mutation: changeGroupMemberRoleMutation, variables: { groupId: 'hidden-group', - userId: 'owner-of-closed-group', - roleInGroup: 'admin', + userId: 'second-owner-member-user', + roleInGroup: 'usual', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'hidden-group', + userId: 'admin-member-user', + roleInGroup: 'usual', + }, + }) + await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'hidden-group', + userId: 'second-owner-member-user', + roleInGroup: 'usual', }, }) - // Wolle: - // const groups = await query({ query: groupQuery, variables: {} }) - // console.log('groups.data.Group: ', groups.data.Group) - // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMembersQuery, - // variables: { - // id: 'hidden-group', - // }, - // }) - // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) authenticatedUser = null }) - describe('public group', () => { - beforeEach(async () => { - variables = { - id: 'public-group', - } - }) + afterAll(async () => { + await cleanDatabase() + }) - describe('query group members', () => { - describe('by owner "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(3) - }) - }) - - describe('by usual member "owner-of-closed-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(3) - }) - }) - - describe('by none member "other-user"', () => { - beforeEach(async () => { - authenticatedUser = await otherUser.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(3) - }) + describe('unauthenticated', () => { + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables: { + groupId: 'not-existing-group', + userId: 'current-user', + roleInGroup: 'pending', + }, }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - describe('closed group', () => { - beforeEach(async () => { - variables = { - id: 'closed-group', - } - }) - - describe('query group members', () => { - describe('by owner "owner-of-closed-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(3) - }) + describe('authenticated', () => { + describe('in all group types – here "closed-group" for example', () => { + beforeEach(async () => { + variables = { + groupId: 'closed-group', + } }) - describe('by usual member "owner-of-hidden-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'owner', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'usual', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(3) - }) - }) - - describe('by pending member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('by none member "other-user"', () => { - beforeEach(async () => { - authenticatedUser = await otherUser.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - - describe('hidden group', () => { - beforeEach(async () => { - variables = { - id: 'hidden-group', - } - }) - - describe('query group members', () => { - describe('by owner "owner-of-hidden-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfHiddenGroupUser.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'pending-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'admin', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(4) - }) - }) - - describe('by usual member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'pending-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'admin', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(4) - }) - }) - - describe('by admin member "owner-of-closed-group"', () => { - beforeEach(async () => { - authenticatedUser = await ownerOfClosedGroupUser.toJson() - }) - - it('finds all members', async () => { - const result = await mutate({ - mutation: groupMembersQuery, - variables, - }) - expect(result).toMatchObject({ - data: { - GroupMembers: expect.arrayContaining([ - expect.objectContaining({ - id: 'pending-user', - myRoleInGroup: 'pending', - }), - expect.objectContaining({ - id: 'current-user', - myRoleInGroup: 'usual', - }), - expect.objectContaining({ - id: 'owner-of-closed-group', - myRoleInGroup: 'admin', - }), - expect.objectContaining({ - id: 'owner-of-hidden-group', - myRoleInGroup: 'owner', - }), - ]), - }, - errors: undefined, - }) - expect(result.data.GroupMembers.length).toBe(4) - }) - }) - - describe('by pending member "pending-user"', () => { - beforeEach(async () => { - authenticatedUser = await pendingUser.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('by none member "other-user"', () => { - beforeEach(async () => { - authenticatedUser = await otherUser.toJson() - }) - - it('throws authorization error', async () => { - const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - }) - }) - - describe('ChangeGroupMemberRole', () => { - let pendingMemberUser - let usualMemberUser - let adminMemberUser - let ownerMemberUser - let secondOwnerMemberUser - - beforeAll(async () => { - await seedBasicsAndClearAuthentication() - // create users - pendingMemberUser = await Factory.build( - 'user', - { - id: 'pending-member-user', - name: 'Pending Member TestUser', - }, - { - email: 'pending-member-user@example.org', - password: '1234', - }, - ) - usualMemberUser = await Factory.build( - 'user', - { - id: 'usual-member-user', - name: 'Usual Member TestUser', - }, - { - email: 'usual-member-user@example.org', - password: '1234', - }, - ) - adminMemberUser = await Factory.build( - 'user', - { - id: 'admin-member-user', - name: 'Admin Member TestUser', - }, - { - email: 'admin-member-user@example.org', - password: '1234', - }, - ) - ownerMemberUser = await Factory.build( - 'user', - { - id: 'owner-member-user', - name: 'Owner Member TestUser', - }, - { - email: 'owner-member-user@example.org', - password: '1234', - }, - ) - secondOwnerMemberUser = await Factory.build( - 'user', - { - id: 'second-owner-member-user', - name: 'Second Owner Member TestUser', - }, - { - email: 'second-owner-member-user@example.org', - password: '1234', - }, - ) - // create groups - // public-group - authenticatedUser = await usualMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'public-group', - name: 'The Best Group', - about: 'We will change the world!', - description: 'Some description' + descriptionAdditional100, - groupType: 'public', - actionRadius: 'regional', - categoryIds, - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'public-group', - userId: 'owner-of-closed-group', - }, - }) - await mutate({ - mutation: joinGroupMutation, - variables: { - groupId: 'public-group', - userId: 'owner-of-hidden-group', - }, - }) - // closed-group - authenticatedUser = await ownerMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'closed-group', - name: 'Uninteresting Group', - about: 'We will change nothing!', - description: 'We love it like it is!?' + descriptionAdditional100, - groupType: 'closed', - actionRadius: 'national', - categoryIds, - }, - }) - // hidden-group - authenticatedUser = await adminMemberUser.toJson() - await mutate({ - mutation: createGroupMutation, - variables: { - id: 'hidden-group', - name: 'Investigative Journalism Group', - about: 'We will change all.', - description: 'We research …' + descriptionAdditional100, - groupType: 'hidden', - actionRadius: 'global', - categoryIds, - }, - }) - // 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'hidden-group', - userId: 'admin-member-user', - roleInGroup: 'usual', - }, - }) - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'hidden-group', - userId: 'second-owner-member-user', - roleInGroup: 'usual', - }, - }) - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'hidden-group', - userId: 'admin-member-user', - roleInGroup: 'usual', - }, - }) - await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'hidden-group', - userId: 'second-owner-member-user', - roleInGroup: 'usual', - }, - }) - - authenticatedUser = null - }) - - afterAll(async () => { - await cleanDatabase() - }) - - describe('unauthenticated', () => { - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables: { - groupId: 'not-existing-group', - userId: 'current-user', - roleInGroup: 'pending', - }, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('authenticated', () => { - describe('in all group types – here "closed-group" for example', () => { - beforeEach(async () => { - variables = { - groupId: 'closed-group', - } - }) - - describe('join the members and give them their prospective roles', () => { - describe('by owner "owner-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() - }) - - describe('for "usual-member-user"', () => { + describe('join the members and give them their prospective roles', () => { + describe('by owner "owner-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - userId: 'usual-member-user', - } + authenticatedUser = await ownerMemberUser.toJson() }) - describe('as usual', () => { + describe('for "usual-member-user"', () => { beforeEach(async () => { variables = { ...variables, - roleInGroup: 'usual', + userId: 'usual-member-user', } }) - it('has role usual', async () => { - await expect( - mutate({ + describe('as usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('has role usual', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'usual-member-user', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + }) + }) + + // the GQL mutation needs this fields in the result for testing + it.todo('has "updatedAt" newer as "createdAt"') + }) + }) + + describe('for "admin-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'admin-member-user', + } + }) + + describe('as admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('has role admin', async () => { + // Wolle: + // const groups = await query({ query: groupQuery, variables: {} }) + // console.log('groups.data.Group: ', groups.data.Group) + // const groupMemberOfClosedGroup = await mutate({ + // mutation: groupMembersQuery, + // variables: { + // id: 'closed-group', + // }, + // }) + // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'admin-member-user', + myRoleInGroup: 'admin', + }, + }, + errors: undefined, + }) + }) + }) + }) + + describe('for "second-owner-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'second-owner-member-user', + } + }) + + describe('as owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('has role owner', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'second-owner-member-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + }) + }) + }) + }) + }) + }) + + describe('switch role', () => { + describe('of owner "owner-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'owner-member-user', + } + }) + + describe('by owner themself "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'usual-member-user', - myRoleInGroup: 'usual', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + // shall this be possible in the future? + // or shall only an owner who gave the second owner the owner role downgrade themself for savety? + // otherwise the first owner who downgrades the other one has the victory over the group! + describe('by second owner "second-owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await secondOwnerMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - // the GQL mutation needs this fields in the result for testing - it.todo('has "updatedAt" newer as "createdAt"') + describe('to same role owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('has role owner still', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'owner-member-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + }) + }) + }) + }) + + describe('by admin "admin-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await adminMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by still pending member "pending-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingMemberUser.toJson() + }) + + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) }) }) - describe('for "admin-member-user"', () => { + describe('of admin "admin-member-user"', () => { beforeEach(async () => { variables = { ...variables, @@ -1308,730 +1545,495 @@ describe('in mode: building up – separate for each resolver', () => { } }) - describe('as admin', () => { + describe('by owner "owner-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } + authenticatedUser = await ownerMemberUser.toJson() }) - it('has role admin', async () => { - // Wolle: - // const groups = await query({ query: groupQuery, variables: {} }) - // console.log('groups.data.Group: ', groups.data.Group) - // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMembersQuery, - // variables: { - // id: 'closed-group', - // }, - // }) - // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) - await expect( - mutate({ + describe('to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('has role owner', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'admin-member-user', + myRoleInGroup: 'owner', + }, + }, + errors: undefined, + }) + }) + }) + + describe('back to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'admin-member-user', - myRoleInGroup: 'admin', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('upgrade to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by still pending member "pending-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await pendingMemberUser.toJson() + }) + + describe('upgrade to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + + describe('by none member "current-user"', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + describe('upgrade to owner', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'owner', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + + describe('degrade to pending again', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) }) - describe('for "second-owner-member-user"', () => { + describe('of usual member "usual-member-user"', () => { beforeEach(async () => { variables = { ...variables, - userId: 'second-owner-member-user', + userId: 'usual-member-user', } }) - describe('as owner', () => { + describe('by owner "owner-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'owner', - } + authenticatedUser = await ownerMemberUser.toJson() }) - it('has role owner', async () => { - await expect( - mutate({ + describe('to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('has role admin', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'usual-member-user', + myRoleInGroup: 'admin', + }, + }, + errors: undefined, + }) + }) + }) + + describe('back to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('has role usual again', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'usual-member-user', + myRoleInGroup: 'usual', + }, + }, + errors: undefined, + }) + }) + }) + }) + + describe('by usual member "usual-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await usualMemberUser.toJson() + }) + + describe('upgrade to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'second-owner-member-user', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - }) - }) - }) - }) - describe('switch role', () => { - describe('of owner "owner-member-user"', () => { - beforeEach(async () => { - variables = { - ...variables, - userId: 'owner-member-user', - } - }) - - describe('by owner themself "owner-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() - }) - - describe('to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + describe('degrade to pending', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - // shall this be possible in the future? - // or shall only an owner who gave the second owner the owner role downgrade themself for savety? - // otherwise the first owner who downgrades the other one has the victory over the group! - describe('by second owner "second-owner-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await secondOwnerMemberUser.toJson() - }) - - describe('to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('to same role owner', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'owner', - } - }) - - it('has role owner still', async () => { - await expect( - mutate({ + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'owner-member-user', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) - }) - describe('by admin "admin-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await adminMemberUser.toJson() - }) - - describe('to admin', () => { + describe('by still pending member "pending-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } + authenticatedUser = await pendingMemberUser.toJson() }) - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + describe('upgrade to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - describe('by usual member "usual-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await usualMemberUser.toJson() - }) - - describe('to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - - describe('by still pending member "pending-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await pendingMemberUser.toJson() - }) - - describe('to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - - describe('of admin "admin-member-user"', () => { - beforeEach(async () => { - variables = { - ...variables, - userId: 'admin-member-user', - } - }) - - describe('by owner "owner-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() - }) - - describe('to owner', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'owner', - } - }) - - it('has role owner', async () => { - await expect( - mutate({ + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'admin-member-user', - myRoleInGroup: 'owner', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - }) - describe('back to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + describe('degrade to pending', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - describe('by usual member "usual-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await usualMemberUser.toJson() - }) - - describe('upgrade to owner', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'owner', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('degrade to usual', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - - describe('by still pending member "pending-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await pendingMemberUser.toJson() - }) - - describe('upgrade to owner', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'owner', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('degrade to usual', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - - describe('by none member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - describe('upgrade to owner', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'owner', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('degrade to pending again', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'pending', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - - describe('of usual member "usual-member-user"', () => { - beforeEach(async () => { - variables = { - ...variables, - userId: 'usual-member-user', - } - }) - - describe('by owner "owner-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() - }) - - describe('to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('has role admin', async () => { - await expect( - mutate({ + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'usual-member-user', - myRoleInGroup: 'admin', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) - describe('back to usual', () => { + describe('by none member "current-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } + authenticatedUser = await user.toJson() }) - it('has role usual again', async () => { - await expect( - mutate({ + describe('upgrade to admin', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'admin', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'usual-member-user', - myRoleInGroup: 'usual', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - }) - }) - describe('by usual member "usual-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await usualMemberUser.toJson() - }) - - describe('upgrade to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + describe('degrade to pending again', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - describe('degrade to pending', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'pending', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - - describe('by still pending member "pending-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await pendingMemberUser.toJson() - }) - - describe('upgrade to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('degrade to pending', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'pending', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - - describe('by none member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - describe('upgrade to admin', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'admin', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - - describe('degrade to pending again', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'pending', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, - }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - }) - - describe('of still pending member "pending-member-user"', () => { - beforeEach(async () => { - variables = { - ...variables, - userId: 'pending-member-user', - } - }) - - describe('by owner "owner-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await ownerMemberUser.toJson() - }) - - describe('to usual', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } - }) - - it('has role usual', async () => { - await expect( - mutate({ + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'pending-member-user', - myRoleInGroup: 'usual', + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + }) + }) + }) + }) + + describe('of still pending member "pending-member-user"', () => { + beforeEach(async () => { + variables = { + ...variables, + userId: 'pending-member-user', + } + }) + + describe('by owner "owner-member-user"', () => { + beforeEach(async () => { + authenticatedUser = await ownerMemberUser.toJson() + }) + + describe('to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('has role usual', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'pending-member-user', + myRoleInGroup: 'usual', + }, }, - }, - errors: undefined, + errors: undefined, + }) + }) + }) + + describe('back to pending', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'pending', + } + }) + + it('has role usual again', async () => { + await expect( + mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }), + ).resolves.toMatchObject({ + data: { + ChangeGroupMemberRole: { + id: 'pending-member-user', + myRoleInGroup: 'pending', + }, + }, + errors: undefined, + }) }) }) }) - describe('back to pending', () => { + describe('by usual member "usual-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'pending', - } + authenticatedUser = await usualMemberUser.toJson() }) - it('has role usual again', async () => { - await expect( - mutate({ + describe('upgrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ mutation: changeGroupMemberRoleMutation, variables, - }), - ).resolves.toMatchObject({ - data: { - ChangeGroupMemberRole: { - id: 'pending-member-user', - myRoleInGroup: 'pending', - }, - }, - errors: undefined, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) - }) - describe('by usual member "usual-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await usualMemberUser.toJson() - }) - - describe('upgrade to usual', () => { + describe('by still pending member "pending-member-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } + authenticatedUser = await pendingMemberUser.toJson() }) - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + describe('upgrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } + }) + + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) - }) - describe('by still pending member "pending-member-user"', () => { - beforeEach(async () => { - authenticatedUser = await pendingMemberUser.toJson() - }) - - describe('upgrade to usual', () => { + describe('by none member "current-user"', () => { beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } + authenticatedUser = await user.toJson() }) - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + describe('upgrade to usual', () => { + beforeEach(async () => { + variables = { + ...variables, + roleInGroup: 'usual', + } }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') - }) - }) - }) - describe('by none member "current-user"', () => { - beforeEach(async () => { - authenticatedUser = await user.toJson() - }) - - describe('upgrade to usual', () => { - beforeEach(async () => { - variables = { - ...variables, - roleInGroup: 'usual', - } - }) - - it('throws authorization error', async () => { - const { errors } = await mutate({ - mutation: changeGroupMemberRoleMutation, - variables, + it('throws authorization error', async () => { + const { errors } = await mutate({ + mutation: changeGroupMemberRoleMutation, + variables, + }) + expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') }) }) }) From cd090420cf318f5b9fbd7618ac3a0f8d65d67700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 12:30:01 +0200 Subject: [PATCH 45/67] Move 'JoinGroup' to building up mode in 'groups.spec.js' --- backend/src/schema/resolvers/groups.spec.js | 56 +++++++++++++-------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 054e3abb0..e966506a7 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -122,34 +122,40 @@ describe('in mode', () => { }) it('creates a group', async () => { - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ - data: { - CreateGroup: { - name: 'The Best Group', - slug: 'the-group', - about: 'We will change the world!', + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + { + data: { + CreateGroup: { + name: 'The Best Group', + slug: 'the-group', + about: 'We will change the world!', + }, }, + errors: undefined, }, - errors: undefined, - }) + ) }) it('assigns the authenticated user as owner', async () => { - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ - data: { - CreateGroup: { - name: 'The Best Group', - myRole: 'owner', + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + { + data: { + CreateGroup: { + name: 'The Best Group', + myRole: 'owner', + }, }, + errors: undefined, }, - errors: undefined, - }) + ) }) it('has "disabled" and "deleted" default to "false"', async () => { - await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject({ - data: { CreateGroup: { disabled: false, deleted: false } }, - }) + await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject( + { + data: { CreateGroup: { disabled: false, deleted: false } }, + }, + ) }) describe('description', () => { @@ -313,8 +319,18 @@ describe('in mode', () => { }) }) }) + }) + describe('building up – clean db after each resolver', () => { describe('JoinGroup', () => { + beforeAll(async () => { + await seedBasicsAndClearAuthentication() + }) + + afterAll(async () => { + await cleanDatabase() + }) + describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ @@ -332,7 +348,7 @@ describe('in mode', () => { let ownerOfClosedGroupUser let ownerOfHiddenGroupUser - beforeEach(async () => { + beforeAll(async () => { // create users ownerOfClosedGroupUser = await Factory.build( 'user', @@ -535,9 +551,7 @@ describe('in mode', () => { }) }) }) - }) - describe('building up – clean db after each resolver', () => { describe('GroupMembers', () => { beforeAll(async () => { await seedBasicsAndClearAuthentication() From 47027ad86bca4e82b4d314f880d5f78260669a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 12:47:57 +0200 Subject: [PATCH 46/67] Move 'Group' resolver to building up mode in 'groups.spec.js' --- backend/src/schema/resolvers/groups.spec.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index e966506a7..7a5f9504a 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -204,8 +204,18 @@ describe('in mode', () => { }) }) }) + }) + describe('building up – clean db after each resolver', () => { describe('Group', () => { + beforeAll(async () => { + await seedBasicsAndClearAuthentication() + }) + + afterAll(async () => { + await cleanDatabase() + }) + describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupQuery, variables: {} }) @@ -216,7 +226,7 @@ describe('in mode', () => { describe('authenticated', () => { let otherUser - beforeEach(async () => { + beforeAll(async () => { otherUser = await Factory.build( 'user', { @@ -319,9 +329,7 @@ describe('in mode', () => { }) }) }) - }) - describe('building up – clean db after each resolver', () => { describe('JoinGroup', () => { beforeAll(async () => { await seedBasicsAndClearAuthentication() From 72eedef8d0d5b5f2e53858e6fee9c15f2e17b15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Tue, 23 Aug 2022 13:12:38 +0200 Subject: [PATCH 47/67] Cleanup --- .../src/middleware/permissionsMiddleware.js | 62 ------------------- backend/src/schema/resolvers/groups.js | 8 --- backend/src/schema/resolvers/groups.spec.js | 20 ------ 3 files changed, 90 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 926f824e4..bfd10537a 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -57,8 +57,6 @@ const isAllowedSeeingMembersOfGroup = rule({ })(async (_parent, args, { user, driver }) => { if (!(user && user.id)) return false const { id: groupId } = args - // Wolle: console.log('groupId: ', groupId) - // console.log('user.id: ', user.id) const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { const transactionResponse = await transaction.run( @@ -76,8 +74,6 @@ const isAllowedSeeingMembersOfGroup = rule({ }) try { const { member, group } = await readTxPromise - // Wolle: console.log('member: ', member) - // console.log('group: ', group) return ( !!group && (group.groupType === 'public' || @@ -86,7 +82,6 @@ const isAllowedSeeingMembersOfGroup = rule({ ['usual', 'admin', 'owner'].includes(member.myRoleInGroup))) ) } catch (error) { - // Wolle: console.log('error: ', error) throw new Error(error) } finally { session.close() @@ -100,12 +95,6 @@ const isAllowedToChangeGroupMemberRole = rule({ const adminId = user.id const { groupId, userId, roleInGroup } = args if (adminId === userId) return false - // Wolle: - // console.log('isAllowedToChangeGroupMemberRole !!!') - // console.log('adminId: ', adminId) - // console.log('groupId: ', groupId) - // console.log('userId: ', userId) - // console.log('roleInGroup: ', roleInGroup) const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { const transactionResponse = await transaction.run( @@ -116,23 +105,6 @@ const isAllowedToChangeGroupMemberRole = rule({ `, { groupId, adminId, userId }, ) - // Wolle: - // console.log( - // 'transactionResponse: ', - // transactionResponse, - // ) - // console.log( - // 'transaction admins: ', - // transactionResponse.records.map((record) => record.get('admin')), - // ) - // console.log( - // 'transaction groups: ', - // transactionResponse.records.map((record) => record.get('group')), - // ) - // console.log( - // 'transaction members: ', - // transactionResponse.records.map((record) => record.get('member')), - // ) return { admin: transactionResponse.records.map((record) => record.get('admin'))[0], group: transactionResponse.records.map((record) => record.get('group'))[0], @@ -140,14 +112,7 @@ const isAllowedToChangeGroupMemberRole = rule({ } }) try { - // Wolle: - // console.log('enter try !!!') const { admin, group, member } = await readTxPromise - // Wolle: - // console.log('after !!!') - // console.log('admin: ', admin) - // console.log('group: ', group) - // console.log('member: ', member) return ( !!group && !!admin && @@ -160,8 +125,6 @@ const isAllowedToChangeGroupMemberRole = rule({ ['pending', 'usual', 'admin', 'owner'].includes(roleInGroup))) ) } catch (error) { - // Wolle: - // console.log('error: ', error) throw new Error(error) } finally { session.close() @@ -173,11 +136,6 @@ const isAllowedToJoinGroup = rule({ })(async (_parent, args, { user, driver }) => { if (!(user && user.id)) return false const { groupId, userId } = args - // Wolle: - // console.log('adminId: ', adminId) - // console.log('groupId: ', groupId) - // console.log('userId: ', userId) - // console.log('roleInGroup: ', roleInGroup) const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { const transactionResponse = await transaction.run( @@ -188,35 +146,15 @@ const isAllowedToJoinGroup = rule({ `, { groupId, userId }, ) - // Wolle: - // console.log( - // 'transactionResponse: ', - // transactionResponse, - // ) - // console.log( - // 'transaction groups: ', - // transactionResponse.records.map((record) => record.get('group')), - // ) - // console.log( - // 'transaction members: ', - // transactionResponse.records.map((record) => record.get('member')), - // ) return { group: transactionResponse.records.map((record) => record.get('group'))[0], member: transactionResponse.records.map((record) => record.get('member'))[0], } }) try { - // Wolle: - // console.log('enter try !!!') const { group, member } = await readTxPromise - // Wolle: - // console.log('after !!!') - // console.log('group: ', group) - // console.log('member: ', member) return !!group && (group.groupType !== 'hidden' || (!!member && !!member.myRoleInGroup)) } catch (error) { - // Wolle: console.log('error: ', error) throw new Error(error) } finally { session.close() diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 6ca09d72a..c47cf6085 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -48,7 +48,6 @@ export default { }, GroupMembers: async (_object, params, context, _resolveInfo) => { const { id: groupId } = params - // Wolle: console.log('groupId: ', groupId) const session = context.driver.session() const readTxResultPromise = session.readTransaction(async (txc) => { const groupMemberCypher = ` @@ -160,11 +159,6 @@ export default { }, ChangeGroupMemberRole: async (_parent, params, context, _resolveInfo) => { const { groupId, userId, roleInGroup } = params - // Wolle - // console.log('ChangeGroupMemberRole !!!') - // console.log('groupId: ', groupId) - // console.log('userId: ', userId) - // console.log('roleInGroup: ', roleInGroup) const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { const joinGroupCypher = ` @@ -180,8 +174,6 @@ export default { ` const result = await transaction.run(joinGroupCypher, { groupId, userId, roleInGroup }) const [member] = await result.records.map((record) => record.get('member')) - // Wolle - // console.log('member: ', member) return member }) try { diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 7a5f9504a..be9ba4f3d 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -728,16 +728,6 @@ describe('in mode', () => { roleInGroup: 'admin', }, }) - // Wolle: - // const groups = await query({ query: groupQuery, variables: {} }) - // console.log('groups.data.Group: ', groups.data.Group) - // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMembersQuery, - // variables: { - // id: 'hidden-group', - // }, - // }) - // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) authenticatedUser = null }) @@ -1340,16 +1330,6 @@ describe('in mode', () => { }) it('has role admin', async () => { - // Wolle: - // const groups = await query({ query: groupQuery, variables: {} }) - // console.log('groups.data.Group: ', groups.data.Group) - // const groupMemberOfClosedGroup = await mutate({ - // mutation: groupMembersQuery, - // variables: { - // id: 'closed-group', - // }, - // }) - // console.log('groupMemberOfClosedGroup.data.GroupMembers: ', groupMemberOfClosedGroup.data.GroupMembers) await expect( mutate({ mutation: changeGroupMemberRoleMutation, From 15ce0702886d1fdc00b0e9ba5f70a74af03f9055 Mon Sep 17 00:00:00 2001 From: Tima Gixe Date: Thu, 25 Aug 2022 09:08:14 +0300 Subject: [PATCH 48/67] Update tests to expect `Not Authorized!` --- .../middleware/permissionsMiddleware.spec.js | 10 +++---- backend/src/schema/resolvers/comments.spec.js | 14 +++++----- .../src/schema/resolvers/donations.spec.js | 8 +++--- backend/src/schema/resolvers/emails.spec.js | 4 +-- backend/src/schema/resolvers/follow.spec.js | 4 +-- .../src/schema/resolvers/moderation.spec.js | 12 ++++----- .../schema/resolvers/notifications.spec.js | 4 +-- backend/src/schema/resolvers/posts.spec.js | 26 +++++++++---------- .../src/schema/resolvers/registration.spec.js | 2 +- backend/src/schema/resolvers/reports.spec.js | 6 ++--- backend/src/schema/resolvers/rewards.spec.js | 8 +++--- backend/src/schema/resolvers/shout.spec.js | 4 +-- .../src/schema/resolvers/socialMedia.spec.js | 12 ++++----- .../schema/resolvers/user_management.spec.js | 4 +-- backend/src/schema/resolvers/users.spec.js | 6 ++--- .../schema/resolvers/users/mutedUsers.spec.js | 6 ++--- .../ContributionForm/ContributionForm.spec.js | 4 +-- .../components/DeleteData/DeleteData.spec.js | 4 +-- webapp/components/Modal/DisableModal.spec.js | 4 +-- .../ReleaseModal/ReleaseModal.spec.js | 4 +-- 20 files changed, 73 insertions(+), 73 deletions(-) diff --git a/backend/src/middleware/permissionsMiddleware.spec.js b/backend/src/middleware/permissionsMiddleware.spec.js index e29e0a4af..9d71314bb 100644 --- a/backend/src/middleware/permissionsMiddleware.spec.js +++ b/backend/src/middleware/permissionsMiddleware.spec.js @@ -102,7 +102,7 @@ describe('authorization', () => { await expect( query({ query: userQuery, variables: { name: 'Owner' } }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { User: [null] }, }) }) @@ -132,7 +132,7 @@ describe('authorization', () => { await expect( query({ query: userQuery, variables: { name: 'Owner' } }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { User: [null] }, }) }) @@ -147,7 +147,7 @@ describe('authorization', () => { await expect( query({ query: userQuery, variables: { name: 'Owner' } }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { User: [null] }, }) }) @@ -198,7 +198,7 @@ describe('authorization', () => { it('denies permission', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { Signup: null }, }) }) @@ -288,7 +288,7 @@ describe('authorization', () => { it('denies permission', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { Signup: null }, }) }) diff --git a/backend/src/schema/resolvers/comments.spec.js b/backend/src/schema/resolvers/comments.spec.js index cbd2b98fc..f0081b726 100644 --- a/backend/src/schema/resolvers/comments.spec.js +++ b/backend/src/schema/resolvers/comments.spec.js @@ -88,10 +88,10 @@ describe('CreateComment', () => { variables = { ...variables, postId: 'p1', - content: "I'm not authorised to comment", + content: "I'm Not Authorized to comment", } const { errors } = await mutate({ mutation: createCommentMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -150,7 +150,7 @@ describe('UpdateComment', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: updateCommentMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -162,7 +162,7 @@ describe('UpdateComment', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: updateCommentMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -217,7 +217,7 @@ describe('UpdateComment', () => { it('returns null', async () => { const { data, errors } = await mutate({ mutation: updateCommentMutation, variables }) expect(data).toMatchObject({ UpdateComment: null }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -242,7 +242,7 @@ describe('DeleteComment', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const result = await mutate({ mutation: deleteCommentMutation, variables }) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -254,7 +254,7 @@ describe('DeleteComment', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: deleteCommentMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) diff --git a/backend/src/schema/resolvers/donations.spec.js b/backend/src/schema/resolvers/donations.spec.js index a9210f6a5..11df0c67b 100644 --- a/backend/src/schema/resolvers/donations.spec.js +++ b/backend/src/schema/resolvers/donations.spec.js @@ -72,7 +72,7 @@ describe('donations', () => { it('throws authorization error', async () => { authenticatedUser = undefined await expect(query({ query: donationsQuery, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -106,7 +106,7 @@ describe('donations', () => { await expect( mutate({ mutation: updateDonationsMutation, variables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -126,7 +126,7 @@ describe('donations', () => { mutate({ mutation: updateDonationsMutation, variables }), ).resolves.toMatchObject({ data: { UpdateDonations: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -145,7 +145,7 @@ describe('donations', () => { mutate({ mutation: updateDonationsMutation, variables }), ).resolves.toMatchObject({ data: { UpdateDonations: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) diff --git a/backend/src/schema/resolvers/emails.spec.js b/backend/src/schema/resolvers/emails.spec.js index 39b70ac0b..b527ca3b0 100644 --- a/backend/src/schema/resolvers/emails.spec.js +++ b/backend/src/schema/resolvers/emails.spec.js @@ -63,7 +63,7 @@ describe('AddEmailAddress', () => { it('throws AuthorizationError', async () => { await expect(mutate({ mutation, variables })).resolves.toMatchObject({ data: { AddEmailAddress: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -169,7 +169,7 @@ describe('VerifyEmailAddress', () => { it('throws AuthorizationError', async () => { await expect(mutate({ mutation, variables })).resolves.toMatchObject({ data: { VerifyEmailAddress: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) diff --git a/backend/src/schema/resolvers/follow.spec.js b/backend/src/schema/resolvers/follow.spec.js index 9cc8403e5..e0b2a277a 100644 --- a/backend/src/schema/resolvers/follow.spec.js +++ b/backend/src/schema/resolvers/follow.spec.js @@ -117,7 +117,7 @@ describe('follow', () => { variables, }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { followUser: null }, }) }) @@ -191,7 +191,7 @@ describe('follow', () => { authenticatedUser = null await expect(mutate({ mutation: mutationUnfollowUser, variables })).resolves.toMatchObject({ data: { unfollowUser: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) diff --git a/backend/src/schema/resolvers/moderation.spec.js b/backend/src/schema/resolvers/moderation.spec.js index 662be41bd..3c2926c14 100644 --- a/backend/src/schema/resolvers/moderation.spec.js +++ b/backend/src/schema/resolvers/moderation.spec.js @@ -120,7 +120,7 @@ describe('moderate resources', () => { await expect( mutate({ mutation: reviewMutation, variables: disableVariables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -134,7 +134,7 @@ describe('moderate resources', () => { await expect( mutate({ mutation: reviewMutation, variables: disableVariables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -218,7 +218,7 @@ describe('moderate resources', () => { await expect( mutate({ mutation: reviewMutation, variables: disableVariables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -232,7 +232,7 @@ describe('moderate resources', () => { await expect( mutate({ mutation: reviewMutation, variables: disableVariables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -488,7 +488,7 @@ describe('moderate resources', () => { await expect( mutate({ mutation: reviewMutation, variables: enableVariables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -507,7 +507,7 @@ describe('moderate resources', () => { await expect( mutate({ mutation: reviewMutation, variables: enableVariables }), ).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.js index 2ea468914..924154488 100644 --- a/backend/src/schema/resolvers/notifications.spec.js +++ b/backend/src/schema/resolvers/notifications.spec.js @@ -165,7 +165,7 @@ describe('given some notifications', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await query({ query: notificationQuery }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -313,7 +313,7 @@ describe('given some notifications', () => { mutation: markAsReadMutation, variables: { ...variables, id: 'p1' }, }) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) diff --git a/backend/src/schema/resolvers/posts.spec.js b/backend/src/schema/resolvers/posts.spec.js index 2c8b7e90b..52bd8fcd0 100644 --- a/backend/src/schema/resolvers/posts.spec.js +++ b/backend/src/schema/resolvers/posts.spec.js @@ -281,7 +281,7 @@ describe('CreatePost', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: createPostMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -369,7 +369,7 @@ describe('UpdatePost', () => { it('throws authorization error', async () => { authenticatedUser = null expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { UpdatePost: null }, }) }) @@ -382,7 +382,7 @@ describe('UpdatePost', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: updatePostMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -547,7 +547,7 @@ describe('pin posts', () => { it('throws authorization error', async () => { authenticatedUser = null await expect(mutate({ mutation: pinPostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { pinPost: null }, }) }) @@ -556,7 +556,7 @@ describe('pin posts', () => { describe('ordinary users', () => { it('throws authorization error', async () => { await expect(mutate({ mutation: pinPostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { pinPost: null }, }) }) @@ -571,7 +571,7 @@ describe('pin posts', () => { it('throws authorization error', async () => { await expect(mutate({ mutation: pinPostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { pinPost: null }, }) }) @@ -854,7 +854,7 @@ describe('unpin posts', () => { it('throws authorization error', async () => { authenticatedUser = null await expect(mutate({ mutation: unpinPostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { unpinPost: null }, }) }) @@ -863,7 +863,7 @@ describe('unpin posts', () => { describe('users cannot unpin posts', () => { it('throws authorization error', async () => { await expect(mutate({ mutation: unpinPostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { unpinPost: null }, }) }) @@ -878,7 +878,7 @@ describe('unpin posts', () => { it('throws authorization error', async () => { await expect(mutate({ mutation: unpinPostMutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], data: { unpinPost: null }, }) }) @@ -975,7 +975,7 @@ describe('DeletePost', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: deletePostMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -986,7 +986,7 @@ describe('DeletePost', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: deletePostMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1128,7 +1128,7 @@ describe('emotions', () => { variables, }) - expect(addPostEmotions.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(addPostEmotions.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1249,7 +1249,7 @@ describe('emotions', () => { mutation: removePostEmotionsMutation, variables: removePostEmotionsVariables, }) - expect(removePostEmotions.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(removePostEmotions.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) diff --git a/backend/src/schema/resolvers/registration.spec.js b/backend/src/schema/resolvers/registration.spec.js index 573af1d35..ebe36456b 100644 --- a/backend/src/schema/resolvers/registration.spec.js +++ b/backend/src/schema/resolvers/registration.spec.js @@ -61,7 +61,7 @@ describe('Signup', () => { CONFIG.INVITE_REGISTRATION = false CONFIG.PUBLIC_REGISTRATION = false await expect(mutate({ mutation, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 09d0869fc..7cf4d9a34 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -130,7 +130,7 @@ describe('file a report on a resource', () => { authenticatedUser = null await expect(mutate({ mutation: fileReportMutation, variables })).resolves.toMatchObject({ data: { fileReport: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -729,7 +729,7 @@ describe('file a report on a resource', () => { authenticatedUser = null expect(query({ query: reportsQuery })).resolves.toMatchObject({ data: { reports: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -739,7 +739,7 @@ describe('file a report on a resource', () => { authenticatedUser = await currentUser.toJson() expect(query({ query: reportsQuery })).resolves.toMatchObject({ data: { reports: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) diff --git a/backend/src/schema/resolvers/rewards.spec.js b/backend/src/schema/resolvers/rewards.spec.js index 718378699..f44cf51f6 100644 --- a/backend/src/schema/resolvers/rewards.spec.js +++ b/backend/src/schema/resolvers/rewards.spec.js @@ -97,7 +97,7 @@ describe('rewards', () => { authenticatedUser = null await expect(mutate({ mutation: rewardMutation, variables })).resolves.toMatchObject({ data: { reward: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -255,7 +255,7 @@ describe('rewards', () => { it('throws authorization error', async () => { await expect(mutate({ mutation: rewardMutation, variables })).resolves.toMatchObject({ data: { reward: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -308,7 +308,7 @@ describe('rewards', () => { authenticatedUser = null await expect(mutate({ mutation: unrewardMutation, variables })).resolves.toMatchObject({ data: { unreward: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -341,7 +341,7 @@ describe('rewards', () => { it('throws authorization error', async () => { await expect(mutate({ mutation: unrewardMutation, variables })).resolves.toMatchObject({ data: { unreward: null }, - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) diff --git a/backend/src/schema/resolvers/shout.spec.js b/backend/src/schema/resolvers/shout.spec.js index a4e9890d5..087c452da 100644 --- a/backend/src/schema/resolvers/shout.spec.js +++ b/backend/src/schema/resolvers/shout.spec.js @@ -90,7 +90,7 @@ describe('shout and unshout posts', () => { variables = { id: 'post-to-shout-id' } authenticatedUser = undefined await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) @@ -165,7 +165,7 @@ describe('shout and unshout posts', () => { authenticatedUser = undefined variables = { id: 'post-to-shout-id' } await expect(mutate({ mutation: mutationUnshoutPost, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) }) diff --git a/backend/src/schema/resolvers/socialMedia.spec.js b/backend/src/schema/resolvers/socialMedia.spec.js index bb7886c3f..fc9ee8f70 100644 --- a/backend/src/schema/resolvers/socialMedia.spec.js +++ b/backend/src/schema/resolvers/socialMedia.spec.js @@ -94,7 +94,7 @@ describe('SocialMedia', () => { const user = null const result = await socialMediaAction(user, mutation, variables) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -186,7 +186,7 @@ describe('SocialMedia', () => { const user = null const result = await socialMediaAction(user, mutation, variables) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -195,7 +195,7 @@ describe('SocialMedia', () => { const user = someUser const result = await socialMediaAction(user, mutation, variables) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -222,7 +222,7 @@ describe('SocialMedia', () => { variables.id = 'some-id' const result = await socialMediaAction(user, mutation, variables) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -249,7 +249,7 @@ describe('SocialMedia', () => { const user = null const result = await socialMediaAction(user, mutation, variables) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -258,7 +258,7 @@ describe('SocialMedia', () => { const user = someUser const result = await socialMediaAction(user, mutation, variables) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) diff --git a/backend/src/schema/resolvers/user_management.spec.js b/backend/src/schema/resolvers/user_management.spec.js index 2dcb14855..264cf2752 100644 --- a/backend/src/schema/resolvers/user_management.spec.js +++ b/backend/src/schema/resolvers/user_management.spec.js @@ -310,8 +310,8 @@ describe('change password', () => { }) describe('unauthenticated', () => { - it('throws "Not Authorised!"', async () => { - await respondsWith({ errors: [{ message: 'Not Authorised!' }] }) + it('throws "Not Authorized!"', async () => { + await respondsWith({ errors: [{ message: 'Not Authorized!' }] }) }) }) diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index 9a88dc945..920ef52ea 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -101,7 +101,7 @@ describe('User', () => { it('is forbidden', async () => { await expect(query({ query: userQuery, variables })).resolves.toMatchObject({ - errors: [{ message: 'Not Authorised!' }], + errors: [{ message: 'Not Authorized!' }], }) }) @@ -207,7 +207,7 @@ describe('UpdateUser', () => { it('is not allowed to change other user accounts', async () => { const { errors } = await mutate({ mutation: updateUserMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -500,7 +500,7 @@ describe('switch user role', () => { expect.objectContaining({ errors: [ expect.objectContaining({ - message: 'Not Authorised!', + message: 'Not Authorized!', }), ], }), diff --git a/backend/src/schema/resolvers/users/mutedUsers.spec.js b/backend/src/schema/resolvers/users/mutedUsers.spec.js index 36b526268..d8efacfae 100644 --- a/backend/src/schema/resolvers/users/mutedUsers.spec.js +++ b/backend/src/schema/resolvers/users/mutedUsers.spec.js @@ -58,7 +58,7 @@ describe('mutedUsers', () => { it('throws permission error', async () => { const { query } = createTestClient(server) const result = await query({ query: mutedUserQuery }) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) describe('authenticated and given a muted user', () => { @@ -116,7 +116,7 @@ describe('muteUser', () => { it('throws permission error', async () => { const result = await muteAction({ id: 'u2' }) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) describe('authenticated', () => { @@ -333,7 +333,7 @@ describe('unmuteUser', () => { it('throws permission error', async () => { const result = await unmuteAction({ id: 'u2' }) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') }) describe('authenticated', () => { diff --git a/webapp/components/ContributionForm/ContributionForm.spec.js b/webapp/components/ContributionForm/ContributionForm.spec.js index ce432fc42..f5083a8a0 100644 --- a/webapp/components/ContributionForm/ContributionForm.spec.js +++ b/webapp/components/ContributionForm/ContributionForm.spec.js @@ -202,7 +202,7 @@ describe('ContributionForm.vue', () => { beforeEach(async () => { jest.useFakeTimers() mocks.$apollo.mutate = jest.fn().mockRejectedValueOnce({ - message: 'Not Authorised!', + message: 'Not Authorized!', }) wrapper = Wrapper() postTitleInput = wrapper.find('.ds-input') @@ -213,7 +213,7 @@ describe('ContributionForm.vue', () => { it('shows an error toaster when apollo mutation rejects', async () => { await wrapper.find('form').trigger('submit') await mocks.$apollo.mutate - await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorised!') + await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorized!') }) }) }) diff --git a/webapp/components/DeleteData/DeleteData.spec.js b/webapp/components/DeleteData/DeleteData.spec.js index 70f98424a..c540c9832 100644 --- a/webapp/components/DeleteData/DeleteData.spec.js +++ b/webapp/components/DeleteData/DeleteData.spec.js @@ -29,7 +29,7 @@ describe('DeleteData.vue', () => { }, }, }) - .mockRejectedValue({ message: 'Not authorised!' }), + .mockRejectedValue({ message: 'Not Authorized!' }), }, $toast: { error: jest.fn(), @@ -180,7 +180,7 @@ describe('DeleteData.vue', () => { // second submission causes mutation to reject await deleteAccountBtn.trigger('click') await mocks.$apollo.mutate - expect(mocks.$toast.error).toHaveBeenCalledWith('Not authorised!') + expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorized!') }) }) }) diff --git a/webapp/components/Modal/DisableModal.spec.js b/webapp/components/Modal/DisableModal.spec.js index ed306a6cc..b7e52b5a0 100644 --- a/webapp/components/Modal/DisableModal.spec.js +++ b/webapp/components/Modal/DisableModal.spec.js @@ -25,7 +25,7 @@ describe('DisableModal.vue', () => { $t: jest.fn(), $apollo: { mutate: jest.fn().mockResolvedValueOnce().mockRejectedValue({ - message: 'Not Authorised!', + message: 'Not Authorized!', }), }, location: { @@ -184,7 +184,7 @@ describe('DisableModal.vue', () => { }) it('shows an error toaster when mutation rejects', async () => { - await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorised!') + await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorized!') }) }) }) diff --git a/webapp/components/ReleaseModal/ReleaseModal.spec.js b/webapp/components/ReleaseModal/ReleaseModal.spec.js index d1dafa5c9..9cded646f 100644 --- a/webapp/components/ReleaseModal/ReleaseModal.spec.js +++ b/webapp/components/ReleaseModal/ReleaseModal.spec.js @@ -25,7 +25,7 @@ describe('ReleaseModal.vue', () => { }, $t: jest.fn(), $apollo: { - mutate: jest.fn().mockResolvedValueOnce().mockRejectedValue({ message: 'Not Authorised!' }), + mutate: jest.fn().mockResolvedValueOnce().mockRejectedValue({ message: 'Not Authorized!' }), }, location: { reload: jest.fn(), @@ -181,7 +181,7 @@ describe('ReleaseModal.vue', () => { }) it('shows an error toaster when mutation rejects', async () => { - await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorised!') + await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorized!') }) }) }) From c83096fe3967ac6667416b107f0e4d1643927780 Mon Sep 17 00:00:00 2001 From: Tima Gixe Date: Thu, 25 Aug 2022 09:10:59 +0300 Subject: [PATCH 49/67] Adjust comments test to expect `authorized` --- backend/src/schema/resolvers/comments.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/schema/resolvers/comments.spec.js b/backend/src/schema/resolvers/comments.spec.js index f0081b726..addcf9591 100644 --- a/backend/src/schema/resolvers/comments.spec.js +++ b/backend/src/schema/resolvers/comments.spec.js @@ -107,14 +107,14 @@ describe('CreateComment', () => { variables = { ...variables, postId: 'p1', - content: "I'm authorised to comment", + content: "I'm authorized to comment", } }) it('creates a comment', async () => { await expect(mutate({ mutation: createCommentMutation, variables })).resolves.toMatchObject( { - data: { CreateComment: { content: "I'm authorised to comment" } }, + data: { CreateComment: { content: "I'm authorized to comment" } }, errors: undefined, }, ) From f0157442b9357c0a64ad5b38e0fce5f5bf435c95 Mon Sep 17 00:00:00 2001 From: Tima Gixe Date: Thu, 25 Aug 2022 09:11:23 +0300 Subject: [PATCH 50/67] Provide custom fallbackError to graphql-shield --- backend/src/middleware/permissionsMiddleware.js | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index b10389f50..b5ce4fe07 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -188,5 +188,6 @@ export default shield( debug, allowExternalErrors, fallbackRule: allow, + fallbackError: Error('Not Authorized!'), }, ) From c40179ebaf50dc754747408eb9bf121faa94a71c Mon Sep 17 00:00:00 2001 From: Tima Gixe <60817786+timagixe@users.noreply.github.com> Date: Thu, 25 Aug 2022 11:17:34 +0300 Subject: [PATCH 51/67] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6cfe4c30c..8117660d2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,4 @@ -## 🍰 Pullrequest +## 🍰 Pull Request ### Issues From 4031605467fad8c52d072d97f30d6d1bd1aca90e Mon Sep 17 00:00:00 2001 From: Tima Gixe Date: Thu, 25 Aug 2022 12:43:55 +0300 Subject: [PATCH 52/67] Revert comment's content --- backend/src/schema/resolvers/comments.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/schema/resolvers/comments.spec.js b/backend/src/schema/resolvers/comments.spec.js index addcf9591..33b33ed3e 100644 --- a/backend/src/schema/resolvers/comments.spec.js +++ b/backend/src/schema/resolvers/comments.spec.js @@ -88,7 +88,7 @@ describe('CreateComment', () => { variables = { ...variables, postId: 'p1', - content: "I'm Not Authorized to comment", + content: "I'm not authorized to comment", } const { errors } = await mutate({ mutation: createCommentMutation, variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorized!') From 966d515bafba2d522c45d1775a78f8d52a9e42d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Aug 2022 12:16:32 +0200 Subject: [PATCH 53/67] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8117660d2..655c5cc93 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,15 @@ ## 🍰 Pull Request +XXX + ### Issues - + - fixes #XXX - relates #XXX ---> -- None ### Todo -- [X] None + +- [ ] XXX list here … From 407f4f8d2d27605c41fb529c0f514e9fea5e7bd8 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 25 Aug 2022 13:29:08 +0200 Subject: [PATCH 54/67] fix test (mock .CATEGORIES_ACTIVE) --- webapp/components/FilterMenu/FilterMenu.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webapp/components/FilterMenu/FilterMenu.spec.js b/webapp/components/FilterMenu/FilterMenu.spec.js index 9e7ebfec0..6e9741e79 100644 --- a/webapp/components/FilterMenu/FilterMenu.spec.js +++ b/webapp/components/FilterMenu/FilterMenu.spec.js @@ -8,6 +8,9 @@ let wrapper describe('FilterMenu.vue', () => { const mocks = { $t: jest.fn((string) => string), + $env: { + CATEGORIES_ACTIVE: true, + }, } const getters = { From c3ab014d9c7f371bf96cdbc641d918ed681eb1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Aug 2022 13:44:05 +0200 Subject: [PATCH 55/67] Set 'updatedAt' to 'null' on 'MEMBER_OF' creation in all group resolvers --- backend/src/schema/resolvers/groups.js | 8 +++++-- backend/src/schema/types/type/Group.gql | 28 ++++++++++++------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index c47cf6085..abaa1716f 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -107,8 +107,10 @@ export default { MATCH (owner:User {id: $userId}) MERGE (owner)-[:CREATED]->(group) MERGE (owner)-[membership:MEMBER_OF]->(group) - SET membership.createdAt = toString(datetime()) - SET membership.role = 'owner' + SET + membership.createdAt = toString(datetime()), + membership.updatedAt = null, + membership.role = 'owner' ${categoriesCypher} RETURN group {.*, myRole: membership.role} `, @@ -138,6 +140,7 @@ export default { MERGE (member)-[membership:MEMBER_OF]->(group) ON CREATE SET membership.createdAt = toString(datetime()), + membership.updatedAt = null, membership.role = CASE WHEN group.groupType = 'public' THEN 'usual' @@ -166,6 +169,7 @@ export default { MERGE (member)-[membership:MEMBER_OF]->(group) ON CREATE SET membership.createdAt = toString(datetime()), + membership.updatedAt = null, membership.role = $roleInGroup ON MATCH SET membership.updatedAt = toString(datetime()), diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index 5c98e49e8..e254e5086 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -59,7 +59,7 @@ input _GroupFilter { type Query { Group( - isMember: Boolean # if 'undefined' or 'null' then all groups + isMember: Boolean # if 'undefined' or 'null' then get all groups id: ID name: String slug: String @@ -81,11 +81,11 @@ type Query { filter: _UserFilter ): [User] - AvailableGroupTypes: [GroupType]! + # AvailableGroupTypes: [GroupType]! - AvailableGroupActionRadii: [GroupActionRadius]! + # AvailableGroupActionRadii: [GroupActionRadius]! - AvailableGroupMemberRoles: [GroupMemberRole]! + # AvailableGroupMemberRoles: [GroupMemberRole]! } type Mutation { @@ -102,17 +102,17 @@ type Mutation { locationName: String ): Group - UpdateGroup( - id: ID! - name: String - slug: String - avatar: ImageInput - locationName: String - about: String - description: String - ): Group + # UpdateGroup( + # id: ID! + # name: String + # slug: String + # avatar: ImageInput + # locationName: String + # about: String + # description: String + # ): Group - DeleteGroup(id: ID!): Group + # DeleteGroup(id: ID!): Group JoinGroup( groupId: ID! From 921adb9d8b785d73eb6ec734cc3646dda63368da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Aug 2022 13:47:37 +0200 Subject: [PATCH 56/67] Fixed all tests --- backend/src/schema/resolvers/groups.spec.js | 62 ++++++++++----------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index be9ba4f3d..1d272de2b 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -112,7 +112,7 @@ describe('in mode', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: createGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -219,7 +219,7 @@ describe('in mode', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupQuery, variables: {} }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -348,7 +348,7 @@ describe('in mode', () => { userId: 'current-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -529,7 +529,7 @@ describe('in mode', () => { userId: 'owner-of-closed-group', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -575,7 +575,7 @@ describe('in mode', () => { id: 'not-existing-group', } const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -922,7 +922,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -933,7 +933,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1065,7 +1065,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1076,7 +1076,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1257,7 +1257,7 @@ describe('in mode', () => { roleInGroup: 'pending', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1412,7 +1412,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1438,7 +1438,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1487,7 +1487,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1510,7 +1510,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1533,7 +1533,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1591,7 +1591,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1614,7 +1614,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1631,7 +1631,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1654,7 +1654,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1671,7 +1671,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1694,7 +1694,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1711,7 +1711,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1801,7 +1801,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1818,7 +1818,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1841,7 +1841,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1858,7 +1858,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1881,7 +1881,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1898,7 +1898,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1988,7 +1988,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2011,7 +2011,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2034,7 +2034,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation, variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) }) From eef8d60046481d9cf96c37582fe1198534d9ae57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 15:37:22 +0000 Subject: [PATCH 57/67] Bump eslint-plugin-prettier from 3.1.2 to 3.4.1 in /backend Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 3.1.2 to 3.4.1. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/commits) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- backend/package.json | 4 ++-- backend/yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/package.json b/backend/package.json index c19019ca1..62db1cf0f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -110,7 +110,7 @@ "npm-run-all": "~4.1.5", "request": "~2.88.2", "sanitize-html": "~1.22.0", - "slug": "~4.0.2", + "slug": "~6.0.0", "subscriptions-transport-ws": "^0.9.19", "trunc-html": "~1.1.2", "uuid": "~8.3.2", @@ -129,7 +129,7 @@ "eslint-plugin-import": "~2.20.2", "eslint-plugin-jest": "~23.8.2", "eslint-plugin-node": "~11.1.0", - "eslint-plugin-prettier": "~3.1.2", + "eslint-plugin-prettier": "~3.4.1", "eslint-plugin-promise": "~4.3.1", "eslint-plugin-standard": "~4.0.1", "jest": "~25.3.0", diff --git a/backend/yarn.lock b/backend/yarn.lock index 24bd00b3a..18f65abee 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -4253,10 +4253,10 @@ eslint-plugin-node@~11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" - integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== +eslint-plugin-prettier@~3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" + integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== dependencies: prettier-linter-helpers "^1.0.0" @@ -9262,10 +9262,10 @@ slug@^0.9.2: dependencies: unicode ">= 0.3.1" -slug@~4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/slug/-/slug-4.0.2.tgz#35a62b4e71582778ac08bb30a1bf439fd0a43ea7" - integrity sha512-c5XbWkwxHU13gAdSvBHQgnGy2sxv/REMz0ugcM0SOSBCO/N4wfU0TDBC3pgdOwVGjZwGnLBTRljXzdVYE+KYNw== +slug@~6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/slug/-/slug-6.0.0.tgz#39637b32e5a873bc692812a630842880499ed6c9" + integrity sha512-0MpNLyCSUSf0G1nAZmp9gY1cvesPP35a1Live25vZ23gWQ5SAopF0N+0hk9KI4ytNuTebJrHGNrgTnxboofcSg== smart-buffer@^4.1.0: version "4.1.0" From f2aba3e12e284e8a0bc78ac0afe52aed01420711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Aug 2022 18:03:21 +0200 Subject: [PATCH 58/67] Put exclamation mark behind console log text of successfully created default admin user for consistency --- backend/src/db/migrate/store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index 61d591cb7..3a1b321e4 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -69,7 +69,7 @@ const createDefaultAdminUser = async (session) => { }) try { await createAdminTxResultPromise - console.log('Successfully created default admin user') // eslint-disable-line no-console + console.log('Successfully created default admin user!') // eslint-disable-line no-console } catch (error) { console.log(error) // eslint-disable-line no-console } From 0a02e1e402751a0cf90d9564730708df681bf233 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 18:15:25 +0000 Subject: [PATCH 59/67] Bump prettier from 2.2.1 to 2.7.1 in /webapp Bumps [prettier](https://github.com/prettier/prettier) from 2.2.1 to 2.7.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.2.1...2.7.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- webapp/package.json | 2 +- webapp/yarn.lock | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/webapp/package.json b/webapp/package.json index ea425d49f..1231ecace 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -141,7 +141,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "~26.6.3", "mutation-observer": "^1.0.3", - "prettier": "~2.2.1", + "prettier": "~2.7.1", "sass-loader": "~10.1.1", "storybook-design-token": "^0.8.1", "storybook-vue-router": "^1.0.7", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 596fe5700..c42c1b73b 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -16422,6 +16422,11 @@ prettier@~2.2.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== +prettier@~2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + pretty-bytes@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" From 512784e580dee2b995bb5c8f09c0278b247a74f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Aug 2022 20:17:23 +0200 Subject: [PATCH 60/67] Fix group tests --- backend/src/schema/resolvers/groups.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 707558a06..6890e9147 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -89,7 +89,7 @@ describe('Group', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupQuery, variables: {} }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -225,7 +225,7 @@ describe('CreateGroup', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: createGroupMutation, variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorised!') + expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) From e82d35c824774a8dca2b8e76cf421d9600c81e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Aug 2022 23:17:50 +0200 Subject: [PATCH 61/67] Fix linting --- .../components/CommentCard/CommentCard.story.js | 3 +-- webapp/components/DeleteData/DeleteData.vue | 2 +- webapp/components/Editor/Editor.story.js | 3 +-- webapp/components/Editor/nodes/Embed.spec.js | 3 +-- webapp/components/Embed/EmbedComponent.spec.js | 3 +-- webapp/components/Emotions/Emotions.vue | 2 +- webapp/components/LocaleSwitch/LocaleSwitch.vue | 2 +- webapp/components/Modal/DeleteUserModal.vue | 2 +- webapp/components/Modal/DisableModal.vue | 2 +- webapp/components/Password/Change.vue | 2 +- .../components/PasswordReset/ChangePassword.vue | 2 +- webapp/components/PasswordReset/Request.vue | 2 +- webapp/components/PostTeaser/PostTeaser.story.js | 3 +-- .../Registration/RegistrationSlideEmail.vue | 7 +++---- .../Registration/RegistrationSlideInvite.vue | 2 +- .../Registration/RegistrationSlideNonce.vue | 2 +- webapp/components/Registration/Signup.vue | 2 +- webapp/components/ReleaseModal/ReleaseModal.vue | 2 +- .../SearchableInput/SearchableInput.story.js | 12 ++++-------- webapp/graphql/CommentMutations.js | 4 ++-- webapp/graphql/Donations.js | 2 +- webapp/graphql/EmailAddress.js | 4 ++-- webapp/graphql/EmbedQuery.js | 2 +- webapp/graphql/Moderation.js | 6 +++--- webapp/graphql/PostMutations.js | 16 ++++++++-------- webapp/graphql/Registration.js | 2 +- webapp/graphql/Search.js | 8 ++++---- webapp/graphql/User.js | 14 +++++++------- webapp/graphql/admin/Roles.js | 2 +- webapp/graphql/location.js | 2 +- webapp/graphql/settings/BlockedUsers.js | 4 ++-- webapp/graphql/settings/MutedUsers.js | 4 ++-- webapp/pages/admin/users.vue | 2 +- webapp/pages/post/_id.vue | 4 ++-- webapp/pages/profile/_id.vue | 4 ++-- webapp/pages/settings/my-social-media.vue | 6 +++--- 36 files changed, 67 insertions(+), 77 deletions(-) diff --git a/webapp/components/CommentCard/CommentCard.story.js b/webapp/components/CommentCard/CommentCard.story.js index 467a125d5..75078657e 100644 --- a/webapp/components/CommentCard/CommentCard.story.js +++ b/webapp/components/CommentCard/CommentCard.story.js @@ -18,8 +18,7 @@ const comment = { author: { id: '1', avatar: { - url: - 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', + url: 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', }, slug: 'jenny-rostock', name: 'Rainer Unsinn', diff --git a/webapp/components/DeleteData/DeleteData.vue b/webapp/components/DeleteData/DeleteData.vue index 21b842fe6..a0cdcf29b 100644 --- a/webapp/components/DeleteData/DeleteData.vue +++ b/webapp/components/DeleteData/DeleteData.vue @@ -103,7 +103,7 @@ export default { this.$apollo .mutate({ mutation: gql` - mutation($id: ID!, $resource: [Deletable]) { + mutation ($id: ID!, $resource: [Deletable]) { DeleteUser(id: $id, resource: $resource) { id } diff --git a/webapp/components/Editor/Editor.story.js b/webapp/components/Editor/Editor.story.js index dfcc3cdf4..6e38eab7f 100644 --- a/webapp/components/Editor/Editor.story.js +++ b/webapp/components/Editor/Editor.story.js @@ -9,8 +9,7 @@ const embed = { title: 'Video Titel', // html: null, description: 'Video Description', - html: - '', + html: '', } const plugins = [ diff --git a/webapp/components/Editor/nodes/Embed.spec.js b/webapp/components/Editor/nodes/Embed.spec.js index e87ee1570..372b189f9 100644 --- a/webapp/components/Editor/nodes/Embed.spec.js +++ b/webapp/components/Editor/nodes/Embed.spec.js @@ -33,8 +33,7 @@ describe('Embed.vue', () => { video: null, lang: 'de', sources: ['resource', 'oembed'], - html: - '', + html: '', }), } }) diff --git a/webapp/components/Embed/EmbedComponent.spec.js b/webapp/components/Embed/EmbedComponent.spec.js index fd7452c01..cd3526368 100644 --- a/webapp/components/Embed/EmbedComponent.spec.js +++ b/webapp/components/Embed/EmbedComponent.spec.js @@ -114,8 +114,7 @@ describe('EmbedComponent.vue', () => { video: null, lang: 'de', sources: ['resource', 'oembed'], - html: - '', + html: '', } wrapper = Wrapper() }) diff --git a/webapp/components/Emotions/Emotions.vue b/webapp/components/Emotions/Emotions.vue index e75c8848d..b4dc14a61 100644 --- a/webapp/components/Emotions/Emotions.vue +++ b/webapp/components/Emotions/Emotions.vue @@ -83,7 +83,7 @@ export default { this.$apollo .query({ query: gql` - query($postId: ID!, $data: _EMOTEDInput!) { + query ($postId: ID!, $data: _EMOTEDInput!) { PostsEmotionsCountByEmotion(postId: $postId, data: $data) } `, diff --git a/webapp/components/LocaleSwitch/LocaleSwitch.vue b/webapp/components/LocaleSwitch/LocaleSwitch.vue index 47e53028b..353fc406a 100644 --- a/webapp/components/LocaleSwitch/LocaleSwitch.vue +++ b/webapp/components/LocaleSwitch/LocaleSwitch.vue @@ -82,7 +82,7 @@ export default { try { await this.$apollo.mutate({ mutation: gql` - mutation($id: ID!, $locale: String) { + mutation ($id: ID!, $locale: String) { UpdateUser(id: $id, locale: $locale) { id locale diff --git a/webapp/components/Modal/DeleteUserModal.vue b/webapp/components/Modal/DeleteUserModal.vue index 87aa557d8..8618582ee 100644 --- a/webapp/components/Modal/DeleteUserModal.vue +++ b/webapp/components/Modal/DeleteUserModal.vue @@ -127,7 +127,7 @@ export default { this.$apollo .mutate({ mutation: gql` - mutation($id: ID!, $resource: [Deletable]) { + mutation ($id: ID!, $resource: [Deletable]) { DeleteUser(id: $id, resource: $resource) { id } diff --git a/webapp/components/Modal/DisableModal.vue b/webapp/components/Modal/DisableModal.vue index 19ef64332..d28033ff8 100644 --- a/webapp/components/Modal/DisableModal.vue +++ b/webapp/components/Modal/DisableModal.vue @@ -53,7 +53,7 @@ export default { // await this.modalData.buttons.confirm.callback() await this.$apollo.mutate({ mutation: gql` - mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) { + mutation ($resourceId: ID!, $disable: Boolean, $closed: Boolean) { review(resourceId: $resourceId, disable: $disable, closed: $closed) { disable } diff --git a/webapp/components/Password/Change.vue b/webapp/components/Password/Change.vue index cd955973f..94b69a8f6 100644 --- a/webapp/components/Password/Change.vue +++ b/webapp/components/Password/Change.vue @@ -65,7 +65,7 @@ export default { async handleSubmit(data) { this.loading = true const mutation = gql` - mutation($oldPassword: String!, $password: String!) { + mutation ($oldPassword: String!, $password: String!) { changePassword(oldPassword: $oldPassword, newPassword: $password) } ` diff --git a/webapp/components/PasswordReset/ChangePassword.vue b/webapp/components/PasswordReset/ChangePassword.vue index e65a7a04f..c53afcc01 100644 --- a/webapp/components/PasswordReset/ChangePassword.vue +++ b/webapp/components/PasswordReset/ChangePassword.vue @@ -93,7 +93,7 @@ export default { methods: { async handleSubmitPassword() { const mutation = gql` - mutation($nonce: String!, $email: String!, $password: String!) { + mutation ($nonce: String!, $email: String!, $password: String!) { resetPassword(nonce: $nonce, email: $email, newPassword: $password) } ` diff --git a/webapp/components/PasswordReset/Request.vue b/webapp/components/PasswordReset/Request.vue index 5f4baf357..5398c13ed 100644 --- a/webapp/components/PasswordReset/Request.vue +++ b/webapp/components/PasswordReset/Request.vue @@ -85,7 +85,7 @@ export default { }, async handleSubmit() { const mutation = gql` - mutation($email: String!) { + mutation ($email: String!) { requestPasswordReset(email: $email) } ` diff --git a/webapp/components/PostTeaser/PostTeaser.story.js b/webapp/components/PostTeaser/PostTeaser.story.js index c82396101..e77e85585 100644 --- a/webapp/components/PostTeaser/PostTeaser.story.js +++ b/webapp/components/PostTeaser/PostTeaser.story.js @@ -17,8 +17,7 @@ export const post = { author: { id: 'u3', avatar: { - url: - 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', + url: 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', }, slug: 'jenny-rostock', name: 'Rainer Unsinn', diff --git a/webapp/components/Registration/RegistrationSlideEmail.vue b/webapp/components/Registration/RegistrationSlideEmail.vue index 045269f00..6ba443996 100644 --- a/webapp/components/Registration/RegistrationSlideEmail.vue +++ b/webapp/components/Registration/RegistrationSlideEmail.vue @@ -35,7 +35,7 @@ import normalizeEmail from '~/components/utils/NormalizeEmail' import translateErrorMessage from '~/components/utils/TranslateErrorMessage' export const SignupMutation = gql` - mutation($email: String!, $inviteCode: String) { + mutation ($email: String!, $inviteCode: String) { Signup(email: $email, inviteCode: $inviteCode) { email } @@ -165,9 +165,8 @@ export default { }) this.setButtonValues() - const { email: responseEmail } = this.sliderData.sliders[ - this.sliderIndex - ].data.response.Signup + const { email: responseEmail } = + this.sliderData.sliders[this.sliderIndex].data.response.Signup this.$toast.success( this.$t('components.registration.email.form.success', { email: responseEmail }), ) diff --git a/webapp/components/Registration/RegistrationSlideInvite.vue b/webapp/components/Registration/RegistrationSlideInvite.vue index f9ce15ee9..48c62d412 100644 --- a/webapp/components/Registration/RegistrationSlideInvite.vue +++ b/webapp/components/Registration/RegistrationSlideInvite.vue @@ -25,7 +25,7 @@ import gql from 'graphql-tag' import CONSTANTS_REGISTRATION from './../../constants/registration' export const isValidInviteCodeQuery = gql` - query($code: ID!) { + query ($code: ID!) { isValidInviteCode(code: $code) } ` diff --git a/webapp/components/Registration/RegistrationSlideNonce.vue b/webapp/components/Registration/RegistrationSlideNonce.vue index 147e84336..b9de7afd1 100644 --- a/webapp/components/Registration/RegistrationSlideNonce.vue +++ b/webapp/components/Registration/RegistrationSlideNonce.vue @@ -30,7 +30,7 @@ import CONSTANTS_REGISTRATION from './../../constants/registration' import EmailDisplayAndVerify from './EmailDisplayAndVerify' export const verifyNonceQuery = gql` - query($email: String!, $nonce: String!) { + query ($email: String!, $nonce: String!) { VerifyNonce(email: $email, nonce: $nonce) } ` diff --git a/webapp/components/Registration/Signup.vue b/webapp/components/Registration/Signup.vue index 86142c338..91b9ecd61 100644 --- a/webapp/components/Registration/Signup.vue +++ b/webapp/components/Registration/Signup.vue @@ -70,7 +70,7 @@ import { SweetalertIcon } from 'vue-sweetalert-icons' import translateErrorMessage from '~/components/utils/TranslateErrorMessage' export const SignupMutation = gql` - mutation($email: String!, $inviteCode: String) { + mutation ($email: String!, $inviteCode: String) { Signup(email: $email, inviteCode: $inviteCode) { email } diff --git a/webapp/components/ReleaseModal/ReleaseModal.vue b/webapp/components/ReleaseModal/ReleaseModal.vue index fef0d79d0..fceb4b7a1 100644 --- a/webapp/components/ReleaseModal/ReleaseModal.vue +++ b/webapp/components/ReleaseModal/ReleaseModal.vue @@ -52,7 +52,7 @@ export default { // await this.modalData.buttons.confirm.callback() await this.$apollo.mutate({ mutation: gql` - mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) { + mutation ($resourceId: ID!, $disable: Boolean, $closed: Boolean) { review(resourceId: $resourceId, disable: $disable, closed: $closed) { disable } diff --git a/webapp/components/generic/SearchableInput/SearchableInput.story.js b/webapp/components/generic/SearchableInput/SearchableInput.story.js index 62e422a67..f483129eb 100644 --- a/webapp/components/generic/SearchableInput/SearchableInput.story.js +++ b/webapp/components/generic/SearchableInput/SearchableInput.story.js @@ -78,8 +78,7 @@ export const searchResults = [ id: 'u1', __typename: 'User', avatar: { - url: - 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', + url: 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', }, name: 'Peter Lustig', slug: 'peter-lustig', @@ -88,8 +87,7 @@ export const searchResults = [ id: 'cdbca762-0632-4564-b646-415a0c42d8b8', __typename: 'User', avatar: { - url: - 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', + url: 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', }, name: 'Herbert Schultz', slug: 'herbert-schultz', @@ -98,8 +96,7 @@ export const searchResults = [ id: 'u2', __typename: 'User', avatar: { - url: - 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', + url: 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', }, name: 'Bob der Baumeister', slug: 'bob-der-baumeister', @@ -108,8 +105,7 @@ export const searchResults = [ id: '7b654f72-f4da-4315-8bed-39de0859754b', __typename: 'User', avatar: { - url: - 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', + url: 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/db/dbc9e03ebcc384b920c31542af2d27dd8eea9dc2_full.jpg', }, name: 'Tonya Mohr', slug: 'tonya-mohr', diff --git a/webapp/graphql/CommentMutations.js b/webapp/graphql/CommentMutations.js index a73ebb00c..191edf217 100644 --- a/webapp/graphql/CommentMutations.js +++ b/webapp/graphql/CommentMutations.js @@ -4,7 +4,7 @@ export default (i18n) => { const lang = i18n.locale().toUpperCase() return { CreateComment: gql` - mutation($postId: ID!, $content: String!) { + mutation ($postId: ID!, $content: String!) { CreateComment(postId: $postId, content: $content) { id contentExcerpt @@ -36,7 +36,7 @@ export default (i18n) => { } `, UpdateComment: gql` - mutation($content: String!, $id: ID!) { + mutation ($content: String!, $id: ID!) { UpdateComment(content: $content, id: $id) { id contentExcerpt diff --git a/webapp/graphql/Donations.js b/webapp/graphql/Donations.js index e412ee4fa..573158cbf 100644 --- a/webapp/graphql/Donations.js +++ b/webapp/graphql/Donations.js @@ -13,7 +13,7 @@ export const DonationsQuery = () => gql` export const UpdateDonations = () => { return gql` - mutation($showDonations: Boolean, $goal: Int, $progress: Int) { + mutation ($showDonations: Boolean, $goal: Int, $progress: Int) { UpdateDonations(showDonations: $showDonations, goal: $goal, progress: $progress) { id showDonations diff --git a/webapp/graphql/EmailAddress.js b/webapp/graphql/EmailAddress.js index 675ec6bed..b3b4df695 100644 --- a/webapp/graphql/EmailAddress.js +++ b/webapp/graphql/EmailAddress.js @@ -1,7 +1,7 @@ import gql from 'graphql-tag' export const AddEmailAddressMutation = gql` - mutation($email: String!) { + mutation ($email: String!) { AddEmailAddress(email: $email) { email createdAt @@ -10,7 +10,7 @@ export const AddEmailAddressMutation = gql` ` export const VerifyEmailAddressMutation = gql` - mutation($email: String!, $nonce: String!) { + mutation ($email: String!, $nonce: String!) { VerifyEmailAddress(email: $email, nonce: $nonce) { email verifiedAt diff --git a/webapp/graphql/EmbedQuery.js b/webapp/graphql/EmbedQuery.js index 685095d34..70450722d 100644 --- a/webapp/graphql/EmbedQuery.js +++ b/webapp/graphql/EmbedQuery.js @@ -2,7 +2,7 @@ import gql from 'graphql-tag' export default function () { return gql` - query($url: String!) { + query ($url: String!) { embed(url: $url) { type title diff --git a/webapp/graphql/Moderation.js b/webapp/graphql/Moderation.js index f4796d080..8dc20f987 100644 --- a/webapp/graphql/Moderation.js +++ b/webapp/graphql/Moderation.js @@ -3,7 +3,7 @@ import gql from 'graphql-tag' export const reportsListQuery = () => { // no limit for the moment like before: "reports(first: 20, orderBy: createdAt_desc)" return gql` - query( + query ( $orderBy: ReportOrdering $first: Int $offset: Int @@ -94,7 +94,7 @@ export const reportsListQuery = () => { export const reportMutation = () => { return gql` - mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { + mutation ($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { fileReport( resourceId: $resourceId reasonCategory: $reasonCategory @@ -108,7 +108,7 @@ export const reportMutation = () => { export const reviewMutation = () => { return gql` - mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) { + mutation ($resourceId: ID!, $disable: Boolean, $closed: Boolean) { review(resourceId: $resourceId, disable: $disable, closed: $closed) { disable } diff --git a/webapp/graphql/PostMutations.js b/webapp/graphql/PostMutations.js index af91d245e..ee61efc3b 100644 --- a/webapp/graphql/PostMutations.js +++ b/webapp/graphql/PostMutations.js @@ -3,7 +3,7 @@ import gql from 'graphql-tag' export default () => { return { CreatePost: gql` - mutation($title: String!, $content: String!, $categoryIds: [ID], $image: ImageInput) { + mutation ($title: String!, $content: String!, $categoryIds: [ID], $image: ImageInput) { CreatePost(title: $title, content: $content, categoryIds: $categoryIds, image: $image) { title slug @@ -18,7 +18,7 @@ export default () => { } `, UpdatePost: gql` - mutation( + mutation ( $id: ID! $title: String! $content: String! @@ -52,14 +52,14 @@ export default () => { } `, DeletePost: gql` - mutation($id: ID!) { + mutation ($id: ID!) { DeletePost(id: $id) { id } } `, AddPostEmotionsMutation: gql` - mutation($to: _PostInput!, $data: _EMOTEDInput!) { + mutation ($to: _PostInput!, $data: _EMOTEDInput!) { AddPostEmotions(to: $to, data: $data) { emotion from { @@ -72,7 +72,7 @@ export default () => { } `, RemovePostEmotionsMutation: gql` - mutation($to: _PostInput!, $data: _EMOTEDInput!) { + mutation ($to: _PostInput!, $data: _EMOTEDInput!) { RemovePostEmotions(to: $to, data: $data) { emotion from { @@ -85,7 +85,7 @@ export default () => { } `, pinPost: gql` - mutation($id: ID!) { + mutation ($id: ID!) { pinPost(id: $id) { id title @@ -102,7 +102,7 @@ export default () => { } `, unpinPost: gql` - mutation($id: ID!) { + mutation ($id: ID!) { unpinPost(id: $id) { id title @@ -119,7 +119,7 @@ export default () => { } `, markTeaserAsViewed: gql` - mutation($id: ID!) { + mutation ($id: ID!) { markTeaserAsViewed(id: $id) { id } diff --git a/webapp/graphql/Registration.js b/webapp/graphql/Registration.js index fcf9c52a7..b6cc610d9 100644 --- a/webapp/graphql/Registration.js +++ b/webapp/graphql/Registration.js @@ -1,6 +1,6 @@ import gql from 'graphql-tag' export const SignupVerificationMutation = gql` - mutation( + mutation ( $nonce: String! $name: String! $email: String! diff --git a/webapp/graphql/Search.js b/webapp/graphql/Search.js index 96e507b2d..56f5d7c4c 100644 --- a/webapp/graphql/Search.js +++ b/webapp/graphql/Search.js @@ -5,7 +5,7 @@ export const searchQuery = gql` ${userFragment} ${postFragment} - query($query: String!) { + query ($query: String!) { searchResults(query: $query, limit: 5) { __typename ... on Post { @@ -33,7 +33,7 @@ export const searchPosts = gql` ${postFragment} ${tagsCategoriesAndPinnedFragment} - query($query: String!, $firstPosts: Int, $postsOffset: Int) { + query ($query: String!, $firstPosts: Int, $postsOffset: Int) { searchPosts(query: $query, firstPosts: $firstPosts, postsOffset: $postsOffset) { postCount posts { @@ -55,7 +55,7 @@ export const searchPosts = gql` export const searchUsers = gql` ${userFragment} - query($query: String!, $firstUsers: Int, $usersOffset: Int) { + query ($query: String!, $firstUsers: Int, $usersOffset: Int) { searchUsers(query: $query, firstUsers: $firstUsers, usersOffset: $usersOffset) { userCount users { @@ -67,7 +67,7 @@ export const searchUsers = gql` ` export const searchHashtags = gql` - query($query: String!, $firstHashtags: Int, $hashtagsOffset: Int) { + query ($query: String!, $firstHashtags: Int, $hashtagsOffset: Int) { searchHashtags(query: $query, firstHashtags: $firstHashtags, hashtagsOffset: $hashtagsOffset) { hashtagCount hashtags { diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index b3f131238..f16323073 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -68,7 +68,7 @@ export const notificationQuery = (i18n) => { ${commentFragment} ${postFragment} - query($read: Boolean, $orderBy: NotificationOrdering, $first: Int, $offset: Int) { + query ($read: Boolean, $orderBy: NotificationOrdering, $first: Int, $offset: Int) { notifications(read: $read, orderBy: $orderBy, first: $first, offset: $offset) { id read @@ -107,7 +107,7 @@ export const markAsReadMutation = (i18n) => { ${commentFragment} ${postFragment} - mutation($id: ID!) { + mutation ($id: ID!) { markAsRead(id: $id) { id read @@ -180,7 +180,7 @@ export const followUserMutation = (i18n) => { ${userFragment} ${userCountsFragment} - mutation($id: ID!) { + mutation ($id: ID!) { followUser(id: $id) { ...user ...userCounts @@ -200,7 +200,7 @@ export const unfollowUserMutation = (i18n) => { ${userFragment} ${userCountsFragment} - mutation($id: ID!) { + mutation ($id: ID!) { unfollowUser(id: $id) { ...user ...userCounts @@ -217,7 +217,7 @@ export const unfollowUserMutation = (i18n) => { export const updateUserMutation = () => { return gql` - mutation( + mutation ( $id: ID! $slug: String $name: String @@ -260,7 +260,7 @@ export const updateUserMutation = () => { } export const checkSlugAvailableQuery = gql` - query($slug: String!) { + query ($slug: String!) { User(slug: $slug) { slug } @@ -303,7 +303,7 @@ export const userDataQuery = (i18n) => { ${userFragment} ${postFragment} ${commentFragment} - query($id: ID!) { + query ($id: ID!) { userData(id: $id) { user { ...user diff --git a/webapp/graphql/admin/Roles.js b/webapp/graphql/admin/Roles.js index 4365cb533..4015ad06c 100644 --- a/webapp/graphql/admin/Roles.js +++ b/webapp/graphql/admin/Roles.js @@ -10,7 +10,7 @@ export const FetchAllRoles = () => { export const updateUserRole = (role, id) => { return gql` - mutation($role: UserRole!, $id: ID!) { + mutation ($role: UserRole!, $id: ID!) { switchUserRole(role: $role, id: $id) { name role diff --git a/webapp/graphql/location.js b/webapp/graphql/location.js index 0fa2c2a2d..1fff64782 100644 --- a/webapp/graphql/location.js +++ b/webapp/graphql/location.js @@ -1,7 +1,7 @@ import gql from 'graphql-tag' export const queryLocations = () => gql` - query($place: String!, $lang: String!) { + query ($place: String!, $lang: String!) { queryLocations(place: $place, lang: $lang) { place_name id diff --git a/webapp/graphql/settings/BlockedUsers.js b/webapp/graphql/settings/BlockedUsers.js index be1765138..0c642b352 100644 --- a/webapp/graphql/settings/BlockedUsers.js +++ b/webapp/graphql/settings/BlockedUsers.js @@ -20,7 +20,7 @@ export const blockedUsers = () => { export const blockUser = () => { return gql` - mutation($id: ID!) { + mutation ($id: ID!) { blockUser(id: $id) { id name @@ -33,7 +33,7 @@ export const blockUser = () => { export const unblockUser = () => { return gql` - mutation($id: ID!) { + mutation ($id: ID!) { unblockUser(id: $id) { id name diff --git a/webapp/graphql/settings/MutedUsers.js b/webapp/graphql/settings/MutedUsers.js index f498534e3..10db085af 100644 --- a/webapp/graphql/settings/MutedUsers.js +++ b/webapp/graphql/settings/MutedUsers.js @@ -20,7 +20,7 @@ export const mutedUsers = () => { export const muteUser = () => { return gql` - mutation($id: ID!) { + mutation ($id: ID!) { muteUser(id: $id) { id name @@ -33,7 +33,7 @@ export const muteUser = () => { export const unmuteUser = () => { return gql` - mutation($id: ID!) { + mutation ($id: ID!) { unmuteUser(id: $id) { id name diff --git a/webapp/pages/admin/users.vue b/webapp/pages/admin/users.vue index 6c324fd97..cbd7433ad 100644 --- a/webapp/pages/admin/users.vue +++ b/webapp/pages/admin/users.vue @@ -139,7 +139,7 @@ export default { User: { query() { return gql` - query($filter: _UserFilter, $first: Int, $offset: Int, $email: String) { + query ($filter: _UserFilter, $first: Int, $offset: Int, $email: String) { User( email: $email filter: $filter diff --git a/webapp/pages/post/_id.vue b/webapp/pages/post/_id.vue index 8d425eab7..14cc65a4e 100644 --- a/webapp/pages/post/_id.vue +++ b/webapp/pages/post/_id.vue @@ -19,7 +19,7 @@ import PersistentLinks from '~/mixins/persistentLinks.js' const options = { queryId: gql` - query($idOrSlug: ID) { + query ($idOrSlug: ID) { Post(id: $idOrSlug) { id slug @@ -27,7 +27,7 @@ const options = { } `, querySlug: gql` - query($idOrSlug: String) { + query ($idOrSlug: String) { Post(slug: $idOrSlug) { id slug diff --git a/webapp/pages/profile/_id.vue b/webapp/pages/profile/_id.vue index b9bbef83e..7a771425d 100644 --- a/webapp/pages/profile/_id.vue +++ b/webapp/pages/profile/_id.vue @@ -8,7 +8,7 @@ import PersistentLinks from '~/mixins/persistentLinks.js' const options = { queryId: gql` - query($idOrSlug: ID) { + query ($idOrSlug: ID) { User(id: $idOrSlug) { id slug @@ -16,7 +16,7 @@ const options = { } `, querySlug: gql` - query($idOrSlug: String) { + query ($idOrSlug: String) { User(slug: $idOrSlug) { id slug diff --git a/webapp/pages/settings/my-social-media.vue b/webapp/pages/settings/my-social-media.vue index a985371d6..d392032bb 100644 --- a/webapp/pages/settings/my-social-media.vue +++ b/webapp/pages/settings/my-social-media.vue @@ -112,7 +112,7 @@ export default { let mutation, variables, successMessage if (isCreation) { mutation = gql` - mutation($url: String!) { + mutation ($url: String!) { CreateSocialMedia(url: $url) { id url @@ -123,7 +123,7 @@ export default { successMessage = thisList.$t('settings.social-media.successAdd') } else { mutation = gql` - mutation($id: ID!, $url: String!) { + mutation ($id: ID!, $url: String!) { UpdateSocialMedia(id: $id, url: $url) { id url @@ -160,7 +160,7 @@ export default { try { await thisList.$apollo.mutate({ mutation: gql` - mutation($id: ID!) { + mutation ($id: ID!) { DeleteSocialMedia(id: $id) { id url From 1252e79be2c37bafd1630e878f932924af57e5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 27 Aug 2022 16:42:11 +0200 Subject: [PATCH 62/67] Fix test description from 'enter-nonce' to 'change-password' --- webapp/pages/password-reset/change-password.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/pages/password-reset/change-password.spec.js b/webapp/pages/password-reset/change-password.spec.js index cad031c95..103004d67 100644 --- a/webapp/pages/password-reset/change-password.spec.js +++ b/webapp/pages/password-reset/change-password.spec.js @@ -1,9 +1,9 @@ import { mount } from '@vue/test-utils' -import changePassword from './change-password.vue' +import changePassword from './change-password' const localVue = global.localVue -describe('enter-nonce.vue', () => { +describe('change-password', () => { let wrapper let mocks From 3607ed4b68f6a713239dd1949f65ef13cd89d424 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Aug 2022 14:53:33 +0000 Subject: [PATCH 63/67] Bump cookie-universal-nuxt from 2.1.5 to 2.2.2 in /webapp Bumps [cookie-universal-nuxt](https://github.com/microcipcip/cookie-universal) from 2.1.5 to 2.2.2. - [Release notes](https://github.com/microcipcip/cookie-universal/releases) - [Commits](https://github.com/microcipcip/cookie-universal/compare/v2.1.5...v2.2.2) --- updated-dependencies: - dependency-name: cookie-universal-nuxt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- webapp/package.json | 4 ++-- webapp/yarn.lock | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index ea425d49f..e4f9eb81c 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -73,7 +73,7 @@ "accounting": "~0.4.1", "apollo-cache-inmemory": "~1.6.6", "apollo-client": "~2.6.8", - "cookie-universal-nuxt": "~2.1.5", + "cookie-universal-nuxt": "~2.2.2", "cropperjs": "^1.5.5", "cross-env": "~7.0.3", "date-fns": "2.22.1", @@ -141,7 +141,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "~26.6.3", "mutation-observer": "^1.0.3", - "prettier": "~2.2.1", + "prettier": "~2.7.1", "sass-loader": "~10.1.1", "storybook-design-token": "^0.8.1", "storybook-vue-router": "^1.0.7", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 596fe5700..b5ba692fa 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -8254,18 +8254,18 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie-universal-nuxt@~2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/cookie-universal-nuxt/-/cookie-universal-nuxt-2.1.5.tgz#669f2ff95b1bc1962c86edd69c954f60729e71e5" - integrity sha512-P0WCTKIyemWNtHi9lxrS5cxZmieOIEjt28B7Alu6cdSB9RqtUtpkqYyV9PRK6oJrT5eIPDYjHsJQlh6SUrFJOg== +cookie-universal-nuxt@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cookie-universal-nuxt/-/cookie-universal-nuxt-2.2.2.tgz#107815f03f5b769de7018670d6370368205387bb" + integrity sha512-Pr6P5UCzl1EAvPh7z7jFkknBw0KTdykm6gFmPHrH4LV9s3flVmAH0ZP/ZqUXcp6b0SKZfizkn+XR1cO+QinGhQ== dependencies: "@types/cookie" "^0.3.3" - cookie-universal "^2.1.5" + cookie-universal "^2.2.2" -cookie-universal@^2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/cookie-universal/-/cookie-universal-2.1.5.tgz#9a6cefbfb61c750a1b8ee2610bf71566bd719544" - integrity sha512-nqOOmEkovCQxNYGIyzhcwsmh4c7xnxe7RWdiYFOoml9MP4L32IlU3LdPC7r7nQEnnM+9Uxlk/UhtvBl5is6M/w== +cookie-universal@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cookie-universal/-/cookie-universal-2.2.2.tgz#415a4d67b6f7f0819c4914cd69b8c2f496111d30" + integrity sha512-nUXF6HH2YKbn8vGcdSzWJhjRkDHbnbekuVu2nsRu00zYsX7o/H3xGJRlPVoM4wX/8cpJYpyi9nDt+boER0Wjug== dependencies: "@types/cookie" "^0.3.3" cookie "^0.4.0" @@ -16422,6 +16422,11 @@ prettier@~2.2.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== +prettier@~2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + pretty-bytes@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" From 3e6cabaa1c4e8e7cccf11634d4c893f822767ca1 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 30 Aug 2022 10:13:56 +0200 Subject: [PATCH 64/67] Update backend/src/db/migrate/store.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wolfgang Huß --- backend/src/db/migrate/store.js | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index 3a1b321e4..d6fd25bd8 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -29,6 +29,7 @@ const createCategories = async (session) => { }) try { await createCategoriesTxResultPromise + console.log('Successfully created categories!') // eslint-disable-line no-console } catch (error) { console.log(`Error creating categories: ${error}`) // eslint-disable-line no-console } From 0d1da0d83d2bb5b183c203e2db69f58978e1cd1d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 30 Aug 2022 10:14:39 +0200 Subject: [PATCH 65/67] Update backend/src/db/migrate/store.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wolfgang Huß --- backend/src/db/migrate/store.js | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index d6fd25bd8..98014f05c 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -30,6 +30,7 @@ const createCategories = async (session) => { try { await createCategoriesTxResultPromise console.log('Successfully created categories!') // eslint-disable-line no-console + console.log('Successfully created categories!') // eslint-disable-line no-console } catch (error) { console.log(`Error creating categories: ${error}`) // eslint-disable-line no-console } From c61e983102042b7a6fd568767ee81bf555425f70 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 30 Aug 2022 10:21:15 +0200 Subject: [PATCH 66/67] remove double console log --- backend/src/db/migrate/store.js | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index 98014f05c..d6fd25bd8 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -30,7 +30,6 @@ const createCategories = async (session) => { try { await createCategoriesTxResultPromise console.log('Successfully created categories!') // eslint-disable-line no-console - console.log('Successfully created categories!') // eslint-disable-line no-console } catch (error) { console.log(`Error creating categories: ${error}`) // eslint-disable-line no-console } From a5878ab505ba546fbc7ee2c8232f93a43c74140b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 31 Aug 2022 09:22:38 +0200 Subject: [PATCH 67/67] Fix linting --- backend/src/db/seed.js | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index a3ba8c16b..b516ca529 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -5,7 +5,6 @@ import createServer from '../server' import faker from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' -import { gql } from '../helpers/jest' import { createGroupMutation, joinGroupMutation,