Refactor GQL schema, resolvers and moderators report list

- Co-Authored-By: mattwr18 <mattwr18@gmail.com>
This commit is contained in:
Wolfgang Huß 2020-02-20 10:35:37 +01:00
parent a84d78e3ee
commit 4bd7f61fcc
6 changed files with 78 additions and 162 deletions

View File

@ -152,15 +152,7 @@ export default shield(
User: { User: {
email: or(isMyOwn, isAdmin), email: or(isMyOwn, isAdmin),
}, },
Report: { Report: isModerator,
createdAt: or(isModerator),
updatedAt: or(isModerator),
rule: or(isModerator),
disable: or(isModerator),
closed: or(isModerator),
filed: or(isModerator),
reviewed: or(isModerator),
},
}, },
{ {
debug, debug,

View File

@ -57,7 +57,6 @@ export default {
orderByClause = '' orderByClause = ''
} }
// Wolle This should be only for open reports or?
switch (params.reviewed) { switch (params.reviewed) {
case true: case true:
filterClause = 'AND ((report)<-[:REVIEWED]-(:User))' filterClause = 'AND ((report)<-[:REVIEWED]-(:User))'
@ -69,8 +68,6 @@ export default {
filterClause = '' filterClause = ''
} }
// Wolle console.log('params.closed: ', params.closed)
// Wolle if (params.closed) filterClause = 'AND report.closed = true'
switch (params.closed) { switch (params.closed) {
case true: case true:
filterClause = 'AND report.closed = true' filterClause = 'AND report.closed = true'
@ -86,8 +83,9 @@ export default {
params.offset && typeof params.offset === 'number' ? `SKIP ${params.offset}` : '' params.offset && typeof params.offset === 'number' ? `SKIP ${params.offset}` : ''
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${params.first}` : '' const limit = params.first && typeof params.first === 'number' ? `LIMIT ${params.first}` : ''
const reportReadTxPromise = session.readTransaction(async transaction => { const reportsReadTxPromise = session.readTransaction(async transaction => {
const allReportsTransactionResponse = await transaction.run( const reportsTransactionResponse = await transaction.run(
// !!! this Cypher query returns multiple reports on the same resource! i will create an issue for refactoring (bug fixing)
` `
MATCH (report:Report)-[:BELONGS_TO]->(resource) MATCH (report:Report)-[:BELONGS_TO]->(resource)
WHERE (resource:User OR resource:Post OR resource:Comment) WHERE (resource:User OR resource:Post OR resource:Comment)
@ -105,11 +103,11 @@ export default {
${offset} ${limit} ${offset} ${limit}
`, `,
) )
log(allReportsTransactionResponse) log(reportsTransactionResponse)
return allReportsTransactionResponse.records.map(record => record.get('report')) return reportsTransactionResponse.records.map(record => record.get('report'))
}) })
try { try {
const reports = await reportReadTxPromise const reports = await reportsReadTxPromise
return reports return reports
} finally { } finally {
session.close() session.close()

View File

@ -10,41 +10,6 @@ const driver = getDriver()
describe('file a report on a resource', () => { 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']
// Wolle const reportMutation = gql`
// mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
// fileReport(
// resourceId: $resourceId
// reasonCategory: $reasonCategory
// reasonDescription: $reasonDescription
// ) {
// id
// createdAt
// updatedAt
// closed
// rule
// resource {
// __typename
// ... on User {
// name
// }
// ... on Post {
// title
// }
// ... on Comment {
// content
// }
// }
// filed {
// submitter {
// id
// }
// createdAt
// reasonCategory
// reasonDescription
// }
// }
// }
// `
const fileReportMutation = gql` const fileReportMutation = gql`
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
fileReport( fileReport(
@ -61,6 +26,7 @@ describe('file a report on a resource', () => {
... on User { ... on User {
name name
# Wolle filedUnclosedReportByCurrentUser # Wolle filedUnclosedReportByCurrentUser
# Wolle test followedByCurrentUser
} }
... on Post { ... on Post {
title title
@ -90,8 +56,6 @@ describe('file a report on a resource', () => {
__typename __typename
... on User { ... on User {
id id
# Wolle filedUnclosedReportByCurrentUser
# Wolle test followedByCurrentUser
} }
... on Post { ... on Post {
id id
@ -264,31 +228,31 @@ describe('file a report on a resource', () => {
mutation: fileReportMutation, mutation: fileReportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' }, variables: { ...variables, resourceId: 'abusive-user-id' },
}) })
expect(firstReport.data.fileReport.reportId).toEqual( expect(firstReport.data.fileReport.reportId).toEqual(
secondReport.data.fileReport.reportId, secondReport.data.fileReport.reportId,
) )
}) })
describe('report properties are set correctly', () => {
const reportsCypherQuery =
'MATCH (resource:User {id: $resourceId})<-[:BELONGS_TO]-(report:Report {closed: false})<-[filed:FILED]-(user:User {id: $currentUserId}) RETURN report'
it('with the rule for how the report will be decided', async () => { it('with the rule for how the report will be decided', async () => {
await mutate({ await mutate({
mutation: fileReportMutation, mutation: fileReportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' }, variables: { ...variables, resourceId: 'abusive-user-id' },
}) })
authenticatedUser = await moderator.toJson()
await expect( const reportsCypherQueryResponse = await instance.cypher(reportsCypherQuery, {
query({ resourceId: 'abusive-user-id',
query: reportsQuery, currentUserId: authenticatedUser.id,
}),
).resolves.toMatchObject({
data: {
reports: [
{
rule: 'latestReviewUpdatedAtRules',
},
],
},
errors: undefined,
}) })
expect(reportsCypherQueryResponse.records).toHaveLength(1)
const [reportProperties] = reportsCypherQueryResponse.records.map(
record => record.get('report').properties,
)
expect(reportProperties).toMatchObject({ rule: 'latestReviewUpdatedAtRules' })
}) })
describe('with overtaken disabled from resource in disable property', () => { describe('with overtaken disabled from resource in disable property', () => {
@ -297,21 +261,16 @@ describe('file a report on a resource', () => {
mutation: fileReportMutation, mutation: fileReportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' }, variables: { ...variables, resourceId: 'abusive-user-id' },
}) })
authenticatedUser = await moderator.toJson()
await expect( const reportsCypherQueryResponse = await instance.cypher(reportsCypherQuery, {
query({ resourceId: 'abusive-user-id',
query: reportsQuery, currentUserId: authenticatedUser.id,
}),
).resolves.toMatchObject({
data: {
reports: [
{
disable: false,
},
],
},
errors: undefined,
}) })
expect(reportsCypherQueryResponse.records).toHaveLength(1)
const [reportProperties] = reportsCypherQueryResponse.records.map(
record => record.get('report').properties,
)
expect(reportProperties).toMatchObject({ disable: false })
}) })
it('disable is true', async () => { it('disable is true', async () => {
@ -330,26 +289,21 @@ describe('file a report on a resource', () => {
}, },
}) })
authenticatedUser = await currentUser.toJson() authenticatedUser = await currentUser.toJson()
// second time filling a report to see if the "disabled is true" of the resource is overtaken // second time filling a report to see if the "disable is true" of the resource is overtaken
await mutate({ await mutate({
mutation: fileReportMutation, mutation: fileReportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' }, variables: { ...variables, resourceId: 'abusive-user-id' },
}) })
authenticatedUser = await moderator.toJson()
await expect( const reportsCypherQueryResponse = await instance.cypher(reportsCypherQuery, {
query({ resourceId: 'abusive-user-id',
query: reportsQuery, currentUserId: authenticatedUser.id,
variables: { closed: false }, })
}), expect(reportsCypherQueryResponse.records).toHaveLength(1)
).resolves.toMatchObject({ const [reportProperties] = reportsCypherQueryResponse.records.map(
data: { record => record.get('report').properties,
reports: [ )
{ expect(reportProperties).toMatchObject({ disable: true })
disable: true,
},
],
},
errors: undefined,
}) })
}) })
}) })
@ -395,28 +349,6 @@ describe('file a report on a resource', () => {
}) })
}) })
it.skip('returns the submitter', async () => {
await expect(
mutate({
mutation: fileReportMutation,
variables: { ...variables, resourceId: 'abusive-user-id' },
}),
).resolves.toMatchObject({
data: {
fileReport: {
filed: [
{
submitter: {
id: 'current-user-id',
},
},
],
},
},
errors: undefined,
})
})
it('returns a createdAt', async () => { it('returns a createdAt', async () => {
await expect( await expect(
mutate({ mutate({

View File

@ -5,9 +5,9 @@ type Report {
rule: ReportRule! rule: ReportRule!
disable: Boolean! disable: Boolean!
closed: Boolean! closed: Boolean!
filed: [FILED] filed: [FILED]!
reviewed: [REVIEWED]! reviewed: [REVIEWED]!
resource: ReportedResource resource: ReportedResource!
} }
union ReportedResource = User | Post | Comment union ReportedResource = User | Post | Comment

View File

@ -43,14 +43,13 @@ export default {
computed: { computed: {
filterOptions() { filterOptions() {
return [ return [
{ label: this.$t('moderation.reports.filterLabel.all'), value: { reviewed: null } }, { label: this.$t('moderation.reports.filterLabel.all'), value: { reviewed: null, closed: null } },
{ // Wolle This should be only for open reports or? {
label: this.$t('moderation.reports.filterLabel.unreviewed'), label: this.$t('moderation.reports.filterLabel.unreviewed'),
value: { reviewed: false }, value: { reviewed: false, closed: false },
}, },
// Wolle This should be only for open reports or? { label: this.$t('moderation.reports.filterLabel.reviewed'), value: { reviewed: true, closed: false } },
{ label: this.$t('moderation.reports.filterLabel.reviewed'), value: { reviewed: true } }, { label: this.$t('moderation.reports.filterLabel.closed'), value: { reviewed: null, closed: true } },
{ label: this.$t('moderation.reports.filterLabel.closed'), value: { closed: true } },
] ]
}, },
modalData() { modalData() {
@ -108,13 +107,8 @@ export default {
filter(option) { filter(option) {
this.selected = option.label this.selected = option.label
this.offset = 0 this.offset = 0
if (option.value.closed) {
this.closed = option.value.closed
this.reviewed = null
return
}
this.closed = null
this.reviewed = option.value.reviewed this.reviewed = option.value.reviewed
this.closed = option.value.closed
}, },
async confirmCallback(resource) { async confirmCallback(resource) {
const { disabled: disable, id: resourceId } = resource const { disabled: disable, id: resourceId } = resource

View File

@ -100,7 +100,7 @@ export const reportMutation = () => {
reasonCategory: $reasonCategory reasonCategory: $reasonCategory
reasonDescription: $reasonDescription reasonDescription: $reasonDescription
) { ) {
id reportId
} }
} }
` `