diff --git a/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js
index d04eeeece..723dbdc05 100644
--- a/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js
+++ b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.js
@@ -6,33 +6,56 @@ const notifyUsers = async (label, id, idsOfUsers, reason, context) => {
if (!idsOfUsers.length) return
// Done here, because Neode validation is not working.
- const reasonsAllowed = ['mentioned_in_post', 'mentioned_in_comment', 'comment_on_your_post']
+ const reasonsAllowed = ['mentioned_in_post', 'mentioned_in_comment', 'comment_on_post']
if (!reasonsAllowed.includes(reason)) {
throw new UserInputError('Notification reason is not allowed!')
}
+ if (
+ (label === 'Post' && reason !== 'mentioned_in_post') ||
+ (label === 'Comment' && !['mentioned_in_comment', 'comment_on_post'].includes(reason))
+ ) {
+ throw new UserInputError('Notification fits not to reason!')
+ }
const session = context.driver.session()
const createdAt = new Date().toISOString()
let cypher
- if (label === 'Post') {
- cypher = `
- MATCH (post: Post { id: $id })<-[:WROTE]-(author: User)
- MATCH (user: User)
- WHERE user.id in $idsOfUsers
- AND NOT (user)<-[:BLOCKED]-(author)
- CREATE (notification: Notification {id: apoc.create.uuid(), read: false, reason: $reason, createdAt: $createdAt })
- MERGE (post)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
- `
- } else {
- cypher = `
- 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)
- CREATE (notification: Notification {id: apoc.create.uuid(), read: false, reason: $reason, createdAt: $createdAt })
- MERGE (comment)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
- `
+ switch (reason) {
+ case 'mentioned_in_post': {
+ cypher = `
+ MATCH (post: Post { id: $id })<-[:WROTE]-(author: User)
+ MATCH (user: User)
+ WHERE user.id in $idsOfUsers
+ AND NOT (user)<-[:BLOCKED]-(author)
+ CREATE (notification: Notification {id: apoc.create.uuid(), read: false, reason: $reason, createdAt: $createdAt })
+ MERGE (post)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
+ `
+ break
+ }
+ case 'mentioned_in_comment': {
+ cypher = `
+ 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)
+ CREATE (notification: Notification {id: apoc.create.uuid(), read: false, reason: $reason, createdAt: $createdAt })
+ MERGE (comment)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
+ `
+ break
+ }
+ case 'comment_on_post': {
+ cypher = `
+ 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 (author)<-[:BLOCKED]-(user)
+ CREATE (notification: Notification {id: apoc.create.uuid(), read: false, reason: $reason, createdAt: $createdAt })
+ MERGE (comment)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
+ `
+ break
+ }
}
await session.run(cypher, {
label,
@@ -116,7 +139,7 @@ const handleCreateComment = async (resolve, root, args, context, resolveInfo) =>
return record.get('user')
})
if (context.user.id !== postAuthor.id) {
- await notifyUsers('Comment', comment.id, [postAuthor.id], 'comment_on_your_post', context)
+ await notifyUsers('Comment', comment.id, [postAuthor.id], 'comment_on_post', context)
}
}
diff --git a/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js
index cb6aa9844..f5d2c61c8 100644
--- a/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js
+++ b/backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js
@@ -63,16 +63,17 @@ describe('notifications', () => {
describe('authenticated', () => {
beforeEach(async () => {
- authenticatedUser = user
+ authenticatedUser = await user.toJson()
})
describe('given another user', () => {
- let title
- let content
+ let postTitle
+ let postContent
+ let postAuthor
const createPostAction = async () => {
const createPostMutation = gql`
- mutation($id: ID, $title: String!, $content: String!) {
- CreatePost(id: $id, title: $title, content: $content) {
+ mutation($id: ID, $postTitle: String!, $postContent: String!) {
+ CreatePost(id: $id, title: $postTitle, content: $postContent) {
id
title
content
@@ -84,38 +85,154 @@ describe('notifications', () => {
mutation: createPostMutation,
variables: {
id: 'p47',
- title,
- content,
+ postTitle,
+ postContent,
},
})
authenticatedUser = await user.toJson()
}
- let postAuthor
- beforeEach(async () => {
- postAuthor = await instance.create('User', {
- email: 'post-author@example.org',
- password: '1234',
- id: 'postAuthor',
+ let commentContent
+ let commentAuthor
+ const createCommentOnPostAction = async () => {
+ await createPostAction()
+ const createCommentMutation = gql`
+ mutation($id: ID, $postId: ID!, $commentContent: String!) {
+ CreateComment(id: $id, postId: $postId, content: $commentContent) {
+ id
+ content
+ }
+ }
+ `
+ authenticatedUser = await commentAuthor.toJson()
+ await mutate({
+ mutation: createCommentMutation,
+ variables: {
+ id: 'c47',
+ postId: 'p47',
+ commentContent,
+ },
+ })
+ authenticatedUser = await user.toJson()
+ }
+
+ describe('comments on my post', () => {
+ beforeEach(async () => {
+ postTitle = 'My post'
+ postContent = 'My post content.'
+ postAuthor = user
+ })
+
+ describe('commenter is not me', () => {
+ beforeEach(async () => {
+ commentContent = 'Commenters comment.'
+ commentAuthor = await instance.create('User', {
+ id: 'commentAuthor',
+ name: 'Mrs Comment',
+ slug: 'mrs-comment',
+ email: 'commentauthor@example.org',
+ password: '1234',
+ })
+ })
+
+ it('sends me a notification', async () => {
+ await createCommentOnPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [
+ {
+ read: false,
+ reason: 'comment_on_post',
+ post: null,
+ comment: {
+ content: commentContent,
+ },
+ },
+ ],
+ },
+ },
+ })
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+
+ it('sends me no notification if I block the comment author', async () => {
+ await user.relateTo(commentAuthor, 'blocked')
+ await createCommentOnPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [],
+ },
+ },
+ })
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+ })
+
+ describe('commenter is me', () => {
+ beforeEach(async () => {
+ commentContent = 'My comment.'
+ commentAuthor = user
+ })
+
+ it('sends me no notification', async () => {
+ await user.relateTo(commentAuthor, 'blocked')
+ await createCommentOnPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [],
+ },
+ },
+ })
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
})
})
- describe('comments on my post', () => {
- title = 'My post'
- content = 'My content'
-
- // it('sends me a notification', async () => {
- // await createPostAction()
- // XXX
- // })
+ beforeEach(async () => {
+ postAuthor = await instance.create('User', {
+ id: 'postAuthor',
+ name: 'Mrs Post',
+ slug: 'mrs-post',
+ email: 'post-author@example.org',
+ password: '1234',
+ })
})
describe('mentions me in a post', () => {
- title = 'Mentioning Al Capone'
- content =
- 'Hey @al-capone how do you do?'
+ beforeEach(async () => {
+ postTitle = 'Mentioning Al Capone'
+ postContent =
+ 'Hey @al-capone how do you do?'
+ })
- it('sends you a notification', async () => {
+ it('sends me a notification', async () => {
await createPostAction()
const expectedContent =
'Hey @al-capone how do you do?'
@@ -163,8 +280,8 @@ describe('notifications', () => {
`
const updatePostMutation = gql`
- mutation($id: ID!, $title: String!, $content: String!) {
- UpdatePost(id: $id, content: $content, title: $title) {
+ mutation($id: ID!, $postTitle: String!, $postContent: String!) {
+ UpdatePost(id: $id, content: $postContent, title: $postTitle) {
title
content
}
@@ -175,8 +292,8 @@ describe('notifications', () => {
mutation: updatePostMutation,
variables: {
id: 'p47',
- title,
- content: updatedContent,
+ postTitle,
+ postContent: updatedContent,
},
})
authenticatedUser = await user.toJson()
@@ -247,39 +364,67 @@ describe('notifications', () => {
).resolves.toEqual(expected)
})
})
+ })
- describe('but the author of the post blocked me and a mentioner mentions me in a comment', () => {
- const createCommentOnPostAction = async () => {
- await createPostAction()
- const createCommentMutation = gql`
- mutation($id: ID, $postId: ID!, $commentContent: String!) {
- CreateComment(id: $id, postId: $postId, content: $commentContent) {
- id
- content
- }
- }
- `
- authenticatedUser = await commentMentioner.toJson()
- await mutate({
- mutation: createCommentMutation,
- variables: {
- id: 'c47',
- postId: 'p47',
- commentContent:
- 'One mention of me with .',
+ describe('mentions me in a comment', () => {
+ beforeEach(async () => {
+ postTitle = 'Post where I get mentioned in a comment'
+ postContent = 'Content of post where I get mentioned in a comment.'
+ })
+
+ describe('I am not blocked at all', () => {
+ beforeEach(async () => {
+ commentContent =
+ 'One mention about me with @al-capone.'
+ commentAuthor = await instance.create('User', {
+ id: 'commentAuthor',
+ name: 'Mrs Comment',
+ slug: 'mrs-comment',
+ email: 'comment-author@example.org',
+ password: '1234',
+ })
+ })
+
+ it('sends a notification', async () => {
+ await createCommentOnPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [
+ {
+ read: false,
+ reason: 'mentioned_in_comment',
+ post: null,
+ comment: {
+ content: commentContent,
+ },
+ },
+ ],
+ },
},
})
- authenticatedUser = await user.toJson()
- }
- let commentMentioner
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+ })
+ describe('but the author of the post blocked me', () => {
beforeEach(async () => {
await postAuthor.relateTo(user, 'blocked')
- commentMentioner = await instance.create('User', {
- id: 'mentioner',
- name: 'Mr Mentioner',
- slug: 'mr-mentioner',
- email: 'mentioner@example.org',
+ commentContent =
+ 'One mention about me with @al-capone.'
+ commentAuthor = await instance.create('User', {
+ id: 'commentAuthor',
+ name: 'Mrs Comment',
+ slug: 'mrs-comment',
+ email: 'comment-author@example.org',
password: '1234',
})
})
diff --git a/backend/src/models/Notification.js b/backend/src/models/Notification.js
index 93c4cd6cb..b54a99574 100644
--- a/backend/src/models/Notification.js
+++ b/backend/src/models/Notification.js
@@ -12,7 +12,8 @@ module.exports = {
},
reason: {
type: 'string',
- valid: ['mentioned_in_post', 'mentioned_in_comment', 'comment_on_your_post'],
+ valid: ['mentioned_in_post', 'mentioned_in_comment', 'comment_on_post'],
+ invalid: [null],
default: 'mentioned_in_post',
},
createdAt: {
diff --git a/backend/src/schema/types/enum/ReasonNotification.gql b/backend/src/schema/types/enum/ReasonNotification.gql
new file mode 100644
index 000000000..a66c446be
--- /dev/null
+++ b/backend/src/schema/types/enum/ReasonNotification.gql
@@ -0,0 +1,5 @@
+enum ReasonNotification {
+ mentioned_in_post
+ mentioned_in_comment
+ comment_on_post
+}
\ No newline at end of file
diff --git a/backend/src/schema/types/type/Notification.gql b/backend/src/schema/types/type/Notification.gql
index a03b86769..a3543445f 100644
--- a/backend/src/schema/types/type/Notification.gql
+++ b/backend/src/schema/types/type/Notification.gql
@@ -1,7 +1,7 @@
type Notification {
id: ID!
read: Boolean
- reason: String
+ reason: ReasonNotification
createdAt: String
user: User @relation(name: "NOTIFIED", direction: "OUT")
post: Post @relation(name: "NOTIFIED", direction: "IN")
diff --git a/webapp/components/notifications/Notification/Notification.vue b/webapp/components/notifications/Notification/Notification.vue
index 1aa930fc7..8afde5793 100644
--- a/webapp/components/notifications/Notification/Notification.vue
+++ b/webapp/components/notifications/Notification/Notification.vue
@@ -56,7 +56,7 @@ export default {
notificationTextIdents: {
mentioned_in_post: 'notifications.menu.mentionedInPost',
mentioned_in_comment: 'notifications.menu.mentionedInComment',
- comment_on_your_post: 'notifications.menu.commentedOnPost',
+ comment_on_post: 'notifications.menu.commentedOnPost',
},
}
},