diff --git a/backend/src/middleware/notifications/notificationsMiddleware.js b/backend/src/middleware/notifications/notificationsMiddleware.js index 837193773..e0b831b59 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.js @@ -50,7 +50,7 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => { MATCH (post: Post { id: $id })<-[:WROTE]-(author: User) MATCH (user: User) WHERE user.id in $idsOfUsers - AND NOT (user)<-[:BLOCKED]-(author) + AND NOT (user)-[:BLOCKED]-(author) MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user) ` break @@ -60,8 +60,8 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => { MATCH (postAuthor: User)-[:WROTE]->(post: Post)<-[:COMMENTS]-(comment: Comment { id: $id })<-[:WROTE]-(author: User) MATCH (user: User) WHERE user.id in $idsOfUsers - AND NOT (user)<-[:BLOCKED]-(author) - AND NOT (user)<-[:BLOCKED]-(postAuthor) + AND NOT (user)-[:BLOCKED]-(author) + AND NOT (user)-[:BLOCKED]-(postAuthor) MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user) ` break diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js index c3a7cfc98..994d19fa2 100644 --- a/backend/src/schema/resolvers/searches.js +++ b/backend/src/schema/resolvers/searches.js @@ -20,6 +20,7 @@ export default { AND NOT ( author.deleted = true OR author.disabled = true OR resource.deleted = true OR resource.disabled = true + OR (:User {id: $thisUserId})-[:MUTED]->(author) ) WITH resource, author, [(resource)<-[:COMMENTS]-(comment:Comment) | comment] as comments, diff --git a/cypress/integration/common/search.js b/cypress/integration/common/search.js index f6589763b..c42ec3ff0 100644 --- a/cypress/integration/common/search.js +++ b/cypress/integration/common/search.js @@ -11,15 +11,24 @@ Then("I should have one item in the select dropdown", () => { }); }); -Then("the search has no results", () => { +Then("the search should not contain posts by the annoying user", () => { cy.get(".searchable-input .ds-select-dropdown").should($li => { expect($li).to.have.length(1); - }); - cy.get(".ds-select-dropdown").should("contain", 'Nothing found'); + }) + cy.get(".ds-select-dropdown") + .should("not.have.class", '.search-post') + .should("not.contain", 'Spam') +}); + +Then("the search should contain the annoying user", () => { + cy.get(".searchable-input .ds-select-dropdown").should($li => { + expect($li).to.have.length(1); + }) + cy.get(".ds-select-dropdown .user-teaser .slug").should("contain", '@spammy-spammer'); cy.get(".searchable-input .ds-select-search") .focus() .type("{esc}"); -}); +}) Then("I should see the following posts in the select dropdown:", table => { table.hashes().forEach(({ title }) => { diff --git a/cypress/integration/common/steps.js b/cypress/integration/common/steps.js index 29f2fa85a..85e43b6ee 100644 --- a/cypress/integration/common/steps.js +++ b/cypress/integration/common/steps.js @@ -31,6 +31,7 @@ const narratorParams = { const annoyingParams = { email: "spammy-spammer@example.org", + slug: 'spammy-spammer', password: "1234", ...termsAndConditionsAgreedVersion }; @@ -39,8 +40,12 @@ Given("I am logged in", () => { cy.login(loginCredentials); }); -Given("I am logged in as the {string} user", _ => { - cy.login({ email: annoyingParams.email, password: '1234' }); +Given("the {string} user searches for {string}", (_, postTitle) => { + cy.logout() + .login({ email: annoyingParams.email, password: '1234' }) + .get(".searchable-input .ds-select-search") + .focus() + .type(postTitle); }); Given("we have a selection of categories", () => { @@ -123,7 +128,7 @@ When("I visit the {string} page", page => { cy.openPage(page); }); -When("the blocked user visits my post", () => { +When("a blocked user visits the post page of one of my authored posts", () => { cy.logout() .login({ email: annoyingParams.email, password: annoyingParams.password }) .openPage('/post/previously-created-post') @@ -506,7 +511,7 @@ Then("the list of posts of this user is empty", () => { cy.get(".main-container").find(".ds-space.hc-empty"); }); -Then("nobody is following the user profile anymore", () => { +Then("I get removed from his follower collection", () => { cy.get(".ds-card-content").not(".post-link"); cy.get(".main-container").contains( ".ds-card-content", diff --git a/cypress/integration/user_profile/BlockUser.feature b/cypress/integration/user_profile/BlockUser.feature index a04455b53..43efe7807 100644 --- a/cypress/integration/user_profile/BlockUser.feature +++ b/cypress/integration/user_profile/BlockUser.feature @@ -19,7 +19,7 @@ Feature: Block a User Scenario: Blocked user cannot interact with my contributions Given I block the user "Harassing User" And I previously created a post - And the blocked user visits my post + And a blocked user visits the post page of one of my authored posts Then they should not see the comment from And they should see a text explaining commenting is not possible @@ -27,7 +27,7 @@ Feature: Block a User Given I follow the user "Harassing User" When I visit the profile page of the annoying user And I click on "Block user" from the content menu in the user info box - And nobody is following the user profile anymore + And I get removed from his follower collection Scenario: Posts of blocked users are not filtered from search results Given "Harassing User" wrote a post "You can still see my posts" @@ -40,9 +40,7 @@ Feature: Block a User Scenario: Blocked users can still see my posts Given I previously created a post And I block the user "Harassing User" - Given I log out - And I am logged in as the "blocked" user - When I search for "previously created" + And the "blocked" user searches for "previously created" Then I should see the following posts in the select dropdown: | title | | previously created post | diff --git a/cypress/integration/user_profile/mute-users/Mute.feature b/cypress/integration/user_profile/mute-users/Mute.feature index cd7d1c827..03ac4370b 100644 --- a/cypress/integration/user_profile/mute-users/Mute.feature +++ b/cypress/integration/user_profile/mute-users/Mute.feature @@ -21,9 +21,9 @@ Feature: Mute a User When I visit the profile page of the annoying user And I click on "Mute user" from the content menu in the user info box Then the list of posts of this user is empty - And nobody is following the user profile anymore + And I get removed from his follower collection - Scenario: Posts of muted users are filtered from search results + Scenario: Posts of muted users are filtered from search results, users are not Given we have the following posts in our database: | id | title | content | | im-not-muted | Post that should be seen | cause I'm not muted | @@ -35,18 +35,17 @@ Feature: Mute a User When I mute the user "Spammy Spammer" And I refresh the page And I search for "Spam" - Then the search has no results + Then the search should not contain posts by the annoying user + But the search should contain the annoying user But I search for "not muted" Then I should see the following posts in the select dropdown: | title | | Post that should be seen | - + Scenario: Muted users can still see my posts Given I previously created a post And I mute the user "Spammy Spammer" - Given I log out - And I am logged in as the "muted" user - When I search for "previously created" + And the "muted" user searches for "previously created" Then I should see the following posts in the select dropdown: | title | | previously created post | diff --git a/webapp/components/generic/SearchableInput/SearchableInput.vue b/webapp/components/generic/SearchableInput/SearchableInput.vue index 448c154e0..3260ff082 100644 --- a/webapp/components/generic/SearchableInput/SearchableInput.vue +++ b/webapp/components/generic/SearchableInput/SearchableInput.vue @@ -71,7 +71,7 @@ export default { }, computed: { emptyText() { - return this.isActive && !this.pending ? this.$t('search.failed') : this.$t('search.hint') + return this.isActive && !this.loading ? this.$t('search.failed') : this.$t('search.hint') }, isActive() { return !isEmpty(this.previousSearchTerm) @@ -104,7 +104,7 @@ export default { */ onEnter(event) { clearTimeout(this.searchProcess) - if (!this.pending) { + if (!this.loading) { this.previousSearchTerm = this.unprocessedSearchInput this.$emit('query', this.unprocessedSearchInput) } diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index 8962830dc..6bc680fc9 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -24,6 +24,7 @@ export default i18n => { createdAt followedByCurrentUser isMuted + isBlocked following(first: 7) { ...user ...userCounts diff --git a/webapp/locales/de.json b/webapp/locales/de.json index bbf446f76..e2416ffd9 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -169,11 +169,12 @@ "name": "Blocked users", "explanation": { "intro": "Wenn ein anderer Benutzer von dir blockiert wurde, dann passiert folgendes:", - "your-perspective": "In deiner Beitragsübersicht tauchen keine Beiträge der blockierten Person mehr auf.", - "their-perspective": "Umgekehrt das gleiche: Die blockierte Person sieht deine Beiträge auch nicht mehr in ihrer Übersicht.", - "search": "Die Beiträge von blockierten Personen verschwinden aus deinen Suchergebnissen.", + "your-perspective": "Du kannst keine Beiträge der blockierten Person mehr kommentieren.", + "their-perspective": "Die blockierte Person kann deine Beiträge nicht mehr kommentieren", "notifications": "Von dir blockierte Personen erhalten keine Benachrichtigungen mehr, wenn sie in deinen Beiträgen erwähnt werden.", - "closing": "Das sollte fürs Erste genügen, damit blockierte Benutzer dich nicht mehr länger belästigen können." + "closing": "Das sollte fürs Erste genügen, damit blockierte Benutzer dich nicht mehr länger belästigen können.", + "commenting-disabled": "Du kannst den Beitrag derzeit nicht kommentieren.", + "commenting-explanation": "Dafür kann es mehrere Gründe geben, bitte schau in unsere " }, "columns": { "name": "Name", @@ -183,7 +184,7 @@ "empty": "Bislang hast du niemanden blockiert.", "how-to": "Du kannst andere Benutzer auf deren Profilseite über das Inhaltsmenü blockieren.", "block": "Nutzer blockieren", - "unblock": "Nutzer entblocken", + "unblock": "Nutzer entsperren", "unblocked": "{name} ist wieder entsperrt" } }, diff --git a/webapp/pages/profile/_id/_slug.vue b/webapp/pages/profile/_id/_slug.vue index 01190caa2..f83d5bed5 100644 --- a/webapp/pages/profile/_id/_slug.vue +++ b/webapp/pages/profile/_id/_slug.vue @@ -68,16 +68,23 @@