mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge branch 'master' of https://github.com/Human-Connection/Nitro-Backend
This commit is contained in:
commit
a6f96cad78
@ -6,9 +6,11 @@ import reports from './resolvers/reports.js'
|
|||||||
import posts from './resolvers/posts.js'
|
import posts from './resolvers/posts.js'
|
||||||
import moderation from './resolvers/moderation.js'
|
import moderation from './resolvers/moderation.js'
|
||||||
|
|
||||||
export const typeDefs =
|
export const typeDefs = fs
|
||||||
fs.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
|
.readFileSync(
|
||||||
.toString('utf-8')
|
process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql')
|
||||||
|
)
|
||||||
|
.toString('utf-8')
|
||||||
|
|
||||||
export const resolvers = {
|
export const resolvers = {
|
||||||
Query: {
|
Query: {
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import uniqueSlug from './slugify/uniqueSlug'
|
import uniqueSlug from './slugify/uniqueSlug'
|
||||||
|
|
||||||
const isUniqueFor = (context, type) => {
|
const isUniqueFor = (context, type) => {
|
||||||
return async (slug) => {
|
return async slug => {
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const response = await session.run(
|
const response = await session.run(
|
||||||
`MATCH(p:${type} {slug: $slug }) return p.slug`, {
|
`MATCH(p:${type} {slug: $slug }) return p.slug`,
|
||||||
|
{
|
||||||
slug
|
slug
|
||||||
})
|
}
|
||||||
|
)
|
||||||
session.close()
|
session.close()
|
||||||
return response.records.length === 0
|
return response.records.length === 0
|
||||||
}
|
}
|
||||||
@ -15,19 +17,27 @@ const isUniqueFor = (context, type) => {
|
|||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreatePost: async (resolve, root, args, context, info) => {
|
CreatePost: async (resolve, root, args, context, info) => {
|
||||||
args.slug = args.slug || await uniqueSlug(args.title, isUniqueFor(context, 'Post'))
|
args.slug =
|
||||||
|
args.slug ||
|
||||||
|
(await uniqueSlug(args.title, isUniqueFor(context, 'Post')))
|
||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
},
|
},
|
||||||
CreateUser: async (resolve, root, args, context, info) => {
|
CreateUser: async (resolve, root, args, context, info) => {
|
||||||
args.slug = args.slug || await uniqueSlug(args.name, isUniqueFor(context, 'User'))
|
args.slug =
|
||||||
|
args.slug ||
|
||||||
|
(await uniqueSlug(args.name, isUniqueFor(context, 'User')))
|
||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
},
|
},
|
||||||
CreateOrganization: async (resolve, root, args, context, info) => {
|
CreateOrganization: async (resolve, root, args, context, info) => {
|
||||||
args.slug = args.slug || await uniqueSlug(args.name, isUniqueFor(context, 'Organization'))
|
args.slug =
|
||||||
|
args.slug ||
|
||||||
|
(await uniqueSlug(args.name, isUniqueFor(context, 'Organization')))
|
||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
},
|
},
|
||||||
CreateCategory: async (resolve, root, args, context, info) => {
|
CreateCategory: async (resolve, root, args, context, info) => {
|
||||||
args.slug = args.slug || await uniqueSlug(args.name, isUniqueFor(context, 'Category'))
|
args.slug =
|
||||||
|
args.slug ||
|
||||||
|
(await uniqueSlug(args.name, isUniqueFor(context, 'Category')))
|
||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,10 @@ const factory = Factory()
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await factory.create('User', { email: 'user@example.org', password: '1234' })
|
await factory.create('User', { email: 'user@example.org', password: '1234' })
|
||||||
await factory.create('User', { email: 'someone@example.org', password: '1234' })
|
await factory.create('User', {
|
||||||
|
email: 'someone@example.org',
|
||||||
|
password: '1234'
|
||||||
|
})
|
||||||
headers = await login({ email: 'user@example.org', password: '1234' })
|
headers = await login({ email: 'user@example.org', password: '1234' })
|
||||||
authenticatedClient = new GraphQLClient(host, { headers })
|
authenticatedClient = new GraphQLClient(host, { headers })
|
||||||
})
|
})
|
||||||
@ -26,7 +29,9 @@ describe('slugify', () => {
|
|||||||
content: "Some content"
|
content: "Some content"
|
||||||
) { slug }
|
) { slug }
|
||||||
}`)
|
}`)
|
||||||
expect(response).toEqual({ CreatePost: { slug: 'i-am-a-brand-new-post' } })
|
expect(response).toEqual({
|
||||||
|
CreatePost: { slug: 'i-am-a-brand-new-post' }
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('if slug exists', () => {
|
describe('if slug exists', () => {
|
||||||
@ -48,12 +53,15 @@ describe('slugify', () => {
|
|||||||
content: "Some content"
|
content: "Some content"
|
||||||
) { slug }
|
) { slug }
|
||||||
}`)
|
}`)
|
||||||
expect(response).toEqual({ CreatePost: { slug: 'pre-existing-post-1' } })
|
expect(response).toEqual({
|
||||||
|
CreatePost: { slug: 'pre-existing-post-1' }
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('but if the client specifies a slug', () => {
|
describe('but if the client specifies a slug', () => {
|
||||||
it('rejects CreatePost', async () => {
|
it('rejects CreatePost', async () => {
|
||||||
await expect(authenticatedClient.request(`mutation {
|
await expect(
|
||||||
|
authenticatedClient.request(`mutation {
|
||||||
CreatePost(
|
CreatePost(
|
||||||
title: "Pre-existing post",
|
title: "Pre-existing post",
|
||||||
content: "Some content",
|
content: "Some content",
|
||||||
@ -73,28 +81,33 @@ describe('slugify', () => {
|
|||||||
}`)
|
}`)
|
||||||
}
|
}
|
||||||
it('generates a slug based on name', async () => {
|
it('generates a slug based on name', async () => {
|
||||||
await expect(action('CreateUser', 'name: "I am a user"'))
|
await expect(
|
||||||
.resolves.toEqual({ CreateUser: { slug: 'i-am-a-user' } })
|
action('CreateUser', 'name: "I am a user"')
|
||||||
|
).resolves.toEqual({ CreateUser: { slug: 'i-am-a-user' } })
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('if slug exists', () => {
|
describe('if slug exists', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await action('CreateUser', 'name: "Pre-existing user", slug: "pre-existing-user"')
|
await action(
|
||||||
|
'CreateUser',
|
||||||
|
'name: "Pre-existing user", slug: "pre-existing-user"'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('chooses another slug', async () => {
|
it('chooses another slug', async () => {
|
||||||
await expect(action(
|
await expect(
|
||||||
'CreateUser',
|
action('CreateUser', 'name: "pre-existing-user"')
|
||||||
'name: "pre-existing-user"'
|
).resolves.toEqual({ CreateUser: { slug: 'pre-existing-user-1' } })
|
||||||
)).resolves.toEqual({ CreateUser: { slug: 'pre-existing-user-1' } })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('but if the client specifies a slug', () => {
|
describe('but if the client specifies a slug', () => {
|
||||||
it('rejects CreateUser', async () => {
|
it('rejects CreateUser', async () => {
|
||||||
await expect(action(
|
await expect(
|
||||||
'CreateUser',
|
action(
|
||||||
'name: "Pre-existing user", slug: "pre-existing-user"'
|
'CreateUser',
|
||||||
)).rejects.toThrow('already exists')
|
'name: "Pre-existing user", slug: "pre-existing-user"'
|
||||||
|
)
|
||||||
|
).rejects.toThrow('already exists')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -4,6 +4,18 @@ type Query {
|
|||||||
currentUser: User
|
currentUser: User
|
||||||
"Get the latest Network Statistics"
|
"Get the latest Network Statistics"
|
||||||
statistics: Statistics!
|
statistics: Statistics!
|
||||||
|
findPosts(filter: String!, limit: Int = 10): [Post]! @cypher(
|
||||||
|
statement: """
|
||||||
|
CALL db.index.fulltext.queryNodes('full_text_search', $filter)
|
||||||
|
YIELD node as post, score
|
||||||
|
MATCH (post)<-[:WROTE]-(user:User)
|
||||||
|
WHERE score >= 0.2
|
||||||
|
AND NOT user.deleted = true AND NOT user.disabled = true
|
||||||
|
AND NOT post.deleted = true AND NOT post.disabled = true
|
||||||
|
RETURN post
|
||||||
|
LIMIT $limit
|
||||||
|
"""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
type Mutation {
|
type Mutation {
|
||||||
"Get a JWT Token for the given Email and password"
|
"Get a JWT Token for the given Email and password"
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { GraphQLClient, request } from 'graphql-request'
|
import { GraphQLClient, request } from 'graphql-request'
|
||||||
import { getDriver } from '../../bootstrap/neo4j'
|
import { getDriver } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
import createBadge from './badges.js'
|
import createBadge from './badges.js'
|
||||||
import createUser from './users.js'
|
import createUser from './users.js'
|
||||||
import createOrganization from './organizations.js'
|
import createOrganization from './organizations.js'
|
||||||
@ -23,26 +22,24 @@ const authenticatedHeaders = async ({ email, password }, host) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const factories = {
|
const factories = {
|
||||||
'Badge': createBadge,
|
Badge: createBadge,
|
||||||
'User': createUser,
|
User: createUser,
|
||||||
'Organization': createOrganization,
|
Organization: createOrganization,
|
||||||
'Post': createPost,
|
Post: createPost,
|
||||||
'Comment': createComment,
|
Comment: createComment,
|
||||||
'Category': createCategory,
|
Category: createCategory,
|
||||||
'Tag': createTag,
|
Tag: createTag,
|
||||||
'Report': createReport
|
Report: createReport
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cleanDatabase = async (options = {}) => {
|
export const cleanDatabase = async (options = {}) => {
|
||||||
const {
|
const { driver = getDriver() } = options
|
||||||
driver = getDriver()
|
|
||||||
} = options
|
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
const cypher = 'MATCH (n) DETACH DELETE n'
|
const cypher = 'MATCH (n) DETACH DELETE n'
|
||||||
try {
|
try {
|
||||||
return await session.run(cypher)
|
return await session.run(cypher)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw (error)
|
throw error
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
@ -63,7 +60,10 @@ export default function Factory (options = {}) {
|
|||||||
factories,
|
factories,
|
||||||
lastResponse: null,
|
lastResponse: null,
|
||||||
async authenticateAs ({ email, password }) {
|
async authenticateAs ({ email, password }) {
|
||||||
const headers = await authenticatedHeaders({ email, password }, seedServerHost)
|
const headers = await authenticatedHeaders(
|
||||||
|
{ email, password },
|
||||||
|
seedServerHost
|
||||||
|
)
|
||||||
this.lastResponse = headers
|
this.lastResponse = headers
|
||||||
this.graphQLClient = new GraphQLClient(seedServerHost, { headers })
|
this.graphQLClient = new GraphQLClient(seedServerHost, { headers })
|
||||||
return this
|
return this
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user