mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
refactor(backend): put config into context (#8603)
This is a side quest of #8558. The motivation is to be able to do dependency injection in the tests without overwriting global data. I saw the first merge conflict from #8551 and voila: It seems @Mogge could have used this already. refactor: follow @Mogge's review See: https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8603#pullrequestreview-2880714796 refactor: better test helper methods wip: continue refactoring wip: continue posts continue wip: continue groups continue registration registration continue messages continue observeposts continue categories continue posts in groups continue invite codes refactor: continue notificationsMiddleware continue statistics spec followed-users online-status mentions-in-groups posts-in-groups email spec finish all tests improve typescript missed one test remove one more reference of CONFIG eliminate one more global import of CONFIG fix language spec test fix two more test suites refactor: completely mock out 3rd part API request refactor test fixed user_management spec fixed more locatoin specs install types for jsonwebtoken one more fetchmock fixed one more suite fix one more spec yet another spec fix spec delete whitespaces remove beforeAll that the same as the default fix merge conflict fix e2e test refactor: use single callback function for `context` setup refactor: display logs from backend during CI Because why not? fix seeds fix login refactor: one unnecessary naming refactor: better editor support refactor: fail early Interestingly, I've had to destructure `context.user` in order to make typescript happy. Weird. refactor: undo changes to workflows - no effect We're running in `--detached` mode on CI, so I guess we won't be able to see the logs anyways. refactor: remove fetch from context after review See: refactor: found an easier way for required props Co-authored-by: Max <maxharz@gmail.com> Co-authored-by: Ulf Gebhardt <ulf.gebhardt@webcraft-media.de>
This commit is contained in:
parent
3c59e08412
commit
61813c4eb8
@ -98,6 +98,8 @@
|
|||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/lodash": "^4.17.19",
|
"@types/lodash": "^4.17.19",
|
||||||
"@types/node": "^24.0.10",
|
"@types/node": "^24.0.10",
|
||||||
|
"@types/jsonwebtoken": "~8.5.1",
|
||||||
|
"@types/request": "^2.48.12",
|
||||||
"@types/slug": "^5.0.9",
|
"@types/slug": "^5.0.9",
|
||||||
"@types/uuid": "~9.0.1",
|
"@types/uuid": "~9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
|
|||||||
@ -38,6 +38,21 @@ const required = {
|
|||||||
PRIVATE_KEY_PASSPHRASE: env.PRIVATE_KEY_PASSPHRASE,
|
PRIVATE_KEY_PASSPHRASE: env.PRIVATE_KEY_PASSPHRASE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/53050575
|
||||||
|
type NoUndefinedField<T> = { [P in keyof T]-?: NoUndefinedField<NonNullable<T[P]>> }
|
||||||
|
|
||||||
|
function assertRequiredConfig(
|
||||||
|
conf: typeof required,
|
||||||
|
): asserts conf is NoUndefinedField<typeof required> {
|
||||||
|
Object.entries(conf).forEach(([key, value]) => {
|
||||||
|
if (!value) {
|
||||||
|
throw new Error(`ERROR: "${key}" env variable is missing.`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
assertRequiredConfig(required)
|
||||||
|
|
||||||
const server = {
|
const server = {
|
||||||
CLIENT_URI: env.CLIENT_URI ?? 'http://localhost:3000',
|
CLIENT_URI: env.CLIENT_URI ?? 'http://localhost:3000',
|
||||||
GRAPHQL_URI: env.GRAPHQL_URI ?? 'http://localhost:4000',
|
GRAPHQL_URI: env.GRAPHQL_URI ?? 'http://localhost:4000',
|
||||||
@ -147,15 +162,7 @@ const language = {
|
|||||||
LANGUAGE_DEFAULT: process.env.LANGUAGE_DEFAULT ?? 'en',
|
LANGUAGE_DEFAULT: process.env.LANGUAGE_DEFAULT ?? 'en',
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if all required configs are present
|
const CONFIG = {
|
||||||
Object.entries(required).map((entry) => {
|
|
||||||
if (!entry[1]) {
|
|
||||||
throw new Error(`ERROR: "${entry[0]}" env variable is missing.`)
|
|
||||||
}
|
|
||||||
return entry
|
|
||||||
})
|
|
||||||
|
|
||||||
export default {
|
|
||||||
...environment,
|
...environment,
|
||||||
...server,
|
...server,
|
||||||
...required,
|
...required,
|
||||||
@ -167,4 +174,7 @@ export default {
|
|||||||
...language,
|
...language,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Config = typeof CONFIG
|
||||||
|
export default CONFIG
|
||||||
|
|
||||||
export { nodemailerTransportOptions }
|
export { nodemailerTransportOptions }
|
||||||
|
|||||||
61
backend/src/context/index.ts
Normal file
61
backend/src/context/index.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
|
|
||||||
|
import databaseContext from '@context/database'
|
||||||
|
import pubsubContext from '@context/pubsub'
|
||||||
|
import CONFIG from '@src/config'
|
||||||
|
import type { DecodedUser } from '@src/jwt/decode'
|
||||||
|
import { decode } from '@src/jwt/decode'
|
||||||
|
import ocelotLogger from '@src/logger'
|
||||||
|
import type OcelotLogger from '@src/logger'
|
||||||
|
|
||||||
|
import type { ApolloServerExpressConfig } from 'apollo-server-express'
|
||||||
|
|
||||||
|
const serverDatabase = databaseContext()
|
||||||
|
const serverPubsub = pubsubContext()
|
||||||
|
|
||||||
|
export const getContext =
|
||||||
|
(opts?: {
|
||||||
|
database?: ReturnType<typeof databaseContext>
|
||||||
|
pubsub?: ReturnType<typeof pubsubContext>
|
||||||
|
authenticatedUser: DecodedUser | null | undefined
|
||||||
|
logger?: typeof OcelotLogger
|
||||||
|
config: typeof CONFIG
|
||||||
|
}) =>
|
||||||
|
async (req: { headers: { authorization?: string } }) => {
|
||||||
|
const {
|
||||||
|
database = serverDatabase,
|
||||||
|
pubsub = serverPubsub,
|
||||||
|
authenticatedUser = undefined,
|
||||||
|
logger = ocelotLogger,
|
||||||
|
config = CONFIG,
|
||||||
|
} = opts ?? {}
|
||||||
|
const { driver } = database
|
||||||
|
const user =
|
||||||
|
authenticatedUser === null
|
||||||
|
? null
|
||||||
|
: (authenticatedUser ?? (await decode({ driver, config })(req.headers.authorization)))
|
||||||
|
const result = {
|
||||||
|
database,
|
||||||
|
driver,
|
||||||
|
neode: database.neode,
|
||||||
|
pubsub,
|
||||||
|
logger,
|
||||||
|
user,
|
||||||
|
req,
|
||||||
|
cypherParams: {
|
||||||
|
currentUserId: user ? user.id : null,
|
||||||
|
},
|
||||||
|
config,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export const context: ApolloServerExpressConfig['context'] = async (options) => {
|
||||||
|
const { connection, req } = options
|
||||||
|
if (connection) {
|
||||||
|
return connection.context
|
||||||
|
} else {
|
||||||
|
return getContext()(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type Context = Awaited<ReturnType<ReturnType<typeof getContext>>>
|
||||||
@ -13,7 +13,7 @@ import { v4 as uuid } from 'uuid'
|
|||||||
import { generateInviteCode } from '@graphql/resolvers/inviteCodes'
|
import { generateInviteCode } from '@graphql/resolvers/inviteCodes'
|
||||||
import { isUniqueFor } from '@middleware/sluggifyMiddleware'
|
import { isUniqueFor } from '@middleware/sluggifyMiddleware'
|
||||||
import uniqueSlug from '@middleware/slugify/uniqueSlug'
|
import uniqueSlug from '@middleware/slugify/uniqueSlug'
|
||||||
import { Context } from '@src/server'
|
import { Context } from '@src/context'
|
||||||
|
|
||||||
import { getDriver, getNeode } from './neo4j'
|
import { getDriver, getNeode } from './neo4j'
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||||
/* eslint-disable n/no-process-exit */
|
/* eslint-disable n/no-process-exit */
|
||||||
import { faker } from '@faker-js/faker'
|
import { faker } from '@faker-js/faker'
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import sample from 'lodash/sample'
|
import sample from 'lodash/sample'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import CONFIG from '@config/index'
|
||||||
@ -16,10 +15,9 @@ import { CreateMessage } from '@graphql/queries/CreateMessage'
|
|||||||
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
||||||
import { createRoomMutation } from '@graphql/queries/createRoomMutation'
|
import { createRoomMutation } from '@graphql/queries/createRoomMutation'
|
||||||
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
||||||
import createServer from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
|
||||||
import Factory from './factories'
|
import Factory from './factories'
|
||||||
import { getNeode, getDriver } from './neo4j'
|
|
||||||
import { trophies, verification } from './seed/badges'
|
import { trophies, verification } from './seed/badges'
|
||||||
|
|
||||||
if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
|
if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
|
||||||
@ -35,22 +33,21 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
console.log('Seeded Data...')
|
console.log('Seeded Data...')
|
||||||
|
|
||||||
let authenticatedUser = null
|
let authenticatedUser = null
|
||||||
const driver = getDriver()
|
|
||||||
const neode = getNeode()
|
// locations
|
||||||
const { server } = createServer({
|
const context = () => ({
|
||||||
context: () => {
|
authenticatedUser,
|
||||||
return {
|
config: CONFIG,
|
||||||
driver,
|
|
||||||
neode,
|
|
||||||
user: authenticatedUser,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
const { mutate } = createTestClient(server)
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
|
const { mutate, server, database } = apolloSetup
|
||||||
|
const { neode } = database
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('seed', 'locations')
|
console.log('seed', 'locations')
|
||||||
|
|
||||||
|
// locations
|
||||||
const Hamburg = await Factory.build('location', {
|
const Hamburg = await Factory.build('location', {
|
||||||
id: 'region.5127278006398860',
|
id: 'region.5127278006398860',
|
||||||
name: 'Hamburg',
|
name: 'Hamburg',
|
||||||
@ -1618,7 +1615,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
throw err
|
throw err
|
||||||
} finally {
|
} finally {
|
||||||
await server.stop()
|
await server.stop()
|
||||||
await driver.close()
|
await database.driver.close()
|
||||||
// eslint-disable-next-line @typescript-eslint/await-thenable
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
||||||
await neode.close()
|
await neode.close()
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
|
|||||||
@ -9,15 +9,14 @@ import { Readable } from 'node:stream'
|
|||||||
import { S3Client } from '@aws-sdk/client-s3'
|
import { S3Client } from '@aws-sdk/client-s3'
|
||||||
import { Upload } from '@aws-sdk/lib-storage'
|
import { Upload } from '@aws-sdk/lib-storage'
|
||||||
import { UserInputError } from 'apollo-server'
|
import { UserInputError } from 'apollo-server'
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import File from '@db/models/File'
|
import File from '@db/models/File'
|
||||||
import { CreateMessage } from '@graphql/queries/CreateMessage'
|
import { CreateMessage } from '@graphql/queries/CreateMessage'
|
||||||
import { createRoomMutation } from '@graphql/queries/createRoomMutation'
|
import { createRoomMutation } from '@graphql/queries/createRoomMutation'
|
||||||
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
import type { S3Configured } from '@src/config'
|
import type { S3Configured } from '@src/config'
|
||||||
import createServer, { getContext } from '@src/server'
|
|
||||||
|
|
||||||
import { attachments } from './attachments'
|
import { attachments } from './attachments'
|
||||||
|
|
||||||
@ -47,20 +46,19 @@ const config: S3Configured = {
|
|||||||
S3_PUBLIC_GATEWAY: undefined,
|
S3_PUBLIC_GATEWAY: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
let authenticatedUser, server, mutate
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
|
||||||
const contextUser = async (_req) => authenticatedUser
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const context = getContext({ user: contextUser, database })
|
mutate = apolloSetup.mutate
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -115,7 +113,7 @@ describe('delete Attachment', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
message = m.data.CreateMessage
|
message = (m.data as any).CreateMessage // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
await database.write({
|
await database.write({
|
||||||
query: `
|
query: `
|
||||||
|
|||||||
@ -1,37 +1,32 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
|
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { rewardTrophyBadge } from '@graphql/queries/rewardTrophyBadge'
|
import { rewardTrophyBadge } from '@graphql/queries/rewardTrophyBadge'
|
||||||
import { setTrophyBadgeSelected } from '@graphql/queries/setTrophyBadgeSelected'
|
import { setTrophyBadgeSelected } from '@graphql/queries/setTrophyBadgeSelected'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let regularUser, administrator, moderator, badge, verification
|
let regularUser, administrator, moderator, badge, verification
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser })
|
||||||
let server: ApolloServer
|
let mutate: ApolloTestSetup['mutate']
|
||||||
let authenticatedUser
|
let query: ApolloTestSetup['query']
|
||||||
let query, mutate
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@ -838,7 +833,7 @@ describe('Badges', () => {
|
|||||||
|
|
||||||
describe('check test setup', () => {
|
describe('check test setup', () => {
|
||||||
it('user has one badge and has it selected', async () => {
|
it('user has one badge and has it selected', async () => {
|
||||||
authenticatedUser = regularUser.toJson()
|
authenticatedUser = await regularUser.toJson()
|
||||||
const userQuery = gql`
|
const userQuery = gql`
|
||||||
{
|
{
|
||||||
User(id: "regular-user-id") {
|
User(id: "regular-user-id") {
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||||
|
|
||||||
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
|
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
|
||||||
import { Context } from '@src/server'
|
import { Context } from '@src/context'
|
||||||
|
|
||||||
export const defaultTrophyBadge = {
|
export const defaultTrophyBadge = {
|
||||||
id: 'default_trophy',
|
id: 'default_trophy',
|
||||||
@ -32,7 +32,10 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Mutation: {
|
Mutation: {
|
||||||
setVerificationBadge: async (_object, args, context, _resolveInfo) => {
|
setVerificationBadge: async (_object, args, context: Context, _resolveInfo) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
user: { id: currentUserId },
|
user: { id: currentUserId },
|
||||||
} = context
|
} = context
|
||||||
@ -70,11 +73,14 @@ export default {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
rewardTrophyBadge: async (_object, args, context: Context, _resolveInfo) => {
|
rewardTrophyBadge: async (_object, args, context: Context, _resolveInfo) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
user: { id: currentUserId },
|
user: { id: currentUserId },
|
||||||
} = context
|
} = context
|
||||||
|
|||||||
@ -2,29 +2,26 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const database = databaseContext()
|
let variables, commentAuthor, newlyCreatedComment
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let variables, mutate, authenticatedUser, commentAuthor, newlyCreatedComment
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = apolloSetup.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = apolloSetup.server
|
||||||
|
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -35,6 +32,7 @@ afterAll(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
authenticatedUser = null
|
||||||
variables = {}
|
variables = {}
|
||||||
await database.neode.create('Category', {
|
await database.neode.create('Category', {
|
||||||
id: 'cat9',
|
id: 'cat9',
|
||||||
@ -98,14 +96,14 @@ describe('CreateComment', () => {
|
|||||||
content: "I'm not authorized to comment",
|
content: "I'm not authorized to comment",
|
||||||
}
|
}
|
||||||
const { errors } = await mutate({ mutation: createCommentMutation, variables })
|
const { errors } = await mutate({ mutation: createCommentMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const user = await database.neode.create('User', { name: 'Author' })
|
const user = await database.neode.create('User', { name: 'Author' })
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = (await user.toJson()) as Context['user']
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('given a post', () => {
|
describe('given a post', () => {
|
||||||
@ -157,7 +155,7 @@ describe('UpdateComment', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: updateCommentMutation, variables })
|
const { errors } = await mutate({ mutation: updateCommentMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -169,7 +167,7 @@ describe('UpdateComment', () => {
|
|||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: updateCommentMutation, variables })
|
const { errors } = await mutate({ mutation: updateCommentMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -208,7 +206,7 @@ describe('UpdateComment', () => {
|
|||||||
newlyCreatedComment = await newlyCreatedComment.toJson()
|
newlyCreatedComment = await newlyCreatedComment.toJson()
|
||||||
const {
|
const {
|
||||||
data: { UpdateComment },
|
data: { UpdateComment },
|
||||||
} = await mutate({ mutation: updateCommentMutation, variables })
|
} = (await mutate({ mutation: updateCommentMutation, variables })) as any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
expect(newlyCreatedComment.updatedAt).toBeTruthy()
|
expect(newlyCreatedComment.updatedAt).toBeTruthy()
|
||||||
expect(Date.parse(newlyCreatedComment.updatedAt)).toEqual(expect.any(Number))
|
expect(Date.parse(newlyCreatedComment.updatedAt)).toEqual(expect.any(Number))
|
||||||
expect(UpdateComment.updatedAt).toBeTruthy()
|
expect(UpdateComment.updatedAt).toBeTruthy()
|
||||||
@ -224,7 +222,7 @@ describe('UpdateComment', () => {
|
|||||||
it('returns null', async () => {
|
it('returns null', async () => {
|
||||||
const { data, errors } = await mutate({ mutation: updateCommentMutation, variables })
|
const { data, errors } = await mutate({ mutation: updateCommentMutation, variables })
|
||||||
expect(data).toMatchObject({ UpdateComment: null })
|
expect(data).toMatchObject({ UpdateComment: null })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -249,7 +247,7 @@ describe('DeleteComment', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const result = await mutate({ mutation: deleteCommentMutation, variables })
|
const result = await mutate({ mutation: deleteCommentMutation, variables })
|
||||||
expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(result.errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -261,7 +259,7 @@ describe('DeleteComment', () => {
|
|||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: deleteCommentMutation, variables })
|
const { errors } = await mutate({ mutation: deleteCommentMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,44 +1,37 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
|
||||||
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
||||||
import { filterPosts } from '@graphql/queries/filterPosts'
|
import { filterPosts } from '@graphql/queries/filterPosts'
|
||||||
import createServer from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
const driver = getDriver()
|
|
||||||
const neode = getNeode()
|
|
||||||
|
|
||||||
let query
|
|
||||||
let mutate
|
|
||||||
let authenticatedUser
|
|
||||||
let user
|
let user
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const { server } = createServer({
|
mutate = apolloSetup.mutate
|
||||||
context: () => {
|
query = apolloSetup.query
|
||||||
return {
|
database = apolloSetup.database
|
||||||
driver,
|
server = apolloSetup.server
|
||||||
neode,
|
|
||||||
user: authenticatedUser,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
query = createTestClient(server).query
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
await driver.close()
|
void server.stop()
|
||||||
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Filter Posts', () => {
|
describe('Filter Posts', () => {
|
||||||
@ -99,7 +92,7 @@ describe('Filter Posts', () => {
|
|||||||
it('finds all posts', async () => {
|
it('finds all posts', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({ query: filterPosts() })
|
} = (await query({ query: filterPosts() })) as any
|
||||||
expect(result).toHaveLength(4)
|
expect(result).toHaveLength(4)
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
@ -116,7 +109,10 @@ describe('Filter Posts', () => {
|
|||||||
it('finds the articles', async () => {
|
it('finds the articles', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Article'] } } })
|
} = (await query({
|
||||||
|
query: filterPosts(),
|
||||||
|
variables: { filter: { postType_in: ['Article'] } },
|
||||||
|
})) as any
|
||||||
expect(result).toHaveLength(2)
|
expect(result).toHaveLength(2)
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
@ -131,7 +127,10 @@ describe('Filter Posts', () => {
|
|||||||
it('finds the articles', async () => {
|
it('finds the articles', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Event'] } } })
|
} = (await query({
|
||||||
|
query: filterPosts(),
|
||||||
|
variables: { filter: { postType_in: ['Event'] } },
|
||||||
|
})) as any
|
||||||
expect(result).toHaveLength(2)
|
expect(result).toHaveLength(2)
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
@ -146,10 +145,10 @@ describe('Filter Posts', () => {
|
|||||||
it('finds all posts', async () => {
|
it('finds all posts', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({
|
} = (await query({
|
||||||
query: filterPosts(),
|
query: filterPosts(),
|
||||||
variables: { filter: { postType_in: ['Article', 'Event'] } },
|
variables: { filter: { postType_in: ['Article', 'Event'] } },
|
||||||
})
|
})) as any
|
||||||
expect(result).toHaveLength(4)
|
expect(result).toHaveLength(4)
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
@ -166,10 +165,10 @@ describe('Filter Posts', () => {
|
|||||||
it('finds the events ordered accordingly', async () => {
|
it('finds the events ordered accordingly', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({
|
} = (await query({
|
||||||
query: filterPosts(),
|
query: filterPosts(),
|
||||||
variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_desc'] },
|
variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_desc'] },
|
||||||
})
|
})) as any
|
||||||
expect(result).toHaveLength(2)
|
expect(result).toHaveLength(2)
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -190,10 +189,10 @@ describe('Filter Posts', () => {
|
|||||||
it('finds the events ordered accordingly', async () => {
|
it('finds the events ordered accordingly', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({
|
} = (await query({
|
||||||
query: filterPosts(),
|
query: filterPosts(),
|
||||||
variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_asc'] },
|
variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_asc'] },
|
||||||
})
|
})) as any
|
||||||
expect(result).toHaveLength(2)
|
expect(result).toHaveLength(2)
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -214,7 +213,7 @@ describe('Filter Posts', () => {
|
|||||||
it('finds only events after given date', async () => {
|
it('finds only events after given date', async () => {
|
||||||
const {
|
const {
|
||||||
data: { Post: result },
|
data: { Post: result },
|
||||||
} = await query({
|
} = (await query({
|
||||||
query: filterPosts(),
|
query: filterPosts(),
|
||||||
variables: {
|
variables: {
|
||||||
filter: {
|
filter: {
|
||||||
@ -226,7 +225,7 @@ describe('Filter Posts', () => {
|
|||||||
).toISOString(),
|
).toISOString(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})) as any
|
||||||
expect(result).toHaveLength(1)
|
expect(result).toHaveLength(1)
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
|||||||
@ -3,10 +3,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
@ -16,9 +12,11 @@ import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
|||||||
import { leaveGroupMutation } from '@graphql/queries/leaveGroupMutation'
|
import { leaveGroupMutation } from '@graphql/queries/leaveGroupMutation'
|
||||||
import { removeUserFromGroupMutation } from '@graphql/queries/removeUserFromGroupMutation'
|
import { removeUserFromGroupMutation } from '@graphql/queries/removeUserFromGroupMutation'
|
||||||
import { updateGroupMutation } from '@graphql/queries/updateGroupMutation'
|
import { updateGroupMutation } from '@graphql/queries/updateGroupMutation'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
// import CONFIG from '@src/config'
|
||||||
|
|
||||||
let authenticatedUser
|
|
||||||
let user
|
let user
|
||||||
let noMemberUser
|
let noMemberUser
|
||||||
let pendingMemberUser
|
let pendingMemberUser
|
||||||
@ -27,18 +25,21 @@ let adminMemberUser
|
|||||||
let ownerMemberUser
|
let ownerMemberUser
|
||||||
let secondOwnerMemberUser
|
let secondOwnerMemberUser
|
||||||
|
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const categoryIds = ['cat9', 'cat4', 'cat15']
|
const categoryIds = ['cat9', 'cat4', 'cat15']
|
||||||
const descriptionAdditional100 =
|
const descriptionAdditional100 =
|
||||||
' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789'
|
' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789'
|
||||||
let variables = {}
|
let variables = {}
|
||||||
|
const config = {
|
||||||
const database = databaseContext()
|
CATEGORIES_ACTIVE: true,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
// MAPBOX_TOKEN: CONFIG.MAPBOX_TOKEN,
|
||||||
const contextUser = async (_req) => authenticatedUser
|
}
|
||||||
const context = getContext({ user: contextUser, database })
|
|
||||||
|
|
||||||
const { server } = createServer({ context })
|
|
||||||
const { mutate, query } = createTestClient(server)
|
|
||||||
|
|
||||||
const seedBasicsAndClearAuthentication = async () => {
|
const seedBasicsAndClearAuthentication = async () => {
|
||||||
variables = {}
|
variables = {}
|
||||||
@ -230,7 +231,11 @@ const seedComplexScenarioAndClearAuthentication = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
|
mutate = apolloSetup.mutate
|
||||||
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -270,7 +275,7 @@ describe('in mode', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: createGroupMutation(), variables })
|
const { errors } = await mutate({ mutation: createGroupMutation(), variables })
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -339,17 +344,13 @@ describe('in mode', () => {
|
|||||||
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0</a>',
|
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0</a>',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Description too short!')
|
expect(errors?.[0]).toHaveProperty('message', 'Description too short!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('categories', () => {
|
describe('categories', () => {
|
||||||
beforeEach(() => {
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = true
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('with matching amount of categories', () => {
|
describe('with matching amount of categories', () => {
|
||||||
it('has new categories', async () => {
|
it('has new categories', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
@ -382,7 +383,7 @@ describe('in mode', () => {
|
|||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
variables: { ...variables, categoryIds: null },
|
variables: { ...variables, categoryIds: null },
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Too few categories!')
|
expect(errors?.[0]).toHaveProperty('message', 'Too few categories!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -392,7 +393,7 @@ describe('in mode', () => {
|
|||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
variables: { ...variables, categoryIds: [] },
|
variables: { ...variables, categoryIds: [] },
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Too few categories!')
|
expect(errors?.[0]).toHaveProperty('message', 'Too few categories!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -403,7 +404,7 @@ describe('in mode', () => {
|
|||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] },
|
variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] },
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Too many categories!')
|
expect(errors?.[0]).toHaveProperty('message', 'Too many categories!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -581,10 +582,6 @@ describe('in mode', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('categories', () => {
|
describe('categories', () => {
|
||||||
beforeEach(() => {
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = true
|
|
||||||
})
|
|
||||||
|
|
||||||
it('has set categories', async () => {
|
it('has set categories', async () => {
|
||||||
await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({
|
await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
@ -811,7 +808,7 @@ describe('in mode', () => {
|
|||||||
userId: 'current-user',
|
userId: 'current-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1566,7 +1563,7 @@ describe('in mode', () => {
|
|||||||
roleInGroup: 'pending',
|
roleInGroup: 'pending',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1721,7 +1718,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1747,7 +1744,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1796,7 +1793,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1819,7 +1816,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1842,7 +1839,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1900,7 +1897,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1923,7 +1920,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1940,7 +1937,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1963,7 +1960,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1980,7 +1977,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2003,7 +2000,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2020,7 +2017,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2110,7 +2107,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2127,7 +2124,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2150,7 +2147,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2167,7 +2164,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2190,7 +2187,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2207,7 +2204,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2297,7 +2294,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2320,7 +2317,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2343,7 +2340,7 @@ describe('in mode', () => {
|
|||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2407,7 +2404,7 @@ describe('in mode', () => {
|
|||||||
userId: 'current-user',
|
userId: 'current-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2524,7 +2521,7 @@ describe('in mode', () => {
|
|||||||
userId: 'owner-member-user',
|
userId: 'owner-member-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2538,7 +2535,7 @@ describe('in mode', () => {
|
|||||||
userId: 'second-owner-member-user',
|
userId: 'second-owner-member-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2552,7 +2549,7 @@ describe('in mode', () => {
|
|||||||
userId: 'none-member-user',
|
userId: 'none-member-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2566,7 +2563,7 @@ describe('in mode', () => {
|
|||||||
userId: 'usual-member-user',
|
userId: 'usual-member-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2580,7 +2577,7 @@ describe('in mode', () => {
|
|||||||
userId: 'admin-member-user',
|
userId: 'admin-member-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2606,7 +2603,7 @@ describe('in mode', () => {
|
|||||||
slug: 'my-best-group',
|
slug: 'my-best-group',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2859,17 +2856,13 @@ describe('in mode', () => {
|
|||||||
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0</a>',
|
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0</a>',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Description too short!')
|
expect(errors?.[0]).toHaveProperty('message', 'Description too short!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('categories', () => {
|
describe('categories', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = true
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('with matching amount of categories', () => {
|
describe('with matching amount of categories', () => {
|
||||||
it('has new categories', async () => {
|
it('has new categories', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
@ -2906,7 +2899,7 @@ describe('in mode', () => {
|
|||||||
categoryIds: [],
|
categoryIds: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Too few categories!')
|
expect(errors?.[0]).toHaveProperty('message', 'Too few categories!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2920,7 +2913,7 @@ describe('in mode', () => {
|
|||||||
categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'],
|
categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Too many categories!')
|
expect(errors?.[0]).toHaveProperty('message', 'Too many categories!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2940,7 +2933,7 @@ describe('in mode', () => {
|
|||||||
categoryIds: ['cat4', 'cat27'],
|
categoryIds: ['cat4', 'cat27'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2958,7 +2951,7 @@ describe('in mode', () => {
|
|||||||
categoryIds: ['cat4', 'cat27'],
|
categoryIds: ['cat4', 'cat27'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(errors![0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,11 +8,10 @@
|
|||||||
import { UserInputError } from 'apollo-server'
|
import { UserInputError } from 'apollo-server'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import { CATEGORIES_MIN, CATEGORIES_MAX } from '@constants/categories'
|
import { CATEGORIES_MIN, CATEGORIES_MAX } from '@constants/categories'
|
||||||
import { DESCRIPTION_WITHOUT_HTML_LENGTH_MIN } from '@constants/groups'
|
import { DESCRIPTION_WITHOUT_HTML_LENGTH_MIN } from '@constants/groups'
|
||||||
import { removeHtmlTags } from '@middleware/helpers/cleanHtml'
|
import { removeHtmlTags } from '@middleware/helpers/cleanHtml'
|
||||||
import type { Context } from '@src/server'
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
import Resolver, {
|
import Resolver, {
|
||||||
removeUndefinedNullValuesFromObject,
|
removeUndefinedNullValuesFromObject,
|
||||||
@ -32,6 +31,9 @@ export default {
|
|||||||
removeUndefinedNullValuesFromObject(matchParams)
|
removeUndefinedNullValuesFromObject(matchParams)
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const readTxResultPromise = session.readTransaction(async (txc) => {
|
const readTxResultPromise = session.readTransaction(async (txc) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const groupMatchParamsCypher = convertObjectToCypherMapLiteral(matchParams, true)
|
const groupMatchParamsCypher = convertObjectToCypherMapLiteral(matchParams, true)
|
||||||
let groupCypher
|
let groupCypher
|
||||||
if (isMember === true) {
|
if (isMember === true) {
|
||||||
@ -139,13 +141,14 @@ export default {
|
|||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreateGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
CreateGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
|
const { config } = context
|
||||||
const { categoryIds } = params
|
const { categoryIds } = params
|
||||||
delete params.categoryIds
|
delete params.categoryIds
|
||||||
params.locationName = params.locationName === '' ? null : params.locationName
|
params.locationName = params.locationName === '' ? null : params.locationName
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && (!categoryIds || categoryIds.length < CATEGORIES_MIN)) {
|
if (config.CATEGORIES_ACTIVE && (!categoryIds || categoryIds.length < CATEGORIES_MIN)) {
|
||||||
throw new UserInputError('Too few categories!')
|
throw new UserInputError('Too few categories!')
|
||||||
}
|
}
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length > CATEGORIES_MAX) {
|
if (config.CATEGORIES_ACTIVE && categoryIds && categoryIds.length > CATEGORIES_MAX) {
|
||||||
throw new UserInputError('Too many categories!')
|
throw new UserInputError('Too many categories!')
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@ -158,8 +161,11 @@ export default {
|
|||||||
params.id = params.id || uuid()
|
params.id = params.id || uuid()
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const categoriesCypher =
|
const categoriesCypher =
|
||||||
CONFIG.CATEGORIES_ACTIVE && categoryIds
|
config.CATEGORIES_ACTIVE && categoryIds
|
||||||
? `
|
? `
|
||||||
WITH group, membership
|
WITH group, membership
|
||||||
UNWIND $categoryIds AS categoryId
|
UNWIND $categoryIds AS categoryId
|
||||||
@ -194,7 +200,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const group = await writeTxResultPromise
|
const group = await writeTxResultPromise
|
||||||
// TODO: put in a middleware, see "UpdateGroup", "UpdateUser"
|
// TODO: put in a middleware, see "UpdateGroup", "UpdateUser"
|
||||||
await createOrUpdateLocations('Group', params.id, params.locationName, session)
|
await createOrUpdateLocations('Group', params.id, params.locationName, session, context)
|
||||||
return group
|
return group
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||||
@ -205,13 +211,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdateGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
UpdateGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
|
const { config } = context
|
||||||
const { categoryIds } = params
|
const { categoryIds } = params
|
||||||
delete params.categoryIds
|
delete params.categoryIds
|
||||||
const { id: groupId, avatar: avatarInput } = params
|
const { id: groupId, avatar: avatarInput } = params
|
||||||
delete params.avatar
|
delete params.avatar
|
||||||
params.locationName = params.locationName === '' ? null : params.locationName
|
params.locationName = params.locationName === '' ? null : params.locationName
|
||||||
|
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && categoryIds) {
|
if (config.CATEGORIES_ACTIVE && categoryIds) {
|
||||||
if (categoryIds.length < CATEGORIES_MIN) {
|
if (categoryIds.length < CATEGORIES_MIN) {
|
||||||
throw new UserInputError('Too few categories!')
|
throw new UserInputError('Too few categories!')
|
||||||
}
|
}
|
||||||
@ -226,7 +233,7 @@ export default {
|
|||||||
throw new UserInputError('Description too short!')
|
throw new UserInputError('Description too short!')
|
||||||
}
|
}
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
|
if (config.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
|
||||||
const cypherDeletePreviousRelations = `
|
const cypherDeletePreviousRelations = `
|
||||||
MATCH (group:Group {id: $groupId})-[previousRelations:CATEGORIZED]->(category:Category)
|
MATCH (group:Group {id: $groupId})-[previousRelations:CATEGORIZED]->(category:Category)
|
||||||
DELETE previousRelations
|
DELETE previousRelations
|
||||||
@ -237,13 +244,16 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
let updateGroupCypher = `
|
let updateGroupCypher = `
|
||||||
MATCH (group:Group {id: $groupId})
|
MATCH (group:Group {id: $groupId})
|
||||||
SET group += $params
|
SET group += $params
|
||||||
SET group.updatedAt = toString(datetime())
|
SET group.updatedAt = toString(datetime())
|
||||||
WITH group
|
WITH group
|
||||||
`
|
`
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
|
if (config.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
|
||||||
updateGroupCypher += `
|
updateGroupCypher += `
|
||||||
UNWIND $categoryIds AS categoryId
|
UNWIND $categoryIds AS categoryId
|
||||||
MATCH (category:Category {id: categoryId})
|
MATCH (category:Category {id: categoryId})
|
||||||
@ -263,14 +273,16 @@ export default {
|
|||||||
})
|
})
|
||||||
const [group] = transactionResponse.records.map((record) => record.get('group'))
|
const [group] = transactionResponse.records.map((record) => record.get('group'))
|
||||||
if (avatarInput) {
|
if (avatarInput) {
|
||||||
await images.mergeImage(group, 'AVATAR_IMAGE', avatarInput, { transaction })
|
await images(context.config).mergeImage(group, 'AVATAR_IMAGE', avatarInput, {
|
||||||
|
transaction,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return group
|
return group
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const group = await writeTxResultPromise
|
const group = await writeTxResultPromise
|
||||||
// TODO: put in a middleware, see "CreateGroup", "UpdateUser"
|
// TODO: put in a middleware, see "CreateGroup", "UpdateUser"
|
||||||
await createOrUpdateLocations('Group', params.id, params.locationName, session)
|
await createOrUpdateLocations('Group', params.id, params.locationName, session, context)
|
||||||
return group
|
return group
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||||
@ -380,10 +392,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
muteGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
muteGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const { groupId } = params
|
const { groupId } = params
|
||||||
const userId = context.user.id
|
const userId = context.user.id
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const transactionResponse = await transaction.run(
|
const transactionResponse = await transaction.run(
|
||||||
`
|
`
|
||||||
MATCH (group:Group { id: $groupId })
|
MATCH (group:Group { id: $groupId })
|
||||||
@ -409,6 +427,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
unmuteGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
unmuteGroup: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const { groupId } = params
|
const { groupId } = params
|
||||||
const userId = context.user.id
|
const userId = context.user.id
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
import normalizeEmail from './normalizeEmail'
|
import normalizeEmail from './normalizeEmail'
|
||||||
|
|
||||||
export default async function createPasswordReset(options) {
|
export default async function createPasswordReset(options: {
|
||||||
|
driver: Context['driver']
|
||||||
|
nonce: string
|
||||||
|
email: string
|
||||||
|
issuedAt?: Date
|
||||||
|
}) {
|
||||||
const { driver, nonce, email, issuedAt = new Date() } = options
|
const { driver, nonce, email, issuedAt = new Date() } = options
|
||||||
const normalizedEmail = normalizeEmail(email)
|
const normalizedEmail = normalizeEmail(email)
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
@ -33,6 +38,6 @@ export default async function createPasswordReset(options) {
|
|||||||
const [records] = await createPasswordResetTxPromise
|
const [records] = await createPasswordResetTxPromise
|
||||||
return records || {}
|
return records || {}
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import CONFIG, { isS3configured } from '@config/index'
|
import { isS3configured } from '@config/index'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
import type { FileDeleteCallback, FileUploadCallback } from '@src/uploads/types'
|
import type { FileDeleteCallback, FileUploadCallback } from '@src/uploads/types'
|
||||||
|
|
||||||
import { images as imagesLocal } from './imagesLocal'
|
import { images as imagesLocal } from './imagesLocal'
|
||||||
@ -51,4 +52,5 @@ export interface Images {
|
|||||||
) => Promise<any>
|
) => Promise<any>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const images = isS3configured(CONFIG) ? imagesS3(CONFIG) : imagesLocal
|
export const images = (config: Context['config']) =>
|
||||||
|
isS3configured(config) ? imagesS3(config) : imagesLocal
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
import { currentUser } from '@graphql/queries/currentUser'
|
import { currentUser } from '@graphql/queries/currentUser'
|
||||||
@ -20,26 +16,24 @@ import {
|
|||||||
authenticatedValidateInviteCode,
|
authenticatedValidateInviteCode,
|
||||||
unauthenticatedValidateInviteCode,
|
unauthenticatedValidateInviteCode,
|
||||||
} from '@graphql/queries/validateInviteCode'
|
} from '@graphql/queries/validateInviteCode'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup, TEST_CONFIG } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser })
|
||||||
let server: ApolloServer
|
let mutate: ApolloTestSetup['mutate']
|
||||||
let authenticatedUser
|
let query: ApolloTestSetup['query']
|
||||||
let query, mutate
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@ -479,7 +473,7 @@ describe('generatePersonalInviteCode', () => {
|
|||||||
|
|
||||||
it('throws an error when the max amount of invite links was reached', async () => {
|
it('throws an error when the max amount of invite links was reached', async () => {
|
||||||
let lastCode
|
let lastCode
|
||||||
for (let i = 0; i < CONFIG.INVITE_CODES_PERSONAL_PER_USER; i++) {
|
for (let i = 0; i < TEST_CONFIG.INVITE_CODES_PERSONAL_PER_USER; i++) {
|
||||||
lastCode = await mutate({ mutation: generatePersonalInviteCode })
|
lastCode = await mutate({ mutation: generatePersonalInviteCode })
|
||||||
expect(lastCode).toMatchObject({
|
expect(lastCode).toMatchObject({
|
||||||
errors: undefined,
|
errors: undefined,
|
||||||
@ -740,7 +734,7 @@ describe('generateGroupInviteCode', () => {
|
|||||||
|
|
||||||
it('throws an error when the max amount of invite links was reached', async () => {
|
it('throws an error when the max amount of invite links was reached', async () => {
|
||||||
let lastCode
|
let lastCode
|
||||||
for (let i = 0; i < CONFIG.INVITE_CODES_GROUP_PER_USER; i++) {
|
for (let i = 0; i < TEST_CONFIG.INVITE_CODES_GROUP_PER_USER; i++) {
|
||||||
lastCode = await mutate({
|
lastCode = await mutate({
|
||||||
mutation: generateGroupInviteCode,
|
mutation: generateGroupInviteCode,
|
||||||
variables: { groupId: 'public-group' },
|
variables: { groupId: 'public-group' },
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import registrationConstants from '@constants/registrationBranded'
|
import registrationConstants from '@constants/registrationBranded'
|
||||||
// eslint-disable-next-line import/no-cycle
|
import { Context } from '@src/context'
|
||||||
import { Context } from '@src/server'
|
|
||||||
|
|
||||||
import Resolver from './helpers/Resolver'
|
import Resolver from './helpers/Resolver'
|
||||||
|
|
||||||
@ -53,6 +51,9 @@ export const validateInviteCode = async (context: Context, inviteCode) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const redeemInviteCode = async (context: Context, code, newUser = false) => {
|
export const redeemInviteCode = async (context: Context, code, newUser = false) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const result = (
|
const result = (
|
||||||
await context.database.query({
|
await context.database.query({
|
||||||
query: `
|
query: `
|
||||||
@ -159,7 +160,9 @@ export default {
|
|||||||
})
|
})
|
||||||
).records[0].get('count')
|
).records[0].get('count')
|
||||||
|
|
||||||
if (parseInt(userInviteCodeAmount as string) >= CONFIG.INVITE_CODES_PERSONAL_PER_USER) {
|
if (
|
||||||
|
parseInt(userInviteCodeAmount as string) >= context.config.INVITE_CODES_PERSONAL_PER_USER
|
||||||
|
) {
|
||||||
throw new Error('You have reached the maximum of Invite Codes you can generate')
|
throw new Error('You have reached the maximum of Invite Codes you can generate')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +201,7 @@ export default {
|
|||||||
})
|
})
|
||||||
).records[0].get('count')
|
).records[0].get('count')
|
||||||
|
|
||||||
if (parseInt(userInviteCodeAmount as string) >= CONFIG.INVITE_CODES_GROUP_PER_USER) {
|
if (parseInt(userInviteCodeAmount as string) >= context.config.INVITE_CODES_GROUP_PER_USER) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'You have reached the maximum of Invite Codes you can generate for this group',
|
'You have reached the maximum of Invite Codes you can generate for this group',
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
import { UserInputError } from 'apollo-server'
|
import { UserInputError } from 'apollo-server'
|
||||||
|
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
import Resolver from './helpers/Resolver'
|
import Resolver from './helpers/Resolver'
|
||||||
import { queryLocations } from './users/location'
|
import { queryLocations } from './users/location'
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ export default {
|
|||||||
'nameRU',
|
'nameRU',
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
distanceToMe: async (parent, _params, context, _resolveInfo) => {
|
distanceToMe: async (parent, _params, context: Context, _resolveInfo) => {
|
||||||
if (!parent.id) {
|
if (!parent.id) {
|
||||||
throw new Error('Can not identify selected Location!')
|
throw new Error('Can not identify selected Location!')
|
||||||
}
|
}
|
||||||
@ -53,9 +54,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Query: {
|
Query: {
|
||||||
queryLocations: async (_object, args, _context, _resolveInfo) => {
|
queryLocations: async (_object, args, context: Context, _resolveInfo) => {
|
||||||
try {
|
try {
|
||||||
return queryLocations(args)
|
return queryLocations(args, context)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new UserInputError(e.message)
|
throw new UserInputError(e.message)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,11 +5,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { Readable } from 'node:stream'
|
import { Readable } from 'node:stream'
|
||||||
|
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import { Upload } from 'graphql-upload/public/index'
|
import { Upload } from 'graphql-upload/public/index'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import pubsubContext from '@context/pubsub'
|
import pubsubContext from '@context/pubsub'
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { CreateMessage } from '@graphql/queries/CreateMessage'
|
import { CreateMessage } from '@graphql/queries/CreateMessage'
|
||||||
@ -17,29 +14,28 @@ import { createRoomMutation } from '@graphql/queries/createRoomMutation'
|
|||||||
import { MarkMessagesAsSeen } from '@graphql/queries/MarkMessagesAsSeen'
|
import { MarkMessagesAsSeen } from '@graphql/queries/MarkMessagesAsSeen'
|
||||||
import { Message } from '@graphql/queries/Message'
|
import { Message } from '@graphql/queries/Message'
|
||||||
import { roomQuery } from '@graphql/queries/roomQuery'
|
import { roomQuery } from '@graphql/queries/roomQuery'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let query
|
let authenticatedUser: Context['user']
|
||||||
let mutate
|
const context = () => ({ authenticatedUser, pubsub })
|
||||||
let authenticatedUser
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
let chattingUser, otherChattingUser, notChattingUser
|
let chattingUser, otherChattingUser, notChattingUser
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
const pubsub = pubsubContext()
|
const pubsub = pubsubContext()
|
||||||
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database, pubsub })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
query = createTestClient(server).query
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -79,6 +75,10 @@ describe('Message', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
authenticatedUser = null
|
||||||
|
})
|
||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
@ -128,7 +128,7 @@ describe('Message', () => {
|
|||||||
userId: 'other-chatting-user',
|
userId: 'other-chatting-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
roomId = room.data.CreateRoom.id
|
roomId = (room.data as any).CreateRoom.id // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('user chats in room', () => {
|
describe('user chats in room', () => {
|
||||||
@ -180,7 +180,7 @@ describe('Message', () => {
|
|||||||
lastMessageAt: expect.any(String),
|
lastMessageAt: expect.any(String),
|
||||||
unreadCount: 0,
|
unreadCount: 0,
|
||||||
lastMessage: expect.objectContaining({
|
lastMessage: expect.objectContaining({
|
||||||
_id: result.data.Room[0].lastMessage.id,
|
_id: result.data?.Room[0].lastMessage.id,
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
content: 'Some nice message to other chatting user',
|
content: 'Some nice message to other chatting user',
|
||||||
senderId: 'chatting-user',
|
senderId: 'chatting-user',
|
||||||
@ -410,7 +410,7 @@ describe('Message', () => {
|
|||||||
userId: 'other-chatting-user',
|
userId: 'other-chatting-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
roomId = room.data.CreateRoom.id
|
roomId = (room.data as any).CreateRoom.id // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: CreateMessage,
|
mutation: CreateMessage,
|
||||||
@ -434,7 +434,7 @@ describe('Message', () => {
|
|||||||
Message: [
|
Message: [
|
||||||
{
|
{
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
_id: result.data.Message[0].id,
|
_id: result.data?.Message[0].id,
|
||||||
indexId: 0,
|
indexId: 0,
|
||||||
content: 'Some nice message to other chatting user',
|
content: 'Some nice message to other chatting user',
|
||||||
senderId: 'chatting-user',
|
senderId: 'chatting-user',
|
||||||
@ -642,7 +642,7 @@ describe('Message', () => {
|
|||||||
userId: 'other-chatting-user',
|
userId: 'other-chatting-user',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
roomId = room.data.CreateRoom.id
|
roomId = (room.data as any).CreateRoom.id // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: CreateMessage,
|
mutation: CreateMessage,
|
||||||
variables: {
|
variables: {
|
||||||
@ -673,7 +673,7 @@ describe('Message', () => {
|
|||||||
roomId,
|
roomId,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
msgs.data.Message.forEach((m) => messageIds.push(m.id))
|
msgs.data?.Message.forEach((m) => messageIds.push(m.id))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns true', async () => {
|
it('returns true', async () => {
|
||||||
|
|||||||
@ -3,42 +3,40 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getDriver } from '@db/neo4j'
|
|
||||||
import { markAllAsReadMutation } from '@graphql/queries/markAllAsReadMutation'
|
import { markAllAsReadMutation } from '@graphql/queries/markAllAsReadMutation'
|
||||||
import { markAsReadMutation } from '@graphql/queries/markAsReadMutation'
|
import { markAsReadMutation } from '@graphql/queries/markAsReadMutation'
|
||||||
import { notificationQuery } from '@graphql/queries/notificationQuery'
|
import { notificationQuery } from '@graphql/queries/notificationQuery'
|
||||||
import createServer from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const driver = getDriver()
|
|
||||||
let authenticatedUser
|
|
||||||
let user
|
let user
|
||||||
let author
|
let author
|
||||||
let variables
|
let variables
|
||||||
let query
|
let authenticatedUser: Context['user']
|
||||||
let mutate
|
const context = () => ({ authenticatedUser })
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const { server } = createServer({
|
query = apolloSetup.query
|
||||||
context: () => {
|
mutate = apolloSetup.mutate
|
||||||
return {
|
database = apolloSetup.database
|
||||||
driver,
|
server = apolloSetup.server
|
||||||
user: authenticatedUser,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
query = createTestClient(server).query
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
await driver.close()
|
void server.stop()
|
||||||
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -157,7 +155,7 @@ describe('given some notifications', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await query({ query: notificationQuery() })
|
const { errors } = await query({ query: notificationQuery() })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -241,7 +239,7 @@ describe('given some notifications', () => {
|
|||||||
variables: { ...variables, read: false },
|
variables: { ...variables, read: false },
|
||||||
})
|
})
|
||||||
await expect(response).toMatchObject(expected)
|
await expect(response).toMatchObject(expected)
|
||||||
await expect(response.data.notifications).toHaveLength(2) // double-check
|
await expect(response.data?.notifications).toHaveLength(2) // double-check
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('if a resource gets deleted', () => {
|
describe('if a resource gets deleted', () => {
|
||||||
@ -288,7 +286,7 @@ describe('given some notifications', () => {
|
|||||||
mutation: markAsReadMutation(),
|
mutation: markAsReadMutation(),
|
||||||
variables: { ...variables, id: 'p1' },
|
variables: { ...variables, id: 'p1' },
|
||||||
})
|
})
|
||||||
expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(result.errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -307,7 +305,7 @@ describe('given some notifications', () => {
|
|||||||
|
|
||||||
it('returns null', async () => {
|
it('returns null', async () => {
|
||||||
const response = await mutate({ mutation: markAsReadMutation(), variables })
|
const response = await mutate({ mutation: markAsReadMutation(), variables })
|
||||||
expect(response.data.markAsRead).toEqual(null)
|
expect(response.data?.markAsRead).toEqual(null)
|
||||||
expect(response.errors).toBeUndefined()
|
expect(response.errors).toBeUndefined()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -344,7 +342,7 @@ describe('given some notifications', () => {
|
|||||||
})
|
})
|
||||||
it('returns null', async () => {
|
it('returns null', async () => {
|
||||||
const response = await mutate({ mutation: markAsReadMutation(), variables })
|
const response = await mutate({ mutation: markAsReadMutation(), variables })
|
||||||
expect(response.data.markAsRead).toEqual(null)
|
expect(response.data?.markAsRead).toEqual(null)
|
||||||
expect(response.errors).toBeUndefined()
|
expect(response.errors).toBeUndefined()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -382,7 +380,7 @@ describe('given some notifications', () => {
|
|||||||
const result = await mutate({
|
const result = await mutate({
|
||||||
mutation: markAllAsReadMutation(),
|
mutation: markAllAsReadMutation(),
|
||||||
})
|
})
|
||||||
expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(result.errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -400,7 +398,7 @@ describe('given some notifications', () => {
|
|||||||
|
|
||||||
it('returns all as read', async () => {
|
it('returns all as read', async () => {
|
||||||
const response = await mutate({ mutation: markAllAsReadMutation(), variables })
|
const response = await mutate({ mutation: markAllAsReadMutation(), variables })
|
||||||
expect(response.data.markAllAsRead).toEqual(
|
expect(response.data?.markAllAsRead).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{
|
{
|
||||||
createdAt: '2019-08-30T19:33:48.651Z',
|
createdAt: '2019-08-30T19:33:48.651Z',
|
||||||
|
|||||||
@ -1,23 +1,23 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
let query
|
|
||||||
let mutate
|
|
||||||
let authenticatedUser
|
|
||||||
let user
|
let user
|
||||||
let otherUser
|
let otherUser
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: true }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const createCommentMutation = gql`
|
const createCommentMutation = gql`
|
||||||
mutation ($id: ID, $postId: ID!, $content: String!) {
|
mutation ($id: ID, $postId: ID!, $content: String!) {
|
||||||
@ -38,20 +38,13 @@ const postQuery = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
query = createTestClient(server).query
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -1,51 +1,45 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import registrationConstants from '@constants/registrationBranded'
|
import registrationConstants from '@constants/registrationBranded'
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
|
||||||
import createPasswordReset from './helpers/createPasswordReset'
|
import createPasswordReset from './helpers/createPasswordReset'
|
||||||
|
|
||||||
const neode = getNeode()
|
|
||||||
const driver = getDriver()
|
|
||||||
|
|
||||||
let mutate
|
|
||||||
let authenticatedUser
|
|
||||||
let variables
|
let variables
|
||||||
|
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const getAllPasswordResets = async () => {
|
const getAllPasswordResets = async () => {
|
||||||
const passwordResetQuery = await neode.cypher(
|
const passwordResetQuery = await database.neode.cypher(
|
||||||
'MATCH (passwordReset:PasswordReset) RETURN passwordReset',
|
'MATCH (passwordReset:PasswordReset) RETURN passwordReset',
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
const resets = passwordResetQuery.records.map((record) => record.get('passwordReset'))
|
const resets = passwordResetQuery.records.map((record) => record.get('passwordReset'))
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
return resets
|
return resets
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup()
|
||||||
const { server } = createServer({
|
mutate = apolloSetup.mutate
|
||||||
context: () => {
|
database = apolloSetup.database
|
||||||
return {
|
server = apolloSetup.server
|
||||||
driver,
|
|
||||||
neode,
|
|
||||||
user: authenticatedUser,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
await driver.close()
|
void server.stop()
|
||||||
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -129,7 +123,7 @@ describe('resetPassword', () => {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const setup = async (options: any = {}) => {
|
const setup = async (options: any = {}) => {
|
||||||
const { email = 'user@example.org', issuedAt = new Date(), nonce = '12345' } = options
|
const { email = 'user@example.org', issuedAt = new Date(), nonce = '12345' } = options
|
||||||
await createPasswordReset({ driver, email, issuedAt, nonce })
|
await createPasswordReset({ driver: database.driver, email, issuedAt, nonce })
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutation = gql`
|
const mutation = gql`
|
||||||
|
|||||||
@ -8,13 +8,15 @@ import bcrypt from 'bcryptjs'
|
|||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
import registrationConstants from '@constants/registrationBranded'
|
import registrationConstants from '@constants/registrationBranded'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
import createPasswordReset from './helpers/createPasswordReset'
|
import createPasswordReset from './helpers/createPasswordReset'
|
||||||
import normalizeEmail from './helpers/normalizeEmail'
|
import normalizeEmail from './helpers/normalizeEmail'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
requestPasswordReset: async (_parent, { email }, { driver }) => {
|
requestPasswordReset: async (_parent, { email }, context: Context) => {
|
||||||
|
const { driver } = context
|
||||||
email = normalizeEmail(email)
|
email = normalizeEmail(email)
|
||||||
// TODO: why this is generated differntly from 'backend/src/schema/resolvers/helpers/generateNonce.js'?
|
// TODO: why this is generated differntly from 'backend/src/schema/resolvers/helpers/generateNonce.js'?
|
||||||
const nonce = uuid().substring(0, registrationConstants.NONCE_LENGTH)
|
const nonce = uuid().substring(0, registrationConstants.NONCE_LENGTH)
|
||||||
|
|||||||
@ -2,12 +2,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import Image from '@db/models/Image'
|
import Image from '@db/models/Image'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
@ -15,30 +11,32 @@ import { createPostMutation } from '@graphql/queries/createPostMutation'
|
|||||||
import { Post } from '@graphql/queries/Post'
|
import { Post } from '@graphql/queries/Post'
|
||||||
import { pushPost } from '@graphql/queries/pushPost'
|
import { pushPost } from '@graphql/queries/pushPost'
|
||||||
import { unpushPost } from '@graphql/queries/unpushPost'
|
import { unpushPost } from '@graphql/queries/unpushPost'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
CONFIG.CATEGORIES_ACTIVE = true
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let user
|
let user
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let server: ApolloServer
|
const defaultConfig = {
|
||||||
let authenticatedUser
|
CATEGORIES_ACTIVE: true,
|
||||||
let query, mutate
|
// MAPBOX_TOKEN: CONFIG.MAPBOX_TOKEN,
|
||||||
|
}
|
||||||
|
let config: Partial<Context['config']>
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
query = createTestClientResult.query
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@ -51,6 +49,7 @@ const categoryIds = ['cat9', 'cat4', 'cat15']
|
|||||||
let variables
|
let variables
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
config = { ...defaultConfig }
|
||||||
variables = {}
|
variables = {}
|
||||||
user = await Factory.build(
|
user = await Factory.build(
|
||||||
'user',
|
'user',
|
||||||
@ -271,7 +270,7 @@ describe('CreatePost', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: createPostMutation(), variables })
|
const { errors } = await mutate({ mutation: createPostMutation(), variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -708,7 +707,7 @@ describe('UpdatePost', () => {
|
|||||||
categoryIds,
|
categoryIds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
newlyCreatedPost = data.CreatePost
|
newlyCreatedPost = (data as any).CreatePost // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
variables = {
|
variables = {
|
||||||
id: newlyCreatedPost.id,
|
id: newlyCreatedPost.id,
|
||||||
title: 'New title',
|
title: 'New title',
|
||||||
@ -733,7 +732,7 @@ describe('UpdatePost', () => {
|
|||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: updatePostMutation, variables })
|
const { errors } = await mutate({ mutation: updatePostMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -771,7 +770,7 @@ describe('UpdatePost', () => {
|
|||||||
it('updates the updatedAt attribute', async () => {
|
it('updates the updatedAt attribute', async () => {
|
||||||
const {
|
const {
|
||||||
data: { UpdatePost },
|
data: { UpdatePost },
|
||||||
} = await mutate({ mutation: updatePostMutation, variables })
|
} = (await mutate({ mutation: updatePostMutation, variables })) as any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
expect(UpdatePost.updatedAt).toBeTruthy()
|
expect(UpdatePost.updatedAt).toBeTruthy()
|
||||||
expect(Date.parse(UpdatePost.updatedAt)).toEqual(expect.any(Number))
|
expect(Date.parse(UpdatePost.updatedAt)).toEqual(expect.any(Number))
|
||||||
expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePost.updatedAt)
|
expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePost.updatedAt)
|
||||||
@ -1377,7 +1376,8 @@ describe('pin posts', () => {
|
|||||||
|
|
||||||
describe('MAX_PINNED_POSTS is 0', () => {
|
describe('MAX_PINNED_POSTS is 0', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
CONFIG.MAX_PINNED_POSTS = 0
|
config = { ...defaultConfig, MAX_PINNED_POSTS: 0 }
|
||||||
|
|
||||||
await Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{
|
{
|
||||||
@ -1400,7 +1400,7 @@ describe('pin posts', () => {
|
|||||||
|
|
||||||
describe('MAX_PINNED_POSTS is 1', () => {
|
describe('MAX_PINNED_POSTS is 1', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
CONFIG.MAX_PINNED_POSTS = 1
|
config = { ...defaultConfig, MAX_PINNED_POSTS: 1 }
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('are allowed to pin posts', () => {
|
describe('are allowed to pin posts', () => {
|
||||||
@ -1752,7 +1752,8 @@ describe('pin posts', () => {
|
|||||||
const postsPinnedCountsQuery = `query { PostsPinnedCounts { maxPinnedPosts, currentlyPinnedPosts } }`
|
const postsPinnedCountsQuery = `query { PostsPinnedCounts { maxPinnedPosts, currentlyPinnedPosts } }`
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
CONFIG.MAX_PINNED_POSTS = 3
|
config = { ...defaultConfig, MAX_PINNED_POSTS: 3 }
|
||||||
|
|
||||||
await Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{
|
{
|
||||||
@ -2127,7 +2128,7 @@ describe('DeletePost', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: deletePostMutation, variables })
|
const { errors } = await mutate({ mutation: deletePostMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2138,7 +2139,7 @@ describe('DeletePost', () => {
|
|||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const { errors } = await mutate({ mutation: deletePostMutation, variables })
|
const { errors } = await mutate({ mutation: deletePostMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2280,7 +2281,7 @@ describe('emotions', () => {
|
|||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(addPostEmotions.errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(addPostEmotions.errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2401,7 +2402,7 @@ describe('emotions', () => {
|
|||||||
mutation: removePostEmotionsMutation,
|
mutation: removePostEmotionsMutation,
|
||||||
variables: removePostEmotionsVariables,
|
variables: removePostEmotionsVariables,
|
||||||
})
|
})
|
||||||
expect(removePostEmotions.errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(removePostEmotions.errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,7 @@ import { isEmpty } from 'lodash'
|
|||||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import { Context } from '@src/context'
|
||||||
import { Context } from '@src/server'
|
|
||||||
|
|
||||||
import { validateEventParams } from './helpers/events'
|
import { validateEventParams } from './helpers/events'
|
||||||
import { filterForMutedUsers } from './helpers/filterForMutedUsers'
|
import { filterForMutedUsers } from './helpers/filterForMutedUsers'
|
||||||
@ -41,7 +40,7 @@ const filterEventDates = (params) => {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
Query: {
|
Query: {
|
||||||
Post: async (object, params, context, resolveInfo) => {
|
Post: async (object, params, context: Context, resolveInfo) => {
|
||||||
params = await filterPostsOfMyGroups(params, context)
|
params = await filterPostsOfMyGroups(params, context)
|
||||||
params = await filterInvisiblePosts(params, context)
|
params = await filterInvisiblePosts(params, context)
|
||||||
params = await filterForMutedUsers(params, context)
|
params = await filterForMutedUsers(params, context)
|
||||||
@ -77,10 +76,13 @@ export default {
|
|||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PostsEmotionsByCurrentUser: async (_object, params, context, _resolveInfo) => {
|
PostsEmotionsByCurrentUser: async (_object, params, context: Context, _resolveInfo) => {
|
||||||
const { postId } = params
|
const { postId } = params
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const readTxResultPromise = session.readTransaction(async (transaction) => {
|
const readTxResultPromise = session.readTransaction(async (transaction) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
const emotionsTransactionResponse = await transaction.run(
|
const emotionsTransactionResponse = await transaction.run(
|
||||||
`
|
`
|
||||||
MATCH (user:User {id: $userId})-[emoted:EMOTED]->(post:Post {id: $postId})
|
MATCH (user:User {id: $userId})-[emoted:EMOTED]->(post:Post {id: $postId})
|
||||||
@ -94,23 +96,29 @@ export default {
|
|||||||
const [emotions] = await readTxResultPromise
|
const [emotions] = await readTxResultPromise
|
||||||
return emotions
|
return emotions
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PostsPinnedCounts: async (_object, params, context: Context, _resolveInfo) => {
|
PostsPinnedCounts: async (_object, params, context: Context, _resolveInfo) => {
|
||||||
|
const { config } = context
|
||||||
const [postsPinnedCount] = (
|
const [postsPinnedCount] = (
|
||||||
await context.database.query({
|
await context.database.query({
|
||||||
query: 'MATCH (p:Post { pinned: true }) RETURN COUNT (p) AS count',
|
query: 'MATCH (p:Post { pinned: true }) RETURN COUNT (p) AS count',
|
||||||
})
|
})
|
||||||
).records.map((r) => Number(r.get('count').toString()))
|
).records.map((r) => Number(r.get('count').toString()))
|
||||||
return {
|
return {
|
||||||
maxPinnedPosts: CONFIG.MAX_PINNED_POSTS,
|
maxPinnedPosts: config.MAX_PINNED_POSTS,
|
||||||
currentlyPinnedPosts: postsPinnedCount,
|
currentlyPinnedPosts: postsPinnedCount,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreatePost: async (_parent, params, context, _resolveInfo) => {
|
CreatePost: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
|
const { user } = context
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
|
const { config } = context
|
||||||
const { categoryIds, groupId } = params
|
const { categoryIds, groupId } = params
|
||||||
const { image: imageInput } = params
|
const { image: imageInput } = params
|
||||||
|
|
||||||
@ -146,7 +154,7 @@ export default {
|
|||||||
)`
|
)`
|
||||||
}
|
}
|
||||||
const categoriesCypher =
|
const categoriesCypher =
|
||||||
CONFIG.CATEGORIES_ACTIVE && categoryIds
|
config.CATEGORIES_ACTIVE && categoryIds
|
||||||
? `WITH post
|
? `WITH post
|
||||||
UNWIND $categoryIds AS categoryId
|
UNWIND $categoryIds AS categoryId
|
||||||
MATCH (category:Category {id: categoryId})
|
MATCH (category:Category {id: categoryId})
|
||||||
@ -173,18 +181,18 @@ export default {
|
|||||||
${groupCypher}
|
${groupCypher}
|
||||||
RETURN post {.*, postType: [l IN labels(post) WHERE NOT l = 'Post'] }
|
RETURN post {.*, postType: [l IN labels(post) WHERE NOT l = 'Post'] }
|
||||||
`,
|
`,
|
||||||
{ userId: context.user.id, categoryIds, groupId, params },
|
{ userId: user.id, categoryIds, groupId, params },
|
||||||
)
|
)
|
||||||
const [post] = createPostTransactionResponse.records.map((record) => record.get('post'))
|
const [post] = createPostTransactionResponse.records.map((record) => record.get('post'))
|
||||||
if (imageInput) {
|
if (imageInput) {
|
||||||
await images.mergeImage(post, 'HERO_IMAGE', imageInput, { transaction })
|
await images(context.config).mergeImage(post, 'HERO_IMAGE', imageInput, { transaction })
|
||||||
}
|
}
|
||||||
return post
|
return post
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const post = await writeTxResultPromise
|
const post = await writeTxResultPromise
|
||||||
if (locationName) {
|
if (locationName) {
|
||||||
await createOrUpdateLocations('Post', post.id, locationName, session)
|
await createOrUpdateLocations('Post', post.id, locationName, session, context)
|
||||||
}
|
}
|
||||||
return post
|
return post
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -192,10 +200,11 @@ export default {
|
|||||||
throw new UserInputError('Post with this slug already exists!')
|
throw new UserInputError('Post with this slug already exists!')
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdatePost: async (_parent, params, context, _resolveInfo) => {
|
UpdatePost: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
|
const { config } = context
|
||||||
const { categoryIds } = params
|
const { categoryIds } = params
|
||||||
const { image: imageInput } = params
|
const { image: imageInput } = params
|
||||||
|
|
||||||
@ -211,7 +220,7 @@ export default {
|
|||||||
WITH post
|
WITH post
|
||||||
`
|
`
|
||||||
|
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
|
if (config.CATEGORIES_ACTIVE && categoryIds && categoryIds.length) {
|
||||||
const cypherDeletePreviousRelations = `
|
const cypherDeletePreviousRelations = `
|
||||||
MATCH (post:Post { id: $params.id })-[previousRelations:CATEGORIZED]->(category:Category)
|
MATCH (post:Post { id: $params.id })-[previousRelations:CATEGORIZED]->(category:Category)
|
||||||
DELETE previousRelations
|
DELETE previousRelations
|
||||||
@ -248,20 +257,20 @@ export default {
|
|||||||
updatePostVariables,
|
updatePostVariables,
|
||||||
)
|
)
|
||||||
const [post] = updatePostTransactionResponse.records.map((record) => record.get('post'))
|
const [post] = updatePostTransactionResponse.records.map((record) => record.get('post'))
|
||||||
await images.mergeImage(post, 'HERO_IMAGE', imageInput, { transaction })
|
await images(context.config).mergeImage(post, 'HERO_IMAGE', imageInput, { transaction })
|
||||||
return post
|
return post
|
||||||
})
|
})
|
||||||
const post = await writeTxResultPromise
|
const post = await writeTxResultPromise
|
||||||
if (locationName) {
|
if (locationName) {
|
||||||
await createOrUpdateLocations('Post', post.id, locationName, session)
|
await createOrUpdateLocations('Post', post.id, locationName, session, context)
|
||||||
}
|
}
|
||||||
return post
|
return post
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DeletePost: async (_object, args, context, _resolveInfo) => {
|
DeletePost: async (_object, args, context: Context, _resolveInfo) => {
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
const deletePostTransactionResponse = await transaction.run(
|
const deletePostTransactionResponse = await transaction.run(
|
||||||
@ -278,17 +287,17 @@ export default {
|
|||||||
{ postId: args.id },
|
{ postId: args.id },
|
||||||
)
|
)
|
||||||
const [post] = deletePostTransactionResponse.records.map((record) => record.get('post'))
|
const [post] = deletePostTransactionResponse.records.map((record) => record.get('post'))
|
||||||
await images.deleteImage(post, 'HERO_IMAGE', { transaction })
|
await images(context.config).deleteImage(post, 'HERO_IMAGE', { transaction })
|
||||||
return post
|
return post
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const post = await writeTxResultPromise
|
const post = await writeTxResultPromise
|
||||||
return post
|
return post
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AddPostEmotions: async (_object, params, context, _resolveInfo) => {
|
AddPostEmotions: async (_object, params, context: Context, _resolveInfo) => {
|
||||||
const { to, data } = params
|
const { to, data } = params
|
||||||
const { user } = context
|
const { user } = context
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
@ -312,7 +321,7 @@ export default {
|
|||||||
const [emoted] = await writeTxResultPromise
|
const [emoted] = await writeTxResultPromise
|
||||||
return emoted
|
return emoted
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RemovePostEmotions: async (_object, params, context, _resolveInfo) => {
|
RemovePostEmotions: async (_object, params, context, _resolveInfo) => {
|
||||||
@ -344,7 +353,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
pinPost: async (_parent, params, context: Context, _resolveInfo) => {
|
pinPost: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
if (CONFIG.MAX_PINNED_POSTS === 0) throw new Error('Pinned posts are not allowed!')
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
|
const { config } = context
|
||||||
|
if (config.MAX_PINNED_POSTS === 0) throw new Error('Pinned posts are not allowed!')
|
||||||
let pinnedPostWithNestedAttributes
|
let pinnedPostWithNestedAttributes
|
||||||
const { driver, user } = context
|
const { driver, user } = context
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
@ -358,7 +371,7 @@ export default {
|
|||||||
SET post.pinned = true
|
SET post.pinned = true
|
||||||
RETURN post, pinned.createdAt as pinnedAt`
|
RETURN post, pinned.createdAt as pinnedAt`
|
||||||
|
|
||||||
if (CONFIG.MAX_PINNED_POSTS === 1) {
|
if (config.MAX_PINNED_POSTS === 1) {
|
||||||
let writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
let writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||||
const deletePreviousRelationsResponse = await transaction.run(
|
const deletePreviousRelationsResponse = await transaction.run(
|
||||||
`
|
`
|
||||||
@ -403,7 +416,7 @@ export default {
|
|||||||
query: `MATCH (:User)-[:PINNED]->(post:Post { pinned: true }) RETURN COUNT(post) AS count`,
|
query: `MATCH (:User)-[:PINNED]->(post:Post { pinned: true }) RETURN COUNT(post) AS count`,
|
||||||
})
|
})
|
||||||
).records.map((r) => Number(r.get('count').toString()))
|
).records.map((r) => Number(r.get('count').toString()))
|
||||||
if (currentPinnedPostCount >= CONFIG.MAX_PINNED_POSTS) {
|
if (currentPinnedPostCount >= config.MAX_PINNED_POSTS) {
|
||||||
throw new Error('Max number of pinned posts is reached!')
|
throw new Error('Max number of pinned posts is reached!')
|
||||||
}
|
}
|
||||||
const [pinPostResult] = (
|
const [pinPostResult] = (
|
||||||
|
|||||||
@ -2,11 +2,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
||||||
import { createCommentMutation } from '@graphql/queries/createCommentMutation'
|
import { createCommentMutation } from '@graphql/queries/createCommentMutation'
|
||||||
@ -18,9 +13,9 @@ import { postQuery } from '@graphql/queries/postQuery'
|
|||||||
import { profilePagePosts } from '@graphql/queries/profilePagePosts'
|
import { profilePagePosts } from '@graphql/queries/profilePagePosts'
|
||||||
import { searchPosts } from '@graphql/queries/searchPosts'
|
import { searchPosts } from '@graphql/queries/searchPosts'
|
||||||
import { signupVerificationMutation } from '@graphql/queries/signupVerificationMutation'
|
import { signupVerificationMutation } from '@graphql/queries/signupVerificationMutation'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
jest.mock('@constants/groups', () => {
|
jest.mock('@constants/groups', () => {
|
||||||
return {
|
return {
|
||||||
@ -29,30 +24,28 @@ jest.mock('@constants/groups', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let query
|
|
||||||
let mutate
|
|
||||||
let anyUser
|
let anyUser
|
||||||
let allGroupsUser
|
let allGroupsUser
|
||||||
let pendingUser
|
let pendingUser
|
||||||
let publicUser
|
let publicUser
|
||||||
let closedUser
|
let closedUser
|
||||||
let hiddenUser
|
let hiddenUser
|
||||||
let authenticatedUser
|
|
||||||
let newUser
|
let newUser
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
query = createTestClient(server).query
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -545,7 +538,7 @@ describe('Posts in Groups', () => {
|
|||||||
describe('visibility of posts', () => {
|
describe('visibility of posts', () => {
|
||||||
describe('query post by ID', () => {
|
describe('query post by ID', () => {
|
||||||
describe('without authentication', () => {
|
describe('without authentication', () => {
|
||||||
beforeAll(async () => {
|
beforeEach(() => {
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -608,7 +601,7 @@ describe('Posts in Groups', () => {
|
|||||||
termsAndConditionsAgreedVersion: '0.0.1',
|
termsAndConditionsAgreedVersion: '0.0.1',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
newUser = result.data.SignupVerification
|
newUser = result.data?.SignupVerification
|
||||||
authenticatedUser = newUser
|
authenticatedUser = newUser
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -802,13 +795,13 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
describe('filter posts', () => {
|
describe('filter posts', () => {
|
||||||
describe('without authentication', () => {
|
describe('without authentication', () => {
|
||||||
beforeAll(async () => {
|
beforeEach(() => {
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(2)
|
expect(result.data?.Post).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -838,7 +831,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(2)
|
expect(result.data?.Post).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -868,7 +861,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(2)
|
expect(result.data?.Post).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -898,7 +891,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(2)
|
expect(result.data?.Post).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -928,7 +921,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows all posts', async () => {
|
it('shows all posts', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -966,13 +959,13 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
describe('profile page posts', () => {
|
describe('profile page posts', () => {
|
||||||
describe('without authentication', () => {
|
describe('without authentication', () => {
|
||||||
beforeAll(async () => {
|
beforeEach(() => {
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: profilePagePosts(), variables: {} })
|
const result = await query({ query: profilePagePosts(), variables: {} })
|
||||||
expect(result.data.profilePagePosts).toHaveLength(2)
|
expect(result.data?.profilePagePosts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
profilePagePosts: expect.arrayContaining([
|
profilePagePosts: expect.arrayContaining([
|
||||||
@ -1000,7 +993,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: profilePagePosts(), variables: {} })
|
const result = await query({ query: profilePagePosts(), variables: {} })
|
||||||
expect(result.data.profilePagePosts).toHaveLength(2)
|
expect(result.data?.profilePagePosts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
profilePagePosts: expect.arrayContaining([
|
profilePagePosts: expect.arrayContaining([
|
||||||
@ -1028,7 +1021,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: profilePagePosts(), variables: {} })
|
const result = await query({ query: profilePagePosts(), variables: {} })
|
||||||
expect(result.data.profilePagePosts).toHaveLength(2)
|
expect(result.data?.profilePagePosts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
profilePagePosts: expect.arrayContaining([
|
profilePagePosts: expect.arrayContaining([
|
||||||
@ -1056,7 +1049,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the post of the public group and the post without group', async () => {
|
it('shows the post of the public group and the post without group', async () => {
|
||||||
const result = await query({ query: profilePagePosts(), variables: {} })
|
const result = await query({ query: profilePagePosts(), variables: {} })
|
||||||
expect(result.data.profilePagePosts).toHaveLength(2)
|
expect(result.data?.profilePagePosts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
profilePagePosts: expect.arrayContaining([
|
profilePagePosts: expect.arrayContaining([
|
||||||
@ -1084,7 +1077,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows all posts', async () => {
|
it('shows all posts', async () => {
|
||||||
const result = await query({ query: profilePagePosts(), variables: {} })
|
const result = await query({ query: profilePagePosts(), variables: {} })
|
||||||
expect(result.data.profilePagePosts).toHaveLength(4)
|
expect(result.data?.profilePagePosts).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
profilePagePosts: expect.arrayContaining([
|
profilePagePosts: expect.arrayContaining([
|
||||||
@ -1118,7 +1111,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
describe('searchPosts', () => {
|
describe('searchPosts', () => {
|
||||||
describe('without authentication', () => {
|
describe('without authentication', () => {
|
||||||
beforeAll(async () => {
|
beforeEach(() => {
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1131,7 +1124,7 @@ describe('Posts in Groups', () => {
|
|||||||
firstPosts: 25,
|
firstPosts: 25,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(result.data.searchPosts.posts).toHaveLength(0)
|
expect(result.data?.searchPosts.posts).toHaveLength(0)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
searchPosts: {
|
searchPosts: {
|
||||||
@ -1157,7 +1150,7 @@ describe('Posts in Groups', () => {
|
|||||||
firstPosts: 25,
|
firstPosts: 25,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(result.data.searchPosts.posts).toHaveLength(2)
|
expect(result.data?.searchPosts.posts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
searchPosts: {
|
searchPosts: {
|
||||||
@ -1194,7 +1187,7 @@ describe('Posts in Groups', () => {
|
|||||||
firstPosts: 25,
|
firstPosts: 25,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(result.data.searchPosts.posts).toHaveLength(2)
|
expect(result.data?.searchPosts.posts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
searchPosts: {
|
searchPosts: {
|
||||||
@ -1231,7 +1224,7 @@ describe('Posts in Groups', () => {
|
|||||||
firstPosts: 25,
|
firstPosts: 25,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(result.data.searchPosts.posts).toHaveLength(2)
|
expect(result.data?.searchPosts.posts).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
searchPosts: {
|
searchPosts: {
|
||||||
@ -1268,7 +1261,7 @@ describe('Posts in Groups', () => {
|
|||||||
firstPosts: 25,
|
firstPosts: 25,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(result.data.searchPosts.posts).toHaveLength(4)
|
expect(result.data?.searchPosts.posts).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
searchPosts: {
|
searchPosts: {
|
||||||
@ -1321,7 +1314,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the posts of the closed group', async () => {
|
it('shows the posts of the closed group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(3)
|
expect(result.data?.Post).toHaveLength(3)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1366,7 +1359,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows all the posts', async () => {
|
it('shows all the posts', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1419,7 +1412,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('does not show the posts of the closed group anymore', async () => {
|
it('does not show the posts of the closed group anymore', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(3)
|
expect(result.data?.Post).toHaveLength(3)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1464,7 +1457,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows only the public posts', async () => {
|
it('shows only the public posts', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(2)
|
expect(result.data?.Post).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1503,7 +1496,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('still shows the posts of the public group', async () => {
|
it('still shows the posts of the public group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1552,7 +1545,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('stil shows the posts of the closed group', async () => {
|
it('stil shows the posts of the closed group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1601,7 +1594,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('still shows the post of the hidden group', async () => {
|
it('still shows the post of the hidden group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1654,7 +1647,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows the posts of the closed group', async () => {
|
it('shows the posts of the closed group', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1705,7 +1698,7 @@ describe('Posts in Groups', () => {
|
|||||||
|
|
||||||
it('shows all posts', async () => {
|
it('shows all posts', async () => {
|
||||||
const result = await query({ query: filterPosts(), variables: {} })
|
const result = await query({ query: filterPosts(), variables: {} })
|
||||||
expect(result.data.Post).toHaveLength(4)
|
expect(result.data?.Post).toHaveLength(4)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
@ -1752,7 +1745,7 @@ describe('Posts in Groups', () => {
|
|||||||
query: filterPosts(),
|
query: filterPosts(),
|
||||||
variables: { filter: { postsInMyGroups: true } },
|
variables: { filter: { postsInMyGroups: true } },
|
||||||
})
|
})
|
||||||
expect(result.data.Post).toHaveLength(0)
|
expect(result.data?.Post).toHaveLength(0)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: [],
|
Post: [],
|
||||||
@ -1773,7 +1766,7 @@ describe('Posts in Groups', () => {
|
|||||||
query: filterPosts(),
|
query: filterPosts(),
|
||||||
variables: { filter: { postsInMyGroups: true } },
|
variables: { filter: { postsInMyGroups: true } },
|
||||||
})
|
})
|
||||||
expect(result.data.Post).toHaveLength(2)
|
expect(result.data?.Post).toHaveLength(2)
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: expect.arrayContaining([
|
Post: expect.arrayContaining([
|
||||||
|
|||||||
@ -1,36 +1,30 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import EmailAddress from '@db/models/EmailAddress'
|
import EmailAddress from '@db/models/EmailAddress'
|
||||||
import User from '@db/models/User'
|
import User from '@db/models/User'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let variables
|
let variables
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
let server: ApolloServer
|
let mutate: ApolloTestSetup['mutate']
|
||||||
let authenticatedUser
|
let database: ApolloTestSetup['database']
|
||||||
let mutate
|
let server: ApolloTestSetup['server']
|
||||||
|
let config: Partial<Context['config']> = {}
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = apolloSetup.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = apolloSetup.server
|
||||||
|
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@ -40,6 +34,7 @@ afterAll(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
config = {}
|
||||||
variables = {}
|
variables = {}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -62,11 +57,13 @@ describe('Signup', () => {
|
|||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
|
config = {
|
||||||
|
INVITE_REGISTRATION: false,
|
||||||
|
PUBLIC_REGISTRATION: false,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws AuthorizationError', async () => {
|
it('throws AuthorizationError', async () => {
|
||||||
CONFIG.INVITE_REGISTRATION = false
|
|
||||||
CONFIG.PUBLIC_REGISTRATION = false
|
|
||||||
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
|
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
|
||||||
errors: [{ message: 'Not Authorized!' }],
|
errors: [{ message: 'Not Authorized!' }],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { UserInputError } from 'apollo-server'
|
|||||||
import { hash } from 'bcryptjs'
|
import { hash } from 'bcryptjs'
|
||||||
|
|
||||||
import { getNeode } from '@db/neo4j'
|
import { getNeode } from '@db/neo4j'
|
||||||
import { Context } from '@src/server'
|
import { Context } from '@src/context'
|
||||||
|
|
||||||
import existingEmailAddress from './helpers/existingEmailAddress'
|
import existingEmailAddress from './helpers/existingEmailAddress'
|
||||||
import generateNonce from './helpers/generateNonce'
|
import generateNonce from './helpers/generateNonce'
|
||||||
@ -106,7 +106,7 @@ export default {
|
|||||||
await redeemInviteCode(context, inviteCode, true)
|
await redeemInviteCode(context, inviteCode, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
await createOrUpdateLocations('User', user.id, locationName, session)
|
await createOrUpdateLocations('User', user.id, locationName, session, context)
|
||||||
return user
|
return user
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||||
|
|||||||
@ -2,30 +2,21 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { statistics } from '@graphql/queries/statistics'
|
import { statistics } from '@graphql/queries/statistics'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
|
||||||
const database = databaseContext()
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
let server: ApolloServer
|
let query: ApolloTestSetup['query']
|
||||||
let query, authenticatedUser
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup()
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
query = apolloSetup.query
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = apolloSetup.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = apolloSetup.server
|
||||||
|
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/dot-notation */
|
/* eslint-disable @typescript-eslint/dot-notation */
|
||||||
import { Context } from '@src/server'
|
import { Context } from '@src/context'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Query: {
|
Query: {
|
||||||
|
|||||||
@ -1,31 +1,32 @@
|
|||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable promise/prefer-await-to-callbacks */
|
/* eslint-disable promise/prefer-await-to-callbacks */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
/* eslint-disable jest/unbound-method */
|
/* eslint-disable jest/unbound-method */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import jwt from 'jsonwebtoken'
|
import { verify } from 'jsonwebtoken'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import { categories } from '@constants/categories'
|
import { categories } from '@constants/categories'
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
|
||||||
import { loginMutation } from '@graphql/queries/loginMutation'
|
import { loginMutation } from '@graphql/queries/loginMutation'
|
||||||
import encode from '@jwt/encode'
|
import { decode } from '@jwt/decode'
|
||||||
import createServer, { context } from '@src/server'
|
import { encode } from '@jwt/encode'
|
||||||
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup, TEST_CONFIG } from '@root/test/helpers'
|
||||||
|
|
||||||
const neode = getNeode()
|
const jwt = { verify }
|
||||||
const driver = getDriver()
|
let variables, req, user
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
let query, mutate, variables, req, user
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const disable = async (id) => {
|
const disable = async (id) => {
|
||||||
const moderator = await Factory.build('user', { id: 'u2', role: 'moderator' })
|
const moderator = await Factory.build('user', { id: 'u2', role: 'moderator' })
|
||||||
const user = await neode.find('User', id)
|
const user = await database.neode.find('User', id)
|
||||||
const reportAgainstUser = await Factory.build('report')
|
const reportAgainstUser = await Factory.build('report')
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
reportAgainstUser.relateTo(moderator, 'filed', {
|
reportAgainstUser.relateTo(moderator, 'filed', {
|
||||||
@ -42,23 +43,34 @@ const disable = async (id) => {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
JWT_SECRET: 'I am the JWT secret',
|
||||||
|
JWT_EXPIRES: TEST_CONFIG.JWT_EXPIRES,
|
||||||
|
CLIENT_URI: TEST_CONFIG.CLIENT_URI,
|
||||||
|
GRAPHQL_URI: TEST_CONFIG.GRAPHQL_URI,
|
||||||
|
}
|
||||||
|
const context = { config }
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const context = async () => {
|
||||||
const { server } = createServer({
|
const authenticatedUser = await decode({ driver: database.driver, config })(
|
||||||
context: () => {
|
req.headers.authorization,
|
||||||
// One of the rare occasions where we test
|
)
|
||||||
// the actual `context` implementation here
|
return { authenticatedUser, config }
|
||||||
return context({ req })
|
}
|
||||||
},
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
})
|
mutate = apolloSetup.mutate
|
||||||
query = createTestClient(server).query
|
query = apolloSetup.query
|
||||||
mutate = createTestClient(server).mutate
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
await driver.close()
|
void server.stop()
|
||||||
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -120,7 +132,7 @@ describe('currentUser', () => {
|
|||||||
avatar,
|
avatar,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
const userBearerToken = encode({ id: 'u3' })
|
const userBearerToken = encode(context)({ id: 'u3' })
|
||||||
req = { headers: { authorization: `Bearer ${userBearerToken}` } }
|
req = { headers: { authorization: `Bearer ${userBearerToken}` } }
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -203,11 +215,11 @@ describe('currentUser', () => {
|
|||||||
|
|
||||||
it('returns only the saved active categories', async () => {
|
it('returns only the saved active categories', async () => {
|
||||||
const result = await query({ query: currentUserQuery, variables })
|
const result = await query({ query: currentUserQuery, variables })
|
||||||
expect(result.data.currentUser.activeCategories).toHaveLength(4)
|
expect(result.data?.currentUser.activeCategories).toHaveLength(4)
|
||||||
expect(result.data.currentUser.activeCategories).toContain('cat1')
|
expect(result.data?.currentUser.activeCategories).toContain('cat1')
|
||||||
expect(result.data.currentUser.activeCategories).toContain('cat3')
|
expect(result.data?.currentUser.activeCategories).toContain('cat3')
|
||||||
expect(result.data.currentUser.activeCategories).toContain('cat5')
|
expect(result.data?.currentUser.activeCategories).toContain('cat5')
|
||||||
expect(result.data.currentUser.activeCategories).toContain('cat7')
|
expect(result.data?.currentUser.activeCategories).toContain('cat7')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -236,8 +248,8 @@ describe('login', () => {
|
|||||||
it('responds with a JWT bearer token', async () => {
|
it('responds with a JWT bearer token', async () => {
|
||||||
const {
|
const {
|
||||||
data: { login: token },
|
data: { login: token },
|
||||||
} = await mutate({ mutation: loginMutation, variables })
|
} = (await mutate({ mutation: loginMutation, variables })) as any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
jwt.verify(token, CONFIG.JWT_SECRET, (err, data) => {
|
jwt.verify(token, config.JWT_SECRET, (err, data) => {
|
||||||
expect(data).toMatchObject({
|
expect(data).toMatchObject({
|
||||||
id: 'acb2d923-f3af-479e-9f00-61b12e864666',
|
id: 'acb2d923-f3af-479e-9f00-61b12e864666',
|
||||||
})
|
})
|
||||||
@ -274,7 +286,7 @@ describe('login', () => {
|
|||||||
describe('normalization', () => {
|
describe('normalization', () => {
|
||||||
describe('email address is a gmail address ', () => {
|
describe('email address is a gmail address ', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const email = await neode.first(
|
const email = await database.neode.first(
|
||||||
'EmailAddress',
|
'EmailAddress',
|
||||||
{ email: 'test@example.org' },
|
{ email: 'test@example.org' },
|
||||||
undefined,
|
undefined,
|
||||||
@ -354,7 +366,7 @@ describe('change password', () => {
|
|||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Factory.build('user', { id: 'u3' })
|
await Factory.build('user', { id: 'u3' })
|
||||||
const userBearerToken = encode({ id: 'u3' })
|
const userBearerToken = encode(context)({ id: 'u3' })
|
||||||
req = { headers: { authorization: `Bearer ${userBearerToken}` } }
|
req = { headers: { authorization: `Bearer ${userBearerToken}` } }
|
||||||
})
|
})
|
||||||
describe('old password === new password', () => {
|
describe('old password === new password', () => {
|
||||||
|
|||||||
@ -9,7 +9,8 @@ import bcrypt from 'bcryptjs'
|
|||||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||||
|
|
||||||
import { getNeode } from '@db/neo4j'
|
import { getNeode } from '@db/neo4j'
|
||||||
import encode from '@jwt/encode'
|
import { encode } from '@jwt/encode'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
import normalizeEmail from './helpers/normalizeEmail'
|
import normalizeEmail from './helpers/normalizeEmail'
|
||||||
|
|
||||||
@ -21,7 +22,8 @@ export default {
|
|||||||
neo4jgraphql(object, { id: context.user.id }, context, resolveInfo),
|
neo4jgraphql(object, { id: context.user.id }, context, resolveInfo),
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
login: async (_, { email, password }, { driver }) => {
|
login: async (_, { email, password }, context: Context) => {
|
||||||
|
const { driver } = context
|
||||||
// if (user && user.id) {
|
// if (user && user.id) {
|
||||||
// throw new Error('Already logged in.')
|
// throw new Error('Already logged in.')
|
||||||
// }
|
// }
|
||||||
@ -45,17 +47,21 @@ export default {
|
|||||||
!currentUser.disabled
|
!currentUser.disabled
|
||||||
) {
|
) {
|
||||||
delete currentUser.encryptedPassword
|
delete currentUser.encryptedPassword
|
||||||
return encode(currentUser)
|
return encode(context)(currentUser)
|
||||||
} else if (currentUser?.disabled) {
|
} else if (currentUser?.disabled) {
|
||||||
throw new AuthenticationError('Your account has been disabled.')
|
throw new AuthenticationError('Your account has been disabled.')
|
||||||
} else {
|
} else {
|
||||||
throw new AuthenticationError('Incorrect email address or password.')
|
throw new AuthenticationError('Incorrect email address or password.')
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changePassword: async (_, { oldPassword, newPassword }, { user }) => {
|
changePassword: async (_, { oldPassword, newPassword }, context: Context) => {
|
||||||
|
if (!context.user) {
|
||||||
|
throw new Error('Missing authenticated user.')
|
||||||
|
}
|
||||||
|
const { user } = context
|
||||||
const currentUser = await neode.find('User', user.id)
|
const currentUser = await neode.find('User', user.id)
|
||||||
|
|
||||||
const encryptedPassword = currentUser.get<string>('encryptedPassword')
|
const encryptedPassword = currentUser.get<string>('encryptedPassword')
|
||||||
@ -73,7 +79,7 @@ export default {
|
|||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
|
|
||||||
return encode(await currentUser.toJson())
|
return encode(context)(await currentUser.toJson())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,29 +3,34 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import { categories } from '@constants/categories'
|
import { categories } from '@constants/categories'
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import pubsubContext from '@context/pubsub'
|
import pubsubContext from '@context/pubsub'
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import User from '@db/models/User'
|
import User from '@db/models/User'
|
||||||
import { setTrophyBadgeSelected } from '@graphql/queries/setTrophyBadgeSelected'
|
import { setTrophyBadgeSelected } from '@graphql/queries/setTrophyBadgeSelected'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
import type { DecodedUser } from '@src/jwt/decode'
|
||||||
|
// import CONFIG from '@src/config'
|
||||||
|
|
||||||
const categoryIds = ['cat9']
|
const categoryIds = ['cat9']
|
||||||
let user
|
let user
|
||||||
let admin
|
let admin
|
||||||
let authenticatedUser
|
|
||||||
|
|
||||||
let query
|
|
||||||
let mutate
|
|
||||||
let variables
|
let variables
|
||||||
|
|
||||||
const pubsub = pubsubContext()
|
const pubsub = pubsubContext()
|
||||||
|
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser, pubsub })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const deleteUserMutation = gql`
|
const deleteUserMutation = gql`
|
||||||
mutation ($id: ID!, $resource: [Deletable]) {
|
mutation ($id: ID!, $resource: [Deletable]) {
|
||||||
DeleteUser(id: $id, resource: $resource) {
|
DeleteUser(id: $id, resource: $resource) {
|
||||||
@ -94,21 +99,13 @@ const resetTrophyBadgesSelected = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const contextUser = async (_req) => authenticatedUser
|
mutate = apolloSetup.mutate
|
||||||
const context = getContext({ user: contextUser, database, pubsub })
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -118,6 +115,10 @@ afterAll(async () => {
|
|||||||
database.neode.close()
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
authenticatedUser = null
|
||||||
|
})
|
||||||
|
|
||||||
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543
|
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
@ -128,6 +129,11 @@ describe('User', () => {
|
|||||||
let userQuery
|
let userQuery
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
const user = await Factory.build('user', {
|
||||||
|
id: 'user',
|
||||||
|
role: 'user',
|
||||||
|
})
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
userQuery = gql`
|
userQuery = gql`
|
||||||
query ($email: String) {
|
query ($email: String) {
|
||||||
User(email: $email) {
|
User(email: $email) {
|
||||||
@ -254,7 +260,7 @@ describe('UpdateUser', () => {
|
|||||||
|
|
||||||
it('is not allowed to change other user accounts', async () => {
|
it('is not allowed to change other user accounts', async () => {
|
||||||
const { errors } = await mutate({ mutation: updateUserMutation, variables })
|
const { errors } = await mutate({ mutation: updateUserMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -326,7 +332,7 @@ describe('UpdateUser', () => {
|
|||||||
termsAndConditionsAgreedVersion: 'invalid version format',
|
termsAndConditionsAgreedVersion: 'invalid version format',
|
||||||
}
|
}
|
||||||
const { errors } = await mutate({ mutation: updateUserMutation, variables })
|
const { errors } = await mutate({ mutation: updateUserMutation, variables })
|
||||||
expect(errors[0]).toHaveProperty('message', 'Invalid version format!')
|
expect(errors?.[0]).toHaveProperty('message', 'Invalid version format!')
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('supports updating location', () => {
|
describe('supports updating location', () => {
|
||||||
@ -684,7 +690,10 @@ describe('emailNotificationSettings', () => {
|
|||||||
it('returns the emailNotificationSettings', async () => {
|
it('returns the emailNotificationSettings', async () => {
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await user.toJson()
|
||||||
await expect(
|
await expect(
|
||||||
query({ query: emailNotificationSettingsQuery, variables: { id: authenticatedUser.id } }),
|
query({
|
||||||
|
query: emailNotificationSettingsQuery,
|
||||||
|
variables: { id: authenticatedUser?.id },
|
||||||
|
}),
|
||||||
).resolves.toEqual(
|
).resolves.toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
@ -778,7 +787,7 @@ describe('emailNotificationSettings', () => {
|
|||||||
|
|
||||||
describe('as self', () => {
|
describe('as self', () => {
|
||||||
it('updates the emailNotificationSettings', async () => {
|
it('updates the emailNotificationSettings', async () => {
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = (await user.toJson()) as DecodedUser
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: emailNotificationSettingsMutation,
|
mutation: emailNotificationSettingsMutation,
|
||||||
@ -876,7 +885,7 @@ describe('save category settings', () => {
|
|||||||
|
|
||||||
describe('not authenticated', () => {
|
describe('not authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = undefined
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
@ -921,7 +930,7 @@ describe('save category settings', () => {
|
|||||||
|
|
||||||
it('returns the active categories when user is queried', async () => {
|
it('returns the active categories when user is queried', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
query({ query: userQuery, variables: { id: authenticatedUser.id } }),
|
query({ query: userQuery, variables: { id: authenticatedUser?.id } }),
|
||||||
).resolves.toEqual(
|
).resolves.toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
@ -963,7 +972,7 @@ describe('save category settings', () => {
|
|||||||
|
|
||||||
it('returns the new active categories when user is queried', async () => {
|
it('returns the new active categories when user is queried', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
query({ query: userQuery, variables: { id: authenticatedUser.id } }),
|
query({ query: userQuery, variables: { id: authenticatedUser?.id } }),
|
||||||
).resolves.toEqual(
|
).resolves.toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
@ -1000,7 +1009,7 @@ describe('updateOnlineStatus', () => {
|
|||||||
|
|
||||||
describe('not authenticated', () => {
|
describe('not authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = undefined
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
@ -1030,7 +1039,7 @@ describe('updateOnlineStatus', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const cypher = 'MATCH (u:User {id: $id}) RETURN u'
|
const cypher = 'MATCH (u:User {id: $id}) RETURN u'
|
||||||
const result = await database.neode.cypher(cypher, { id: authenticatedUser.id })
|
const result = await database.neode.cypher(cypher, { id: authenticatedUser?.id })
|
||||||
const dbUser = database.neode.hydrateFirst(result, 'u', database.neode.model('User'))
|
const dbUser = database.neode.hydrateFirst(result, 'u', database.neode.model('User'))
|
||||||
await expect(dbUser.toJson()).resolves.toMatchObject({
|
await expect(dbUser.toJson()).resolves.toMatchObject({
|
||||||
lastOnlineStatus: 'online',
|
lastOnlineStatus: 'online',
|
||||||
@ -1056,7 +1065,7 @@ describe('updateOnlineStatus', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const cypher = 'MATCH (u:User {id: $id}) RETURN u'
|
const cypher = 'MATCH (u:User {id: $id}) RETURN u'
|
||||||
const result = await database.neode.cypher(cypher, { id: authenticatedUser.id })
|
const result = await database.neode.cypher(cypher, { id: authenticatedUser?.id })
|
||||||
const dbUser = database.neode.hydrateFirst(result, 'u', database.neode.model('User'))
|
const dbUser = database.neode.hydrateFirst(result, 'u', database.neode.model('User'))
|
||||||
await expect(dbUser.toJson()).resolves.toMatchObject({
|
await expect(dbUser.toJson()).resolves.toMatchObject({
|
||||||
lastOnlineStatus: 'away',
|
lastOnlineStatus: 'away',
|
||||||
@ -1072,7 +1081,7 @@ describe('updateOnlineStatus', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const cypher = 'MATCH (u:User {id: $id}) RETURN u'
|
const cypher = 'MATCH (u:User {id: $id}) RETURN u'
|
||||||
const result = await database.neode.cypher(cypher, { id: authenticatedUser.id })
|
const result = await database.neode.cypher(cypher, { id: authenticatedUser?.id })
|
||||||
const dbUser = database.neode.hydrateFirst<typeof User>(
|
const dbUser = database.neode.hydrateFirst<typeof User>(
|
||||||
result,
|
result,
|
||||||
'u',
|
'u',
|
||||||
@ -1091,7 +1100,7 @@ describe('updateOnlineStatus', () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const result2 = await database.neode.cypher(cypher, { id: authenticatedUser.id })
|
const result2 = await database.neode.cypher(cypher, { id: authenticatedUser?.id })
|
||||||
const dbUser2 = database.neode.hydrateFirst(result2, 'u', database.neode.model('User'))
|
const dbUser2 = database.neode.hydrateFirst(result2, 'u', database.neode.model('User'))
|
||||||
await expect(dbUser2.toJson()).resolves.toMatchObject({
|
await expect(dbUser2.toJson()).resolves.toMatchObject({
|
||||||
lastOnlineStatus: 'away',
|
lastOnlineStatus: 'away',
|
||||||
@ -1133,7 +1142,7 @@ describe('setTrophyBadgeSelected', () => {
|
|||||||
|
|
||||||
describe('not authenticated', () => {
|
describe('not authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = undefined
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
@ -1515,8 +1524,8 @@ describe('resetTrophyBadgesSelected', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('not authenticated', () => {
|
describe('not authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(() => {
|
||||||
authenticatedUser = undefined
|
authenticatedUser = null
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { neo4jgraphql } from 'neo4j-graphql-js'
|
|||||||
|
|
||||||
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
|
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
|
||||||
import { getNeode } from '@db/neo4j'
|
import { getNeode } from '@db/neo4j'
|
||||||
import { Context } from '@src/server'
|
import { Context } from '@src/context'
|
||||||
|
|
||||||
import { defaultTrophyBadge, defaultVerificationBadge } from './badges'
|
import { defaultTrophyBadge, defaultVerificationBadge } from './badges'
|
||||||
import normalizeEmail from './helpers/normalizeEmail'
|
import normalizeEmail from './helpers/normalizeEmail'
|
||||||
@ -168,10 +168,10 @@ export default {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new UserInputError(error.message)
|
throw new UserInputError(error.message)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdateUser: async (_parent, params, context, _resolveInfo) => {
|
UpdateUser: async (_parent, params, context: Context, _resolveInfo) => {
|
||||||
const { avatar: avatarInput } = params
|
const { avatar: avatarInput } = params
|
||||||
delete params.avatar
|
delete params.avatar
|
||||||
params.locationName = params.locationName === '' ? null : params.locationName
|
params.locationName = params.locationName === '' ? null : params.locationName
|
||||||
@ -210,22 +210,24 @@ export default {
|
|||||||
)
|
)
|
||||||
const [user] = updateUserTransactionResponse.records.map((record) => record.get('user'))
|
const [user] = updateUserTransactionResponse.records.map((record) => record.get('user'))
|
||||||
if (avatarInput) {
|
if (avatarInput) {
|
||||||
await images.mergeImage(user, 'AVATAR_IMAGE', avatarInput, { transaction })
|
await images(context.config).mergeImage(user, 'AVATAR_IMAGE', avatarInput, {
|
||||||
|
transaction,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return user
|
return user
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const user = await writeTxResultPromise
|
const user = await writeTxResultPromise
|
||||||
// TODO: put in a middleware, see "CreateGroup", "UpdateGroup"
|
// TODO: put in a middleware, see "CreateGroup", "UpdateGroup"
|
||||||
await createOrUpdateLocations('User', params.id, params.locationName, session)
|
await createOrUpdateLocations('User', params.id, params.locationName, session, context)
|
||||||
return user
|
return user
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new UserInputError(error.message)
|
throw new UserInputError(error.message)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DeleteUser: async (_object, params, context, _resolveInfo) => {
|
DeleteUser: async (_object, params, context: Context, _resolveInfo) => {
|
||||||
const { resource, id: userId } = params
|
const { resource, id: userId } = params
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
|
|
||||||
@ -253,7 +255,9 @@ export default {
|
|||||||
return Promise.all(
|
return Promise.all(
|
||||||
txResult.records
|
txResult.records
|
||||||
.map((record) => record.get('resource'))
|
.map((record) => record.get('resource'))
|
||||||
.map((resource) => images.deleteImage(resource, 'HERO_IMAGE', { transaction })),
|
.map((resource) =>
|
||||||
|
images(context.config).deleteImage(resource, 'HERO_IMAGE', { transaction }),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@ -281,14 +285,14 @@ export default {
|
|||||||
{ userId },
|
{ userId },
|
||||||
)
|
)
|
||||||
const [user] = deleteUserTransactionResponse.records.map((record) => record.get('user'))
|
const [user] = deleteUserTransactionResponse.records.map((record) => record.get('user'))
|
||||||
await images.deleteImage(user, 'AVATAR_IMAGE', { transaction })
|
await images(context.config).deleteImage(user, 'AVATAR_IMAGE', { transaction })
|
||||||
return user
|
return user
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const user = await deleteUserTxResultPromise
|
const user = await deleteUserTxResultPromise
|
||||||
return user
|
return user
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
switchUserRole: async (_object, args, context, _resolveInfo) => {
|
switchUserRole: async (_object, args, context, _resolveInfo) => {
|
||||||
|
|||||||
@ -1,16 +1,22 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const neode = getNeode()
|
let variables
|
||||||
const driver = getDriver()
|
let authenticatedUser: Context['user']
|
||||||
let authenticatedUser, mutate, query, variables
|
const context = () => ({
|
||||||
|
authenticatedUser,
|
||||||
|
})
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const updateUserMutation = gql`
|
const updateUserMutation = gql`
|
||||||
mutation ($id: ID!, $name: String!, $locationName: String) {
|
mutation ($id: ID!, $name: String!, $locationName: String) {
|
||||||
@ -78,23 +84,19 @@ const newlyCreatedNodesWithLocales = [
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({
|
||||||
const { server } = createServer({
|
context,
|
||||||
context: () => {
|
|
||||||
return {
|
|
||||||
user: authenticatedUser,
|
|
||||||
neode,
|
|
||||||
driver,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
mutate = createTestClient(server).mutate
|
mutate = apolloSetup.mutate
|
||||||
query = createTestClient(server).query
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(() => {
|
||||||
await cleanDatabase()
|
void server.stop()
|
||||||
await driver.close()
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -110,9 +112,8 @@ afterEach(async () => {
|
|||||||
describe('Location Service', () => {
|
describe('Location Service', () => {
|
||||||
// Authentication
|
// Authentication
|
||||||
// TODO: unify, externalize, simplify, wtf?
|
// TODO: unify, externalize, simplify, wtf?
|
||||||
let user
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await Factory.build('user', {
|
const user = await Factory.build('user', {
|
||||||
id: 'location-user',
|
id: 'location-user',
|
||||||
})
|
})
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await user.toJson()
|
||||||
@ -195,9 +196,8 @@ describe('Location Service', () => {
|
|||||||
|
|
||||||
describe('userMiddleware', () => {
|
describe('userMiddleware', () => {
|
||||||
describe('UpdateUser', () => {
|
describe('UpdateUser', () => {
|
||||||
let user
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await Factory.build('user', {
|
const user = await Factory.build('user', {
|
||||||
id: 'updating-user',
|
id: 'updating-user',
|
||||||
})
|
})
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await user.toJson()
|
||||||
@ -211,7 +211,7 @@ describe('userMiddleware', () => {
|
|||||||
locationName: 'Welzheim, Baden-Württemberg, Germany',
|
locationName: 'Welzheim, Baden-Württemberg, Germany',
|
||||||
}
|
}
|
||||||
await mutate({ mutation: updateUserMutation, variables })
|
await mutate({ mutation: updateUserMutation, variables })
|
||||||
const locations = await neode.cypher(
|
const locations = await database.neode.cypher(
|
||||||
`MATCH (city:Location)-[:IS_IN]->(district:Location)-[:IS_IN]->(state:Location)-[:IS_IN]->(country:Location) return city {.*}, state {.*}, country {.*}`,
|
`MATCH (city:Location)-[:IS_IN]->(district:Location)-[:IS_IN]->(state:Location)-[:IS_IN]->(country:Location) return city {.*}, state {.*}, country {.*}`,
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
/* eslint-disable n/no-unsupported-features/node-builtins */
|
/* eslint-disable n/no-unsupported-features/node-builtins */
|
||||||
import { UserInputError } from 'apollo-server'
|
import { UserInputError } from 'apollo-server'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl', 'ru']
|
const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl', 'ru']
|
||||||
|
|
||||||
@ -61,7 +61,13 @@ const createLocation = async (session, mapboxData) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, session) => {
|
export const createOrUpdateLocations = async (
|
||||||
|
nodeLabel,
|
||||||
|
nodeId,
|
||||||
|
locationName,
|
||||||
|
session,
|
||||||
|
context: Context,
|
||||||
|
) => {
|
||||||
if (locationName === undefined) return
|
if (locationName === undefined) return
|
||||||
|
|
||||||
let locationId
|
let locationId
|
||||||
@ -72,7 +78,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s
|
|||||||
`https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
|
`https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
|
||||||
locationName,
|
locationName,
|
||||||
)}.json?access_token=${
|
)}.json?access_token=${
|
||||||
CONFIG.MAPBOX_TOKEN
|
context.config.MAPBOX_TOKEN
|
||||||
}&types=region,place,country,address&language=${locales.join(',')}`,
|
}&types=region,place,country,address&language=${locales.join(',')}`,
|
||||||
{
|
{
|
||||||
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
|
||||||
@ -156,10 +162,10 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const queryLocations = async ({ place, lang }) => {
|
export const queryLocations = async ({ place, lang }, context: Context) => {
|
||||||
try {
|
try {
|
||||||
const res: any = await fetch(
|
const res: any = await fetch(
|
||||||
`https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${CONFIG.MAPBOX_TOKEN}&types=region,place,country&language=${lang}`,
|
`https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${context.config.MAPBOX_TOKEN}&types=region,place,country&language=${lang}`,
|
||||||
{
|
{
|
||||||
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,12 +4,20 @@
|
|||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import User from '@db/models/User'
|
import User from '@db/models/User'
|
||||||
import { getDriver, getNeode } from '@db/neo4j'
|
import { getDriver, getNeode } from '@db/neo4j'
|
||||||
|
import { TEST_CONFIG } from '@root/test/helpers'
|
||||||
|
|
||||||
import decode from './decode'
|
import { decode } from './decode'
|
||||||
import encode from './encode'
|
import { encode } from './encode'
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
|
const config = {
|
||||||
|
JWT_SECRET: 'supersecret',
|
||||||
|
JWT_EXPIRES: TEST_CONFIG.JWT_EXPIRES,
|
||||||
|
CLIENT_URI: TEST_CONFIG.CLIENT_URI,
|
||||||
|
GRAPHQL_URI: TEST_CONFIG.GRAPHQL_URI,
|
||||||
|
}
|
||||||
|
const context = { driver, config }
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
@ -26,9 +34,9 @@ afterEach(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('decode', () => {
|
describe('decode', () => {
|
||||||
let authorizationHeader
|
let authorizationHeader: string | undefined | null
|
||||||
const returnsNull = async () => {
|
const returnsNull = async () => {
|
||||||
await expect(decode(driver, authorizationHeader)).resolves.toBeNull()
|
await expect(decode(context)(authorizationHeader)).resolves.toBeNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('given `null` as JWT Bearer token', () => {
|
describe('given `null` as JWT Bearer token', () => {
|
||||||
@ -57,7 +65,8 @@ describe('decode', () => {
|
|||||||
|
|
||||||
describe('given valid JWT Bearer token', () => {
|
describe('given valid JWT Bearer token', () => {
|
||||||
describe('and corresponding user in the database', () => {
|
describe('and corresponding user in the database', () => {
|
||||||
let user, validAuthorizationHeader
|
let user
|
||||||
|
let validAuthorizationHeader: string
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await Factory.build(
|
user = await Factory.build(
|
||||||
'user',
|
'user',
|
||||||
@ -74,11 +83,11 @@ describe('decode', () => {
|
|||||||
email: 'user@example.org',
|
email: 'user@example.org',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
validAuthorizationHeader = encode(await user.toJson())
|
validAuthorizationHeader = encode(context)(await user.toJson())
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns user object without email', async () => {
|
it('returns user object without email', async () => {
|
||||||
await expect(decode(driver, validAuthorizationHeader)).resolves.toMatchObject({
|
await expect(decode(context)(validAuthorizationHeader)).resolves.toMatchObject({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
name: 'Jenny Rostock',
|
name: 'Jenny Rostock',
|
||||||
id: 'u3',
|
id: 'u3',
|
||||||
@ -89,7 +98,7 @@ describe('decode', () => {
|
|||||||
it('sets `lastActiveAt`', async () => {
|
it('sets `lastActiveAt`', async () => {
|
||||||
let user = await neode.first<typeof User>('User', { id: 'u3' }, undefined)
|
let user = await neode.first<typeof User>('User', { id: 'u3' }, undefined)
|
||||||
await expect(user.toJson()).resolves.not.toHaveProperty('lastActiveAt')
|
await expect(user.toJson()).resolves.not.toHaveProperty('lastActiveAt')
|
||||||
await decode(driver, validAuthorizationHeader)
|
await decode(context)(validAuthorizationHeader)
|
||||||
user = await neode.first<typeof User>('User', { id: 'u3' }, undefined)
|
user = await neode.first<typeof User>('User', { id: 'u3' }, undefined)
|
||||||
await expect(user.toJson()).resolves.toMatchObject({
|
await expect(user.toJson()).resolves.toMatchObject({
|
||||||
lastActiveAt: expect.any(String),
|
lastActiveAt: expect.any(String),
|
||||||
@ -107,7 +116,7 @@ describe('decode', () => {
|
|||||||
await expect(user.toJson()).resolves.toMatchObject({
|
await expect(user.toJson()).resolves.toMatchObject({
|
||||||
lastActiveAt: '2019-10-03T23:33:08.598Z',
|
lastActiveAt: '2019-10-03T23:33:08.598Z',
|
||||||
})
|
})
|
||||||
await decode(driver, validAuthorizationHeader)
|
await decode(context)(validAuthorizationHeader)
|
||||||
user = await neode.first<typeof User>('User', { id: 'u3' }, undefined)
|
user = await neode.first<typeof User>('User', { id: 'u3' }, undefined)
|
||||||
await expect(user.toJson()).resolves.toMatchObject({
|
await expect(user.toJson()).resolves.toMatchObject({
|
||||||
// should be a different time by now ;)
|
// should be a different time by now ;)
|
||||||
|
|||||||
@ -1,44 +1,56 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
||||||
import jwt from 'jsonwebtoken'
|
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import { verify } from 'jsonwebtoken'
|
||||||
|
|
||||||
export default async (driver, authorizationHeader) => {
|
import type CONFIG from '@src/config'
|
||||||
if (!authorizationHeader) return null
|
|
||||||
const token = authorizationHeader.replace('Bearer ', '')
|
|
||||||
let id = null
|
|
||||||
try {
|
|
||||||
const decoded = await jwt.verify(token, CONFIG.JWT_SECRET)
|
|
||||||
id = decoded.sub
|
|
||||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
|
||||||
} catch (err) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const session = driver.session()
|
|
||||||
|
|
||||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
import type { JwtPayload } from 'jsonwebtoken'
|
||||||
const updateUserLastActiveTransactionResponse = await transaction.run(
|
import type { Driver } from 'neo4j-driver'
|
||||||
`
|
|
||||||
|
export interface DecodedUser {
|
||||||
|
id: string
|
||||||
|
slug: string
|
||||||
|
name: string
|
||||||
|
role: string
|
||||||
|
disabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const jwt = { verify }
|
||||||
|
export const decode =
|
||||||
|
(context: { config: Pick<typeof CONFIG, 'JWT_SECRET'>; driver: Driver }) =>
|
||||||
|
async (authorizationHeader: string | undefined | null) => {
|
||||||
|
if (!authorizationHeader) return null
|
||||||
|
const token = authorizationHeader.replace('Bearer ', '')
|
||||||
|
let id: null | string = null
|
||||||
|
try {
|
||||||
|
const decoded = jwt.verify(token, context.config.JWT_SECRET) as JwtPayload
|
||||||
|
id = decoded.sub ?? null
|
||||||
|
// eslint-disable-next-line no-catch-all/no-catch-all
|
||||||
|
} catch (err) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const session = context.driver.session()
|
||||||
|
|
||||||
|
const writeTxResultPromise = session.writeTransaction<DecodedUser[]>(async (transaction) => {
|
||||||
|
const updateUserLastActiveTransactionResponse = await transaction.run(
|
||||||
|
`
|
||||||
MATCH (user:User {id: $id, deleted: false, disabled: false })
|
MATCH (user:User {id: $id, deleted: false, disabled: false })
|
||||||
SET user.lastActiveAt = toString(datetime())
|
SET user.lastActiveAt = toString(datetime())
|
||||||
RETURN user {.id, .slug, .name, .role, .disabled, .actorId}
|
RETURN user {.id, .slug, .name, .role, .disabled, .actorId}
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`,
|
`,
|
||||||
{ id },
|
{ id },
|
||||||
)
|
)
|
||||||
return updateUserLastActiveTransactionResponse.records.map((record) => record.get('user'))
|
return updateUserLastActiveTransactionResponse.records.map((record) => record.get('user'))
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const [currentUser] = await writeTxResultPromise
|
const [currentUser] = await writeTxResultPromise
|
||||||
if (!currentUser) return null
|
if (!currentUser) return null
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
...currentUser,
|
...currentUser,
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await session.close()
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
session.close()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import jwt from 'jsonwebtoken'
|
import { verify } from 'jsonwebtoken'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import { TEST_CONFIG } from '@root/test/helpers'
|
||||||
|
|
||||||
import encode from './encode'
|
import { encode } from './encode'
|
||||||
|
|
||||||
|
const jwt = { verify }
|
||||||
|
const config = {
|
||||||
|
JWT_SECRET: 'supersecret',
|
||||||
|
JWT_EXPIRES: TEST_CONFIG.JWT_EXPIRES,
|
||||||
|
CLIENT_URI: TEST_CONFIG.CLIENT_URI,
|
||||||
|
GRAPHQL_URI: TEST_CONFIG.GRAPHQL_URI,
|
||||||
|
}
|
||||||
|
const context = { config }
|
||||||
|
|
||||||
describe('encode', () => {
|
describe('encode', () => {
|
||||||
let payload
|
let payload
|
||||||
@ -18,9 +25,9 @@ describe('encode', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('encodes a valided JWT bearer token', () => {
|
it('encodes a valided JWT bearer token', () => {
|
||||||
const token = encode(payload)
|
const token = encode(context)(payload)
|
||||||
expect(token.split('.')).toHaveLength(3)
|
expect(token.split('.')).toHaveLength(3)
|
||||||
const decoded = jwt.verify(token, CONFIG.JWT_SECRET)
|
const decoded = jwt.verify(token, context.config.JWT_SECRET)
|
||||||
expect(decoded).toEqual({
|
expect(decoded).toEqual({
|
||||||
name: 'Some body',
|
name: 'Some body',
|
||||||
slug: 'some-body',
|
slug: 'some-body',
|
||||||
@ -43,7 +50,7 @@ describe('encode', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('does not encode sensitive data', () => {
|
it('does not encode sensitive data', () => {
|
||||||
const token = encode(payload)
|
const token = encode(context)(payload)
|
||||||
expect(payload).toEqual({
|
expect(payload).toEqual({
|
||||||
email: 'none-of-your-business@example.org',
|
email: 'none-of-your-business@example.org',
|
||||||
password: 'topsecret',
|
password: 'topsecret',
|
||||||
@ -51,7 +58,7 @@ describe('encode', () => {
|
|||||||
slug: 'some-body',
|
slug: 'some-body',
|
||||||
id: 'some-id',
|
id: 'some-id',
|
||||||
})
|
})
|
||||||
const decoded = jwt.verify(token, CONFIG.JWT_SECRET)
|
const decoded = jwt.verify(token, context.config.JWT_SECRET)
|
||||||
expect(decoded).toEqual({
|
expect(decoded).toEqual({
|
||||||
name: 'Some body',
|
name: 'Some body',
|
||||||
slug: 'some-body',
|
slug: 'some-body',
|
||||||
|
|||||||
@ -1,19 +1,23 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import jwt from 'jsonwebtoken'
|
import { sign } from 'jsonwebtoken'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
import type CONFIG from '@src/config'
|
||||||
|
|
||||||
|
const jwt = { sign }
|
||||||
// Generate an Access Token for the given User ID
|
// Generate an Access Token for the given User ID
|
||||||
export default function encode(user) {
|
export const encode =
|
||||||
const { id, name, slug } = user
|
(context: {
|
||||||
const token = jwt.sign({ id, name, slug }, CONFIG.JWT_SECRET, {
|
config: Pick<typeof CONFIG, 'JWT_SECRET' | 'JWT_EXPIRES' | 'GRAPHQL_URI' | 'CLIENT_URI'>
|
||||||
expiresIn: CONFIG.JWT_EXPIRES,
|
}) =>
|
||||||
issuer: CONFIG.GRAPHQL_URI,
|
(user) => {
|
||||||
audience: CONFIG.CLIENT_URI,
|
const { id, name, slug } = user
|
||||||
subject: user.id.toString(),
|
const token: string = jwt.sign({ id, name, slug }, context.config.JWT_SECRET, {
|
||||||
})
|
expiresIn: context.config.JWT_EXPIRES,
|
||||||
return token
|
issuer: context.config.GRAPHQL_URI,
|
||||||
}
|
audience: context.config.CLIENT_URI,
|
||||||
|
subject: user.id.toString(),
|
||||||
|
})
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|||||||
@ -1,33 +1,29 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import CONFIG from '@src/config'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
import { categories } from '@src/constants/categories'
|
import { categories } from '@src/constants/categories'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const database = databaseContext()
|
let config: Partial<Context['config']>
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let server: ApolloServer
|
beforeEach(() => {
|
||||||
let query
|
config = {}
|
||||||
|
})
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
const authenticatedUser = null
|
const context = () => ({ config, authenticatedUser: null })
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
query = apolloSetup.query
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = apolloSetup.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = apolloSetup.server
|
||||||
|
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
|
|
||||||
for (const category of categories) {
|
for (const category of categories) {
|
||||||
await Factory.build('category', {
|
await Factory.build('category', {
|
||||||
id: category.id,
|
id: category.id,
|
||||||
@ -55,10 +51,10 @@ const categoriesQuery = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
describe('categroeis middleware', () => {
|
describe('categories middleware', () => {
|
||||||
describe('categories are active', () => {
|
describe('categories are active', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
CONFIG.CATEGORIES_ACTIVE = true
|
config = { ...config, CATEGORIES_ACTIVE: true }
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns the categories', async () => {
|
it('returns the categories', async () => {
|
||||||
@ -78,7 +74,7 @@ describe('categroeis middleware', () => {
|
|||||||
|
|
||||||
describe('categories are not active', () => {
|
describe('categories are not active', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
config = { ...config, CATEGORIES_ACTIVE: false }
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns an empty array though there are categories in the db', async () => {
|
it('returns an empty array though there are categories in the db', async () => {
|
||||||
|
|||||||
@ -1,9 +1,19 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
import type { Context } from '@src/context'
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
import CONFIG from '@src/config'
|
|
||||||
|
|
||||||
const checkCategoriesActive = (resolve, root, args, context, resolveInfo) => {
|
type Resolver = (
|
||||||
if (CONFIG.CATEGORIES_ACTIVE) {
|
root: unknown,
|
||||||
|
args: unknown,
|
||||||
|
context: Context,
|
||||||
|
resolveInfo: unknown,
|
||||||
|
) => Promise<unknown>
|
||||||
|
const checkCategoriesActive = (
|
||||||
|
resolve: Resolver,
|
||||||
|
root: unknown,
|
||||||
|
args: unknown,
|
||||||
|
context: Context,
|
||||||
|
resolveInfo: unknown,
|
||||||
|
) => {
|
||||||
|
if (context.config.CATEGORIES_ACTIVE) {
|
||||||
return resolve(root, args, context, resolveInfo)
|
return resolve(root, args, context, resolveInfo)
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
|
|||||||
@ -1,21 +1,20 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import { cleanDatabase } from '@db/factories'
|
import { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let server
|
|
||||||
let query
|
|
||||||
let mutate
|
|
||||||
let hashtagingUser
|
let hashtagingUser
|
||||||
let authenticatedUser
|
let authenticatedUser: Context['user']
|
||||||
const driver = getDriver()
|
const context = () => ({ authenticatedUser })
|
||||||
const neode = getNeode()
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
const categoryIds = ['cat9']
|
const categoryIds = ['cat9']
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
mutation ($id: ID, $title: String!, $postContent: String!, $categoryIds: [ID]!) {
|
mutation ($id: ID, $title: String!, $postContent: String!, $categoryIds: [ID]!) {
|
||||||
@ -37,34 +36,27 @@ const updatePostMutation = gql`
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const createServerResult = createServer({
|
mutate = apolloSetup.mutate
|
||||||
context: () => {
|
query = apolloSetup.query
|
||||||
return {
|
database = apolloSetup.database
|
||||||
user: authenticatedUser,
|
server = apolloSetup.server
|
||||||
neode,
|
|
||||||
driver,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
server = createServerResult.server
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
await driver.close()
|
void server.stop()
|
||||||
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
hashtagingUser = await neode.create('User', {
|
hashtagingUser = await database.neode.create('User', {
|
||||||
id: 'you',
|
id: 'you',
|
||||||
name: 'Al Capone',
|
name: 'Al Capone',
|
||||||
slug: 'al-capone',
|
slug: 'al-capone',
|
||||||
})
|
})
|
||||||
await neode.create('Category', {
|
await database.neode.create('Category', {
|
||||||
id: 'cat9',
|
id: 'cat9',
|
||||||
name: 'Democracy & Politics',
|
name: 'Democracy & Politics',
|
||||||
icon: 'university',
|
icon: 'university',
|
||||||
|
|||||||
@ -16,7 +16,6 @@ import languages from './languages/languages'
|
|||||||
import login from './login/loginMiddleware'
|
import login from './login/loginMiddleware'
|
||||||
import notifications from './notifications/notificationsMiddleware'
|
import notifications from './notifications/notificationsMiddleware'
|
||||||
import orderBy from './orderByMiddleware'
|
import orderBy from './orderByMiddleware'
|
||||||
// eslint-disable-next-line import/no-cycle
|
|
||||||
import permissions from './permissionsMiddleware'
|
import permissions from './permissionsMiddleware'
|
||||||
import sentry from './sentryMiddleware'
|
import sentry from './sentryMiddleware'
|
||||||
import sluggify from './sluggifyMiddleware'
|
import sluggify from './sluggifyMiddleware'
|
||||||
|
|||||||
@ -1,38 +1,33 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { getNeode, getDriver } from '@db/neo4j'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let mutate
|
let authenticatedUser: Context['user']
|
||||||
let authenticatedUser
|
const context = () => ({ authenticatedUser })
|
||||||
let variables
|
let variables
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
const driver = getDriver()
|
let database: ApolloTestSetup['database']
|
||||||
const neode = getNeode()
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const { server } = createServer({
|
mutate = apolloSetup.mutate
|
||||||
context: () => {
|
database = apolloSetup.database
|
||||||
return {
|
server = apolloSetup.server
|
||||||
driver,
|
|
||||||
neode,
|
|
||||||
user: authenticatedUser,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
mutate = createTestClient(server).mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
await driver.close()
|
void server.stop()
|
||||||
|
void database.driver.close()
|
||||||
|
database.neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
|
|||||||
@ -1,27 +1,29 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
||||||
import CONFIG from '@src/config'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer, { getContext } from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('@src/emails/sendEmail', () => ({
|
jest.mock('@src/emails/sendEmail', () => ({
|
||||||
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let query, mutate, authenticatedUser, emaillessMember
|
let emaillessMember
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let postAuthor, groupMember
|
let postAuthor, groupMember
|
||||||
|
|
||||||
@ -94,21 +96,13 @@ const markAllAsRead = async () =>
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const contextUser = async (_req) => authenticatedUser
|
mutate = apolloSetup.mutate
|
||||||
const context = getContext({ user: contextUser, database })
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -1,25 +1,27 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
import CONFIG from '@src/config'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer, { getContext } from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('@src/emails/sendEmail', () => ({
|
jest.mock('@src/emails/sendEmail', () => ({
|
||||||
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let query, mutate, authenticatedUser
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let postAuthor, firstFollower, secondFollower, thirdFollower, emaillessFollower
|
let postAuthor, firstFollower, secondFollower, thirdFollower, emaillessFollower
|
||||||
|
|
||||||
@ -68,22 +70,13 @@ const followUserMutation = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -1,28 +1,29 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
||||||
import CONFIG from '@src/config'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer, { getContext } from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('@src/emails/sendEmail', () => ({
|
jest.mock('@src/emails/sendEmail', () => ({
|
||||||
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let query, mutate, authenticatedUser
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let postAuthor, groupMember, pendingMember, noMember, emaillessMember
|
let postAuthor, groupMember, pendingMember, noMember, emaillessMember
|
||||||
|
|
||||||
@ -90,21 +91,13 @@ const markAllAsRead = async () =>
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const contextUser = async (_req) => authenticatedUser
|
mutate = apolloSetup.mutate
|
||||||
const context = getContext({ user: contextUser, database })
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('@src/emails/sendEmail', () => ({
|
jest.mock('@src/emails/sendEmail', () => ({
|
||||||
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let query, mutate, authenticatedUser
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let postAuthor, firstCommenter, secondCommenter, emaillessObserver
|
let postAuthor, firstCommenter, secondCommenter, emaillessObserver
|
||||||
|
|
||||||
@ -77,21 +77,13 @@ const toggleObservePostMutation = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const contextUser = async (_req) => authenticatedUser
|
mutate = apolloSetup.mutate
|
||||||
const context = getContext({ user: contextUser, database })
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -2,15 +2,12 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import CONFIG from '@src/config'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer, { getContext } from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('@src/emails/sendEmail', () => ({
|
jest.mock('@src/emails/sendEmail', () => ({
|
||||||
@ -22,7 +19,12 @@ jest.mock('../helpers/isUserOnline', () => ({
|
|||||||
isUserOnline: () => isUserOnlineMock(),
|
isUserOnline: () => isUserOnlineMock(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let mutate, authenticatedUser
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let postAuthor
|
let postAuthor
|
||||||
|
|
||||||
@ -36,23 +38,17 @@ const createPostMutation = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = apolloSetup.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = apolloSetup.server
|
||||||
|
|
||||||
const { server } = createServer({ context })
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
void server.stop()
|
||||||
await database.driver.close()
|
await database.driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,28 +1,29 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
||||||
import CONFIG from '@src/config'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
import createServer, { getContext } from '@src/server'
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
|
||||||
|
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
jest.mock('@src/emails/sendEmail', () => ({
|
jest.mock('@src/emails/sendEmail', () => ({
|
||||||
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
sendNotificationMail: (notification) => sendNotificationMailMock(notification),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let query, mutate, authenticatedUser
|
let authenticatedUser: Context['user']
|
||||||
|
const config = { CATEGORIES_ACTIVE: false }
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let postAuthor, groupMember, pendingMember, emaillessMember
|
let postAuthor, groupMember, pendingMember, emaillessMember
|
||||||
|
|
||||||
@ -92,20 +93,13 @@ const markAllAsRead = async () =>
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const contextUser = async (_req) => authenticatedUser
|
mutate = apolloSetup.mutate
|
||||||
const context = getContext({ user: contextUser, database })
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -4,11 +4,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import pubsubContext from '@context/pubsub'
|
import pubsubContext from '@context/pubsub'
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
import { changeGroupMemberRoleMutation } from '@graphql/queries/changeGroupMemberRoleMutation'
|
||||||
@ -18,7 +15,10 @@ import { createRoomMutation } from '@graphql/queries/createRoomMutation'
|
|||||||
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
import { joinGroupMutation } from '@graphql/queries/joinGroupMutation'
|
||||||
import { leaveGroupMutation } from '@graphql/queries/leaveGroupMutation'
|
import { leaveGroupMutation } from '@graphql/queries/leaveGroupMutation'
|
||||||
import { removeUserFromGroupMutation } from '@graphql/queries/removeUserFromGroupMutation'
|
import { removeUserFromGroupMutation } from '@graphql/queries/removeUserFromGroupMutation'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
import type { DecodedUser } from '@src/jwt/decode'
|
||||||
|
|
||||||
const sendChatMessageMailMock: (notification) => void = jest.fn()
|
const sendChatMessageMailMock: (notification) => void = jest.fn()
|
||||||
const sendNotificationMailMock: (notification) => void = jest.fn()
|
const sendNotificationMailMock: (notification) => void = jest.fn()
|
||||||
@ -32,11 +32,17 @@ jest.mock('../helpers/isUserOnline', () => ({
|
|||||||
isUserOnline: () => isUserOnlineMock(),
|
isUserOnline: () => isUserOnlineMock(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
const pubsub = pubsubContext()
|
const pubsub = pubsubContext()
|
||||||
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
const pubsubSpy = jest.spyOn(pubsub, 'publish')
|
||||||
|
|
||||||
let query, mutate, notifiedUser, authenticatedUser
|
let notifiedUser
|
||||||
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser, pubsub })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
|
||||||
|
let query: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
const categoryIds = ['cat9']
|
const categoryIds = ['cat9']
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
@ -65,19 +71,13 @@ const createCommentMutation = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
let server: ApolloServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
const contextUser = async (_req) => authenticatedUser
|
mutate = apolloSetup.mutate
|
||||||
const context = getContext({ user: contextUser, database, pubsub })
|
query = apolloSetup.query
|
||||||
|
database = apolloSetup.database
|
||||||
server = createServer({ context }).server
|
server = apolloSetup.server
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -910,7 +910,7 @@ describe('notifications', () => {
|
|||||||
userId: 'chatReceiver',
|
userId: 'chatReceiver',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
roomId = room.data.CreateRoom.id
|
roomId = (room.data as any).CreateRoom.id // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('if the chatReceiver is online', () => {
|
describe('if the chatReceiver is online', () => {
|
||||||
@ -1106,7 +1106,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('user joins group', () => {
|
describe('user joins group', () => {
|
||||||
const joinGroupAction = async () => {
|
const joinGroupAction = async () => {
|
||||||
authenticatedUser = await notifiedUser.toJson()
|
authenticatedUser = (await notifiedUser.toJson()) as DecodedUser
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
@ -1193,7 +1193,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('user joins and leaves group', () => {
|
describe('user joins and leaves group', () => {
|
||||||
const leaveGroupAction = async () => {
|
const leaveGroupAction = async () => {
|
||||||
authenticatedUser = await notifiedUser.toJson()
|
authenticatedUser = (await notifiedUser.toJson()) as DecodedUser
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: leaveGroupMutation(),
|
mutation: leaveGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
@ -1206,7 +1206,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
authenticatedUser = await notifiedUser.toJson()
|
authenticatedUser = (await notifiedUser.toJson()) as DecodedUser
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
@ -1318,7 +1318,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('user role in group changes', () => {
|
describe('user role in group changes', () => {
|
||||||
const changeGroupMemberRoleAction = async () => {
|
const changeGroupMemberRoleAction = async () => {
|
||||||
authenticatedUser = await groupOwner.toJson()
|
authenticatedUser = (await groupOwner.toJson()) as DecodedUser
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
@ -1331,7 +1331,7 @@ describe('notifications', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = await notifiedUser.toJson()
|
authenticatedUser = (await notifiedUser.toJson()) as DecodedUser
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
@ -1427,7 +1427,7 @@ describe('notifications', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = await notifiedUser.toJson()
|
authenticatedUser = (await notifiedUser.toJson()) as DecodedUser
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
|
|||||||
@ -1,36 +1,35 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
import CONFIG from '@config/index'
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let variables
|
let variables
|
||||||
let owner, anotherRegularUser, administrator, moderator
|
let owner, anotherRegularUser, administrator, moderator
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser: Context['user']
|
||||||
|
let config: Partial<Context['config']>
|
||||||
|
const context = () => ({ authenticatedUser, config })
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let query: ApolloTestSetup['query']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
let server: ApolloServer
|
beforeEach(() => {
|
||||||
let authenticatedUser
|
config = { CATEGORIES_ACTIVE: true }
|
||||||
let query, mutate
|
})
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
query = apolloSetup.query
|
||||||
const context = getContext({ user: contextUser, database })
|
database = apolloSetup.database
|
||||||
|
server = apolloSetup.server
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
query = createTestClientResult.query
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@ -194,11 +193,16 @@ describe('authorization', () => {
|
|||||||
inviteCode: 'ABCDEF',
|
inviteCode: 'ABCDEF',
|
||||||
locale: 'de',
|
locale: 'de',
|
||||||
}
|
}
|
||||||
CONFIG.INVITE_REGISTRATION = false
|
|
||||||
CONFIG.PUBLIC_REGISTRATION = false
|
|
||||||
await Factory.build('inviteCode', {
|
await Factory.build('inviteCode', {
|
||||||
code: 'ABCDEF',
|
code: 'ABCDEF',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
config = {
|
||||||
|
...config,
|
||||||
|
CATEGORIES_ACTIVE: true,
|
||||||
|
INVITE_REGISTRATION: false,
|
||||||
|
PUBLIC_REGISTRATION: false,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('as user', () => {
|
describe('as user', () => {
|
||||||
@ -237,11 +241,15 @@ describe('authorization', () => {
|
|||||||
inviteCode: 'ABCDEF',
|
inviteCode: 'ABCDEF',
|
||||||
locale: 'de',
|
locale: 'de',
|
||||||
}
|
}
|
||||||
CONFIG.INVITE_REGISTRATION = false
|
|
||||||
CONFIG.PUBLIC_REGISTRATION = true
|
|
||||||
await Factory.build('inviteCode', {
|
await Factory.build('inviteCode', {
|
||||||
code: 'ABCDEF',
|
code: 'ABCDEF',
|
||||||
})
|
})
|
||||||
|
config = {
|
||||||
|
...config,
|
||||||
|
CATEGORIES_ACTIVE: true,
|
||||||
|
INVITE_REGISTRATION: false,
|
||||||
|
PUBLIC_REGISTRATION: true,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('as anyone', () => {
|
describe('as anyone', () => {
|
||||||
@ -262,11 +270,15 @@ describe('authorization', () => {
|
|||||||
|
|
||||||
describe('invite registration', () => {
|
describe('invite registration', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
CONFIG.INVITE_REGISTRATION = true
|
|
||||||
CONFIG.PUBLIC_REGISTRATION = false
|
|
||||||
await Factory.build('inviteCode', {
|
await Factory.build('inviteCode', {
|
||||||
code: 'ABCDEF',
|
code: 'ABCDEF',
|
||||||
})
|
})
|
||||||
|
config = {
|
||||||
|
...config,
|
||||||
|
CATEGORIES_ACTIVE: true,
|
||||||
|
INVITE_REGISTRATION: true,
|
||||||
|
PUBLIC_REGISTRATION: false,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('as anyone with valid invite code', () => {
|
describe('as anyone with valid invite code', () => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
@ -9,9 +9,8 @@ import { rule, shield, deny, allow, or, and } from 'graphql-shield'
|
|||||||
import CONFIG from '@config/index'
|
import CONFIG from '@config/index'
|
||||||
import SocialMedia from '@db/models/SocialMedia'
|
import SocialMedia from '@db/models/SocialMedia'
|
||||||
import { getNeode } from '@db/neo4j'
|
import { getNeode } from '@db/neo4j'
|
||||||
// eslint-disable-next-line import/no-cycle
|
|
||||||
import { validateInviteCode } from '@graphql/resolvers/inviteCodes'
|
import { validateInviteCode } from '@graphql/resolvers/inviteCodes'
|
||||||
import { Context } from '@src/server'
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
const debug = !!CONFIG.DEBUG
|
const debug = !!CONFIG.DEBUG
|
||||||
const allowExternalErrors = true
|
const allowExternalErrors = true
|
||||||
@ -24,29 +23,29 @@ const isAuthenticated = rule({
|
|||||||
return !!ctx?.user?.id
|
return !!ctx?.user?.id
|
||||||
})
|
})
|
||||||
|
|
||||||
const isModerator = rule()(async (_parent, _args, { user }, _info) => {
|
const isModerator = rule()(async (_parent, _args, { user }: Context, _info) => {
|
||||||
return user && (user.role === 'moderator' || user.role === 'admin')
|
return !!(user && (user.role === 'moderator' || user.role === 'admin'))
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAdmin = rule()(async (_parent, _args, { user }, _info) => {
|
const isAdmin = rule()(async (_parent, _args, { user }: Context, _info) => {
|
||||||
return user && user.role === 'admin'
|
return !!(user && user.role === 'admin')
|
||||||
})
|
})
|
||||||
|
|
||||||
const onlyYourself = rule({
|
const onlyYourself = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, context, _info) => {
|
})(async (_parent, args, context: Context, _info) => {
|
||||||
return context.user.id === args.id
|
return context.user?.id === args.id
|
||||||
})
|
})
|
||||||
|
|
||||||
const isMyOwn = rule({
|
const isMyOwn = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (parent, _args, { user }, _info) => {
|
})(async (parent, _args, { user }: Context, _info) => {
|
||||||
return user && user.id === parent.id
|
return !!(user && user.id === parent.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isMySocialMedia = rule({
|
const isMySocialMedia = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_, args, { user }) => {
|
})(async (_, args, { user }: Context) => {
|
||||||
// We need a User
|
// We need a User
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return false
|
return false
|
||||||
@ -65,7 +64,7 @@ const isMySocialMedia = rule({
|
|||||||
|
|
||||||
const isAllowedToChangeGroupSettings = rule({
|
const isAllowedToChangeGroupSettings = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const ownerId = user.id
|
const ownerId = user.id
|
||||||
const { id: groupId } = args
|
const { id: groupId } = args
|
||||||
@ -89,13 +88,13 @@ const isAllowedToChangeGroupSettings = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAllowedSeeingGroupMembers = rule({
|
const isAllowedSeeingGroupMembers = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const { id: groupId } = args
|
const { id: groupId } = args
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
@ -125,13 +124,13 @@ const isAllowedSeeingGroupMembers = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAllowedToChangeGroupMemberRole = rule({
|
const isAllowedToChangeGroupMemberRole = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const currentUserId = user.id
|
const currentUserId = user.id
|
||||||
const { groupId, userId, roleInGroup } = args
|
const { groupId, userId, roleInGroup } = args
|
||||||
@ -172,13 +171,13 @@ const isAllowedToChangeGroupMemberRole = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAllowedToJoinGroup = rule({
|
const isAllowedToJoinGroup = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const { groupId, userId } = args
|
const { groupId, userId } = args
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
@ -202,13 +201,13 @@ const isAllowedToJoinGroup = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAllowedToLeaveGroup = rule({
|
const isAllowedToLeaveGroup = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const { groupId, userId } = args
|
const { groupId, userId } = args
|
||||||
if (user.id !== userId) return false
|
if (user.id !== userId) return false
|
||||||
@ -232,13 +231,13 @@ const isAllowedToLeaveGroup = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isMemberOfGroup = rule({
|
const isMemberOfGroup = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const { groupId } = args
|
const { groupId } = args
|
||||||
if (!groupId) return true
|
if (!groupId) return true
|
||||||
@ -260,13 +259,13 @@ const isMemberOfGroup = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const canRemoveUserFromGroup = rule({
|
const canRemoveUserFromGroup = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const { groupId, userId } = args
|
const { groupId, userId } = args
|
||||||
const currentUserId = user.id
|
const currentUserId = user.id
|
||||||
@ -296,13 +295,13 @@ const canRemoveUserFromGroup = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const canCommentPost = rule({
|
const canCommentPost = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user?.id) return false
|
if (!user?.id) return false
|
||||||
const { postId } = args
|
const { postId } = args
|
||||||
const userId = user.id
|
const userId = user.id
|
||||||
@ -330,13 +329,13 @@ const canCommentPost = rule({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAuthor = rule({
|
const isAuthor = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }: Context) => {
|
||||||
if (!user) return false
|
if (!user) return false
|
||||||
const { id: resourceId } = args
|
const { id: resourceId } = args
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
@ -354,14 +353,14 @@ const isAuthor = rule({
|
|||||||
const [author] = await authorReadTxPromise
|
const [author] = await authorReadTxPromise
|
||||||
return !!author
|
return !!author
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
await session.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isDeletingOwnAccount = rule({
|
const isDeletingOwnAccount = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, context, _info) => {
|
})(async (_parent, args, context: Context, _info) => {
|
||||||
return context.user.id === args.id
|
return context.user?.id === args.id
|
||||||
})
|
})
|
||||||
|
|
||||||
const noEmailFilter = rule({
|
const noEmailFilter = rule({
|
||||||
@ -370,10 +369,12 @@ const noEmailFilter = rule({
|
|||||||
return !('email' in args)
|
return !('email' in args)
|
||||||
})
|
})
|
||||||
|
|
||||||
const publicRegistration = rule()(() => CONFIG.PUBLIC_REGISTRATION)
|
const publicRegistration = rule()(
|
||||||
|
async (_parent, _args, context: Context) => context.config.PUBLIC_REGISTRATION,
|
||||||
|
)
|
||||||
|
|
||||||
const inviteRegistration = rule()(async (_parent, args, context: Context) => {
|
const inviteRegistration = rule()(async (_parent, args, context: Context) => {
|
||||||
if (!CONFIG.INVITE_REGISTRATION) return false
|
if (!context.config.INVITE_REGISTRATION) return false
|
||||||
const { inviteCode } = args
|
const { inviteCode } = args
|
||||||
return validateInviteCode(context, inviteCode)
|
return validateInviteCode(context, inviteCode)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
import type { Context } from '@src/server'
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
import uniqueSlug from './slugify/uniqueSlug'
|
import uniqueSlug from './slugify/uniqueSlug'
|
||||||
|
|
||||||
|
|||||||
@ -2,16 +2,14 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
import { createGroupMutation } from '@graphql/queries/createGroupMutation'
|
||||||
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
import { createPostMutation } from '@graphql/queries/createPostMutation'
|
||||||
import { signupVerificationMutation } from '@graphql/queries/signupVerificationMutation'
|
import { signupVerificationMutation } from '@graphql/queries/signupVerificationMutation'
|
||||||
import { updateGroupMutation } from '@graphql/queries/updateGroupMutation'
|
import { updateGroupMutation } from '@graphql/queries/updateGroupMutation'
|
||||||
import createServer, { getContext } from '@src/server'
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
|
||||||
let variables
|
let variables
|
||||||
const categoryIds = ['cat9']
|
const categoryIds = ['cat9']
|
||||||
@ -19,23 +17,18 @@ const categoryIds = ['cat9']
|
|||||||
const descriptionAdditional100 =
|
const descriptionAdditional100 =
|
||||||
' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789'
|
' 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789'
|
||||||
|
|
||||||
const database = databaseContext()
|
let authenticatedUser: Context['user']
|
||||||
|
const context = () => ({ authenticatedUser })
|
||||||
let server: ApolloServer
|
let mutate: ApolloTestSetup['mutate']
|
||||||
let authenticatedUser
|
let database: ApolloTestSetup['database']
|
||||||
let mutate
|
let server: ApolloTestSetup['server']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const testServer = createApolloTestSetup({ context })
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await
|
mutate = testServer.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = testServer.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = testServer.server
|
||||||
|
|
||||||
server = createServer({ context }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
|||||||
@ -1,33 +1,29 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
import { ApolloServer } from 'apollo-server-express'
|
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
import { ApolloServer } from 'apollo-server-express'
|
||||||
|
|
||||||
import Factory, { cleanDatabase } from '@db/factories'
|
import Factory, { cleanDatabase } from '@db/factories'
|
||||||
|
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import { createApolloTestSetup } from '@root/test/helpers'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
import { loginMutation } from '@src/graphql/queries/loginMutation'
|
import { loginMutation } from '@src/graphql/queries/loginMutation'
|
||||||
import ocelotLogger from '@src/logger'
|
import ocelotLogger from '@src/logger'
|
||||||
import { loggerPlugin } from '@src/plugins/apolloLogger'
|
import { loggerPlugin } from '@src/plugins/apolloLogger'
|
||||||
import createServer, { getContext } from '@src/server'
|
|
||||||
|
|
||||||
const database = databaseContext()
|
|
||||||
|
|
||||||
let server: ApolloServer
|
let server: ApolloServer
|
||||||
|
|
||||||
let mutate, authenticatedUser
|
const authenticatedUser: Context['user'] = null
|
||||||
|
let mutate: ApolloTestSetup['mutate']
|
||||||
|
let database: ApolloTestSetup['database']
|
||||||
|
const context = () => ({ authenticatedUser })
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
const apolloSetup = createApolloTestSetup({ context, plugins: [loggerPlugin] })
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
mutate = apolloSetup.mutate
|
||||||
const contextUser = async (_req) => authenticatedUser
|
database = apolloSetup.database
|
||||||
const context = getContext({ user: contextUser, database })
|
server = apolloSetup.server
|
||||||
|
|
||||||
server = createServer({ context, plugins: [loggerPlugin] }).server
|
|
||||||
|
|
||||||
const createTestClientResult = createTestClient(server)
|
|
||||||
mutate = createTestClientResult.mutate
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable import/no-named-as-default-member */
|
/* eslint-disable import/no-named-as-default-member */
|
||||||
import http from 'node:http'
|
import http from 'node:http'
|
||||||
@ -13,86 +12,31 @@ import express from 'express'
|
|||||||
import { graphqlUploadExpress } from 'graphql-upload'
|
import { graphqlUploadExpress } from 'graphql-upload'
|
||||||
import helmet from 'helmet'
|
import helmet from 'helmet'
|
||||||
|
|
||||||
import databaseContext from '@context/database'
|
|
||||||
import pubsubContext from '@context/pubsub'
|
|
||||||
|
|
||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
|
import { context, getContext } from './context'
|
||||||
import schema from './graphql/schema'
|
import schema from './graphql/schema'
|
||||||
import decode from './jwt/decode'
|
|
||||||
import ocelotLogger from './logger'
|
|
||||||
// eslint-disable-next-line import/no-cycle
|
|
||||||
import middleware from './middleware'
|
import middleware from './middleware'
|
||||||
|
|
||||||
import type OcelotLogger from './logger'
|
import type { ApolloServerExpressConfig } from 'apollo-server-express'
|
||||||
|
|
||||||
const serverDatabase = databaseContext()
|
const createServer = (options?: ApolloServerExpressConfig) => {
|
||||||
const serverPubsub = pubsubContext()
|
const defaults: ApolloServerExpressConfig = {
|
||||||
|
|
||||||
const databaseUser = async (req) => decode(serverDatabase.driver, req.headers.authorization)
|
|
||||||
|
|
||||||
export const getContext =
|
|
||||||
(
|
|
||||||
{
|
|
||||||
database = serverDatabase,
|
|
||||||
pubsub = serverPubsub,
|
|
||||||
user = databaseUser,
|
|
||||||
logger = ocelotLogger,
|
|
||||||
}: {
|
|
||||||
database?: ReturnType<typeof databaseContext>
|
|
||||||
pubsub?: ReturnType<typeof pubsubContext>
|
|
||||||
user?: (any) => Promise<any>
|
|
||||||
logger?: typeof OcelotLogger
|
|
||||||
} = {
|
|
||||||
database: serverDatabase,
|
|
||||||
pubsub: serverPubsub,
|
|
||||||
user: databaseUser,
|
|
||||||
logger: ocelotLogger,
|
|
||||||
},
|
|
||||||
) =>
|
|
||||||
async (req) => {
|
|
||||||
const u = await user(req)
|
|
||||||
return {
|
|
||||||
database,
|
|
||||||
driver: database.driver,
|
|
||||||
neode: database.neode,
|
|
||||||
pubsub,
|
|
||||||
logger,
|
|
||||||
user: u,
|
|
||||||
req,
|
|
||||||
cypherParams: {
|
|
||||||
currentUserId: u ? u.id : null,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Context = Awaited<ReturnType<ReturnType<typeof getContext>>>
|
|
||||||
|
|
||||||
export const context = async (options) => {
|
|
||||||
const { connection, req } = options
|
|
||||||
if (connection) {
|
|
||||||
return connection.context
|
|
||||||
} else {
|
|
||||||
return getContext()(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const createServer = (options?) => {
|
|
||||||
const defaults = {
|
|
||||||
context,
|
context,
|
||||||
schema: middleware(schema),
|
schema: middleware(schema),
|
||||||
subscriptions: {
|
subscriptions: {
|
||||||
onConnect: (connectionParams) => getContext()(connectionParams),
|
onConnect: (connectionParams) =>
|
||||||
|
getContext()(connectionParams as { headers: { authorization?: string } }),
|
||||||
},
|
},
|
||||||
debug: !!CONFIG.DEBUG,
|
debug: !!CONFIG.DEBUG,
|
||||||
uploads: false,
|
uploads: false,
|
||||||
tracing: !!CONFIG.DEBUG,
|
tracing: !!CONFIG.DEBUG,
|
||||||
formatError: (error) => {
|
formatError: (error) => {
|
||||||
|
// console.log(error.originalError)
|
||||||
if (error.message === 'ERROR_VALIDATION') {
|
if (error.message === 'ERROR_VALIDATION') {
|
||||||
return new Error(error.originalError.details.map((d) => d.message))
|
return new Error((error.originalError as any).details.map((d) => d.message))
|
||||||
}
|
}
|
||||||
return error
|
return error
|
||||||
},
|
},
|
||||||
plugins: [],
|
|
||||||
}
|
}
|
||||||
const server = new ApolloServer(Object.assign(defaults, options))
|
const server = new ApolloServer(Object.assign(defaults, options))
|
||||||
|
|
||||||
|
|||||||
100
backend/test/helpers.ts
Normal file
100
backend/test/helpers.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { createTestClient } from 'apollo-server-testing'
|
||||||
|
|
||||||
|
import databaseContext from '@context/database'
|
||||||
|
import type CONFIG from '@src/config'
|
||||||
|
import type { Context } from '@src/context'
|
||||||
|
import { getContext } from '@src/context'
|
||||||
|
import createServer from '@src/server'
|
||||||
|
|
||||||
|
import type { ApolloServerExpressConfig } from 'apollo-server-express'
|
||||||
|
|
||||||
|
export const TEST_CONFIG = {
|
||||||
|
NODE_ENV: 'test',
|
||||||
|
DEBUG: undefined,
|
||||||
|
TEST: true,
|
||||||
|
PRODUCTION: false,
|
||||||
|
PRODUCTION_DB_CLEAN_ALLOW: false,
|
||||||
|
DISABLED_MIDDLEWARES: [],
|
||||||
|
SEND_MAIL: false,
|
||||||
|
|
||||||
|
CLIENT_URI: 'http://webapp:3000',
|
||||||
|
GRAPHQL_URI: 'http://localhost:4000',
|
||||||
|
JWT_EXPIRES: '2y',
|
||||||
|
|
||||||
|
MAPBOX_TOKEN:
|
||||||
|
'pk.eyJ1IjoiYnVzZmFrdG9yIiwiYSI6ImNraDNiM3JxcDBhaWQydG1uczhpZWtpOW4ifQ.7TNRTO-o9aK1Y6MyW_Nd4g',
|
||||||
|
JWT_SECRET: 'JWT_SECRET',
|
||||||
|
PRIVATE_KEY_PASSPHRASE: 'PRIVATE_KEY_PASSPHRASE',
|
||||||
|
|
||||||
|
NEO4J_URI: 'bolt://localhost:7687',
|
||||||
|
NEO4J_USERNAME: 'neo4j',
|
||||||
|
NEO4J_PASSWORD: 'neo4j',
|
||||||
|
|
||||||
|
SENTRY_DSN_BACKEND: undefined,
|
||||||
|
COMMIT: undefined,
|
||||||
|
|
||||||
|
REDIS_DOMAIN: undefined,
|
||||||
|
REDIS_PORT: undefined,
|
||||||
|
REDIS_PASSWORD: undefined,
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID: '',
|
||||||
|
AWS_SECRET_ACCESS_KEY: '',
|
||||||
|
AWS_ENDPOINT: '',
|
||||||
|
AWS_REGION: '',
|
||||||
|
AWS_BUCKET: '',
|
||||||
|
S3_PUBLIC_GATEWAY: undefined,
|
||||||
|
|
||||||
|
EMAIL_DEFAULT_SENDER: '',
|
||||||
|
SUPPORT_EMAIL: '',
|
||||||
|
SUPPORT_URL: '',
|
||||||
|
APPLICATION_NAME: '',
|
||||||
|
ORGANIZATION_URL: '',
|
||||||
|
PUBLIC_REGISTRATION: false,
|
||||||
|
INVITE_REGISTRATION: true,
|
||||||
|
INVITE_CODES_PERSONAL_PER_USER: 7,
|
||||||
|
INVITE_CODES_GROUP_PER_USER: 7,
|
||||||
|
CATEGORIES_ACTIVE: false,
|
||||||
|
MAX_PINNED_POSTS: 1,
|
||||||
|
|
||||||
|
LANGUAGE_DEFAULT: 'en',
|
||||||
|
LOG_LEVEL: 'DEBUG',
|
||||||
|
} as const satisfies typeof CONFIG
|
||||||
|
|
||||||
|
interface OverwritableContextParams {
|
||||||
|
authenticatedUser?: Context['user']
|
||||||
|
config?: Partial<typeof CONFIG>
|
||||||
|
pubsub?: Context['pubsub']
|
||||||
|
}
|
||||||
|
interface CreateTestServerOptions {
|
||||||
|
context: () => OverwritableContextParams | Promise<OverwritableContextParams>
|
||||||
|
plugins?: ApolloServerExpressConfig['plugins']
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createApolloTestSetup = (opts?: CreateTestServerOptions) => {
|
||||||
|
const defaultOpts: CreateTestServerOptions = { context: () => ({ authenticatedUser: null }) }
|
||||||
|
const { context: testContext, plugins } = opts ?? defaultOpts
|
||||||
|
const database = databaseContext()
|
||||||
|
const context = async (req: { headers: { authorization?: string } }) => {
|
||||||
|
const { authenticatedUser, config = {}, pubsub } = await testContext()
|
||||||
|
return getContext({
|
||||||
|
authenticatedUser,
|
||||||
|
database,
|
||||||
|
pubsub,
|
||||||
|
config: { ...TEST_CONFIG, ...config },
|
||||||
|
})(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = createServer({
|
||||||
|
context,
|
||||||
|
plugins,
|
||||||
|
}).server
|
||||||
|
const { mutate, query } = createTestClient(server)
|
||||||
|
return {
|
||||||
|
server,
|
||||||
|
query,
|
||||||
|
mutate,
|
||||||
|
database,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ApolloTestSetup = ReturnType<typeof createApolloTestSetup>
|
||||||
@ -2361,6 +2361,11 @@
|
|||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
"@types/responselike" "*"
|
"@types/responselike" "*"
|
||||||
|
|
||||||
|
"@types/caseless@*":
|
||||||
|
version "0.12.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.5.tgz#db9468cb1b1b5a925b8f34822f1669df0c5472f5"
|
||||||
|
integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==
|
||||||
|
|
||||||
"@types/connect@*":
|
"@types/connect@*":
|
||||||
version "3.4.33"
|
version "3.4.33"
|
||||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
|
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
|
||||||
@ -2504,6 +2509,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||||
|
|
||||||
|
"@types/jsonwebtoken@~8.5.1":
|
||||||
|
version "8.5.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz#2c064ecb0b3128d837d2764aa0b117b0ff6e4586"
|
||||||
|
integrity sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/keygrip@*":
|
"@types/keygrip@*":
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
|
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
|
||||||
@ -2598,6 +2610,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||||
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
|
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
|
||||||
|
|
||||||
|
"@types/request@^2.48.12":
|
||||||
|
version "2.48.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30"
|
||||||
|
integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==
|
||||||
|
dependencies:
|
||||||
|
"@types/caseless" "*"
|
||||||
|
"@types/node" "*"
|
||||||
|
"@types/tough-cookie" "*"
|
||||||
|
form-data "^2.5.0"
|
||||||
|
|
||||||
"@types/responselike@*", "@types/responselike@^1.0.0":
|
"@types/responselike@*", "@types/responselike@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
|
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
|
||||||
@ -2628,6 +2650,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
|
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
|
||||||
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
|
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
|
||||||
|
|
||||||
|
"@types/tough-cookie@*":
|
||||||
|
version "4.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304"
|
||||||
|
integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==
|
||||||
|
|
||||||
"@types/uuid@^9.0.1", "@types/uuid@~9.0.1":
|
"@types/uuid@^9.0.1", "@types/uuid@~9.0.1":
|
||||||
version "9.0.8"
|
version "9.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
|
||||||
@ -4946,6 +4973,16 @@ es-set-tostringtag@^2.0.3:
|
|||||||
has-tostringtag "^1.0.2"
|
has-tostringtag "^1.0.2"
|
||||||
hasown "^2.0.1"
|
hasown "^2.0.1"
|
||||||
|
|
||||||
|
es-set-tostringtag@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
|
||||||
|
integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
|
||||||
|
dependencies:
|
||||||
|
es-errors "^1.3.0"
|
||||||
|
get-intrinsic "^1.2.6"
|
||||||
|
has-tostringtag "^1.0.2"
|
||||||
|
hasown "^2.0.2"
|
||||||
|
|
||||||
es-shim-unscopables@^1.0.0:
|
es-shim-unscopables@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
|
resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
|
||||||
@ -5712,6 +5749,17 @@ foreground-child@^3.1.0:
|
|||||||
cross-spawn "^7.0.6"
|
cross-spawn "^7.0.6"
|
||||||
signal-exit "^4.0.1"
|
signal-exit "^4.0.1"
|
||||||
|
|
||||||
|
form-data@^2.5.0:
|
||||||
|
version "2.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.3.tgz#f9bcf87418ce748513c0c3494bb48ec270c97acc"
|
||||||
|
integrity sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.8"
|
||||||
|
es-set-tostringtag "^2.1.0"
|
||||||
|
mime-types "^2.1.35"
|
||||||
|
safe-buffer "^5.2.1"
|
||||||
|
|
||||||
form-data@^3.0.0:
|
form-data@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
|
||||||
@ -5836,7 +5884,7 @@ get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
|
|||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
hasown "^2.0.0"
|
hasown "^2.0.0"
|
||||||
|
|
||||||
get-intrinsic@^1.2.5, get-intrinsic@^1.3.0:
|
get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
||||||
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
||||||
@ -8078,7 +8126,7 @@ mime-db@^1.54.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
|
||||||
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
||||||
|
|
||||||
mime-types@^2.1.12, mime-types@~2.1.22, mime-types@~2.1.24, mime-types@~2.1.34:
|
mime-types@^2.1.12, mime-types@^2.1.35, mime-types@~2.1.22, mime-types@~2.1.24, mime-types@~2.1.34:
|
||||||
version "2.1.35"
|
version "2.1.35"
|
||||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
@ -9481,7 +9529,7 @@ safe-array-concat@^1.1.2:
|
|||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
isarray "^2.0.5"
|
isarray "^2.0.5"
|
||||||
|
|
||||||
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
|
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||||
import encode from '../../../../backend/build/src/jwt/encode'
|
import CONFIG from '../../../../backend/build/src/config/index'
|
||||||
|
import { encode } from '../../../../backend/build/src/jwt/encode'
|
||||||
|
|
||||||
defineStep('I am logged in as {string}', slug => {
|
defineStep('I am logged in as {string}', slug => {
|
||||||
cy.neode()
|
cy.neode()
|
||||||
@ -13,6 +14,6 @@ defineStep('I am logged in as {string}', slug => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(user => {
|
.then(user => {
|
||||||
cy.setCookie('ocelot-social-token', encode(user))
|
cy.setCookie('ocelot-social-token', encode({ config: CONFIG })(user))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user