mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Update to use enum in tests, seed data, etc, refactor resolver
- Extract validations to the validations middleware to clean it up - Remove resourceId since it throws an error in the mutation if the user asks for it back, and the resourceId is returned in post/comment/user.id - use writeTxResultPromise to benefit from automatic retries - more descriptive variable naming - extract cypher query to make db manipulation into script so that it can be run from the command line, at least locally.
This commit is contained in:
parent
cae897808b
commit
faf0a15aee
@ -57,11 +57,40 @@ const validateUpdatePost = async (resolve, root, args, context, info) => {
|
||||
return validatePost(resolve, root, args, context, info)
|
||||
}
|
||||
|
||||
const validateReport = async (resolve, root, args, context, info) => {
|
||||
const { resourceId } = args
|
||||
const { user, driver } = context
|
||||
if (resourceId === user.id) throw new Error('You cannot report yourself!')
|
||||
const session = driver.session()
|
||||
const reportQueryRes = await session.run(
|
||||
`
|
||||
MATCH (:User {id:$submitterId})-[:REPORTED]->(resource {id:$resourceId})
|
||||
RETURN labels(resource)[0] as label
|
||||
`,
|
||||
{
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
},
|
||||
)
|
||||
const [existingReportedResource] = reportQueryRes.records.map(record => {
|
||||
return {
|
||||
label: record.get('label'),
|
||||
}
|
||||
})
|
||||
|
||||
if (existingReportedResource)
|
||||
throw new Error(
|
||||
`You have already reported the ${existingReportedResource.label}, please only report the same ${existingReportedResource.label} once`,
|
||||
)
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
export default {
|
||||
Mutation: {
|
||||
CreateComment: validateCommentCreation,
|
||||
UpdateComment: validateUpdateComment,
|
||||
CreatePost: validatePost,
|
||||
UpdatePost: validateUpdatePost,
|
||||
report: validateReport,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,87 +1,60 @@
|
||||
export default {
|
||||
Mutation: {
|
||||
report: async (_parent, params, { driver, user }, _resolveInfo) => {
|
||||
let createdRelationshipWithNestedAttributes
|
||||
const { resourceId, reasonCategory, reasonDescription } = params
|
||||
|
||||
const session = driver.session()
|
||||
const reportProperties = {
|
||||
createdAt: new Date().toISOString(),
|
||||
reasonCategory,
|
||||
reasonDescription,
|
||||
}
|
||||
|
||||
const reportQueryRes = await session.run(
|
||||
`
|
||||
MATCH (:User {id:$submitterId})-[:REPORTED]->(resource {id:$resourceId})
|
||||
RETURN labels(resource)[0] as label
|
||||
`,
|
||||
{
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
},
|
||||
)
|
||||
const [rep] = reportQueryRes.records.map(record => {
|
||||
return {
|
||||
label: record.get('label'),
|
||||
}
|
||||
const writeTxResultPromise = session.writeTransaction(async txc => {
|
||||
const reportRelationshipTransactionResponse = await txc.run(
|
||||
`
|
||||
MATCH (submitter:User {id: $submitterId})
|
||||
MATCH (resource {id: $resourceId})
|
||||
WHERE resource:User OR resource:Comment OR resource:Post
|
||||
CREATE (resource)<-[report:REPORTED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter)
|
||||
RETURN report, submitter, resource, labels(resource)[0] as type
|
||||
`,
|
||||
{
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
createdAt: new Date().toISOString(),
|
||||
reasonCategory,
|
||||
reasonDescription,
|
||||
},
|
||||
)
|
||||
return reportRelationshipTransactionResponse.records.map(record => ({
|
||||
report: record.get('report'),
|
||||
submitter: record.get('submitter'),
|
||||
resource: record.get('resource').properties,
|
||||
type: record.get('type'),
|
||||
}))
|
||||
})
|
||||
|
||||
if (rep) {
|
||||
throw new Error(rep.label)
|
||||
}
|
||||
|
||||
const res = await session.run(
|
||||
`
|
||||
MATCH (submitter:User {id: $submitterId})
|
||||
MATCH (resource {id: $resourceId})
|
||||
WHERE resource:User OR resource:Comment OR resource:Post
|
||||
CREATE (resource)<-[report:REPORTED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter)
|
||||
RETURN report, submitter, resource, labels(resource)[0] as type
|
||||
`,
|
||||
{
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
createdAt: reportProperties.createdAt,
|
||||
reasonCategory: reportProperties.reasonCategory,
|
||||
reasonDescription: reportProperties.reasonDescription,
|
||||
},
|
||||
)
|
||||
|
||||
session.close()
|
||||
|
||||
const [dbResponse] = res.records.map(r => {
|
||||
return {
|
||||
report: r.get('report'),
|
||||
submitter: r.get('submitter'),
|
||||
resource: r.get('resource'),
|
||||
type: r.get('type'),
|
||||
try {
|
||||
const txResult = await writeTxResultPromise
|
||||
if (!txResult[0]) return null
|
||||
const { report, submitter, resource, type } = txResult[0]
|
||||
createdRelationshipWithNestedAttributes = {
|
||||
...report.properties,
|
||||
post: null,
|
||||
comment: null,
|
||||
user: null,
|
||||
submitter: submitter.properties,
|
||||
type,
|
||||
}
|
||||
})
|
||||
if (!dbResponse) return null
|
||||
|
||||
const { report, submitter, resource, type } = dbResponse
|
||||
|
||||
const response = {
|
||||
...report.properties,
|
||||
post: null,
|
||||
comment: null,
|
||||
user: null,
|
||||
submitter: submitter.properties,
|
||||
type,
|
||||
switch (type) {
|
||||
case 'Post':
|
||||
createdRelationshipWithNestedAttributes.post = resource
|
||||
break
|
||||
case 'Comment':
|
||||
createdRelationshipWithNestedAttributes.comment = resource
|
||||
break
|
||||
case 'User':
|
||||
createdRelationshipWithNestedAttributes.user = resource
|
||||
break
|
||||
}
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
switch (type) {
|
||||
case 'Post':
|
||||
response.post = resource.properties
|
||||
break
|
||||
case 'Comment':
|
||||
response.comment = resource.properties
|
||||
break
|
||||
case 'User':
|
||||
response.user = resource.properties
|
||||
break
|
||||
}
|
||||
|
||||
return response
|
||||
return createdRelationshipWithNestedAttributes
|
||||
},
|
||||
},
|
||||
Query: {
|
||||
@ -113,13 +86,13 @@ export default {
|
||||
|
||||
const responseEle = {
|
||||
...report.properties,
|
||||
resourceId: resource.properties.id,
|
||||
post: null,
|
||||
comment: null,
|
||||
user: null,
|
||||
submitter: submitter.properties,
|
||||
type,
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'Post':
|
||||
responseEle.post = resource.properties
|
||||
|
||||
@ -20,7 +20,7 @@ describe('report mutation', () => {
|
||||
|
||||
const action = () => {
|
||||
reportMutation = gql`
|
||||
mutation($resourceId: ID!, $reasonCategory: String!, $reasonDescription: String!) {
|
||||
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||
report(
|
||||
resourceId: $resourceId
|
||||
reasonCategory: $reasonCategory
|
||||
@ -166,7 +166,7 @@ describe('report mutation', () => {
|
||||
reasonCategory: 'my_category',
|
||||
}
|
||||
await expect(action()).rejects.toThrow(
|
||||
'Expected a value of type "ReasonCategory" but received: "my_category"',
|
||||
'got invalid value "my_category"; Expected type ReasonCategory',
|
||||
)
|
||||
})
|
||||
|
||||
@ -307,16 +307,11 @@ describe('report mutation', () => {
|
||||
})
|
||||
|
||||
describe('reports query', () => {
|
||||
let query
|
||||
let mutate
|
||||
let authenticatedUser = null
|
||||
let moderator
|
||||
let user
|
||||
let author
|
||||
let query, mutate, authenticatedUser, moderator, user, author
|
||||
const categoryIds = ['cat9']
|
||||
|
||||
const reportMutation = gql`
|
||||
mutation($resourceId: ID!, $reasonCategory: String!, $reasonDescription: String!) {
|
||||
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||
report(
|
||||
resourceId: $resourceId
|
||||
reasonCategory: $reasonCategory
|
||||
@ -335,7 +330,6 @@ describe('reports query', () => {
|
||||
submitter {
|
||||
id
|
||||
}
|
||||
resourceId
|
||||
type
|
||||
user {
|
||||
id
|
||||
@ -350,7 +344,8 @@ describe('reports query', () => {
|
||||
}
|
||||
`
|
||||
|
||||
beforeAll(() => {
|
||||
beforeAll(async () => {
|
||||
await factory.cleanDatabase()
|
||||
const { server } = createServer({
|
||||
context: () => {
|
||||
return {
|
||||
@ -480,7 +475,6 @@ describe('reports query', () => {
|
||||
submitter: expect.objectContaining({
|
||||
id: 'user1',
|
||||
}),
|
||||
resourceId: 'auth1',
|
||||
type: 'User',
|
||||
user: expect.objectContaining({
|
||||
id: 'auth1',
|
||||
@ -495,7 +489,6 @@ describe('reports query', () => {
|
||||
submitter: expect.objectContaining({
|
||||
id: 'user1',
|
||||
}),
|
||||
resourceId: 'p1',
|
||||
type: 'Post',
|
||||
user: null,
|
||||
post: expect.objectContaining({
|
||||
@ -510,7 +503,6 @@ describe('reports query', () => {
|
||||
submitter: expect.objectContaining({
|
||||
id: 'user1',
|
||||
}),
|
||||
resourceId: 'c1',
|
||||
type: 'Comment',
|
||||
user: null,
|
||||
post: null,
|
||||
|
||||
@ -5,10 +5,8 @@ type REPORTED {
|
||||
submitter: User
|
||||
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN user")
|
||||
# not yet supported
|
||||
# resource: ReportReource
|
||||
# resource: ReportResource
|
||||
# @cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN resource")
|
||||
resourceId: ID
|
||||
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN resource {.id}")
|
||||
type: String
|
||||
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN labels(resource)[0]")
|
||||
user: User
|
||||
@ -29,7 +27,7 @@ enum ReasonCategory {
|
||||
}
|
||||
|
||||
# not yet supported
|
||||
# union ReportReource = User | Post | Comment
|
||||
# union ReportResource = User | Post | Comment
|
||||
|
||||
enum ReportOrdering {
|
||||
createdAt_desc
|
||||
@ -40,5 +38,5 @@ type Query {
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
report(resourceId: ID!, reasonCategory: String!, reasonDescription: String!): REPORTED
|
||||
report(resourceId: ID!, reasonCategory: ReasonCategory!, reasonDescription: String!): REPORTED
|
||||
}
|
||||
|
||||
@ -649,7 +649,7 @@ import { gql } from '../jest/helpers'
|
||||
|
||||
// There is no error logged or the 'try' fails if this mutation is wrong. Why?
|
||||
const reportMutation = gql`
|
||||
mutation($resourceId: ID!, $reasonCategory: String!, $reasonDescription: String!) {
|
||||
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||
report(
|
||||
resourceId: $resourceId
|
||||
reasonCategory: $reasonCategory
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
MATCH (submitter:User)-[:REPORTED]->(report:Report)-[:REPORTED]->(resource)
|
||||
DETACH DELETE report
|
||||
CREATE (submitter)-[reported:REPORTED]->(resource)
|
||||
SET reported.createdAt = toString(datetime())
|
||||
SET reported.reasonCategory = 'other'
|
||||
SET reported.reasonDescription = '!!! Created automatically to ensure database consistency! Date-time is this creation date and time.'
|
||||
RETURN reported
|
||||
26
neo4j/change_report_node_to_relationship.sh
Executable file
26
neo4j/change_report_node_to_relationship.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ENV_FILE=$(dirname "$0")/.env
|
||||
[[ -f "$ENV_FILE" ]] && source "$ENV_FILE"
|
||||
|
||||
if [ -z "$NEO4J_USERNAME" ] || [ -z "$NEO4J_PASSWORD" ]; then
|
||||
echo "Please set NEO4J_USERNAME and NEO4J_PASSWORD environment variables."
|
||||
echo "Database manipulation is not possible without connecting to the database."
|
||||
echo "E.g. you could \`cp .env.template .env\` unless you run the script in a docker container"
|
||||
fi
|
||||
|
||||
until echo 'RETURN "Connection successful" as info;' | cypher-shell
|
||||
do
|
||||
echo "Connecting to neo4j failed, trying again..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "
|
||||
MATCH (submitter:User)-[:REPORTED]->(report:Report)-[:REPORTED]->(resource)
|
||||
DETACH DELETE report
|
||||
CREATE (submitter)-[reported:REPORTED]->(resource)
|
||||
SET reported.createdAt = toString(datetime())
|
||||
SET reported.reasonCategory = 'other'
|
||||
SET reported.reasonDescription = '!!! Created automatically to ensure database consistency! createdAt is when the database manipulation happened.'
|
||||
RETURN reported;
|
||||
" | cypher-shell
|
||||
Loading…
x
Reference in New Issue
Block a user