Implement the sanitize directive in applo 3.0
This commit is contained in:
@ -108,8 +108,13 @@ const contextFunc: ContextFunction<ExpressContext, ResolverContext> = async ({
|
||||
}
|
||||
|
||||
export function makeApolloServer(app: Express): ApolloServer {
|
||||
let schema = makeExecutableSchema({ typeDefs, resolvers })
|
||||
let schema = makeExecutableSchema({
|
||||
resolvers,
|
||||
typeDefs
|
||||
})
|
||||
|
||||
schema = sanitizeDirectiveTransformer(schema)
|
||||
|
||||
const apollo = new ApolloServer({
|
||||
schema: schema,
|
||||
context: contextFunc,
|
||||
|
||||
@ -1,63 +1,30 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
// import { SchemaDirectiveVisitor } from 'apollo-server-express'
|
||||
// import { GraphQLInputField, GraphQLScalarType } from 'graphql'
|
||||
// import { SanitizedString } from './scalars'
|
||||
// import { GraphQLNonNull } from 'graphql/type/definition'
|
||||
|
||||
// export class SanitizeDirective extends SchemaDirectiveVisitor {
|
||||
// visitInputFieldDefinition(
|
||||
// field: GraphQLInputField
|
||||
// ): GraphQLInputField | void | null {
|
||||
// const { allowedTags, maxLength } = this.args
|
||||
// if (
|
||||
// field.type instanceof GraphQLNonNull &&
|
||||
// field.type.ofType instanceof GraphQLScalarType
|
||||
// ) {
|
||||
// field.type = new GraphQLNonNull(
|
||||
// new SanitizedString(field.type.ofType, allowedTags, maxLength)
|
||||
// )
|
||||
// } else if (field.type instanceof GraphQLScalarType) {
|
||||
// field.type = new SanitizedString(field.type, allowedTags, maxLength)
|
||||
// } else {
|
||||
// throw new Error(`Not a scalar type: ${field.type}`)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
import { mapSchema, getDirective, MapperKind } from '@graphql-tools/utils'
|
||||
import { GraphQLNonNull, GraphQLScalarType, GraphQLSchema } from 'graphql'
|
||||
import { SanitizedString } from './scalars'
|
||||
|
||||
export const sanitizeDirectiveTransformer = (
|
||||
schema: GraphQLSchema
|
||||
): GraphQLSchema => {
|
||||
export const sanitizeDirectiveTransformer = (schema: GraphQLSchema) => {
|
||||
return mapSchema(schema, {
|
||||
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
|
||||
const deprecatedDirective = getDirective(
|
||||
[MapperKind.FIELD]: (fieldConfig) => {
|
||||
const sanitizeDirective = getDirective(
|
||||
schema,
|
||||
fieldConfig,
|
||||
'sanitize'
|
||||
)?.[0]
|
||||
if (deprecatedDirective) {
|
||||
// const { allowedTags, maxLength } = this.args
|
||||
const allowedTags = undefined
|
||||
const maxLength = undefined
|
||||
if (
|
||||
fieldConfig.type instanceof GraphQLNonNull &&
|
||||
fieldConfig.type.ofType instanceof GraphQLScalarType
|
||||
) {
|
||||
fieldConfig.type = new GraphQLNonNull(
|
||||
new SanitizedString(fieldConfig.type.ofType, allowedTags, maxLength)
|
||||
)
|
||||
} else if (fieldConfig.type instanceof GraphQLScalarType) {
|
||||
fieldConfig.type = new SanitizedString(
|
||||
fieldConfig.type,
|
||||
allowedTags,
|
||||
maxLength
|
||||
)
|
||||
} else {
|
||||
throw new Error(`Not a scalar type: ${fieldConfig.type}`)
|
||||
}
|
||||
)
|
||||
if (!sanitizeDirective || sanitizeDirective.length < 1) {
|
||||
return fieldConfig
|
||||
}
|
||||
|
||||
const maxLength = sanitizeDirective[0].maxLength
|
||||
const allowedTags = sanitizeDirective[0].allowedTags
|
||||
|
||||
if (fieldConfig.type instanceof GraphQLNonNull && fieldConfig.type.ofType instanceof GraphQLScalarType) {
|
||||
fieldConfig.type = new GraphQLNonNull(
|
||||
new SanitizedString(fieldConfig.type.ofType, allowedTags, maxLength)
|
||||
)
|
||||
} else if (fieldConfig.type instanceof GraphQLScalarType) {
|
||||
fieldConfig.type = new SanitizedString(fieldConfig.type, allowedTags, maxLength)
|
||||
} else {
|
||||
throw new Error(`Not a scalar type: ${fieldConfig.type}`)
|
||||
}
|
||||
return fieldConfig
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,69 +1,65 @@
|
||||
// import { createTestUser, deleteTestUser, getProfile, getUser } from '../db'
|
||||
// import { graphqlRequest, request } from '../util'
|
||||
// import { expect } from 'chai'
|
||||
// import {
|
||||
// LoginErrorCode,
|
||||
// SignupErrorCode,
|
||||
// UpdateUserErrorCode,
|
||||
// UpdateUserProfileErrorCode,
|
||||
// } from '../../src/generated/graphql'
|
||||
// import { User } from '../../src/entity/user'
|
||||
// import { hashPassword } from '../../src/utils/auth'
|
||||
// import 'mocha'
|
||||
import { createTestUser, deleteTestUser, getProfile, getUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import { expect } from 'chai'
|
||||
import {
|
||||
LoginErrorCode,
|
||||
SignupErrorCode,
|
||||
UpdateUserErrorCode,
|
||||
UpdateUserProfileErrorCode,
|
||||
} from '../../src/generated/graphql'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { hashPassword } from '../../src/utils/auth'
|
||||
import 'mocha'
|
||||
|
||||
// describe('Sanitize Directive', () => {
|
||||
// const username = 'fake_user'
|
||||
// const correctPassword = 'fakePassword'
|
||||
describe('Sanitize Directive', () => {
|
||||
const username = 'fake_user'
|
||||
const correctPassword = 'fakePassword'
|
||||
|
||||
// let authToken: string
|
||||
// let user: User
|
||||
let authToken: string
|
||||
let user: User
|
||||
|
||||
// before(async () => {
|
||||
// const hashedPassword = hashPassword(correctPassword)
|
||||
// user = await createTestUser(username, '', hashedPassword)
|
||||
// const res = await request
|
||||
// .post('/local/debug/fake-user-login')
|
||||
// .send({ fakeEmail: user.email })
|
||||
before(async () => {
|
||||
const hashedPassword = hashPassword(correctPassword)
|
||||
user = await createTestUser(username, '', hashedPassword)
|
||||
const res = await request
|
||||
.post('/local/debug/fake-user-login')
|
||||
.send({ fakeEmail: user.email })
|
||||
|
||||
// authToken = res.body.authToken
|
||||
// })
|
||||
authToken = res.body.authToken
|
||||
})
|
||||
|
||||
// after(async () => {
|
||||
// await deleteTestUser(username)
|
||||
// })
|
||||
after(async () => {
|
||||
await deleteTestUser(username)
|
||||
})
|
||||
|
||||
// describe('Update user with a bio that is too long', () => {
|
||||
// let bio = "".padStart(500, '*');
|
||||
// let query: string
|
||||
describe('Update user with a bio that is too long', () => {
|
||||
let bio = "".padStart(500, '*');
|
||||
let query: string
|
||||
|
||||
// beforeEach(() => {
|
||||
// query = `
|
||||
// mutation {
|
||||
// updateUser(
|
||||
// input: {
|
||||
// name: "fakeUser"
|
||||
// bio: "${bio}"
|
||||
// }
|
||||
// ) {
|
||||
// ... on UpdateUserSuccess {
|
||||
// user {
|
||||
// id
|
||||
// }
|
||||
// }
|
||||
// ... on UpdateUserError {
|
||||
// errorCodes
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// `
|
||||
// })
|
||||
beforeEach(() => {
|
||||
query = `
|
||||
mutation {
|
||||
updateUser(
|
||||
input: {
|
||||
name: "fakeUser"
|
||||
bio: "${bio}"
|
||||
}
|
||||
) {
|
||||
... on UpdateUserSuccess {
|
||||
user {
|
||||
id
|
||||
}
|
||||
}
|
||||
... on UpdateUserError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
// it('responds with error code EMPTY_NAME', async () => {
|
||||
// const response = await graphqlRequest(query, authToken)
|
||||
// console.log('GOT RESPONSE', response)
|
||||
// expect(response.body.data.updateUser.errorCodes).to.eql([
|
||||
// UpdateUserErrorCode.EmptyName,
|
||||
// ])
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
it('responds with error code EMPTY_NAME', async () => {
|
||||
expect(async () => { await graphqlRequest(query, authToken) }).to.throw
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user