Rename REPORTED Claim to FILED Report

This commit is contained in:
mattwr18 2019-11-26 15:35:48 +01:00
parent ff404e3c37
commit 2f249a73c5
31 changed files with 538 additions and 434 deletions

View File

@ -134,7 +134,7 @@ const permissions = shield(
CreatePost: isAuthenticated, CreatePost: isAuthenticated,
UpdatePost: isAuthor, UpdatePost: isAuthor,
DeletePost: isAuthor, DeletePost: isAuthor,
report: isAuthenticated, fileReport: isAuthenticated,
CreateSocialMedia: isAuthenticated, CreateSocialMedia: isAuthenticated,
UpdateSocialMedia: isMySocialMedia, UpdateSocialMedia: isMySocialMedia,
DeleteSocialMedia: isMySocialMedia, DeleteSocialMedia: isMySocialMedia,

View File

@ -104,14 +104,14 @@ beforeAll(async () => {
const trollingPost = resources[1] const trollingPost = resources[1]
const trollingComment = resources[2] const trollingComment = resources[2]
const claims = await Promise.all([ const reports = await Promise.all([
factory.create('Claim'), factory.create('Report'),
factory.create('Claim'), factory.create('Report'),
factory.create('Claim'), factory.create('Report'),
]) ])
const claimAgainstTroll = claims[0] const reportAgainstTroll = reports[0]
const claimAgainstTrollingPost = claims[1] const reportAgainstTrollingPost = reports[1]
const claimAgainstTrollingComment = claims[2] const reportAgainstTrollingComment = reports[2]
const reportVariables = { const reportVariables = {
resourceId: 'undefined-resource', resourceId: 'undefined-resource',
@ -120,15 +120,15 @@ beforeAll(async () => {
} }
await Promise.all([ await Promise.all([
claimAgainstTroll.relateTo(user, 'reported', { ...reportVariables, resourceId: 'u2' }), reportAgainstTroll.relateTo(user, 'filed', { ...reportVariables, resourceId: 'u2' }),
claimAgainstTroll.relateTo(troll, 'belongsTo'), reportAgainstTroll.relateTo(troll, 'belongsTo'),
claimAgainstTrollingPost.relateTo(user, 'reported', { ...reportVariables, resourceId: 'p2' }), reportAgainstTrollingPost.relateTo(user, 'filed', { ...reportVariables, resourceId: 'p2' }),
claimAgainstTrollingPost.relateTo(trollingPost, 'belongsTo'), reportAgainstTrollingPost.relateTo(trollingPost, 'belongsTo'),
claimAgainstTrollingComment.relateTo(moderator, 'reported', { reportAgainstTrollingComment.relateTo(moderator, 'filed', {
...reportVariables, ...reportVariables,
resourceId: 'c1', resourceId: 'c1',
}), }),
claimAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'), reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'),
]) ])
const disableVariables = { const disableVariables = {
@ -138,14 +138,14 @@ beforeAll(async () => {
} }
await Promise.all([ await Promise.all([
claimAgainstTroll.relateTo(moderator, 'reviewed', { ...disableVariables, resourceId: 'u2' }), reportAgainstTroll.relateTo(moderator, 'reviewed', { ...disableVariables, resourceId: 'u2' }),
troll.update({ disabled: true, updatedAt: new Date().toISOString() }), troll.update({ disabled: true, updatedAt: new Date().toISOString() }),
claimAgainstTrollingPost.relateTo(moderator, 'reviewed', { reportAgainstTrollingPost.relateTo(moderator, 'reviewed', {
...disableVariables, ...disableVariables,
resourceId: 'p2', resourceId: 'p2',
}), }),
trollingPost.update({ disabled: true, updatedAt: new Date().toISOString() }), trollingPost.update({ disabled: true, updatedAt: new Date().toISOString() }),
claimAgainstTrollingComment.relateTo(moderator, 'reviewed', { reportAgainstTrollingComment.relateTo(moderator, 'reviewed', {
...disableVariables, ...disableVariables,
resourceId: 'c1', resourceId: 'c1',
}), }),

View File

@ -64,7 +64,7 @@ const validateReport = async (resolve, root, args, context, info) => {
const session = driver.session() const session = driver.session()
const reportQueryRes = await session.run( const reportQueryRes = await session.run(
` `
MATCH (:User {id: $submitterId})-[:REPORTED]->(:Claim {closed: false})-[:BELONGS_TO]->(resource {id: $resourceId}) MATCH (:User {id: $submitterId})-[:FILED]->(:Report {closed: false})-[:BELONGS_TO]->(resource {id: $resourceId})
WHERE resource:User OR resource:Post OR resource:Comment WHERE resource:User OR resource:Post OR resource:Comment
RETURN labels(resource)[0] AS label RETURN labels(resource)[0] AS label
`, `,
@ -93,9 +93,9 @@ const validateReview = async (resolve, root, args, context, info) => {
` `
MATCH (resource {id: $resourceId}) MATCH (resource {id: $resourceId})
WHERE resource:User OR resource:Post OR resource:Comment WHERE resource:User OR resource:Post OR resource:Comment
OPTIONAL MATCH (:User)-[report:REPORTED]->(:Claim {closed: false})-[:BELONGS_TO]->(resource) OPTIONAL MATCH (:User)-[filed:FILED]->(:Report {closed: false})-[:BELONGS_TO]->(resource)
OPTIONAL MATCH (resource)<-[:WROTE]-(author:User) OPTIONAL MATCH (resource)<-[:WROTE]-(author:User)
RETURN labels(resource)[0] AS label, author, report RETURN labels(resource)[0] AS label, author, filed
`, `,
{ {
resourceId, resourceId,
@ -107,12 +107,12 @@ const validateReview = async (resolve, root, args, context, info) => {
return { return {
label: record.get('label'), label: record.get('label'),
author: record.get('author'), author: record.get('author'),
report: record.get('report'), filed: record.get('filed'),
} }
}) })
if (!existingReportedResource) throw new Error(`Resource not found!`) if (!existingReportedResource) throw new Error(`Resource not found!`)
if (!existingReportedResource.report) if (!existingReportedResource.filed)
throw new Error( throw new Error(
`Before you can start the reviewing process, please report the ${existingReportedResource.label}!`, `Before you can start the reviewing process, please report the ${existingReportedResource.label}!`,
) )
@ -131,7 +131,7 @@ export default {
UpdateComment: validateUpdateComment, UpdateComment: validateUpdateComment,
CreatePost: validatePost, CreatePost: validatePost,
UpdatePost: validateUpdatePost, UpdatePost: validateUpdatePost,
report: validateReport, fileReport: validateReport,
review: validateReview, review: validateReview,
}, },
} }

View File

@ -13,9 +13,9 @@ module.exports = {
target: ['User', 'Comment', 'Post'], target: ['User', 'Comment', 'Post'],
direction: 'out', direction: 'out',
}, },
reported: { filed: {
type: 'relationship', type: 'relationship',
relationship: 'REPORTED', relationship: 'FILED',
target: 'User', target: 'User',
direction: 'in', direction: 'in',
properties: { properties: {

View File

@ -13,5 +13,5 @@ export default {
Tag: require('./Tag.js'), Tag: require('./Tag.js'),
Location: require('./Location.js'), Location: require('./Location.js'),
Donations: require('./Donations.js'), Donations: require('./Donations.js'),
Claim: require('./Claim.js'), Report: require('./Report.js'),
} }

View File

@ -18,9 +18,9 @@ export default makeAugmentedSchema({
'Location', 'Location',
'SocialMedia', 'SocialMedia',
'NOTIFIED', 'NOTIFIED',
'REPORTED', 'FILED',
'REVIEWED', 'REVIEWED',
'Claim', 'Report',
'Donations', 'Donations',
], ],
}, },

View File

@ -1,6 +1,6 @@
import uuid from 'uuid/v4' import uuid from 'uuid/v4'
import Resolver from './helpers/Resolver' import Resolver from './helpers/Resolver'
import { queryReviewedByModerator } from './helpers/claimResource.js' import { queryReviewedByModerator } from './helpers/reportResource.js'
export default { export default {
Mutation: { Mutation: {

View File

@ -2,10 +2,10 @@ export async function queryReviewedByModerator(label, parent, context) {
if (typeof parent.reviewedByModerator !== 'undefined') return parent.reviewedByModerator if (typeof parent.reviewedByModerator !== 'undefined') return parent.reviewedByModerator
const { id } = parent const { id } = parent
const statement = ` const statement = `
MATCH (resource {id: $id})<-[:BELONGS_TO]-(claim:Claim)<-[review:REVIEWED]-(moderator:User) MATCH (resource {id: $id})<-[:BELONGS_TO]-(report:Report)<-[review:REVIEWED]-(moderator:User)
WHERE $label IN labels(resource) WHERE $label IN labels(resource)
RETURN moderator RETURN moderator
ORDER BY claim.updatedAt DESC, review.updatedAt DESC ORDER BY report.updatedAt DESC, review.updatedAt DESC
LIMIT 1 LIMIT 1
` `
let reviewedByModerator let reviewedByModerator

View File

@ -16,21 +16,21 @@ export default {
MATCH (resource {id: $resourceId}) MATCH (resource {id: $resourceId})
WHERE resource:User OR resource:Post OR resource:Comment WHERE resource:User OR resource:Post OR resource:Comment
// no open claim, create one, update existing // no open report, create one, update existing
MERGE (resource)<-[:BELONGS_TO]-(claim:Claim {closed: false}) MERGE (resource)<-[:BELONGS_TO]-(report:Report {closed: false})
ON CREATE SET claim.id = randomUUID(), claim.createdAt = $dateTime, claim.updatedAt = claim.createdAt, claim.rule = 'latestReviewUpdatedAtRules', claim.disable = resource.disabled, claim.closed = false ON CREATE SET report.id = randomUUID(), report.createdAt = $dateTime, report.updatedAt = report.createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = resource.disabled, report.closed = false
ON MATCH SET claim.updatedAt = $dateTime ON MATCH SET report.updatedAt = $dateTime
// claim.disable and claim.closed are set after setting them in review // report.disable and report.closed are set after setting them in review
// Create review on claim // Create review on report
WITH moderator, resource, claim WITH moderator, resource, report
MERGE (claim)<-[review:REVIEWED]-(moderator) MERGE (report)<-[review:REVIEWED]-(moderator)
ON CREATE SET review.createdAt = $dateTime, review.updatedAt = review.createdAt, ON CREATE SET review.createdAt = $dateTime, review.updatedAt = review.createdAt,
review.disable = CASE WHEN $disable IS NULL review.disable = CASE WHEN $disable IS NULL
THEN claim.disable THEN report.disable
ELSE $disable END, ELSE $disable END,
review.closed = CASE WHEN $closed IS NULL review.closed = CASE WHEN $closed IS NULL
THEN claim.closed THEN report.closed
ELSE $closed END ELSE $closed END
ON MATCH SET ON MATCH SET
review.updatedAt = $dateTime, review.updatedAt = $dateTime,
@ -41,10 +41,10 @@ export default {
THEN review.closed THEN review.closed
ELSE $closed END ELSE $closed END
SET claim.disable = review.disable, claim.closed = review.closed SET report.disable = review.disable, report.closed = review.closed
SET resource.disabled = review.disable SET resource.disabled = review.disable
RETURN moderator, review, claim, resource, labels(resource)[0] AS type RETURN moderator, review, report, resource, labels(resource)[0] AS type
` `
const mutateDecisionWriteTxResultPromise = session.writeTransaction(async txc => { const mutateDecisionWriteTxResultPromise = session.writeTransaction(async txc => {
const mutateDecisionTransactionResponse = await txc.run(cypher, { const mutateDecisionTransactionResponse = await txc.run(cypher, {
@ -57,21 +57,21 @@ export default {
return mutateDecisionTransactionResponse.records.map(record => ({ return mutateDecisionTransactionResponse.records.map(record => ({
moderator: record.get('moderator'), moderator: record.get('moderator'),
review: record.get('review'), review: record.get('review'),
claim: record.get('claim'), report: record.get('report'),
resource: record.get('resource'), resource: record.get('resource'),
type: record.get('type'), type: record.get('type'),
})) }))
}) })
const txResult = await mutateDecisionWriteTxResultPromise const txResult = await mutateDecisionWriteTxResultPromise
if (!txResult[0]) return null if (!txResult[0]) return null
const { moderator: moderatorInResult, review, claim, resource, type } = txResult[0] const { moderator: moderatorInResult, review, report, resource, type } = txResult[0]
createdRelationshipWithNestedAttributes = { createdRelationshipWithNestedAttributes = {
...review.properties, ...review.properties,
claimId: claim.properties.id, reportId: report.properties.id,
claimCreatedAt: claim.properties.createdAt, reportCreatedAt: report.properties.createdAt,
claimUpdatedAt: claim.properties.updatedAt, reportUpdatedAt: report.properties.updatedAt,
claimDisable: claim.properties.disable, reportDisable: report.properties.disable,
claimClosed: claim.properties.closed, reportClosed: report.properties.closed,
moderator: moderatorInResult.properties, moderator: moderatorInResult.properties,
type, type,
post: null, post: null,

View File

@ -19,7 +19,7 @@ let query,
const reportMutation = gql` const reportMutation = gql`
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
report( fileReport(
resourceId: $resourceId resourceId: $resourceId
reasonCategory: $reasonCategory reasonCategory: $reasonCategory
reasonDescription: $reasonDescription reasonDescription: $reasonDescription

View File

@ -5,7 +5,7 @@ import { getBlockedUsers, getBlockedByUsers } from './users.js'
import { mergeWith, isArray, isEmpty } from 'lodash' import { mergeWith, isArray, isEmpty } from 'lodash'
import { UserInputError } from 'apollo-server' import { UserInputError } from 'apollo-server'
import Resolver from './helpers/Resolver' import Resolver from './helpers/Resolver'
import { queryReviewedByModerator } from './helpers/claimResource.js' import { queryReviewedByModerator } from './helpers/reportResource.js'
const filterForBlockedUsers = async (params, context) => { const filterForBlockedUsers = async (params, context) => {
if (!context.user) return params if (!context.user) return params

View File

@ -1,6 +1,6 @@
export default { export default {
Mutation: { Mutation: {
report: async (_parent, params, context, _resolveInfo) => { fileReport: async (_parent, params, context, _resolveInfo) => {
let createdRelationshipWithNestedAttributes let createdRelationshipWithNestedAttributes
const { resourceId, reasonCategory, reasonDescription } = params const { resourceId, reasonCategory, reasonDescription } = params
const { driver, user } = context const { driver, user } = context
@ -11,15 +11,15 @@ export default {
MATCH (submitter:User {id: $submitterId}) MATCH (submitter:User {id: $submitterId})
MATCH (resource {id: $resourceId}) MATCH (resource {id: $resourceId})
WHERE resource:User OR resource:Post OR resource:Comment WHERE resource:User OR resource:Post OR resource:Comment
// no open claim, create one // no open report, create one
MERGE (resource)<-[:BELONGS_TO]-(claim:Claim {closed: false}) MERGE (resource)<-[:BELONGS_TO]-(report:Report {closed: false})
ON CREATE SET claim.id = randomUUID(), claim.createdAt = $createdAt, claim.updatedAt = claim.createdAt, claim.rule = 'latestReviewUpdatedAtRules', claim.disable = resource.disabled, claim.closed = false ON CREATE SET report.id = randomUUID(), report.createdAt = $createdAt, report.updatedAt = report.createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = resource.disabled, report.closed = false
// ON MATCH: do not update claim.updatedAt !!! that is only for reviews! // ON MATCH: do not update report.updatedAt !!! that is only for reviews!
// Create report to claim // Create report to report
WITH submitter, resource, claim WITH submitter, resource, report
CREATE (claim)<-[report:REPORTED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter) CREATE (report)<-[filed:FILED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter)
RETURN submitter, report, claim, resource, labels(resource)[0] AS type RETURN submitter, report, filed, resource, labels(resource)[0] AS type
`, `,
{ {
resourceId, resourceId,
@ -32,7 +32,7 @@ export default {
return reportRelationshipTransactionResponse.records.map(record => ({ return reportRelationshipTransactionResponse.records.map(record => ({
submitter: record.get('submitter').properties, submitter: record.get('submitter').properties,
report: record.get('report').properties, report: record.get('report').properties,
claim: record.get('claim').properties, filed: record.get('filed').properties,
resource: record.get('resource').properties, resource: record.get('resource').properties,
type: record.get('type'), type: record.get('type'),
})) }))
@ -40,10 +40,10 @@ export default {
try { try {
const txResult = await writeTxResultPromise const txResult = await writeTxResultPromise
if (!txResult[0]) return null if (!txResult[0]) return null
const { submitter, report, claim, resource, type } = txResult[0] const { submitter, report, filed, resource, type } = txResult[0]
createdRelationshipWithNestedAttributes = { createdRelationshipWithNestedAttributes = {
...report, ...filed,
claim, report,
post: null, post: null,
comment: null, comment: null,
user: null, user: null,
@ -74,10 +74,10 @@ export default {
let reports, orderByClause let reports, orderByClause
switch (params.orderBy) { switch (params.orderBy) {
case 'createdAt_asc': case 'createdAt_asc':
orderByClause = 'ORDER BY claim.createdAt ASC, report.createdAt DESC' orderByClause = 'ORDER BY report.createdAt ASC, filed.createdAt DESC'
break break
case 'createdAt_desc': case 'createdAt_desc':
orderByClause = 'ORDER BY claim.createdAt DESC, report.createdAt DESC' orderByClause = 'ORDER BY report.createdAt DESC, filed.createdAt DESC'
break break
default: default:
orderByClause = '' orderByClause = ''
@ -85,9 +85,9 @@ export default {
const readTxPromise = session.readTransaction(async tx => { const readTxPromise = session.readTransaction(async tx => {
const allReportsTransactionResponse = await tx.run( const allReportsTransactionResponse = await tx.run(
` `
MATCH (submitter:User)-[report:REPORTED]->(claim:Claim)-[:BELONGS_TO]->(resource) MATCH (submitter:User)-[filed:FILED]->(report:Report)-[:BELONGS_TO]->(resource)
WHERE resource:User OR resource:Post OR resource:Comment WHERE resource:User OR resource:Post OR resource:Comment
RETURN submitter, report, claim, resource, labels(resource)[0] as type RETURN submitter, report, filed, resource, labels(resource)[0] as type
${orderByClause} ${orderByClause}
`, `,
{}, {},
@ -95,7 +95,7 @@ export default {
return allReportsTransactionResponse.records.map(record => ({ return allReportsTransactionResponse.records.map(record => ({
submitter: record.get('submitter').properties, submitter: record.get('submitter').properties,
report: record.get('report').properties, report: record.get('report').properties,
claim: record.get('claim').properties, filed: record.get('filed').properties,
resource: record.get('resource').properties, resource: record.get('resource').properties,
type: record.get('type'), type: record.get('type'),
})) }))
@ -104,10 +104,10 @@ export default {
const txResult = await readTxPromise const txResult = await readTxPromise
if (!txResult[0]) return null if (!txResult[0]) return null
reports = txResult.map(reportedRecord => { reports = txResult.map(reportedRecord => {
const { report, submitter, claim, resource, type } = reportedRecord const { report, submitter, filed, resource, type } = reportedRecord
const relationshipWithNestedAttributes = { const relationshipWithNestedAttributes = {
...report, ...report,
claim, filed,
post: null, post: null,
comment: null, comment: null,
user: null, user: null,

View File

@ -8,12 +8,12 @@ const factory = Factory()
const instance = getNeode() const instance = getNeode()
const driver = getDriver() const driver = getDriver()
describe('report resources', () => { describe('file a report on a resource', () => {
let authenticatedUser, currentUser, mutate, query, moderator, abusiveUser, otherReportingUser let authenticatedUser, currentUser, mutate, query, moderator, abusiveUser, otherReportingUser
const categoryIds = ['cat9'] const categoryIds = ['cat9']
const reportMutation = gql` const reportMutation = gql`
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
report( fileReport(
resourceId: $resourceId resourceId: $resourceId
reasonCategory: $reasonCategory reasonCategory: $reasonCategory
reasonDescription: $reasonDescription reasonDescription: $reasonDescription
@ -34,7 +34,7 @@ describe('report resources', () => {
comment { comment {
content content
} }
claim { report {
id id
createdAt createdAt
updatedAt updatedAt
@ -74,7 +74,7 @@ describe('report resources', () => {
it('throws authorization error', async () => { it('throws authorization error', async () => {
authenticatedUser = null authenticatedUser = null
await expect(mutate({ mutation: reportMutation, variables })).resolves.toMatchObject({ await expect(mutate({ mutation: reportMutation, variables })).resolves.toMatchObject({
data: { report: null }, data: { fileReport: null },
errors: [{ message: 'Not Authorised!' }], errors: [{ message: 'Not Authorised!' }],
}) })
}) })
@ -112,14 +112,14 @@ describe('report resources', () => {
describe('invalid resource id', () => { describe('invalid resource id', () => {
it('returns null', async () => { it('returns null', async () => {
await expect(mutate({ mutation: reportMutation, variables })).resolves.toMatchObject({ await expect(mutate({ mutation: reportMutation, variables })).resolves.toMatchObject({
data: { report: null }, data: { fileReport: null },
errors: undefined, errors: undefined,
}) })
}) })
}) })
describe('valid resource', () => { describe('valid resource', () => {
describe('creates claim', () => { describe('creates report', () => {
it('which belongs to resource', async () => { it('which belongs to resource', async () => {
await expect( await expect(
mutate({ mutate({
@ -128,9 +128,9 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
type: 'User', type: 'User',
claim: { report: {
id: expect.any(String), id: expect.any(String),
createdAt: expect.any(String), createdAt: expect.any(String),
updatedAt: expect.any(String), updatedAt: expect.any(String),
@ -143,7 +143,7 @@ describe('report resources', () => {
}) })
}) })
it('creates only one claim for multiple reports on the same resource', async () => { it('creates only one report for multiple reports on the same resource', async () => {
const firstReport = await mutate({ const firstReport = await mutate({
mutation: reportMutation, mutation: reportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' }, variables: { ...variables, resourceId: 'abusive-user-id' },
@ -153,7 +153,7 @@ describe('report resources', () => {
mutation: reportMutation, mutation: reportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' }, variables: { ...variables, resourceId: 'abusive-user-id' },
}) })
expect(firstReport.data.report.claim).toEqual(secondReport.data.report.claim) expect(firstReport.data.fileReport.report).toEqual(secondReport.data.fileReport.report)
}) })
it.todo('creates multiple reports') it.todo('creates multiple reports')
@ -168,7 +168,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
type: 'User', type: 'User',
}, },
}, },
@ -184,7 +184,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
user: { user: {
name: 'abusive-user', name: 'abusive-user',
}, },
@ -202,7 +202,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
submitter: { submitter: {
email: 'test@example.org', email: 'test@example.org',
}, },
@ -220,7 +220,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
createdAt: expect.any(String), createdAt: expect.any(String),
}, },
}, },
@ -240,7 +240,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
reasonCategory: 'criminal_behavior_violation_german_law', reasonCategory: 'criminal_behavior_violation_german_law',
}, },
}, },
@ -281,7 +281,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
reasonDescription: 'My reason!', reasonDescription: 'My reason!',
}, },
}, },
@ -301,7 +301,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
reasonDescription: 'My reason !', reasonDescription: 'My reason !',
}, },
}, },
@ -331,7 +331,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
type: 'Post', type: 'Post',
}, },
}, },
@ -350,7 +350,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
post: { post: {
title: 'This is a post that is going to be reported', title: 'This is a post that is going to be reported',
}, },
@ -371,7 +371,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
user: null, user: null,
}, },
}, },
@ -409,7 +409,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
type: 'Comment', type: 'Comment',
}, },
}, },
@ -428,7 +428,7 @@ describe('report resources', () => {
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { data: {
report: { fileReport: {
comment: { comment: {
content: 'Post comment to be reported.', content: 'Post comment to be reported.',
}, },
@ -456,7 +456,7 @@ describe('report resources', () => {
}, },
}), }),
).resolves.toMatchObject({ ).resolves.toMatchObject({
data: { report: null }, data: { fileReport: null },
errors: undefined, errors: undefined,
}) })
}) })
@ -485,7 +485,7 @@ describe('report resources', () => {
comment { comment {
id id
} }
claim { report {
id id
createdAt createdAt
updatedAt updatedAt
@ -614,7 +614,7 @@ describe('report resources', () => {
}), }),
post: null, post: null,
comment: null, comment: null,
claim: { report: {
id: expect.any(String), id: expect.any(String),
createdAt: expect.any(String), createdAt: expect.any(String),
updatedAt: expect.any(String), updatedAt: expect.any(String),
@ -635,7 +635,7 @@ describe('report resources', () => {
id: 'abusive-post-1', id: 'abusive-post-1',
}), }),
comment: null, comment: null,
claim: { report: {
id: expect.any(String), id: expect.any(String),
createdAt: expect.any(String), createdAt: expect.any(String),
updatedAt: expect.any(String), updatedAt: expect.any(String),
@ -656,7 +656,7 @@ describe('report resources', () => {
comment: expect.objectContaining({ comment: expect.objectContaining({
id: 'abusive-comment-1', id: 'abusive-comment-1',
}), }),
claim: { report: {
id: expect.any(String), id: expect.any(String),
createdAt: expect.any(String), createdAt: expect.any(String),
updatedAt: expect.any(String), updatedAt: expect.any(String),

View File

@ -22,7 +22,7 @@ const disable = async id => {
await mutate({ await mutate({
mutation: gql` mutation: gql`
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
report( fileReport(
resourceId: $resourceId resourceId: $resourceId
reasonCategory: $reasonCategory reasonCategory: $reasonCategory
reasonDescription: $reasonDescription reasonDescription: $reasonDescription

View File

@ -3,7 +3,7 @@ import fileUpload from './fileUpload'
import { neode } from '../../bootstrap/neo4j' import { neode } from '../../bootstrap/neo4j'
import { UserInputError, ForbiddenError } from 'apollo-server' import { UserInputError, ForbiddenError } from 'apollo-server'
import Resolver from './helpers/Resolver' import Resolver from './helpers/Resolver'
import { queryReviewedByModerator } from './helpers/claimResource.js' import { queryReviewedByModerator } from './helpers/reportResource.js'
const instance = neode() const instance = neode()

View File

@ -1,12 +0,0 @@
type Claim {
id: ID!
createdAt: String!
updatedAt: String!
rule: ClaimRule!
disable: Boolean!
closed: Boolean!
}
enum ClaimRule {
latestReviewUpdatedAtRules
}

View File

@ -50,9 +50,9 @@ type Comment {
reviewedByModerator: User reviewedByModerator: User
@cypher( @cypher(
statement: """ statement: """
MATCH (this)<-[:BELONGS_TO]-(claim:Claim)<-[review:REVIEWED]-(moderator:User) MATCH (this)<-[:BELONGS_TO]-(report:Report)<-[review:REVIEWED]-(moderator:User)
RETURN moderator RETURN moderator
ORDER BY claim.updatedAt DESC, review.updatedAt DESC ORDER BY report.updatedAt DESC, review.updatedAt DESC
LIMIT 1 LIMIT 1
""" """
) )

View File

@ -1,15 +1,15 @@
type REPORTED { type FILED {
createdAt: String! createdAt: String!
reasonCategory: ReasonCategory! reasonCategory: ReasonCategory!
reasonDescription: String! reasonDescription: String!
claim: Claim @cypher( report: Report @cypher(
statement: "MATCH (resource)<-[:BELONGS_TO]-(claim:Claim)<-[:REPORTED]-(:User) WHERE NOT resource.deleted = true AND NOT resource.disabled = true RETURN claim" statement: "MATCH (resource)<-[:BELONGS_TO]-(report:Report)<-[:FILED]-(:User) WHERE NOT resource.deleted = true AND NOT resource.disabled = true RETURN report"
) )
submitter: User submitter: User
# @cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN user") # @cypher(statement: "MATCH (resource)<-[:FILED]-(user:User) RETURN user")
type: String type: String
# @cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN labels(resource)[0]") # @cypher(statement: "MATCH (resource)<-[:FILED]-(user:User) RETURN labels(resource)[0]")
user: User user: User
post: Post post: Post
comment: Comment comment: Comment
@ -36,9 +36,9 @@ enum ReportOrdering {
} }
type Query { type Query {
reports(orderBy: ReportOrdering): [REPORTED] reports(orderBy: ReportOrdering): [FILED]
} }
type Mutation { type Mutation {
report(resourceId: ID!, reasonCategory: ReasonCategory!, reasonDescription: String!): REPORTED fileReport(resourceId: ID!, reasonCategory: ReasonCategory!, reasonDescription: String!): FILED
} }

View File

@ -124,9 +124,9 @@ type Post {
reviewedByModerator: User reviewedByModerator: User
@cypher( @cypher(
statement: """ statement: """
MATCH (this)<-[:BELONGS_TO]-(claim:Claim)<-[review:REVIEWED]-(moderator:User) MATCH (this)<-[:BELONGS_TO]-(report:Report)<-[review:REVIEWED]-(moderator:User)
RETURN moderator RETURN moderator
ORDER BY claim.updatedAt DESC, review.updatedAt DESC ORDER BY report.updatedAt DESC, review.updatedAt DESC
LIMIT 1 LIMIT 1
""" """
) )

View File

@ -6,11 +6,11 @@ type REVIEWED {
disable: Boolean! disable: Boolean!
closed: Boolean! closed: Boolean!
claimId: ID! reportId: ID!
claimCreatedAt: String! reportCreatedAt: String!
claimUpdatedAt: String! reportUpdatedAt: String!
claimDisable: Boolean! reportDisable: Boolean!
claimClosed: Boolean! reportClosed: Boolean!
moderator: User moderator: User
type: String type: String

View File

@ -0,0 +1,16 @@
type Report {
id: ID!
createdAt: String!
updatedAt: String!
rule: ReportRule!
disable: Boolean!
closed: Boolean!
resource: ReportResource
filed: [FILED]
}
# not yet supported
union ReportResource = User | Post | Comment
enum ReportRule {
latestReviewUpdatedAtRules
}

View File

@ -36,9 +36,9 @@ type User {
reviewedByModerator: User reviewedByModerator: User
@cypher( @cypher(
statement: """ statement: """
MATCH (this)<-[:BELONGS_TO]-(claim:Claim)<-[review:REVIEWED]-(moderator:User) MATCH (this)<-[:BELONGS_TO]-(report:Report)<-[review:REVIEWED]-(moderator:User)
RETURN moderator RETURN moderator
ORDER BY claim.updatedAt DESC, review.updatedAt DESC ORDER BY report.updatedAt DESC, review.updatedAt DESC
LIMIT 1 LIMIT 1
""" """
) )

View File

@ -10,7 +10,7 @@ import createLocation from './locations.js'
import createEmailAddress from './emailAddresses.js' import createEmailAddress from './emailAddresses.js'
import createDonations from './donations.js' import createDonations from './donations.js'
import createUnverifiedEmailAddresss from './unverifiedEmailAddresses.js' import createUnverifiedEmailAddresss from './unverifiedEmailAddresses.js'
import createClaim from './claims.js' import createReport from './reports.js'
const factories = { const factories = {
Badge: createBadge, Badge: createBadge,
@ -24,7 +24,7 @@ const factories = {
EmailAddress: createEmailAddress, EmailAddress: createEmailAddress,
UnverifiedEmailAddress: createUnverifiedEmailAddresss, UnverifiedEmailAddress: createUnverifiedEmailAddresss,
Donations: createDonations, Donations: createDonations,
Claim: createClaim, Report: createReport,
} }
export const cleanDatabase = async (options = {}) => { export const cleanDatabase = async (options = {}) => {

View File

@ -1,7 +1,7 @@
export default function create() { export default function create() {
return { return {
factory: async ({ args, neodeInstance }) => { factory: async ({ args, neodeInstance }) => {
return neodeInstance.create('Claim', args) return neodeInstance.create('Report', args)
}, },
} }
} }

View File

@ -524,7 +524,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
]) ])
authenticatedUser = null authenticatedUser = null
await Promise.all([ const comments = await Promise.all([
factory.create('Comment', { factory.create('Comment', {
author: jennyRostock, author: jennyRostock,
id: 'c1', id: 'c1',
@ -581,6 +581,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
postId: 'p15', postId: 'p15',
}), }),
]) ])
const trollingComment = comments[0]
await Promise.all([ await Promise.all([
democracy.relateTo(p3, 'post'), democracy.relateTo(p3, 'post'),
@ -644,236 +645,334 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
louie.relateTo(p10, 'shouted'), louie.relateTo(p10, 'shouted'),
]) ])
// There is no error logged or the 'try' fails if this mutation is wrong. Why? const reports = await Promise.all([
const reportMutation = gql` factory.create('Report'),
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { factory.create('Report'),
report( factory.create('Report'),
resourceId: $resourceId ])
reasonCategory: $reasonCategory const reportAgainstDagobert = reports[0]
reasonDescription: $reasonDescription const reportAgainstTrollingPost = reports[1]
) { const reportAgainstTrollingComment = reports[2]
type
}
}
`
authenticatedUser = await huey.toJson()
// report resource first time // report resource first time
await Promise.all([ await Promise.all([
mutate({ reportAgainstDagobert.relateTo(jennyRostock, 'filed', {
mutation: reportMutation, resourceId: 'u7',
variables: { reasonCategory: 'discrimination_etc',
resourceId: 'p11', reasonDescription: 'This user is harassing me with bigoted remarks!',
reasonCategory: 'discrimination_etc',
reasonDescription: 'I am what I am !!!',
},
}), }),
mutate({ reportAgainstDagobert.relateTo(dagobert, 'belongsTo'),
mutation: reportMutation, reportAgainstTrollingPost.relateTo(jennyRostock, 'filed', {
variables: { resourceId: 'p2',
resourceId: 'c5', reasonCategory: 'doxing',
reasonCategory: 'doxing', reasonDescription: "This shouldn't be shown to anybody else! It's my private thing!",
reasonDescription: "This shouldn't be shown to anybody else! It's my privat thing!",
},
}), }),
mutate({ reportAgainstTrollingPost.relateTo(p2, 'belongsTo'),
mutation: reportMutation, reportAgainstTrollingComment.relateTo(huey, 'filed', {
variables: { resourceId: 'c1',
resourceId: 'c1', reasonCategory: 'other',
reasonCategory: 'other', reasonDescription: 'This comment is bigoted',
reasonDescription: 'This comment is bigoted',
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'p1',
reasonCategory: 'discrimination_etc',
reasonDescription: 'This post is bigoted',
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'p2',
reasonCategory: 'doxing',
reasonDescription: 'OMG my data !!!',
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'u1',
reasonCategory: 'doxing',
reasonDescription: 'This user is harassing me with bigoted remarks',
},
}), }),
reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'),
])
// report resource a second time
await Promise.all([
reportAgainstDagobert.relateTo(louie, 'filed', {
resourceId: 'u7',
reasonCategory: 'discrimination_etc',
reasonDescription: 'this user is attacking me for who I am!',
}),
reportAgainstDagobert.relateTo(dagobert, 'belongsTo'),
reportAgainstTrollingPost.relateTo(peterLustig, 'filed', {
resourceId: 'p2',
reasonCategory: 'discrimination_etc',
reasonDescription: 'This post is bigoted',
}),
reportAgainstTrollingPost.relateTo(p2, 'belongsTo'),
reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'filed', {
resourceId: 'c1',
reasonCategory: 'pornographic_content_links',
reasonDescription: 'This comment is porno!!!',
}),
reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'),
]) ])
// report resource a second time
authenticatedUser = await dewey.toJson()
await Promise.all([
mutate({
mutation: reportMutation,
variables: {
resourceId: 'c5',
reasonCategory: 'doxing',
reasonDescription: "That's my friends privat data!",
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'c1',
reasonCategory: 'pornographic_content_links',
reasonDescription: 'This comment is porno!!!',
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'p1',
reasonCategory: 'intentional_intimidation_stalking_persecution',
reasonDescription: '',
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'p2',
reasonCategory: 'intentional_intimidation_stalking_persecution',
reasonDescription: '',
},
}),
mutate({
mutation: reportMutation,
variables: {
resourceId: 'u1',
reasonCategory: 'glorific_trivia_of_cruel_inhuman_acts',
reasonDescription: 'murder',
},
}),
])
authenticatedUser = null
// only review resource after report !!!
const reviewMutation = gql`
mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) {
review(resourceId: $resourceId, disable: $disable, closed: $closed) {
disable
}
}
`
const disableVariables = { const disableVariables = {
resourceId: 'undefined-resource', resourceId: 'undefined-resource',
disable: true, disable: true,
closed: false, closed: false,
} }
// review resource first time // review resource first time
authenticatedUser = await bobDerBaumeister.toJson()
await Promise.all([ await Promise.all([
mutate({ reportAgainstDagobert.relateTo(bobDerBaumeister, 'reviewed', {
mutation: reviewMutation, ...disableVariables,
variables: { resourceId: 'u7',
...disableVariables,
resourceId: 'p2',
},
}), }),
mutate({ dagobert.update({ disabled: true, updatedAt: new Date().toISOString() }),
mutation: reviewMutation, reportAgainstTrollingPost.relateTo(peterLustig, 'reviewed', {
variables: { ...disableVariables,
...disableVariables, resourceId: 'p2',
resourceId: 'p11',
},
}), }),
mutate({ p2.update({ disabled: true, updatedAt: new Date().toISOString() }),
mutation: reviewMutation, reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'reviewed', {
variables: { ...disableVariables,
...disableVariables, resourceId: 'c1',
resourceId: 'c5',
closed: true,
},
}), }),
trollingComment.update({ disabled: true, updatedAt: new Date().toISOString() }),
]) ])
// second review of resource and close claim
authenticatedUser = await peterLustig.toJson()
await Promise.all([
mutate({
mutation: reviewMutation,
variables: {
...disableVariables,
resourceId: 'p2',
disable: false,
closed: true,
},
}),
])
authenticatedUser = null
// report resource after closing of the claim // second review of resource and close report
authenticatedUser = await bobDerBaumeister.toJson()
await Promise.all([ await Promise.all([
mutate({ reportAgainstDagobert.relateTo(peterLustig, 'reviewed', {
mutation: reportMutation, resourceId: 'u7',
variables: { disable: false,
resourceId: 'p2', closed: true,
reasonCategory: 'doxing',
reasonDescription: "That's my friends privat data!",
},
}), }),
]) dagobert.update({ disabled: false, updatedAt: new Date().toISOString(), closed: true }),
// report resource second time after closing of the claim reportAgainstTrollingPost.relateTo(bobDerBaumeister, 'reviewed', {
authenticatedUser = await jennyRostock.toJson() resourceId: 'p2',
await Promise.all([ disable: true,
mutate({ closed: true,
mutation: reportMutation,
variables: {
resourceId: 'p2',
reasonCategory: 'doxing',
reasonDescription: 'I think it is my friends data!',
},
}), }),
p2.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }),
reportAgainstTrollingComment.relateTo(peterLustig, 'reviewed', {
...disableVariables,
resourceId: 'c1',
disable: true,
closed: true,
}),
trollingComment.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }),
]) ])
authenticatedUser = null
// third review of resource and close claim // There is no error logged or the 'try' fails if this mutation is wrong. Why?
authenticatedUser = await bobDerBaumeister.toJson() // const reportMutation = gql`
await Promise.all([ // mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
mutate({ // report(
mutation: reviewMutation, // resourceId: $resourceId
variables: { // reasonCategory: $reasonCategory
...disableVariables, // reasonDescription: $reasonDescription
resourceId: 'p2', // ) {
disable: true, // type
closed: true, // }
}, // }
}), // `
]) // authenticatedUser = await huey.toJson()
authenticatedUser = null // await Promise.all([
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p11',
// reasonCategory: 'discrimination_etc',
// reasonDescription: 'I am what I am !!!',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'c5',
// reasonCategory: 'doxing',
// reasonDescription: "This shouldn't be shown to anybody else! It's my privat thing!",
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'c1',
// reasonCategory: 'other',
// reasonDescription: 'This comment is bigoted',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p1',
// reasonCategory: 'discrimination_etc',
// reasonDescription: 'This post is bigoted',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p2',
// reasonCategory: 'doxing',
// reasonDescription: 'OMG my data !!!',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'u1',
// reasonCategory: 'doxing',
// reasonDescription: 'This user is harassing me with bigoted remarks',
// },
// }),
// ])
// authenticatedUser = await dewey.toJson()
// await Promise.all([
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'c5',
// reasonCategory: 'doxing',
// reasonDescription: "That's my friends privat data!",
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'c1',
// reasonCategory: 'pornographic_content_links',
// reasonDescription: 'This comment is porno!!!',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p1',
// reasonCategory: 'intentional_intimidation_stalking_persecution',
// reasonDescription: '',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p2',
// reasonCategory: 'intentional_intimidation_stalking_persecution',
// reasonDescription: '',
// },
// }),
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'u1',
// reasonCategory: 'glorific_trivia_of_cruel_inhuman_acts',
// reasonDescription: 'murder',
// },
// }),
// ])
// authenticatedUser = null
// report resource after second closing of the claim // only review resource after report !!!
authenticatedUser = await huey.toJson() // const reviewMutation = gql`
await Promise.all([ // mutation($resourceId: ID!, $disable: Boolean, $closed: Boolean) {
mutate({ // review(resourceId: $resourceId, disable: $disable, closed: $closed) {
mutation: reportMutation, // disable
variables: { // }
resourceId: 'p2', // }
reasonCategory: 'doxing', // `
reasonDescription: "That's my privat data!", // const disableVariables = {
}, // resourceId: 'undefined-resource',
}), // disable: true,
]) // closed: false,
// report resource second time after second closing of the claim // }
authenticatedUser = await jennyRostock.toJson() // authenticatedUser = await bobDerBaumeister.toJson()
await Promise.all([ // await Promise.all([
mutate({ // mutate({
mutation: reportMutation, // mutation: reviewMutation,
variables: { // variables: {
resourceId: 'p2', // ...disableVariables,
reasonCategory: 'doxing', // resourceId: 'p2',
reasonDescription: 'I think it is my friends data again!', // },
}, // }),
}), // mutate({
]) // mutation: reviewMutation,
authenticatedUser = null // variables: {
// ...disableVariables,
// resourceId: 'p11',
// },
// }),
// mutate({
// mutation: reviewMutation,
// variables: {
// ...disableVariables,
// resourceId: 'c5',
// closed: true,
// },
// }),
// ])
// authenticatedUser = await peterLustig.toJson()
// await Promise.all([
// mutate({
// mutation: reviewMutation,
// variables: {
// ...disableVariables,
// resourceId: 'p2',
// disable: false,
// closed: true,
// },
// }),
// ])
// authenticatedUser = null
// report resource after closing of the report
// authenticatedUser = await bobDerBaumeister.toJson()
// await Promise.all([
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p2',
// reasonCategory: 'doxing',
// reasonDescription: "That's my friends privat data!",
// },
// }),
// ])
// // report resource second time after closing of the report
// authenticatedUser = await jennyRostock.toJson()
// await Promise.all([
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p2',
// reasonCategory: 'doxing',
// reasonDescription: 'I think it is my friends data!',
// },
// }),
// ])
// authenticatedUser = null
// // third review of resource and close report
// authenticatedUser = await bobDerBaumeister.toJson()
// await Promise.all([
// mutate({
// mutation: reviewMutation,
// variables: {
// ...disableVariables,
// resourceId: 'p2',
// disable: true,
// closed: true,
// },
// }),
// ])
// authenticatedUser = null
// // report resource after second closing of the report
// authenticatedUser = await huey.toJson()
// await Promise.all([
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p2',
// reasonCategory: 'doxing',
// reasonDescription: "That's my privat data!",
// },
// }),
// ])
// // report resource second time after second closing of the report
// authenticatedUser = await jennyRostock.toJson()
// await Promise.all([
// mutate({
// mutation: reportMutation,
// variables: {
// resourceId: 'p2',
// reasonCategory: 'doxing',
// reasonDescription: 'I think it is my friends data again!',
// },
// }),
// ])
// authenticatedUser = null
await Promise.all( await Promise.all(
[...Array(30).keys()].map(i => { [...Array(30).keys()].map(i => {

View File

@ -129,7 +129,7 @@ Given('somebody reported the following posts:', table => {
.create('User', submitter) .create('User', submitter)
.authenticateAs(submitter) .authenticateAs(submitter)
.mutate(`mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { .mutate(`mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
report(resourceId: $resourceId, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription) { fileReport(resourceId: $resourceId, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription) {
type type
} }
}`, { }`, {

View File

@ -16,23 +16,23 @@ do
done done
echo " echo "
// convert old DISABLED to new REVIEWED-Claim-BELONGS_TO structure // convert old DISABLED to new REVIEWED-Report-BELONGS_TO structure
MATCH (moderator:User)-[disabled:DISABLED]->(disabledResource) MATCH (moderator:User)-[disabled:DISABLED]->(disabledResource)
WHERE disabledResource:User OR disabledResource:Comment OR disabledResource:Post WHERE disabledResource:User OR disabledResource:Comment OR disabledResource:Post
DELETE disabled DELETE disabled
CREATE (moderator)-[review:REVIEWED]->(claim:Claim)-[:BELONGS_TO]->(disabledResource) CREATE (moderator)-[review:REVIEWED]->(report:Report)-[:BELONGS_TO]->(disabledResource)
SET review.createdAt = toString(datetime()), review.updatedAt = review.createdAt, review.disable = true SET review.createdAt = toString(datetime()), review.updatedAt = review.createdAt, review.disable = true
SET claim.id = randomUUID(), claim.createdAt = toString(datetime()), claim.updatedAt = claim.createdAt, claim.rule = 'latestReviewUpdatedAtRules', claim.disable = true, claim.closed = false SET report.id = randomUUID(), report.createdAt = toString(datetime()), report.updatedAt = report.createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = true, report.closed = false
// if disabledResource has no report, then create a moderators default report // if disabledResource has no report, then create a moderators default report
WITH moderator, disabledResource, claim WITH moderator, disabledResource, report
OPTIONAL MATCH (disabledResourceReporter:User)-[existingReport:REPORTED]->(disabledResource) OPTIONAL MATCH (disabledResourceReporter:User)-[existingReport:FILED]->(disabledResource)
FOREACH(disabledResource IN CASE WHEN existingReport IS NULL THEN [1] ELSE [] END | FOREACH(disabledResource IN CASE WHEN existingReport IS NULL THEN [1] ELSE [] END |
CREATE (moderator)-[addModeratorReport:REPORTED]->(claim) CREATE (moderator)-[addModeratorReport:FILED]->(report)
SET addModeratorReport.createdAt = toString(datetime()), addModeratorReport.reasonCategory = 'other', addModeratorReport.reasonDescription = 'Old DISABLED relation had no now mandatory report !!! Created automatically to ensure database consistency! Creation date is when the database manipulation happened.' SET addModeratorReport.createdAt = toString(datetime()), addModeratorReport.reasonCategory = 'other', addModeratorReport.reasonDescription = 'Old DISABLED relation had no now mandatory report !!! Created automatically to ensure database consistency! Creation date is when the database manipulation happened.'
) )
FOREACH(disabledResource IN CASE WHEN existingReport IS NOT NULL THEN [1] ELSE [] END | FOREACH(disabledResource IN CASE WHEN existingReport IS NOT NULL THEN [1] ELSE [] END |
CREATE (disabledResourceReporter)-[moveModeratorReport:REPORTED]->(claim) CREATE (disabledResourceReporter)-[moveModeratorReport:FILED]->(report)
SET moveModeratorReport = existingReport SET moveModeratorReport = existingReport
DELETE existingReport DELETE existingReport
) )
@ -41,12 +41,12 @@ RETURN disabledResource {.id};
" | cypher-shell " | cypher-shell
echo " echo "
// for REPORTED resources without DISABLED relation which are handled above, create new REPORTED-Claim-BELONGS_TO structure // for FILED resources without DISABLED relation which are handled above, create new FILED-Report-BELONGS_TO structure
MATCH (reporter:User)-[oldReport:REPORTED]->(notDisabledResource) MATCH (reporter:User)-[oldReport:FILED]->(notDisabledResource)
WHERE notDisabledResource:User OR notDisabledResource:Comment OR notDisabledResource:Post WHERE notDisabledResource:User OR notDisabledResource:Comment OR notDisabledResource:Post
MERGE (claim:Claim)-[:BELONGS_TO]->(notDisabledResource) MERGE (report:Report)-[:BELONGS_TO]->(notDisabledResource)
ON CREATE SET claim.id = randomUUID(), claim.createdAt = toString(datetime()), claim.updatedAt = claim.createdAt, claim.rule = 'latestReviewUpdatedAtRules', claim.disable = false, claim.closed = false ON CREATE SET report.id = randomUUID(), report.createdAt = toString(datetime()), report.updatedAt = report.createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = false, report.closed = false
CREATE (reporter)-[report:REPORTED]->(claim) CREATE (reporter)-[report:FILED]->(report)
SET report = oldReport SET report = oldReport
DELETE oldReport DELETE oldReport

View File

@ -16,9 +16,9 @@ do
done done
echo " echo "
MATCH (submitter:User)-[:REPORTED]->(report:Report)-[:REPORTED]->(resource) MATCH (submitter:User)-[:FILED]->(report:Report)-[:FILED]->(resource)
DETACH DELETE report DETACH DELETE report
CREATE (submitter)-[reported:REPORTED]->(resource) CREATE (submitter)-[reported:FILED]->(resource)
SET reported.createdAt = toString(datetime()) SET reported.createdAt = toString(datetime())
SET reported.reasonCategory = 'other' SET reported.reasonCategory = 'other'
SET reported.reasonDescription = '!!! Created automatically to ensure database consistency! Creation date is when the database manipulation happened.' SET reported.reasonDescription = '!!! Created automatically to ensure database consistency! Creation date is when the database manipulation happened.'

View File

@ -1,4 +1,4 @@
// this list equals to enums in GraphQL schema file "backend/src/schema/types/type/REPORTED.gql" // this list equals to enums in GraphQL schema file "backend/src/schema/types/type/FILED.gql"
export const valuesReasonCategoryOptions = [ export const valuesReasonCategoryOptions = [
'discrimination_etc', 'discrimination_etc',
'pornographic_content_links', 'pornographic_content_links',

View File

@ -8,7 +8,7 @@ export const reportListQuery = () => {
createdAt createdAt
reasonCategory reasonCategory
reasonDescription reasonDescription
claim { report {
id id
createdAt createdAt
updatedAt updatedAt
@ -114,7 +114,7 @@ export const reportListQuery = () => {
export const reportMutation = () => { export const reportMutation = () => {
return gql` return gql`
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
report( fileReport(
resourceId: $resourceId resourceId: $resourceId
reasonCategory: $reasonCategory reasonCategory: $reasonCategory
reasonDescription: $reasonDescription reasonDescription: $reasonDescription

View File

@ -238,84 +238,84 @@ export default {
} }
}, },
}, },
watch: { // watch: {
reports: { // reports: {
immediate: true, // immediate: true,
handler(newReports) { // handler(newReports) {
const newResourcesClaims = [] // const newResourcesClaims = []
// if (!newReports) return null
// newReports.forEach(report => {
// const resource =
// report.type === 'User'
// ? report.user
// : report.type === 'Post'
// ? report.post
// : report.type === 'Comment'
// ? report.comment
// : undefined
// let idxResource = newResourcesClaims.findIndex(
// resourceClaims => resourceClaims.resource.id === resource.id,
// )
// // if resource is not in resource list, then add it
// if (idxResource === -1) {
// idxResource = newResourcesClaims.length
// newResourcesClaims.push({
// type: report.type,
// resource,
// user: report.user,
// post: report.post,
// comment: report.comment,
// contentBelongsToUser: report.type === 'User' ? null : resource.author,
// claims: [],
// })
// }
// let idxClaim = newResourcesClaims[idxResource].claims.findIndex(
// claim => claim.id === report.claim.id,
// )
// // if claim is not in claim list, then add it
// if (idxClaim === -1) {
// idxClaim = newResourcesClaims[idxResource].claims.length
// newResourcesClaims[idxResource].claims.push({
// // it is the same for all reports of a claim
// id: report.claim.id,
// createdAt: report.claim.createdAt,
// updatedAt: report.claim.updatedAt,
// disable: report.claim.disable,
// closed: report.claim.closed,
// reports: [],
// })
// }
// newResourcesClaims[idxResource].claims[idxClaim].reports.push(report)
// })
newReports.forEach(report => { // // sorting of resource claims and their reports
const resource = // newResourcesClaims.forEach(resourceClaims => {
report.type === 'User' // // latestClaim by updatedAt rules
? report.user // resourceClaims.claims.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt))
: report.type === 'Post' // resourceClaims.latestClaim = {
? report.post // id: resourceClaims.claims[0].id,
: report.type === 'Comment' // createdAt: resourceClaims.claims[0].createdAt,
? report.comment // updatedAt: resourceClaims.claims[0].updatedAt,
: undefined // disable: resourceClaims.claims[0].disable,
let idxResource = newResourcesClaims.findIndex( // closed: resourceClaims.claims[0].closed,
resourceClaims => resourceClaims.resource.id === resource.id, // }
) // // display claims always by starting with latest createdAt
// if resource is not in resource list, then add it // resourceClaims.claims.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
if (idxResource === -1) {
idxResource = newResourcesClaims.length
newResourcesClaims.push({
type: report.type,
resource,
user: report.user,
post: report.post,
comment: report.comment,
contentBelongsToUser: report.type === 'User' ? null : resource.author,
claims: [],
})
}
let idxClaim = newResourcesClaims[idxResource].claims.findIndex(
claim => claim.id === report.claimId,
)
// if claim is not in claim list, then add it
if (idxClaim === -1) {
idxClaim = newResourcesClaims[idxResource].claims.length
newResourcesClaims[idxResource].claims.push({
// it is the same for all reports of a claim
id: report.claimId,
createdAt: report.claimCreatedAt,
updatedAt: report.claimUpdatedAt,
disable: report.claimDisable,
closed: report.claimClosed,
reports: [],
})
}
newResourcesClaims[idxResource].claims[idxClaim].reports.push(report)
})
// sorting of resource claims and their reports // resourceClaims.claims.forEach(claim => {
newResourcesClaims.forEach(resourceClaims => { // // display reports always by starting with latest createdAt
// latestClaim by updatedAt rules // claim.reports.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
resourceClaims.claims.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt)) // })
resourceClaims.latestClaim = { // })
id: resourceClaims.claims[0].id, // // display resources by starting with claims by their latest createdAt
createdAt: resourceClaims.claims[0].createdAt, // newResourcesClaims.sort(
updatedAt: resourceClaims.claims[0].updatedAt, // (a, b) => new Date(b.claims[0].createdAt) - new Date(a.claims[0].createdAt),
disable: resourceClaims.claims[0].disable, // )
closed: resourceClaims.claims[0].closed,
}
// display claims always by starting with latest createdAt
resourceClaims.claims.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
resourceClaims.claims.forEach(claim => { // this.resourcesClaims = newResourcesClaims
// display reports always by starting with latest createdAt // },
claim.reports.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)) // },
}) // },
})
// display resources by starting with claims by their latest createdAt
newResourcesClaims.sort(
(a, b) => new Date(b.claims[0].createdAt) - new Date(a.claims[0].createdAt),
)
this.resourcesClaims = newResourcesClaims
},
},
},
methods: { methods: {
confirm(resourceClaims) { confirm(resourceClaims) {
this.openModal(resourceClaims) this.openModal(resourceClaims)
@ -386,7 +386,8 @@ export default {
return {} return {}
}, },
update({ reports }) { update({ reports }) {
return reports console.log(reports)
// this.resourcesClaims = reports
}, },
fetchPolicy: 'cache-and-network', fetchPolicy: 'cache-and-network',
}, },