mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-03-01 12:44:37 +00:00
fix easy types
This commit is contained in:
parent
fc5d3aca8e
commit
a3db2ae89e
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
|
||||
import { hashSync } from 'bcryptjs'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
@ -18,7 +17,7 @@ const defaultAdmin = {
|
||||
const createDefaultAdminUser = async () => {
|
||||
const driver = getDriver()
|
||||
const session = driver.session()
|
||||
const createAdminTxResultPromise = session.writeTransaction(async (txc) => {
|
||||
const createAdminTxResultPromise = session.writeTransaction((txc) => {
|
||||
txc.run(
|
||||
`MERGE (e:EmailAddress {
|
||||
email: "${defaultAdmin.email}",
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
|
||||
@ -38,10 +37,10 @@ const swap = async function (next) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function up(next) {
|
||||
export function up(next) {
|
||||
swap(next)
|
||||
}
|
||||
|
||||
export async function down(next) {
|
||||
export function down(next) {
|
||||
swap(next)
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
@ -42,7 +41,7 @@ export async function up(next) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(next) {
|
||||
export function down(next) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Irreversible migration')
|
||||
next()
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
@ -44,7 +43,7 @@ export async function up(next) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(next) {
|
||||
export function down(next) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Irreversible migration')
|
||||
next()
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
@ -65,6 +64,6 @@ export async function up(next) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function down() {
|
||||
export function down() {
|
||||
throw new Error('Irreversible migration')
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-base-to-string */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
|
||||
import { getDriver } from '@db/neo4j'
|
||||
|
||||
@ -31,9 +30,9 @@ export async function up(_next) {
|
||||
eventEnd = date.toISOString()
|
||||
}
|
||||
await transaction.run(`
|
||||
MATCH (e:Event { id: '${id}' })
|
||||
SET e.eventStart = '${eventStart}'
|
||||
SET (CASE WHEN exists(e.eventEnd) THEN e END).eventEnd = '${eventEnd}'
|
||||
MATCH (e:Event { id: '${String(id)}' })
|
||||
SET e.eventStart = '${String(eventStart)}'
|
||||
SET (CASE WHEN exists(e.eventEnd) THEN e END).eventEnd = '${String(eventEnd)}'
|
||||
RETURN e
|
||||
`)
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
|
||||
import CONFIG from '@config/index'
|
||||
@ -16,7 +15,7 @@ if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
|
||||
process.exit(0)
|
||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
||||
} catch (err) {
|
||||
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`) // eslint-disable-line no-console
|
||||
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${String(err)}`) // eslint-disable-line no-console
|
||||
process.exit(1)
|
||||
}
|
||||
})()
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
|
||||
import CONFIG from '@config/index'
|
||||
@ -16,7 +15,7 @@ if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
|
||||
process.exit(0)
|
||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
||||
} catch (err) {
|
||||
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`) // eslint-disable-line no-console
|
||||
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${String(err)}`) // eslint-disable-line no-console
|
||||
process.exit(1)
|
||||
}
|
||||
})()
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable n/no-unpublished-import */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
||||
|
||||
import { faker } from '@faker-js/faker'
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* 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-member-access */
|
||||
@ -29,7 +28,7 @@ export const defaultVerificationBadge = {
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
Badge: async (object, args, context, resolveInfo) =>
|
||||
Badge: (object, args, context, resolveInfo) =>
|
||||
neo4jgraphql(object, args, context, resolveInfo),
|
||||
},
|
||||
|
||||
@ -172,7 +171,7 @@ export default {
|
||||
},
|
||||
},
|
||||
Badge: {
|
||||
isDefault: async (parent, _params, _context, _resolveInfo) =>
|
||||
isDefault: (parent, _params, _context, _resolveInfo) =>
|
||||
[defaultTrophyBadge.id, defaultVerificationBadge.id].includes(parent.id),
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import scrape from './embeds/scraper'
|
||||
@ -6,7 +5,7 @@ import { undefinedToNullResolver } from './helpers/Resolver'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
embed: async (_object, { url }, _context, _resolveInfo) => {
|
||||
embed: (_object, { url }, _context, _resolveInfo) => {
|
||||
return scrape(url)
|
||||
},
|
||||
},
|
||||
@ -25,7 +24,7 @@ export default {
|
||||
'lang',
|
||||
'html',
|
||||
]),
|
||||
sources: async (parent, _params, _context, _resolveInfo) => {
|
||||
sources: (parent, _params, _context, _resolveInfo) => {
|
||||
return typeof parent.sources === 'undefined' ? [] : parent.sources
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
@ -53,7 +52,7 @@ const fetchEmbed = async (url) => {
|
||||
json = await response.json()
|
||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
||||
} catch (err) {
|
||||
error(`Error fetching embed data: ${err.message}`)
|
||||
error(`Error fetching embed data: ${String(err.message)}`)
|
||||
return {}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
@ -6,7 +5,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
import { CATEGORIES_MIN, CATEGORIES_MAX } from '@constants/categories'
|
||||
@ -20,6 +18,35 @@ import { createOrUpdateLocations } from './users/location'
|
||||
|
||||
import type { Context } from '@src/context'
|
||||
|
||||
const removeUserFromGroupWriteTxResultPromise = async (session, groupId, userId) => {
|
||||
return session.writeTransaction(async (transaction) => {
|
||||
const removeUserFromGroupCypher = `
|
||||
MATCH (user:User {id: $userId})-[membership:MEMBER_OF]->(group:Group {id: $groupId})
|
||||
DELETE membership
|
||||
WITH user, group
|
||||
OPTIONAL MATCH (author:User)-[:WROTE]->(p:Post)-[:IN]->(group)
|
||||
WHERE NOT group.groupType = 'public'
|
||||
AND NOT author.id = $userId
|
||||
WITH user, collect(p) AS posts
|
||||
FOREACH (post IN posts |
|
||||
MERGE (user)-[:CANNOT_SEE]->(post))
|
||||
RETURN user {.*}, NULL as membership
|
||||
`
|
||||
|
||||
const transactionResponse = await transaction.run(removeUserFromGroupCypher, {
|
||||
groupId,
|
||||
userId,
|
||||
})
|
||||
const [result] = transactionResponse.records.map((record) => {
|
||||
return { user: record.get('user'), membership: record.get('membership') }
|
||||
})
|
||||
if (!result) {
|
||||
throw new UserInputError('User is not a member of this group')
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
Group: async (_object, params, context: Context, _resolveInfo) => {
|
||||
@ -488,13 +515,13 @@ export default {
|
||||
membersCount: '<-[:MEMBER_OF]-(related:User)',
|
||||
},
|
||||
}),
|
||||
name: async (parent, _args, context: Context, _resolveInfo) => {
|
||||
name: (parent, _args, context: Context, _resolveInfo) => {
|
||||
if (!context.user) {
|
||||
return parent.groupType === 'hidden' ? '' : parent.name
|
||||
}
|
||||
return parent.name
|
||||
},
|
||||
about: async (parent, _args, context: Context, _resolveInfo) => {
|
||||
about: (parent, _args, context: Context, _resolveInfo) => {
|
||||
if (!context.user) {
|
||||
return parent.groupType === 'hidden' ? '' : parent.about
|
||||
}
|
||||
@ -502,32 +529,3 @@ export default {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const removeUserFromGroupWriteTxResultPromise = async (session, groupId, userId) => {
|
||||
return session.writeTransaction(async (transaction) => {
|
||||
const removeUserFromGroupCypher = `
|
||||
MATCH (user:User {id: $userId})-[membership:MEMBER_OF]->(group:Group {id: $groupId})
|
||||
DELETE membership
|
||||
WITH user, group
|
||||
OPTIONAL MATCH (author:User)-[:WROTE]->(p:Post)-[:IN]->(group)
|
||||
WHERE NOT group.groupType = 'public'
|
||||
AND NOT author.id = $userId
|
||||
WITH user, collect(p) AS posts
|
||||
FOREACH (post IN posts |
|
||||
MERGE (user)-[:CANNOT_SEE]->(post))
|
||||
RETURN user {.*}, NULL as membership
|
||||
`
|
||||
|
||||
const transactionResponse = await transaction.run(removeUserFromGroupCypher, {
|
||||
groupId,
|
||||
userId,
|
||||
})
|
||||
const [result] = transactionResponse.records.map((record) => {
|
||||
return { user: record.get('user'), membership: record.get('membership') }
|
||||
})
|
||||
if (!result) {
|
||||
throw new UserInputError('User is not a member of this group')
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-dynamic-delete */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
@ -11,7 +9,7 @@
|
||||
export const undefinedToNullResolver = (list) => {
|
||||
const resolvers = {}
|
||||
list.forEach((key) => {
|
||||
resolvers[key] = async (parent) => {
|
||||
resolvers[key] = (parent) => {
|
||||
return typeof parent[key] === 'undefined' ? null : parent[key]
|
||||
}
|
||||
})
|
||||
@ -37,7 +35,7 @@ export default function Resolver(type, options: any = {}) {
|
||||
try {
|
||||
let response = await session.readTransaction(async (txc) => {
|
||||
const cypher = `
|
||||
MATCH(:${type} {${idAttribute}: $id})${connection}
|
||||
MATCH(:${String(type)} {${String(idAttribute)}: $id})${String(connection)}
|
||||
RETURN related {.*} as related
|
||||
`
|
||||
const result = await txc.run(cypher, { id, cypherParams })
|
||||
@ -62,7 +60,7 @@ export default function Resolver(type, options: any = {}) {
|
||||
try {
|
||||
return await session.readTransaction(async (txc) => {
|
||||
const nodeCondition = condition.replace('this', 'this {id: $id}')
|
||||
const cypher = `${nodeCondition} as ${key}`
|
||||
const cypher = `${String(nodeCondition)} as ${key}`
|
||||
const result = await txc.run(cypher, { id, cypherParams })
|
||||
const [response] = result.records.map((r) => r.get(key))
|
||||
return response
|
||||
@ -85,7 +83,7 @@ export default function Resolver(type, options: any = {}) {
|
||||
return await session.readTransaction(async (txc) => {
|
||||
const id = parent[idAttribute]
|
||||
const cypher = `
|
||||
MATCH(u:${type} {${idAttribute}: $id})${connection}
|
||||
MATCH(u:${String(type)} {${String(idAttribute)}: $id})${String(connection)}
|
||||
RETURN COUNT(DISTINCT(related)) as count
|
||||
`
|
||||
const result = await txc.run(cypher, { id, cypherParams })
|
||||
@ -141,7 +139,7 @@ export const convertObjectToCypherMapLiteral = (params, addSpaceInfrontIfMapIsNo
|
||||
let mapLiteral = ''
|
||||
paramsEntries.forEach((ele, index) => {
|
||||
mapLiteral += index === 0 ? '{' : ''
|
||||
mapLiteral += `${ele[0]}: "${ele[1]}"`
|
||||
mapLiteral += `${ele[0]}: "${String(ele[1])}"`
|
||||
mapLiteral += index < paramsEntries.length - 1 ? ', ' : '}'
|
||||
})
|
||||
mapLiteral = (addSpaceInfrontIfMapIsNotEmpty && mapLiteral.length > 0 ? ' ' : '') + mapLiteral
|
||||
|
||||
@ -2,9 +2,31 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import { UserInputError } from '@graphql/errors'
|
||||
|
||||
const validateEventDate = (dateString) => {
|
||||
const date = new Date(dateString)
|
||||
if (date.toString() === 'Invalid Date')
|
||||
throw new UserInputError('Event start date must be a valid date!')
|
||||
if (date.toISOString() !== dateString)
|
||||
throw new UserInputError('Event start date must be in ISO format!')
|
||||
const now = new Date()
|
||||
if (date.getTime() < now.getTime()) {
|
||||
throw new UserInputError('Event start date must be in the future!')
|
||||
}
|
||||
}
|
||||
|
||||
const validateEventEnd = (start, end) => {
|
||||
const endDate = new Date(end)
|
||||
if (endDate.toString() === 'Invalid Date')
|
||||
throw new UserInputError('Event end date must be a valid date!')
|
||||
if (endDate.toISOString() !== end)
|
||||
throw new UserInputError('Event end date must be in ISO format!')
|
||||
const startDate = new Date(start)
|
||||
if (endDate < startDate)
|
||||
throw new UserInputError('Event end date must be a after event start date!')
|
||||
}
|
||||
|
||||
export const validateEventParams = (params) => {
|
||||
let locationName = null
|
||||
if (params.postType && params.postType === 'Event') {
|
||||
@ -34,26 +56,3 @@ export const validateEventParams = (params) => {
|
||||
delete params.eventInput
|
||||
return locationName
|
||||
}
|
||||
|
||||
const validateEventDate = (dateString) => {
|
||||
const date = new Date(dateString)
|
||||
if (date.toString() === 'Invalid Date')
|
||||
throw new UserInputError('Event start date must be a valid date!')
|
||||
if (date.toISOString() !== dateString)
|
||||
throw new UserInputError('Event start date must be in ISO format!')
|
||||
const now = new Date()
|
||||
if (date.getTime() < now.getTime()) {
|
||||
throw new UserInputError('Event start date must be in the future!')
|
||||
}
|
||||
}
|
||||
|
||||
const validateEventEnd = (start, end) => {
|
||||
const endDate = new Date(end)
|
||||
if (endDate.toString() === 'Invalid Date')
|
||||
throw new UserInputError('Event end date must be a valid date!')
|
||||
if (endDate.toISOString() !== end)
|
||||
throw new UserInputError('Event end date must be in ISO format!')
|
||||
const startDate = new Date(start)
|
||||
if (endDate < startDate)
|
||||
throw new UserInputError('Event end date must be a after event start date!')
|
||||
}
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import crypto from 'node:crypto'
|
||||
import { join as joinPath } from 'node:path/posix'
|
||||
|
||||
@ -15,6 +13,16 @@ type UrlResolver = (
|
||||
}: Pick<Context, 'config'>,
|
||||
) => string
|
||||
|
||||
const chain: (...methods: UrlResolver[]) => UrlResolver = (...methods) => {
|
||||
return (parent, args, context) => {
|
||||
let { url } = parent
|
||||
for (const method of methods) {
|
||||
url = method({ url }, args, context)
|
||||
}
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
const pointUrlToImagor: (opts: { transformations: UrlResolver[] }) => UrlResolver =
|
||||
({ transformations }) =>
|
||||
({ url }, _args, context) => {
|
||||
@ -59,22 +67,12 @@ const resize: UrlResolver = ({ url }, { height, width }) => {
|
||||
if (!(height || width)) {
|
||||
return url
|
||||
}
|
||||
const window = `/fit-in/${width ?? FALLBACK_MAXIMUM_LENGTH}x${height ?? FALLBACK_MAXIMUM_LENGTH}`
|
||||
const window = `/fit-in/${String(width ?? FALLBACK_MAXIMUM_LENGTH)}x${String(height ?? FALLBACK_MAXIMUM_LENGTH)}`
|
||||
const newUrl = new URL(url)
|
||||
newUrl.pathname = window + newUrl.pathname
|
||||
return newUrl.href
|
||||
}
|
||||
|
||||
const chain: (...methods: UrlResolver[]) => UrlResolver = (...methods) => {
|
||||
return (parent, args, context) => {
|
||||
let { url } = parent
|
||||
for (const method of methods) {
|
||||
url = method({ url }, args, context)
|
||||
}
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
Image: {
|
||||
...Resolver('Image', {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
import path from 'node:path'
|
||||
|
||||
@ -41,6 +40,17 @@ export const images = (config: S3Config) => {
|
||||
return image
|
||||
}
|
||||
|
||||
const uploadImageFile = async (uploadPromise: Promise<FileUpload> | undefined) => {
|
||||
if (!uploadPromise) return undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const upload = await uploadPromise
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
|
||||
const { name, ext } = path.parse(upload.filename)
|
||||
const uniqueFilename = `${uuid()}-${slug(name)}${ext}`
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
return await s3.uploadFile({ ...upload, uniqueFilename })
|
||||
}
|
||||
|
||||
const mergeImage: Images['mergeImage'] = async (
|
||||
resource,
|
||||
relationshipType,
|
||||
@ -84,17 +94,6 @@ export const images = (config: S3Config) => {
|
||||
return mergedImage
|
||||
}
|
||||
|
||||
const uploadImageFile = async (uploadPromise: Promise<FileUpload> | undefined) => {
|
||||
if (!uploadPromise) return undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const upload = await uploadPromise
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
|
||||
const { name, ext } = path.parse(upload.filename)
|
||||
const uniqueFilename = `${uuid()}-${slug(name)}${ext}`
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
return await s3.uploadFile({ ...upload, uniqueFilename })
|
||||
}
|
||||
|
||||
const images = {
|
||||
deleteImage,
|
||||
mergeImage,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
@ -16,7 +15,7 @@ import Resolver from './helpers/Resolver'
|
||||
|
||||
import type { File } from './attachments/attachments'
|
||||
|
||||
const setMessagesAsDistributed = async (undistributedMessagesIds, session) => {
|
||||
const setMessagesAsDistributed = (undistributedMessagesIds, session) => {
|
||||
return session.writeTransaction(async (transaction) => {
|
||||
const setDistributedCypher = `
|
||||
MATCH (m:Message) WHERE m.id IN $undistributedMessagesIds
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
@ -45,8 +43,8 @@ export default {
|
||||
default:
|
||||
orderByClause = ''
|
||||
}
|
||||
const offset = args.offset && typeof args.offset === 'number' ? `SKIP ${args.offset}` : ''
|
||||
const limit = args.first && typeof args.first === 'number' ? `LIMIT ${args.first}` : ''
|
||||
const offset = args.offset && typeof args.offset === 'number' ? `SKIP ${String(args.offset)}` : ''
|
||||
const limit = args.first && typeof args.first === 'number' ? `LIMIT ${String(args.first)}` : ''
|
||||
|
||||
const readTxResultPromise = session.readTransaction(async (transaction) => {
|
||||
const notificationsTransactionResponse = await transaction.run(
|
||||
@ -145,9 +143,9 @@ export default {
|
||||
},
|
||||
},
|
||||
NOTIFIED: {
|
||||
id: async (parent) => {
|
||||
id: (parent) => {
|
||||
// serialize an ID to help the client update the cache
|
||||
return `${parent.reason}/${parent.from.id}/${parent.to.id}`
|
||||
return `${String(parent.reason)}/${String(parent.from.id)}/${String(parent.to.id)}`
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
@ -186,7 +185,7 @@ export default {
|
||||
SET post.sortDate = toString(datetime())
|
||||
SET post.clickedCount = 0
|
||||
SET post.viewedTeaserCount = 0
|
||||
SET post:${params.postType}
|
||||
SET post:${String(params.postType)}
|
||||
WITH post
|
||||
MATCH (author:User {id: $userId})
|
||||
MERGE (post)<-[:WROTE]-(author)
|
||||
@ -260,7 +259,7 @@ export default {
|
||||
updatePostCypher += `
|
||||
REMOVE post:Article
|
||||
REMOVE post:Event
|
||||
SET post:${params.postType}
|
||||
SET post:${String(params.postType)}
|
||||
WITH post
|
||||
`
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
@ -80,8 +79,8 @@ export default {
|
||||
const filterClause = filterClauses.join(' ')
|
||||
|
||||
const offset =
|
||||
params.offset && typeof params.offset === 'number' ? `SKIP ${params.offset}` : ''
|
||||
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${params.first}` : ''
|
||||
params.offset && typeof params.offset === 'number' ? `SKIP ${String(params.offset)}` : ''
|
||||
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${String(params.first)}` : ''
|
||||
|
||||
const reportsReadTxPromise = session.readTransaction(async (transaction) => {
|
||||
const reportsTransactionResponse = await transaction.run(
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
export default {
|
||||
Query: {
|
||||
availableRoles: async (_parent, _args, _context, _resolveInfo) => {
|
||||
availableRoles: (_parent, _args, _context, _resolveInfo) => {
|
||||
return ['admin', 'moderator', 'user']
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
@ -38,7 +37,7 @@ export default {
|
||||
},
|
||||
},
|
||||
Query: {
|
||||
Room: async (object, params, context, resolveInfo) => {
|
||||
Room: (object, params, context, resolveInfo) => {
|
||||
if (!params.filter) params.filter = {}
|
||||
params.filter.users_some = {
|
||||
id: context.user.id,
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
import { queryString } from './searches/queryString'
|
||||
@ -10,16 +8,16 @@ import { queryString } from './searches/queryString'
|
||||
// see http://lucene.apache.org/core/8_3_1/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description
|
||||
|
||||
const cypherTemplate = (setup) => `
|
||||
CALL db.index.fulltext.queryNodes('${setup.fulltextIndex}', $query)
|
||||
CALL db.index.fulltext.queryNodes('${String(setup.fulltextIndex)}', $query)
|
||||
YIELD node AS resource, score
|
||||
${setup.match}
|
||||
${setup.whereClause}
|
||||
${setup.withClause}
|
||||
RETURN
|
||||
${setup.returnClause}
|
||||
${String(setup.match)}
|
||||
${String(setup.whereClause)}
|
||||
${String(setup.withClause)}
|
||||
RETURN
|
||||
${String(setup.returnClause)}
|
||||
AS result
|
||||
SKIP toInteger($skip)
|
||||
${setup.limit}
|
||||
${String(setup.limit)}
|
||||
`
|
||||
|
||||
const simpleWhereClause =
|
||||
@ -148,7 +146,7 @@ const multiSearchMap = [
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
searchPosts: async (_parent, args, context, _resolveInfo) => {
|
||||
searchPosts: (_parent, args, context, _resolveInfo) => {
|
||||
const { query, postsOffset, firstPosts } = args
|
||||
let userId = null
|
||||
if (context.user) userId = context.user.id
|
||||
@ -171,7 +169,7 @@ export default {
|
||||
}),
|
||||
}
|
||||
},
|
||||
searchUsers: async (_parent, args, context, _resolveInfo) => {
|
||||
searchUsers: (_parent, args, context, _resolveInfo) => {
|
||||
const { query, usersOffset, firstUsers } = args
|
||||
return {
|
||||
userCount: getSearchResults(
|
||||
@ -190,7 +188,7 @@ export default {
|
||||
}),
|
||||
}
|
||||
},
|
||||
searchHashtags: async (_parent, args, context, _resolveInfo) => {
|
||||
searchHashtags: (_parent, args, context, _resolveInfo) => {
|
||||
const { query, hashtagsOffset, firstHashtags } = args
|
||||
return {
|
||||
hashtagCount: getSearchResults(
|
||||
@ -209,7 +207,7 @@ export default {
|
||||
}),
|
||||
}
|
||||
},
|
||||
searchGroups: async (_parent, args, context, _resolveInfo) => {
|
||||
searchGroups: (_parent, args, context, _resolveInfo) => {
|
||||
const { query, groupsOffset, firstGroups } = args
|
||||
let userId = null
|
||||
if (context.user) userId = context.user.id
|
||||
|
||||
@ -2,48 +2,7 @@
|
||||
/* 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/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
export function queryString(str) {
|
||||
const normalizedString = normalizeWhitespace(str)
|
||||
const escapedString = escapeSpecialCharacters(normalizedString)
|
||||
return `
|
||||
${matchWholeText(escapedString)}
|
||||
${matchEachWordExactly(escapedString)}
|
||||
${matchSomeWordsExactly(escapedString)}
|
||||
${matchBeginningOfWords(escapedString)}
|
||||
`
|
||||
}
|
||||
|
||||
const matchWholeText = (str, boost = 8) => {
|
||||
return `"${str}"^${boost}`
|
||||
}
|
||||
|
||||
const matchEachWordExactly = (str, boost = 4) => {
|
||||
if (!str.includes(' ')) return ''
|
||||
const tmp = str
|
||||
.split(' ')
|
||||
.map((s, i) => (i === 0 ? `"${s}"` : `AND "${s}"`))
|
||||
.join(' ')
|
||||
return `(${tmp})^${boost}`
|
||||
}
|
||||
|
||||
const matchSomeWordsExactly = (str, boost = 2) => {
|
||||
if (!str.includes(' ')) return ''
|
||||
return str
|
||||
.split(' ')
|
||||
.map((s) => `"${s}"^${boost}`)
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const matchBeginningOfWords = (str) => {
|
||||
return str
|
||||
.split(' ')
|
||||
.filter((s) => s.length >= 2)
|
||||
.map((s) => s + '*')
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
export function normalizeWhitespace(str) {
|
||||
// delete the first character if it is !, @ or #
|
||||
@ -56,3 +15,43 @@ export function normalizeWhitespace(str) {
|
||||
export function escapeSpecialCharacters(str) {
|
||||
return str.replace(/(["[\]&|\\{}+!()^~*?:/-])/g, '\\$1')
|
||||
}
|
||||
|
||||
const matchWholeText = (str, boost = 8) => {
|
||||
return `"${String(str)}"^${String(boost)}`
|
||||
}
|
||||
|
||||
const matchEachWordExactly = (str, boost = 4) => {
|
||||
if (!str.includes(' ')) return ''
|
||||
const tmp = str
|
||||
.split(' ')
|
||||
.map((s, i) => (i === 0 ? `"${String(s)}"` : `AND "${String(s)}"`))
|
||||
.join(' ')
|
||||
return `(${tmp})^${String(boost)}`
|
||||
}
|
||||
|
||||
const matchSomeWordsExactly = (str, boost = 2) => {
|
||||
if (!str.includes(' ')) return ''
|
||||
return str
|
||||
.split(' ')
|
||||
.map((s) => `"${String(s)}"^${String(boost)}`)
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const matchBeginningOfWords = (str) => {
|
||||
return str
|
||||
.split(' ')
|
||||
.filter((s) => s.length >= 2)
|
||||
.map((s) => s + '*')
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
export function queryString(str) {
|
||||
const normalizedString = normalizeWhitespace(str)
|
||||
const escapedString = escapeSpecialCharacters(normalizedString)
|
||||
return `
|
||||
${matchWholeText(escapedString)}
|
||||
${matchEachWordExactly(escapedString)}
|
||||
${matchSomeWordsExactly(escapedString)}
|
||||
${matchBeginningOfWords(escapedString)}
|
||||
`
|
||||
}
|
||||
|
||||
@ -2,7 +2,13 @@
|
||||
/* 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-use-before-define */
|
||||
|
||||
const byCreationDate = (a, b) => {
|
||||
if (a.createdAt < b.createdAt) return -1
|
||||
if (a.createdAt > b.createdAt) return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
userData: async (_object, _args, context, _resolveInfo) => {
|
||||
@ -53,9 +59,3 @@ export default {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const byCreationDate = (a, b) => {
|
||||
if (a.createdAt < b.createdAt) return -1
|
||||
if (a.createdAt > b.createdAt) return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
@ -215,11 +214,11 @@ export default {
|
||||
await Promise.all(
|
||||
resource.map(async (node) => {
|
||||
if (!allowedLabels.includes(node)) {
|
||||
throw new UserInputError(`Invalid resource type: ${node}`)
|
||||
throw new UserInputError(`Invalid resource type: ${String(node)}`)
|
||||
}
|
||||
const txResult = await transaction.run(
|
||||
`
|
||||
MATCH (resource:${node})<-[:WROTE]-(author:User {id: $userId})
|
||||
MATCH (resource:${String(node)})<-[:WROTE]-(author:User {id: $userId})
|
||||
OPTIONAL MATCH (resource)<-[:COMMENTS]-(comment:Comment)
|
||||
SET resource.deleted = true
|
||||
SET resource.content = 'UNAVAILABLE'
|
||||
@ -371,7 +370,7 @@ export default {
|
||||
|
||||
if (slot >= TROPHY_BADGES_SELECTED_MAX || slot < 0) {
|
||||
throw new Error(
|
||||
`Invalid slot! There is only ${TROPHY_BADGES_SELECTED_MAX} badge-slots to fill`,
|
||||
`Invalid slot! There is only ${String(TROPHY_BADGES_SELECTED_MAX)} badge-slots to fill`,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
@ -19,7 +18,7 @@ const REQUEST_TIMEOUT = 3000
|
||||
|
||||
const createLocation = async (session, mapboxData) => {
|
||||
const data = {
|
||||
id: mapboxData.id + (mapboxData.address ? `-${mapboxData.address}` : ''),
|
||||
id: mapboxData.id + (mapboxData.address ? `-${String(mapboxData.address)}` : ''),
|
||||
nameEN: mapboxData.text_en,
|
||||
nameDE: mapboxData.text_de,
|
||||
nameFR: mapboxData.text_fr,
|
||||
@ -77,9 +76,9 @@ export const createOrUpdateLocations = async (
|
||||
if (locationName !== null) {
|
||||
const response: any = await fetch(
|
||||
`https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
|
||||
locationName,
|
||||
String(locationName),
|
||||
)}.json?access_token=${
|
||||
context.config.MAPBOX_TOKEN
|
||||
String(context.config.MAPBOX_TOKEN)
|
||||
}&types=region,place,country,address&language=${locales.join(',')}`,
|
||||
{
|
||||
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
|
||||
@ -115,7 +114,7 @@ export const createOrUpdateLocations = async (
|
||||
let parent = data
|
||||
|
||||
if (parent.address) {
|
||||
parent.id += `-${parent.address}`
|
||||
parent.id += `-${String(parent.address)}`
|
||||
}
|
||||
|
||||
if (data.context) {
|
||||
@ -147,7 +146,7 @@ export const createOrUpdateLocations = async (
|
||||
await session.writeTransaction((transaction) => {
|
||||
return transaction.run(
|
||||
`
|
||||
MATCH (node:${nodeLabel} {id: $nodeId})
|
||||
MATCH (node:${String(nodeLabel)} {id: $nodeId})
|
||||
OPTIONAL MATCH (node)-[relationship:IS_IN]->(:Location)
|
||||
DELETE relationship
|
||||
WITH node
|
||||
@ -162,7 +161,7 @@ export const createOrUpdateLocations = async (
|
||||
|
||||
export const queryLocations = async ({ place, lang }, context: Context) => {
|
||||
const res: any = await fetch(
|
||||
`https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${context.config.MAPBOX_TOKEN}&types=region,place,country&language=${lang}`,
|
||||
`https://api.mapbox.com/geocoding/v5/mapbox.places/${String(place)}.json?access_token=${String(context.config.MAPBOX_TOKEN)}&types=region,place,country&language=${String(lang)}`,
|
||||
{
|
||||
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
|
||||
},
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
@ -9,33 +8,33 @@ import { DESCRIPTION_EXCERPT_HTML_LENGTH } from '@constants/groups'
|
||||
|
||||
import type { IMiddlewareResolver } from 'graphql-middleware/dist/types'
|
||||
|
||||
const createGroup: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const createGroup: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.descriptionExcerpt = trunc(args.description, DESCRIPTION_EXCERPT_HTML_LENGTH).html
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const updateGroup: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const updateGroup: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
if (args.description)
|
||||
args.descriptionExcerpt = trunc(args.description, DESCRIPTION_EXCERPT_HTML_LENGTH).html
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const createPost: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const createPost: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.contentExcerpt = trunc(args.content, 120).html
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const updatePost: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const updatePost: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.contentExcerpt = trunc(args.content, 120).html
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const createComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const createComment: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.contentExcerpt = trunc(args.content, 180).html
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const updateComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const updateComment: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.contentExcerpt = trunc(args.content, 180).html
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable security/detect-object-injection */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
||||
import {
|
||||
@ -43,136 +42,6 @@ const publishNotifications = async (
|
||||
return emailsSent
|
||||
}
|
||||
|
||||
const handleJoinGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context),
|
||||
'emailNotificationsGroupMemberJoined',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleLeaveGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyOwnersOfGroup(groupId, userId, 'user_left_group', context),
|
||||
'emailNotificationsGroupMemberLeft',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleChangeGroupMemberRole: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context),
|
||||
'emailNotificationsGroupMemberRoleChanged',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleRemoveUserFromGroup: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context),
|
||||
'emailNotificationsGroupMemberRemoved',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleContentDataOfPost: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { groupId } = args
|
||||
const idsOfUsers = extractMentionedUsers(args.content)
|
||||
const post = await resolve(root, args, context, resolveInfo)
|
||||
if (post) {
|
||||
const sentEmails: string[] = await publishNotifications(
|
||||
context,
|
||||
notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context),
|
||||
'emailNotificationsMention',
|
||||
)
|
||||
sentEmails.concat(
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyFollowingUsers(post.id, groupId, context),
|
||||
'emailNotificationsFollowingUsers',
|
||||
sentEmails,
|
||||
),
|
||||
)
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyGroupMembersOfNewPost(post.id, groupId, context),
|
||||
'emailNotificationsPostInGroup',
|
||||
sentEmails,
|
||||
)
|
||||
}
|
||||
return post
|
||||
}
|
||||
|
||||
const handleContentDataOfComment: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { content } = args
|
||||
let idsOfMentionedUsers = extractMentionedUsers(content)
|
||||
const comment = await resolve(root, args, context, resolveInfo)
|
||||
const [postAuthor] = await postAuthorOfComment(comment.id, { context })
|
||||
idsOfMentionedUsers = idsOfMentionedUsers.filter((id) => id !== postAuthor.id)
|
||||
const sentEmails: string[] = await publishNotifications(
|
||||
context,
|
||||
notifyUsersOfMention(
|
||||
'Comment',
|
||||
comment.id,
|
||||
idsOfMentionedUsers,
|
||||
'mentioned_in_comment',
|
||||
context,
|
||||
),
|
||||
'emailNotificationsMention',
|
||||
)
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyUsersOfComment('Comment', comment.id, 'commented_on_post', context),
|
||||
'emailNotificationsCommentOnObservedPost',
|
||||
sentEmails,
|
||||
)
|
||||
return comment
|
||||
}
|
||||
|
||||
const postAuthorOfComment = async (commentId, { context }) => {
|
||||
const session = context.driver.session()
|
||||
let postAuthorId
|
||||
@ -448,6 +317,136 @@ const notifyUsersOfComment = async (label, commentId, reason, context) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleJoinGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context),
|
||||
'emailNotificationsGroupMemberJoined',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleLeaveGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyOwnersOfGroup(groupId, userId, 'user_left_group', context),
|
||||
'emailNotificationsGroupMemberLeft',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleChangeGroupMemberRole: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context),
|
||||
'emailNotificationsGroupMemberRoleChanged',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleRemoveUserFromGroup: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context),
|
||||
'emailNotificationsGroupMemberRemoved',
|
||||
)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleContentDataOfPost: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { groupId } = args
|
||||
const idsOfUsers = extractMentionedUsers(args.content)
|
||||
const post = await resolve(root, args, context, resolveInfo)
|
||||
if (post) {
|
||||
const sentEmails: string[] = await publishNotifications(
|
||||
context,
|
||||
notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context),
|
||||
'emailNotificationsMention',
|
||||
)
|
||||
sentEmails.concat(
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyFollowingUsers(post.id, groupId, context),
|
||||
'emailNotificationsFollowingUsers',
|
||||
sentEmails,
|
||||
),
|
||||
)
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyGroupMembersOfNewPost(post.id, groupId, context),
|
||||
'emailNotificationsPostInGroup',
|
||||
sentEmails,
|
||||
)
|
||||
}
|
||||
return post
|
||||
}
|
||||
|
||||
const handleContentDataOfComment: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
args,
|
||||
context,
|
||||
resolveInfo,
|
||||
) => {
|
||||
const { content } = args
|
||||
let idsOfMentionedUsers = extractMentionedUsers(content)
|
||||
const comment = await resolve(root, args, context, resolveInfo)
|
||||
const [postAuthor] = await postAuthorOfComment(comment.id, { context })
|
||||
idsOfMentionedUsers = idsOfMentionedUsers.filter((id) => id !== postAuthor.id)
|
||||
const sentEmails: string[] = await publishNotifications(
|
||||
context,
|
||||
notifyUsersOfMention(
|
||||
'Comment',
|
||||
comment.id,
|
||||
idsOfMentionedUsers,
|
||||
'mentioned_in_comment',
|
||||
context,
|
||||
),
|
||||
'emailNotificationsMention',
|
||||
)
|
||||
await publishNotifications(
|
||||
context,
|
||||
notifyUsersOfComment('Comment', comment.id, 'commented_on_post', context),
|
||||
'emailNotificationsCommentOnObservedPost',
|
||||
sentEmails,
|
||||
)
|
||||
return comment
|
||||
}
|
||||
|
||||
const handleCreateMessage: IMiddlewareResolver = async (
|
||||
resolve,
|
||||
root,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unnecessary-type-conversion */
|
||||
@ -22,27 +21,27 @@ const neode = getNeode()
|
||||
|
||||
const isAuthenticated = rule({
|
||||
cache: 'contextual',
|
||||
})(async (_parent, _args, ctx, _info) => {
|
||||
})((_parent, _args, ctx, _info) => {
|
||||
return !!ctx?.user?.id
|
||||
})
|
||||
|
||||
const isModerator = rule()(async (_parent, _args, { user }: Context, _info) => {
|
||||
const isModerator = rule()((_parent, _args, { user }: Context, _info) => {
|
||||
return !!(user && (user.role === 'moderator' || user.role === 'admin'))
|
||||
})
|
||||
|
||||
const isAdmin = rule()(async (_parent, _args, { user }: Context, _info) => {
|
||||
const isAdmin = rule()((_parent, _args, { user }: Context, _info) => {
|
||||
return !!(user?.role === 'admin')
|
||||
})
|
||||
|
||||
const onlyYourself = rule({
|
||||
cache: 'no_cache',
|
||||
})(async (_parent, args, context: Context, _info) => {
|
||||
})((_parent, args, context: Context, _info) => {
|
||||
return context.user?.id === args.id
|
||||
})
|
||||
|
||||
const isMyOwn = rule({
|
||||
cache: 'no_cache',
|
||||
})(async (parent, _args, { user }: Context, _info) => {
|
||||
})((parent, _args, { user }: Context, _info) => {
|
||||
return !!(user && user.id === parent.id)
|
||||
})
|
||||
|
||||
@ -362,21 +361,21 @@ const isAuthor = rule({
|
||||
|
||||
const isDeletingOwnAccount = rule({
|
||||
cache: 'no_cache',
|
||||
})(async (_parent, args, context: Context, _info) => {
|
||||
})((_parent, args, context: Context, _info) => {
|
||||
return context.user?.id === args.id
|
||||
})
|
||||
|
||||
const noEmailFilter = rule({
|
||||
cache: 'no_cache',
|
||||
})(async (_, args) => {
|
||||
})((_, args) => {
|
||||
return !('email' in args)
|
||||
})
|
||||
|
||||
const publicRegistration = rule()(
|
||||
async (_parent, _args, context: Context) => context.config.PUBLIC_REGISTRATION,
|
||||
(_parent, _args, context: Context) => context.config.PUBLIC_REGISTRATION,
|
||||
)
|
||||
|
||||
const inviteRegistration = rule()(async (_parent, args, context: Context) => {
|
||||
const inviteRegistration = rule()((_parent, args, context: Context) => {
|
||||
if (!context.config.INVITE_REGISTRATION) return false
|
||||
const { inviteCode } = args
|
||||
return validateInviteCode(context, inviteCode)
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import slugify from 'slugify'
|
||||
|
||||
slugify.extend({ Ä: 'AE', ä: 'ae', Ö: 'OE', ö: 'oe', Ü: 'UE', ü: 'ue', ß: 'ss' })
|
||||
@ -16,7 +15,7 @@ export default async function uniqueSlug(str: string, isUnique: IsUnique) {
|
||||
let uniqueSlug: string
|
||||
do {
|
||||
count += 1
|
||||
uniqueSlug = `${slug}-${count}`
|
||||
uniqueSlug = `${slug}-${String(count)}`
|
||||
} while (!(await isUnique(uniqueSlug)))
|
||||
return uniqueSlug
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
@ -8,7 +7,7 @@ const isModerator = ({ user }) => {
|
||||
return user && (user.role === 'moderator' || user.role === 'admin')
|
||||
}
|
||||
|
||||
const setDefaultFilters: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const setDefaultFilters: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.deleted = false
|
||||
|
||||
if (!isModerator(context)) {
|
||||
@ -17,7 +16,7 @@ const setDefaultFilters: IMiddlewareResolver = async (resolve, root, args, conte
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const obfuscate: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const obfuscate: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
if (root.deleted || (!isModerator(context) && root.disabled)) {
|
||||
root.content = 'UNAVAILABLE'
|
||||
root.contentExcerpt = 'UNAVAILABLE'
|
||||
@ -31,7 +30,7 @@ const obfuscate: IMiddlewareResolver = async (resolve, root, args, context, info
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const mutationDefaults: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const mutationDefaults: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args.disabled = false
|
||||
// TODO: remove as soon as our factories don't need this anymore
|
||||
if (typeof args.deleted !== 'boolean') {
|
||||
|
||||
@ -2,16 +2,15 @@
|
||||
/* 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/restrict-template-expressions */
|
||||
import type { IMiddlewareResolver } from 'graphql-middleware/dist/types'
|
||||
|
||||
const createRelatedCypher = (relation) => `
|
||||
MATCH (user:User { id: $currentUser})
|
||||
MATCH (post:Post { id: $postId})
|
||||
OPTIONAL MATCH (post)<-[r:${relation}]-(u:User)
|
||||
OPTIONAL MATCH (post)<-[r:${String(relation)}]-(u:User)
|
||||
WHERE NOT u.disabled AND NOT u.deleted
|
||||
WITH user, post, count(DISTINCT u) AS count
|
||||
MERGE (user)-[relation:${relation} { }]->(post)
|
||||
MERGE (user)-[relation:${String(relation)} { }]->(post)
|
||||
ON CREATE
|
||||
SET relation.count = 1,
|
||||
relation.createdAt = toString(datetime()),
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
@ -16,7 +14,7 @@ const validateCreateComment: IMiddlewareResolver = async (resolve, root, args, c
|
||||
const { postId } = args
|
||||
|
||||
if (!args.content || content.length < COMMENT_MIN_LENGTH) {
|
||||
throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`)
|
||||
throw new UserInputError(`Comment must be at least ${String(COMMENT_MIN_LENGTH)} character long!`)
|
||||
}
|
||||
const session = context.driver.session()
|
||||
try {
|
||||
@ -43,16 +41,16 @@ const validateCreateComment: IMiddlewareResolver = async (resolve, root, args, c
|
||||
}
|
||||
}
|
||||
|
||||
const validateUpdateComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const validateUpdateComment: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
const content = args.content.replace(/<(?:.|\n)*?>/gm, '').trim()
|
||||
if (!args.content || content.length < COMMENT_MIN_LENGTH) {
|
||||
throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`)
|
||||
throw new UserInputError(`Comment must be at least ${String(COMMENT_MIN_LENGTH)} character long!`)
|
||||
}
|
||||
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
const validateReport: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const validateReport: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
const { resourceId } = args
|
||||
const { user } = context
|
||||
if (resourceId === user.id) throw new Error('You cannot report yourself!')
|
||||
@ -92,14 +90,14 @@ const validateReview: IMiddlewareResolver = async (resolve, root, args, context,
|
||||
existingReportedResource = existingReportedResource[0]
|
||||
if (!existingReportedResource.filed)
|
||||
throw new Error(
|
||||
`Before starting the review process, please report the ${existingReportedResource.label}!`,
|
||||
`Before starting the review process, please report the ${String(existingReportedResource.label)}!`,
|
||||
)
|
||||
const authorId =
|
||||
existingReportedResource.label !== 'User' && existingReportedResource.author
|
||||
? existingReportedResource.author.properties.id
|
||||
: null
|
||||
if (authorId && authorId === user.id)
|
||||
throw new Error(`You cannot review your own ${existingReportedResource.label}!`)
|
||||
throw new Error(`You cannot review your own ${String(existingReportedResource.label)}!`)
|
||||
} finally {
|
||||
await session.close()
|
||||
}
|
||||
@ -107,7 +105,7 @@ const validateReview: IMiddlewareResolver = async (resolve, root, args, context,
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
export const validateNotifyUsers = async (label: string, reason: string): Promise<void> => {
|
||||
export const validateNotifyUsers = (label: string, reason: string): void => {
|
||||
const reasonsAllowed = [
|
||||
'mentioned_in_post',
|
||||
'mentioned_in_comment',
|
||||
@ -124,10 +122,10 @@ export const validateNotifyUsers = async (label: string, reason: string): Promis
|
||||
}
|
||||
}
|
||||
|
||||
const validateUpdateUser: IMiddlewareResolver = async (resolve, root, params, context, info) => {
|
||||
const validateUpdateUser: IMiddlewareResolver = (resolve, root, params, context, info) => {
|
||||
const { name } = params
|
||||
if (typeof name === 'string' && name.trim().length < USERNAME_MIN_LENGTH)
|
||||
throw new UserInputError(`Username must be at least ${USERNAME_MIN_LENGTH} character long!`)
|
||||
throw new UserInputError(`Username must be at least ${String(USERNAME_MIN_LENGTH)} character long!`)
|
||||
return resolve(root, params, context, info)
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/* eslint-disable security/detect-object-injection */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable promise/prefer-await-to-callbacks */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
@ -47,7 +46,7 @@ const fields = [
|
||||
{ field: 'descriptionExcerpt' },
|
||||
]
|
||||
|
||||
const mutationXss: IMiddlewareResolver = async (resolve, root, args, context, info) => {
|
||||
const mutationXss: IMiddlewareResolver = (resolve, root, args, context, info) => {
|
||||
args = walkRecursive(args, fields, info.fieldName, cleanHtml)
|
||||
return resolve(root, args, context, info)
|
||||
}
|
||||
|
||||
@ -102,8 +102,7 @@ const createServer = async (options?: CreateServerOptions) => {
|
||||
plugins: [
|
||||
ApolloServerPluginDrainHttpServer({ httpServer }),
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
async serverWillStart() {
|
||||
serverWillStart() {
|
||||
return {
|
||||
async drainServer() {
|
||||
await serverCleanup.dispose()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user