From 7d82b27aaa53a422954a9e18bd7e203147fbf59a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Tue, 12 Mar 2019 12:59:45 +0100 Subject: [PATCH 01/14] Hide disabled comments and posts by default I had to trick neo4j-graphql-js to return disabled and deleted fields by default on any neo4j node. If disabled is not queried, then we don't have it in our middleware and we're not able to filter it. --- src/middleware/idMiddleware.js | 28 -------- src/middleware/includedFieldsMiddleware.js | 29 ++++++++ src/middleware/index.js | 4 +- src/middleware/softDeleteMiddleware.js | 45 +++++++++---- src/middleware/softDeleteMiddleware.spec.js | 73 +++++++++++++++++++-- src/schema.graphql | 4 +- src/seed/seed-db.js | 9 ++- 7 files changed, 136 insertions(+), 56 deletions(-) delete mode 100644 src/middleware/idMiddleware.js create mode 100644 src/middleware/includedFieldsMiddleware.js diff --git a/src/middleware/idMiddleware.js b/src/middleware/idMiddleware.js deleted file mode 100644 index 2f1854fa6..000000000 --- a/src/middleware/idMiddleware.js +++ /dev/null @@ -1,28 +0,0 @@ -import cloneDeep from 'lodash/cloneDeep' - -const includeId = async (resolve, root, args, context, resolveInfo) => { - // Keeping the graphql resolveInfo untouched ensures that we don't add the - // following attributes to the result set returned to the graphQL client. - // We only want to pass these attributes to our resolver for internal - // purposes e.g. authorization. - const copy = cloneDeep(resolveInfo) - - copy.fieldNodes[0].selectionSet.selections.unshift({ - kind: 'Field', - name: { kind: 'Name', value: 'id' } - }) - return resolve(root, args, context, copy) -} - -export default { - Query: { - User: (resolve, root, args, context, info) => { - return includeId(resolve, root, args, context, info) - } - }, - Mutation: { - CreatePost: (resolve, root, args, context, info) => { - return includeId(resolve, root, args, context, info) - } - } -} diff --git a/src/middleware/includedFieldsMiddleware.js b/src/middleware/includedFieldsMiddleware.js new file mode 100644 index 000000000..6d8ccf8f1 --- /dev/null +++ b/src/middleware/includedFieldsMiddleware.js @@ -0,0 +1,29 @@ +import cloneDeep from 'lodash/cloneDeep' + +const _includeFieldsRecursively = (selectionSet, includedFields) => { + if (!selectionSet) return + includedFields.forEach((includedField) => { + selectionSet.selections.unshift({ + kind: 'Field', + name: { kind: 'Name', value: includedField } + }) + }) + selectionSet.selections.forEach((selection) => { + _includeFieldsRecursively(selection.selectionSet, includedFields) + }) +} + +const includeFieldsRecursively = (includedFields) => { + return (resolve, root, args, context, resolveInfo) => { + const copy = cloneDeep(resolveInfo) + copy.fieldNodes.forEach((fieldNode) => { + _includeFieldsRecursively(fieldNode.selectionSet, includedFields) + }) + return resolve(root, args, context, copy) + } +} + +export default { + Query: includeFieldsRecursively(['id', 'disabled', 'deleted']), + Mutation: includeFieldsRecursively(['id', 'disabled', 'deleted']) +} diff --git a/src/middleware/index.js b/src/middleware/index.js index 5cc20f969..6f95c7451 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -7,7 +7,7 @@ import dateTimeMiddleware from './dateTimeMiddleware' import xssMiddleware from './xssMiddleware' import permissionsMiddleware from './permissionsMiddleware' import userMiddleware from './userMiddleware' -import idMiddleware from './idMiddleware' +import includedFieldsMiddleware from './includedFieldsMiddleware' export default schema => { let middleware = [ @@ -19,7 +19,7 @@ export default schema => { fixImageUrlsMiddleware, softDeleteMiddleware, userMiddleware, - idMiddleware + includedFieldsMiddleware ] // add permisions middleware at the first position (unless we're seeding) diff --git a/src/middleware/softDeleteMiddleware.js b/src/middleware/softDeleteMiddleware.js index 0c12e7a72..042219916 100644 --- a/src/middleware/softDeleteMiddleware.js +++ b/src/middleware/softDeleteMiddleware.js @@ -1,26 +1,43 @@ -const setDefaults = (args) => { +const isModerator = ({ user }) => { + return user && (user.role === 'moderator' || user.role === 'admin') +} + +const setDefaultFilters = (resolve, root, args, context, info) => { if (typeof args.deleted !== 'boolean') { args.deleted = false } - if (typeof args.disabled !== 'boolean') { + + if (!isModerator(context)) { args.disabled = false } - return args + return resolve(root, args, context, info) +} + +const hideDisabledComments = async (resolve, root, args, context, info) => { + const { comments } = root + if (!Array.isArray(comments)) return resolve(root, args, context, info) + if (!isModerator(context)) { + root.comments = comments.filter((comment) => { + return !comment.disabled + }) + } + return resolve(root, args, context, info) } export default { Query: { - Post: (resolve, root, args, context, info) => { - return resolve(root, setDefaults(args), context, info) - }, - Comment: async (resolve, root, args, context, info) => { - return resolve(root, setDefaults(args), context, info) - }, - User: async (resolve, root, args, context, info) => { - return resolve(root, setDefaults(args), context, info) - } + Post: setDefaultFilters, + Comment: setDefaultFilters, + User: setDefaultFilters }, Mutation: async (resolve, root, args, context, info) => { - return resolve(root, setDefaults(args), context, info) - } + args.disabled = false + // TODO: remove as soon as our factories don't need this anymore + if (typeof args.deleted !== 'boolean') { + args.deleted = false + } + return resolve(root, args, context, info) + }, + Post: hideDisabledComments, + User: hideDisabledComments } diff --git a/src/middleware/softDeleteMiddleware.spec.js b/src/middleware/softDeleteMiddleware.spec.js index ed132104e..f478feb7c 100644 --- a/src/middleware/softDeleteMiddleware.spec.js +++ b/src/middleware/softDeleteMiddleware.spec.js @@ -9,14 +9,14 @@ let action beforeEach(async () => { await Promise.all([ - factory.create('User', { role: 'user', email: 'user@example.org', password: '1234' }), + factory.create('User', { id: 'u1', role: 'user', email: 'user@example.org', password: '1234' }), factory.create('User', { id: 'm1', role: 'moderator', email: 'moderator@example.org', password: '1234' }) ]) await factory.authenticateAs({ email: 'user@example.org', password: '1234' }) await Promise.all([ - factory.create('Post', { title: 'Deleted post', deleted: true }), - factory.create('Post', { id: 'p2', title: 'Disabled post', deleted: false }), - factory.create('Post', { title: 'Publicly visible post', deleted: false }) + await factory.create('Post', { id: 'p1', title: 'Deleted post', deleted: true }), + await factory.create('Post', { id: 'p2', title: 'Disabled post', deleted: false }), + await factory.create('Post', { id: 'p3', title: 'Publicly visible post', deleted: false }) ]) const moderatorFactory = Factory() await moderatorFactory.authenticateAs({ email: 'moderator@example.org', password: '1234' }) @@ -62,9 +62,68 @@ describe('softDeleteMiddleware', () => { client = new GraphQLClient(host, { headers }) }) - it('hides deleted or disabled posts', async () => { - const expected = { Post: [{ title: 'Publicly visible post' }] } - await expect(action()).resolves.toEqual(expected) + it('shows disabled but hides deleted posts', async () => { + const expected = [ + { title: 'Disabled post' }, + { title: 'Publicly visible post' } + ] + const { Post } = await action() + await expect(Post).toEqual(expect.arrayContaining(expected)) + }) + }) + + describe('.comments', () => { + beforeEach(async () => { + query = '{ Post(id: "p3") { title comments { content } } }' + + const asModerator = Factory() + await asModerator.authenticateAs({ email: 'moderator@example.org', password: '1234' }) + await Promise.all([ + asModerator.create('Comment', { id: 'c1', content: 'Disabled comment' }), + asModerator.create('Comment', { id: 'c2', content: 'Enabled comment on public post' }) + ]) + await Promise.all([ + asModerator.relate('Comment', 'Author', { from: 'u1', to: 'c1' }), + asModerator.relate('Comment', 'Post', { from: 'c1', to: 'p3' }), + asModerator.relate('Comment', 'Author', { from: 'u1', to: 'c2' }), + asModerator.relate('Comment', 'Post', { from: 'c2', to: 'p3' }) + ]) + await asModerator.mutate('mutation { disable( id: "c1") }') + }) + + describe('as user', () => { + beforeEach(async () => { + const headers = await login({ email: 'user@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('hides disabled comments', async () => { + const expected = { Post: [ { + title: 'Publicly visible post', + comments: [ + { content: 'Enabled comment on public post' } + ] + } + ] } + await expect(action()).resolves.toEqual(expected) + }) + }) + + describe('as moderator', () => { + beforeEach(async () => { + const headers = await login({ email: 'moderator@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('shows disabled comments', async () => { + const expected = [ + { content: 'Enabled comment on public post' }, + { content: 'Disabled comment' } + ] + const { Post: [{ comments }] } = await action() + + await expect(comments).toEqual(expect.arrayContaining(expected)) + }) }) }) diff --git a/src/schema.graphql b/src/schema.graphql index 152301715..801eb4502 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -148,7 +148,7 @@ type User { ) comments: [Comment]! @relation(name: "WROTE", direction: "OUT") - commentsCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment) WHERE NOT r.deleted = true RETURN COUNT(r)") + commentsCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(r)") shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT") shoutedCount: Int! @cypher(statement: "MATCH (this)-[:SHOUTED]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)") @@ -189,7 +189,7 @@ type Post { categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT") comments: [Comment]! @relation(name: "COMMENTS", direction: "IN") - commentsCount: Int! @cypher(statement: "MATCH (this)<-[:COMMENTS]-(r:Comment) RETURN COUNT(r)") + commentsCount: Int! @cypher(statement: "MATCH (this)<-[:COMMENTS]-(r:Comment) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(r)") shoutedBy: [User]! @relation(name: "SHOUTED", direction: "IN") shoutedCount: Int! @cypher(statement: "MATCH (this)<-[:SHOUTED]-(r:User) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)") diff --git a/src/seed/seed-db.js b/src/seed/seed-db.js index e8c757db8..d526518b9 100644 --- a/src/seed/seed-db.js +++ b/src/seed/seed-db.js @@ -107,9 +107,6 @@ import Factory from './factories' asTick.create('Post', { id: 'p15' }) ]) - const disableMutation = 'mutation { disable( id: "p11") }' - await asModerator.mutate(disableMutation) - await Promise.all([ f.relate('Post', 'Categories', { from: 'p0', to: 'cat16' }), f.relate('Post', 'Categories', { from: 'p1', to: 'cat1' }), @@ -214,6 +211,12 @@ import Factory from './factories' f.relate('Comment', 'Post', { from: 'c7', to: 'p2' }) ]) + const disableMutation = 'mutation($id: ID!) { disable(id: $id) }' + await Promise.all([ + asModerator.mutate(disableMutation, { id: 'p11' }), + asModerator.mutate(disableMutation, { id: 'c5' }) + ]) + await Promise.all([ asTick.create('Report', { description: 'I don\'t like this comment', id: 'c1' }), asTrick.create('Report', { description: 'I don\'t like this post', id: 'p1' }), From d71cb16a01e98f7d5c069fac2142e762be58dbff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Wed, 13 Mar 2019 20:57:50 +0100 Subject: [PATCH 02/14] Spec a new behaviour of softDisable If we have nested content, the content should be obfuscated instead of being filtered. cc @datenbrei --- src/middleware/softDeleteMiddleware.spec.js | 297 +++++++++++++------- src/seed/factories/users.js | 2 + 2 files changed, 192 insertions(+), 107 deletions(-) diff --git a/src/middleware/softDeleteMiddleware.spec.js b/src/middleware/softDeleteMiddleware.spec.js index f478feb7c..6b8b4bc49 100644 --- a/src/middleware/softDeleteMiddleware.spec.js +++ b/src/middleware/softDeleteMiddleware.spec.js @@ -7,41 +7,103 @@ let client let query let action -beforeEach(async () => { +beforeAll(async () => { + // For performance reasons we do this only once await Promise.all([ factory.create('User', { id: 'u1', role: 'user', email: 'user@example.org', password: '1234' }), - factory.create('User', { id: 'm1', role: 'moderator', email: 'moderator@example.org', password: '1234' }) + factory.create('User', { id: 'm1', role: 'moderator', email: 'moderator@example.org', password: '1234' }), + factory.create('User', { id: 'u2', role: 'user', avatar: '/some/offensive/avatar.jpg', about: 'This self description is very offensive', email: 'troll@example.org', password: '1234' }) ]) + await factory.authenticateAs({ email: 'user@example.org', password: '1234' }) await Promise.all([ - await factory.create('Post', { id: 'p1', title: 'Deleted post', deleted: true }), - await factory.create('Post', { id: 'p2', title: 'Disabled post', deleted: false }), - await factory.create('Post', { id: 'p3', title: 'Publicly visible post', deleted: false }) + factory.follow({ id: 'u2', type: 'User' }), + factory.create('Post', { id: 'p1', title: 'Deleted post', deleted: true }), + factory.create('Post', { id: 'p3', title: 'Publicly visible post', deleted: false }) ]) - const moderatorFactory = Factory() - await moderatorFactory.authenticateAs({ email: 'moderator@example.org', password: '1234' }) - const disableMutation = ` - mutation { - disable( - id: "p2" - ) - } - ` - await moderatorFactory.mutate(disableMutation) + + await Promise.all([ + factory.create('Comment', { id: 'c2', content: 'Enabled comment on public post' }) + ]) + + await Promise.all([ + factory.relate('Comment', 'Author', { from: 'u1', to: 'c2' }), + factory.relate('Comment', 'Post', { from: 'c2', to: 'p3' }) + ]) + + const asTroll = Factory() + await asTroll.authenticateAs({ email: 'troll@example.org', password: '1234' }) + await asTroll.create('Post', { id: 'p2', title: 'Disabled post', content: 'This is an offensive post content', image: '/some/offensive/image.jpg', deleted: false }) + await asTroll.create('Comment', { id: 'c1', content: 'Disabled comment' }) + await Promise.all([ + asTroll.relate('Comment', 'Author', { from: 'u2', to: 'c1' }), + asTroll.relate('Comment', 'Post', { from: 'c1', to: 'p3' }) + ]) + + const asModerator = Factory() + await asModerator.authenticateAs({ email: 'moderator@example.org', password: '1234' }) + await asModerator.mutate('mutation { disable( id: "p2") }') + await asModerator.mutate('mutation { disable( id: "c1") }') + await asModerator.mutate('mutation { disable( id: "u2") }') }) -afterEach(async () => { +afterAll(async () => { await factory.cleanDatabase() }) describe('softDeleteMiddleware', () => { - describe('Post', () => { + describe('read disabled content', () => { + let user + let post + let comment + const beforeComment = async () => { + query = '{ User(id: "u1") { following { comments { content contentExcerpt } } } }' + const response = await action() + comment = response.User[0].following[0].comments[0] + } + const beforeUser = async () => { + query = '{ User(id: "u1") { following { about avatar } } }' + const response = await action() + user = response.User[0].following[0] + } + const beforePost = async () => { + query = '{ User(id: "u1") { following { contributions { title image content contentExcerpt } } } }' + const response = await action() + post = response.User[0].following[0].contributions[0] + } + action = () => { return client.request(query) } - beforeEach(() => { - query = '{ Post { title } }' + describe('as moderator', () => { + beforeEach(async () => { + const headers = await login({ email: 'moderator@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + describe('User', () => { + beforeEach(beforeUser) + + it('displays about', () => expect(user.about).toEqual('This self description is very offensive')) + it('displays avatar', () => expect(user.avatar).toEqual('/some/offensive/avatar.jpg')) + }) + + describe('Post', () => { + beforeEach(beforePost) + + it('displays title', () => expect(post.title).toEqual('Disabled post')) + it('displays content', () => expect(post.content).toEqual('This is an offensive post content')) + it('displays contentExcerpt', () => expect(post.contentExcerpt).toEqual('This is an offensive post content')) + it('displays image', () => expect(post.image).toEqual('/some/offensive/image.jpg')) + }) + + describe('Comment', () => { + beforeEach(beforeComment) + + it('displays content', () => expect(comment.content).toEqual('Disabled comment')) + it('displays contentExcerpt', () => expect(comment.contentExcerpt).toEqual('Disabled comment')) + }) }) describe('as user', () => { @@ -50,45 +112,35 @@ describe('softDeleteMiddleware', () => { client = new GraphQLClient(host, { headers }) }) - it('hides deleted or disabled posts', async () => { - const expected = { Post: [{ title: 'Publicly visible post' }] } - await expect(action()).resolves.toEqual(expected) + describe('User', () => { + beforeEach(beforeUser) + + it('obfuscates about', () => expect(user.about).toEqual('DELETED')) + it('obfuscates avatar', () => expect(user.avatar).toEqual('DELETED')) + }) + + describe('Post', () => { + beforeEach(beforePost) + + it('obfuscates title', () => expect(post.title).toEqual('DELETED')) + it('obfuscates content', () => expect(post.content).toEqual('DELETED')) + it('obfuscates contentExcerpt', () => expect(post.contentExcerpt).toEqual('DELETED')) + it('obfuscates image', () => expect(post.image).toEqual('DELETED')) + }) + + describe('Comment', () => { + beforeEach(beforeComment) + + it('obfuscates content', () => expect(comment.content).toEqual('DELETED')) + it('obfuscates contentExcerpt', () => expect(comment.contentExcerpt).toEqual('DELETED')) }) }) + }) - describe('as moderator', () => { + describe('Query', () => { + describe('Post', () => { beforeEach(async () => { - const headers = await login({ email: 'moderator@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) - }) - - it('shows disabled but hides deleted posts', async () => { - const expected = [ - { title: 'Disabled post' }, - { title: 'Publicly visible post' } - ] - const { Post } = await action() - await expect(Post).toEqual(expect.arrayContaining(expected)) - }) - }) - - describe('.comments', () => { - beforeEach(async () => { - query = '{ Post(id: "p3") { title comments { content } } }' - - const asModerator = Factory() - await asModerator.authenticateAs({ email: 'moderator@example.org', password: '1234' }) - await Promise.all([ - asModerator.create('Comment', { id: 'c1', content: 'Disabled comment' }), - asModerator.create('Comment', { id: 'c2', content: 'Enabled comment on public post' }) - ]) - await Promise.all([ - asModerator.relate('Comment', 'Author', { from: 'u1', to: 'c1' }), - asModerator.relate('Comment', 'Post', { from: 'c1', to: 'p3' }), - asModerator.relate('Comment', 'Author', { from: 'u1', to: 'c2' }), - asModerator.relate('Comment', 'Post', { from: 'c2', to: 'p3' }) - ]) - await asModerator.mutate('mutation { disable( id: "c1") }') + query = '{ Post { title } }' }) describe('as user', () => { @@ -97,14 +149,8 @@ describe('softDeleteMiddleware', () => { client = new GraphQLClient(host, { headers }) }) - it('hides disabled comments', async () => { - const expected = { Post: [ { - title: 'Publicly visible post', - comments: [ - { content: 'Enabled comment on public post' } - ] - } - ] } + it('hides deleted or disabled posts', async () => { + const expected = { Post: [{ title: 'Publicly visible post' }] } await expect(action()).resolves.toEqual(expected) }) }) @@ -115,72 +161,109 @@ describe('softDeleteMiddleware', () => { client = new GraphQLClient(host, { headers }) }) - it('shows disabled comments', async () => { + it('shows disabled but hides deleted posts', async () => { const expected = [ - { content: 'Enabled comment on public post' }, - { content: 'Disabled comment' } + { title: 'Disabled post' }, + { title: 'Publicly visible post' } ] - const { Post: [{ comments }] } = await action() - - await expect(comments).toEqual(expect.arrayContaining(expected)) + const { Post } = await action() + await expect(Post).toEqual(expect.arrayContaining(expected)) }) }) - }) - describe('filter (deleted: true)', () => { - beforeEach(() => { - query = '{ Post(deleted: true) { title } }' - }) - - describe('as user', () => { + describe('.comments', () => { beforeEach(async () => { - const headers = await login({ email: 'user@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) + query = '{ Post(id: "p3") { title comments { content } } }' }) - it('throws authorisation error', async () => { - await expect(action()).rejects.toThrow('Not Authorised!') + describe('as user', () => { + beforeEach(async () => { + const headers = await login({ email: 'user@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('conceals disabled comments', async () => { + const expected = [ + { content: 'Enabled comment on public post' }, + { content: 'DELETED' } + ] + const { Post: [{ comments }] } = await action() + await expect(comments).toEqual(expect.arrayContaining(expected)) + }) + }) + + describe('as moderator', () => { + beforeEach(async () => { + const headers = await login({ email: 'moderator@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('shows disabled comments', async () => { + const expected = [ + { content: 'Enabled comment on public post' }, + { content: 'Disabled comment' } + ] + const { Post: [{ comments }] } = await action() + await expect(comments).toEqual(expect.arrayContaining(expected)) + }) }) }) - describe('as moderator', () => { - beforeEach(async () => { - const headers = await login({ email: 'moderator@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) + describe('filter (deleted: true)', () => { + beforeEach(() => { + query = '{ Post(deleted: true) { title } }' }) - it('shows deleted posts', async () => { - const expected = { Post: [{ title: 'Deleted post' }] } - await expect(action()).resolves.toEqual(expected) - }) - }) - }) + describe('as user', () => { + beforeEach(async () => { + const headers = await login({ email: 'user@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) - describe('filter (disabled: true)', () => { - beforeEach(() => { - query = '{ Post(disabled: true) { title } }' - }) - - describe('as user', () => { - beforeEach(async () => { - const headers = await login({ email: 'user@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) + it('throws authorisation error', async () => { + await expect(action()).rejects.toThrow('Not Authorised!') + }) }) - it('throws authorisation error', async () => { - await expect(action()).rejects.toThrow('Not Authorised!') + describe('as moderator', () => { + beforeEach(async () => { + const headers = await login({ email: 'moderator@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('shows deleted posts', async () => { + const expected = { Post: [{ title: 'Deleted post' }] } + await expect(action()).resolves.toEqual(expected) + }) }) }) - describe('as moderator', () => { - beforeEach(async () => { - const headers = await login({ email: 'moderator@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) + describe('filter (disabled: true)', () => { + beforeEach(() => { + query = '{ Post(disabled: true) { title } }' }) - it('shows disabled posts', async () => { - const expected = { Post: [{ title: 'Disabled post' }] } - await expect(action()).resolves.toEqual(expected) + describe('as user', () => { + beforeEach(async () => { + const headers = await login({ email: 'user@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('throws authorisation error', async () => { + await expect(action()).rejects.toThrow('Not Authorised!') + }) + }) + + describe('as moderator', () => { + beforeEach(async () => { + const headers = await login({ email: 'moderator@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('shows disabled posts', async () => { + const expected = { Post: [{ title: 'Disabled post' }] } + await expect(action()).resolves.toEqual(expected) + }) }) }) }) diff --git a/src/seed/factories/users.js b/src/seed/factories/users.js index c27b2b1ce..491b3f9e1 100644 --- a/src/seed/factories/users.js +++ b/src/seed/factories/users.js @@ -9,6 +9,7 @@ export default function create (params) { password = '1234', role = 'user', avatar = faker.internet.avatar(), + about = faker.lorem.paragraph(), disabled = false, deleted = false } = params @@ -21,6 +22,7 @@ export default function create (params) { password: "${password}", email: "${email}", avatar: "${avatar}", + about: "${about}", role: ${role}, disabled: ${disabled}, deleted: ${deleted} From a252879964d1a715de8692e3b56d25ad75a910e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Wed, 13 Mar 2019 21:03:40 +0100 Subject: [PATCH 03/14] Implement obfuscation behaviour --- src/middleware/softDeleteMiddleware.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/middleware/softDeleteMiddleware.js b/src/middleware/softDeleteMiddleware.js index 042219916..24105c435 100644 --- a/src/middleware/softDeleteMiddleware.js +++ b/src/middleware/softDeleteMiddleware.js @@ -13,13 +13,14 @@ const setDefaultFilters = (resolve, root, args, context, info) => { return resolve(root, args, context, info) } -const hideDisabledComments = async (resolve, root, args, context, info) => { - const { comments } = root - if (!Array.isArray(comments)) return resolve(root, args, context, info) - if (!isModerator(context)) { - root.comments = comments.filter((comment) => { - return !comment.disabled - }) +const obfuscateDisabled = async (resolve, root, args, context, info) => { + if (!isModerator(context) && root.disabled) { + root.content = 'DELETED' + root.contentExcerpt = 'DELETED' + root.title = 'DELETED' + root.image = 'DELETED' + root.avatar = 'DELETED' + root.about = 'DELETED' } return resolve(root, args, context, info) } @@ -38,6 +39,7 @@ export default { } return resolve(root, args, context, info) }, - Post: hideDisabledComments, - User: hideDisabledComments + Post: obfuscateDisabled, + User: obfuscateDisabled, + Comment: obfuscateDisabled } From dc9706caf35a42de84bded5ef411d3656fdaaf7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 12 Mar 2019 04:31:18 +0000 Subject: [PATCH 04/14] Bump jest from 24.3.1 to 24.4.0 Bumps [jest](https://github.com/facebook/jest) from 24.3.1 to 24.4.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/compare/v24.3.1...v24.4.0) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 514 ++++++++++++++++++++++----------------------------- 2 files changed, 217 insertions(+), 299 deletions(-) diff --git a/package.json b/package.json index 1da1f35c6..254b55e5d 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "eslint-plugin-promise": "~4.0.1", "eslint-plugin-standard": "~4.0.0", "graphql-request": "~1.8.2", - "jest": "~24.3.1", + "jest": "~24.4.0", "nodemon": "~1.18.10", "nyc": "~13.3.0", "supertest": "~4.0.0" diff --git a/yarn.lock b/yarn.lock index afbc08dae..24b54ead3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -748,32 +748,32 @@ chalk "^2.0.1" slash "^2.0.0" -"@jest/core@^24.3.1": - version "24.3.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.3.1.tgz#9811596d9fcc6dbb3d4062c67e4c4867bc061585" - integrity sha512-orucOIBKfXgm1IJirtPT0ToprqDVGYKUNJKNc9a6v1Lww6qLPq+xj5OfxyhpJb2rWOgzEkATW1bfZzg3oqV70w== +"@jest/core@^24.5.0": + version "24.5.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.5.0.tgz#2cefc6a69e9ebcae1da8f7c75f8a257152ba1ec0" + integrity sha512-RDZArRzAs51YS7dXG1pbXbWGxK53rvUu8mCDYsgqqqQ6uSOaTjcVyBl2Jce0exT2rSLk38ca7az7t2f3b0/oYQ== dependencies: "@jest/console" "^24.3.0" - "@jest/reporters" "^24.3.1" - "@jest/test-result" "^24.3.0" - "@jest/transform" "^24.3.1" - "@jest/types" "^24.3.0" + "@jest/reporters" "^24.5.0" + "@jest/test-result" "^24.5.0" + "@jest/transform" "^24.5.0" + "@jest/types" "^24.5.0" ansi-escapes "^3.0.0" chalk "^2.0.1" exit "^0.1.2" graceful-fs "^4.1.15" - jest-changed-files "^24.3.0" - jest-config "^24.3.1" - jest-haste-map "^24.3.1" - jest-message-util "^24.3.0" + jest-changed-files "^24.5.0" + jest-config "^24.5.0" + jest-haste-map "^24.5.0" + jest-message-util "^24.5.0" jest-regex-util "^24.3.0" - jest-resolve-dependencies "^24.3.1" - jest-runner "^24.3.1" - jest-runtime "^24.3.1" - jest-snapshot "^24.3.1" - jest-util "^24.3.0" - jest-validate "^24.3.1" - jest-watcher "^24.3.0" + jest-resolve-dependencies "^24.5.0" + jest-runner "^24.5.0" + jest-runtime "^24.5.0" + jest-snapshot "^24.5.0" + jest-util "^24.5.0" + jest-validate "^24.5.0" + jest-watcher "^24.5.0" micromatch "^3.1.10" p-each-series "^1.0.0" pirates "^4.0.1" @@ -781,26 +781,16 @@ rimraf "^2.5.4" strip-ansi "^5.0.0" -"@jest/environment@^24.3.1": - version "24.3.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.3.1.tgz#1fbda3ec8fb8ffbaee665d314da91d662227e11e" - integrity sha512-M8bqEkQqPwZVhMMFMqqCnzqIZtuM5vDMfFQ9ZvnEfRT+2T1zTA4UAOH/V4HagEi6S3BCd/mdxFdYmPgXf7GKCA== +"@jest/environment@^24.5.0": + version "24.5.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.5.0.tgz#a2557f7808767abea3f9e4cc43a172122a63aca8" + integrity sha512-tzUHR9SHjMXwM8QmfHb/EJNbF0fjbH4ieefJBvtwO8YErLTrecc1ROj0uo2VnIT6SlpEGZnvdCK6VgKYBo8LsA== dependencies: - "@jest/fake-timers" "^24.3.0" - "@jest/transform" "^24.3.1" - "@jest/types" "^24.3.0" + "@jest/fake-timers" "^24.5.0" + "@jest/transform" "^24.5.0" + "@jest/types" "^24.5.0" "@types/node" "*" - jest-mock "^24.3.0" - -"@jest/fake-timers@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.3.0.tgz#0a7f8b877b78780c3fa5c3f8683cc0aaf9488331" - integrity sha512-rHwVI17dGMHxHzfAhnZ04+wFznjFfZ246QugeBnbiYr7/bDosPD2P1qeNjWnJUUcfl0HpS6kkr+OB/mqSJxQFg== - dependencies: - "@jest/types" "^24.3.0" - "@types/node" "*" - jest-message-util "^24.3.0" - jest-mock "^24.3.0" + jest-mock "^24.5.0" "@jest/fake-timers@^24.5.0": version "24.5.0" @@ -812,15 +802,15 @@ jest-message-util "^24.5.0" jest-mock "^24.5.0" -"@jest/reporters@^24.3.1": - version "24.3.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.3.1.tgz#68e4abc8d4233acd0dd87287f3bd270d81066248" - integrity sha512-jEIDJcvk20ReUW1Iqb+prlAcFV+kfFhQ/01poCq8X9As7/l/2y1GqVwJ3+6SaPTZuCXh0d0LVDy86zDAa8zlVA== +"@jest/reporters@^24.5.0": + version "24.5.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.5.0.tgz#9363a210d0daa74696886d9cb294eb8b3ad9b4d9" + integrity sha512-vfpceiaKtGgnuC3ss5czWOihKOUSyjJA4M4udm6nH8xgqsuQYcyDCi4nMMcBKsHXWgz9/V5G7iisnZGfOh1w6Q== dependencies: - "@jest/environment" "^24.3.1" - "@jest/test-result" "^24.3.0" - "@jest/transform" "^24.3.1" - "@jest/types" "^24.3.0" + "@jest/environment" "^24.5.0" + "@jest/test-result" "^24.5.0" + "@jest/transform" "^24.5.0" + "@jest/types" "^24.5.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.2" @@ -828,11 +818,11 @@ istanbul-lib-coverage "^2.0.2" istanbul-lib-instrument "^3.0.1" istanbul-lib-source-maps "^3.0.1" - jest-haste-map "^24.3.1" - jest-resolve "^24.3.1" - jest-runtime "^24.3.1" - jest-util "^24.3.0" - jest-worker "^24.3.1" + jest-haste-map "^24.5.0" + jest-resolve "^24.5.0" + jest-runtime "^24.5.0" + jest-util "^24.5.0" + jest-worker "^24.4.0" node-notifier "^5.2.1" slash "^2.0.0" source-map "^0.6.0" @@ -847,15 +837,6 @@ graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/test-result@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.3.0.tgz#4c0b1c9716212111920f7cf8c4329c69bc81924a" - integrity sha512-j7UZ49T8C4CVipEY99nLttnczVTtLyVzFfN20OiBVn7awOs0U3endXSTq7ouPrLR5y4YjI5GDcbcvDUjgeamzg== - dependencies: - "@jest/console" "^24.3.0" - "@jest/types" "^24.3.0" - "@types/istanbul-lib-coverage" "^1.1.0" - "@jest/test-result@^24.5.0": version "24.5.0" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.5.0.tgz#ab66fb7741a04af3363443084e72ea84861a53f2" @@ -865,7 +846,7 @@ "@jest/types" "^24.5.0" "@types/istanbul-lib-coverage" "^1.1.0" -"@jest/transform@^24.3.1", "@jest/transform@^24.5.0": +"@jest/transform@^24.5.0": version "24.5.0" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.5.0.tgz#6709fc26db918e6af63a985f2cc3c464b4cf99d9" integrity sha512-XSsDz1gdR/QMmB8UCKlweAReQsZrD/DK7FuDlNo/pE8EcKMrfi2kqLRk8h8Gy/PDzgqJj64jNEzOce9pR8oj1w== @@ -886,7 +867,7 @@ source-map "^0.6.1" write-file-atomic "2.4.1" -"@jest/types@^24.3.0", "@jest/types@^24.5.0": +"@jest/types@^24.5.0": version "24.5.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.5.0.tgz#feee214a4d0167b0ca447284e95a57aa10b3ee95" integrity sha512-kN7RFzNMf2R8UDadPOl6ReyI+MT8xfqRuAnuVL+i4gwjv/zubdDK+EDeLHYwq1j0CSSR2W/MmgaRlMZJzXdmVA== @@ -1721,7 +1702,7 @@ babel-eslint@~10.0.1: eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" -babel-jest@^24.3.1, babel-jest@~24.5.0: +babel-jest@^24.5.0, babel-jest@~24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.5.0.tgz#0ea042789810c2bec9065f7c8ab4dc18e1d28559" integrity sha512-0fKCXyRwxFTJL0UXDJiT2xYxO9Lu2vBd9n+cC+eDjESzcVG3s2DRGAxbzJX21fceB1WYoBjAh8pQ83dKcl003g== @@ -2969,16 +2950,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.3.1.tgz#7c42507da231a91a8099d065bc8dc9322dc85fc0" - integrity sha512-xnmobSlaqhg4FKqjb5REk4AobQzFMJoctDdREKfSGqrtzRfCWYbfqt3WmikAvQz/J8mCNQhORgYdEjPMJbMQPQ== +expect@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.5.0.tgz#492fb0df8378d8474cc84b827776b069f46294ed" + integrity sha512-p2Gmc0CLxOgkyA93ySWmHFYHUPFIHG6XZ06l7WArWAsrqYVaVEkOU5NtT5i68KUyGKbkQgDCkiT65bWmdoL6Bw== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" ansi-styles "^3.2.0" jest-get-type "^24.3.0" - jest-matcher-utils "^24.3.1" - jest-message-util "^24.3.0" + jest-matcher-utils "^24.5.0" + jest-message-util "^24.5.0" jest-regex-util "^24.3.0" express@^4.0.0, express@^4.16.3: @@ -4223,65 +4204,65 @@ iterall@^1.1.3, iterall@^1.2.1, iterall@^1.2.2: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== -jest-changed-files@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.3.0.tgz#7050ae29aaf1d59437c80f21d5b3cd354e88a499" - integrity sha512-fTq0YAUR6644fgsqLC7Zi2gXA/bAplMRvfXQdutmkwgrCKK6upkj+sgXqsUfUZRm15CVr3YSojr/GRNn71IMvg== +jest-changed-files@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.5.0.tgz#4075269ee115d87194fd5822e642af22133cf705" + integrity sha512-Ikl29dosYnTsH9pYa1Tv9POkILBhN/TLZ37xbzgNsZ1D2+2n+8oEZS2yP1BrHn/T4Rs4Ggwwbp/x8CKOS5YJOg== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.3.1.tgz#52e4ae5f11044b41e06ca39fc7a7302fbbcb1661" - integrity sha512-HdwMgigvDQdlWX7gwM2QMkJJRqSk7tTYKq7kVplblK28RarqquJMWV/lOCN8CukuG9u3DZTeXpCDXR7kpGfB3w== +jest-cli@^24.4.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.5.0.tgz#598139d3446d1942fb7dc93944b9ba766d756d4b" + integrity sha512-P+Jp0SLO4KWN0cGlNtC7JV0dW1eSFR7eRpoOucP2UM0sqlzp/bVHeo71Omonvigrj9AvCKy7NtQANtqJ7FXz8g== dependencies: - "@jest/core" "^24.3.1" - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" + "@jest/core" "^24.5.0" + "@jest/test-result" "^24.5.0" + "@jest/types" "^24.5.0" chalk "^2.0.1" exit "^0.1.2" import-local "^2.0.0" is-ci "^2.0.0" - jest-config "^24.3.1" - jest-util "^24.3.0" - jest-validate "^24.3.1" + jest-config "^24.5.0" + jest-util "^24.5.0" + jest-validate "^24.5.0" prompts "^2.0.1" realpath-native "^1.1.0" yargs "^12.0.2" -jest-config@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.3.1.tgz#271aff2d3aeabf1ff92512024eeca3323cd31a07" - integrity sha512-ujHQywsM//vKFvJwEC02KNZgKAGOzGz1bFPezmTQtuj8XdfsAVq8p6N/dw4yodXV11gSf6TJ075i4ehM+mKatA== +jest-config@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.5.0.tgz#404d1bc6bb81aed6bd1890d07e2dca9fbba2e121" + integrity sha512-t2UTh0Z2uZhGBNVseF8wA2DS2SuBiLOL6qpLq18+OZGfFUxTM7BzUVKyHFN/vuN+s/aslY1COW95j1Rw81huOQ== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^24.3.0" - babel-jest "^24.3.1" + "@jest/types" "^24.5.0" + babel-jest "^24.5.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.3.1" - jest-environment-node "^24.3.1" + jest-environment-jsdom "^24.5.0" + jest-environment-node "^24.5.0" jest-get-type "^24.3.0" - jest-jasmine2 "^24.3.1" + jest-jasmine2 "^24.5.0" jest-regex-util "^24.3.0" - jest-resolve "^24.3.1" - jest-util "^24.3.0" - jest-validate "^24.3.1" + jest-resolve "^24.5.0" + jest-util "^24.5.0" + jest-validate "^24.5.0" micromatch "^3.1.10" - pretty-format "^24.3.1" + pretty-format "^24.5.0" realpath-native "^1.1.0" -jest-diff@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.3.1.tgz#87952e5ea1548567da91df398fa7bf7977d3f96a" - integrity sha512-YRVzDguyzShP3Pb9wP/ykBkV7Z+O4wltrMZ2P4LBtNxrHNpxwI2DECrpD9XevxWubRy5jcE8sSkxyX3bS7W+rA== +jest-diff@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.5.0.tgz#a2d8627964bb06a91893c0fbcb28ab228c257652" + integrity sha512-mCILZd9r7zqL9Uh6yNoXjwGQx0/J43OD2vvWVKwOEOLZliQOsojXwqboubAQ+Tszrb6DHGmNU7m4whGeB9YOqw== dependencies: chalk "^2.0.1" diff-sequences "^24.3.0" jest-get-type "^24.3.0" - pretty-format "^24.3.1" + pretty-format "^24.5.0" jest-docblock@^24.3.0: version "24.3.0" @@ -4290,60 +4271,45 @@ jest-docblock@^24.3.0: dependencies: detect-newline "^2.1.0" -jest-each@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.3.1.tgz#ed8fe8b9f92a835a6625ca8c7ee06bc904440316" - integrity sha512-GTi+nxDaWwSgOPLiiqb/p4LURy0mv3usoqsA2eoTYSmRsLgjgZ6VUyRpUBH5JY9EMBx33suNFXk0iyUm29WRpw== +jest-each@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.5.0.tgz#da14d017a1b7d0f01fb458d338314cafe7f72318" + integrity sha512-6gy3Kh37PwIT5sNvNY2VchtIFOOBh8UCYnBlxXMb5sr5wpJUDPTUATX2Axq1Vfk+HWTMpsYPeVYp4TXx5uqUBw== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" chalk "^2.0.1" jest-get-type "^24.3.0" - jest-util "^24.3.0" - pretty-format "^24.3.1" + jest-util "^24.5.0" + pretty-format "^24.5.0" -jest-environment-jsdom@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.3.1.tgz#49826bcf12fb3e38895f1e2aaeb52bde603cc2e4" - integrity sha512-rz2OSYJiQerDqWDwjisqRwhVNpwkqFXdtyMzEuJ47Ip9NRpRQ+qy7/+zFujPUy/Z+zjWRO5seHLB/dOD4VpEVg== +jest-environment-jsdom@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.5.0.tgz#1c3143063e1374100f8c2723a8b6aad23b6db7eb" + integrity sha512-62Ih5HbdAWcsqBx2ktUnor/mABBo1U111AvZWcLKeWN/n/gc5ZvDBKe4Og44fQdHKiXClrNGC6G0mBo6wrPeGQ== dependencies: - "@jest/environment" "^24.3.1" - "@jest/fake-timers" "^24.3.0" - "@jest/types" "^24.3.0" - jest-mock "^24.3.0" - jest-util "^24.3.0" + "@jest/environment" "^24.5.0" + "@jest/fake-timers" "^24.5.0" + "@jest/types" "^24.5.0" + jest-mock "^24.5.0" + jest-util "^24.5.0" jsdom "^11.5.1" -jest-environment-node@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.3.1.tgz#333d864c569b27658a96bb3b10e02e7172125415" - integrity sha512-Xy+/yFem/yUs9OkzbcawQT237vwDjBhAVLjac1KYAMYVjGb0Vb/Ovw4g61PunVdrEIpfcXNtRUltM4+9c7lARQ== +jest-environment-node@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.5.0.tgz#763eebdf529f75b60aa600c6cf8cb09873caa6ab" + integrity sha512-du6FuyWr/GbKLsmAbzNF9mpr2Iu2zWSaq/BNHzX+vgOcts9f2ayXBweS7RAhr+6bLp6qRpMB6utAMF5Ygktxnw== dependencies: - "@jest/environment" "^24.3.1" - "@jest/fake-timers" "^24.3.0" - "@jest/types" "^24.3.0" - jest-mock "^24.3.0" - jest-util "^24.3.0" + "@jest/environment" "^24.5.0" + "@jest/fake-timers" "^24.5.0" + "@jest/types" "^24.5.0" + jest-mock "^24.5.0" + jest-util "^24.5.0" jest-get-type@^24.3.0: version "24.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.3.0.tgz#582cfd1a4f91b5cdad1d43d2932f816d543c65da" integrity sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow== -jest-haste-map@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.3.1.tgz#b4a66dbe1e6bc45afb9cd19c083bff81cdd535a1" - integrity sha512-OTMQle+astr1lWKi62Ccmk2YWn6OtUoU/8JpJdg8zdsnpFIry/k0S4sQ4nWocdM07PFdvqcthWc78CkCE6sXvA== - dependencies: - "@jest/types" "^24.3.0" - fb-watchman "^2.0.0" - graceful-fs "^4.1.15" - invariant "^2.2.4" - jest-serializer "^24.3.0" - jest-util "^24.3.0" - jest-worker "^24.3.1" - micromatch "^3.1.10" - sane "^4.0.3" - jest-haste-map@^24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.5.0.tgz#3f17d0c548b99c0c96ed2893f9c0ccecb2eb9066" @@ -4359,58 +4325,44 @@ jest-haste-map@^24.5.0: micromatch "^3.1.10" sane "^4.0.3" -jest-jasmine2@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.3.1.tgz#127d628d3ac0829bd3c0fccacb87193e543b420b" - integrity sha512-STo6ar1IyPlIPq9jPxDQhM7lC0dAX7KKN0LmCLMlgJeXwX+1XiVdtZDv1a4zyg6qhNdpo1arOBGY0BcovUK7ug== +jest-jasmine2@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.5.0.tgz#e6af4d7f73dc527d007cca5a5b177c0bcc29d111" + integrity sha512-sfVrxVcx1rNUbBeyIyhkqZ4q+seNKyAG6iM0S2TYBdQsXjoFDdqWFfsUxb6uXSsbimbXX/NMkJIwUZ1uT9+/Aw== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^24.3.1" - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" + "@jest/environment" "^24.5.0" + "@jest/test-result" "^24.5.0" + "@jest/types" "^24.5.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.3.1" + expect "^24.5.0" is-generator-fn "^2.0.0" - jest-each "^24.3.1" - jest-matcher-utils "^24.3.1" - jest-message-util "^24.3.0" - jest-runtime "^24.3.1" - jest-snapshot "^24.3.1" - jest-util "^24.3.0" - pretty-format "^24.3.1" + jest-each "^24.5.0" + jest-matcher-utils "^24.5.0" + jest-message-util "^24.5.0" + jest-runtime "^24.5.0" + jest-snapshot "^24.5.0" + jest-util "^24.5.0" + pretty-format "^24.5.0" throat "^4.0.0" -jest-leak-detector@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.3.1.tgz#ed89d05ca07e91b2b51dac1f676ab354663aa8da" - integrity sha512-GncRwEtAw/SohdSyY4bk2RE06Ac1dZrtQGZQ2j35hSuN4gAAAKSYMszJS2WDixsAEaFN+GHBHG+d8pjVGklKyw== +jest-leak-detector@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.5.0.tgz#21ae2b3b0da252c1171cd494f75696d65fb6fa89" + integrity sha512-LZKBjGovFRx3cRBkqmIg+BZnxbrLqhQl09IziMk3oeh1OV81Hg30RUIx885mq8qBv1PA0comB9bjKcuyNO1bCQ== dependencies: - pretty-format "^24.3.1" + pretty-format "^24.5.0" -jest-matcher-utils@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.3.1.tgz#025e1cd9c54a5fde68e74b12428775d06d123aa8" - integrity sha512-P5VIsUTJeI0FYvWVMwEHjxK1L83vEkDiKMV0XFPIrT2jzWaWPB2+dPCHkP2ID9z4eUKElaHqynZnJiOdNVHfXQ== +jest-matcher-utils@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.5.0.tgz#5995549dcf09fa94406e89526e877b094dad8770" + integrity sha512-QM1nmLROjLj8GMGzg5VBra3I9hLpjMPtF1YqzQS3rvWn2ltGZLrGAO1KQ9zUCVi5aCvrkbS5Ndm2evIP9yZg1Q== dependencies: chalk "^2.0.1" - jest-diff "^24.3.1" + jest-diff "^24.5.0" jest-get-type "^24.3.0" - pretty-format "^24.3.1" - -jest-message-util@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.3.0.tgz#e8f64b63ebc75b1a9c67ee35553752596e70d4a9" - integrity sha512-lXM0YgKYGqN5/eH1NGw4Ix+Pk2I9Y77beyRas7xM24n+XTTK3TbT0VkT3L/qiyS7WkW0YwyxoXnnAaGw4hsEDA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" - "@types/stack-utils" "^1.0.1" - chalk "^2.0.1" - micromatch "^3.1.10" - slash "^2.0.0" - stack-utils "^1.0.1" + pretty-format "^24.5.0" jest-message-util@^24.5.0: version "24.5.0" @@ -4426,13 +4378,6 @@ jest-message-util@^24.5.0: slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.3.0.tgz#95a86b6ad474e3e33227e6dd7c4ff6b07e18d3cb" - integrity sha512-AhAo0qjbVWWGvcbW5nChFjR0ObQImvGtU6DodprNziDOt+pP0CBdht/sYcNIOXeim8083QUi9bC8QdKB8PTK4Q== - dependencies: - "@jest/types" "^24.3.0" - jest-mock@^24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.5.0.tgz#976912c99a93f2a1c67497a9414aa4d9da4c7b76" @@ -4440,131 +4385,113 @@ jest-mock@^24.5.0: dependencies: "@jest/types" "^24.5.0" +jest-pnp-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" + integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + jest-regex-util@^24.3.0: version "24.3.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36" integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== -jest-resolve-dependencies@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.3.1.tgz#a22839d611ba529a74594ee274ce2b77d046bea9" - integrity sha512-9JUejNImGnJjbNR/ttnod+zQIWANpsrYMPt18s2tYGK6rP191qFsyEQ2BhAQMdYDRkTmi8At+Co9tL+jTPqdpw== +jest-resolve-dependencies@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.5.0.tgz#1a0dae9cdd41349ca4a84148b3e78da2ba33fd4b" + integrity sha512-dRVM1D+gWrFfrq2vlL5P9P/i8kB4BOYqYf3S7xczZ+A6PC3SgXYSErX/ScW/469pWMboM1uAhgLF+39nXlirCQ== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" jest-regex-util "^24.3.0" - jest-snapshot "^24.3.1" + jest-snapshot "^24.5.0" -jest-resolve@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.3.1.tgz#103dbd438b59618ea428ec4acbd65c56495ba397" - integrity sha512-N+Q3AcVuKxpn/kjQMxUVLwBk32ZE1diP4MPcHyjVwcKpCUuKrktfRR3Mqe/T2HoD25wyccstaqcPUKIudl41bg== +jest-resolve@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.5.0.tgz#8c16ba08f60a1616c3b1cd7afb24574f50a24d04" + integrity sha512-ZIfGqLX1Rg8xJpQqNjdoO8MuxHV1q/i2OO1hLXjgCWFWs5bsedS8UrOdgjUqqNae6DXA+pCyRmdcB7lQEEbXew== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" browser-resolve "^1.11.3" chalk "^2.0.1" + jest-pnp-resolver "^1.2.1" realpath-native "^1.1.0" -jest-runner@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.3.1.tgz#5488566fa60cdb4b00a89c734ad6b54b9561415d" - integrity sha512-Etc9hQ5ruwg+q7DChm+E8qzHHdNTLeUdlo+whPQRSpNSgl0AEgc2r2mT4lxODREqmnHg9A8JHA44pIG4GE0Gzg== +jest-runner@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.5.0.tgz#9be26ece4fd4ab3dfb528b887523144b7c5ffca8" + integrity sha512-oqsiS9TkIZV5dVkD+GmbNfWBRPIvxqmlTQ+AQUJUQ07n+4xTSDc40r+aKBynHw9/tLzafC00DIbJjB2cOZdvMA== dependencies: "@jest/console" "^24.3.0" - "@jest/environment" "^24.3.1" - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" + "@jest/environment" "^24.5.0" + "@jest/test-result" "^24.5.0" + "@jest/types" "^24.5.0" chalk "^2.4.2" exit "^0.1.2" graceful-fs "^4.1.15" - jest-config "^24.3.1" + jest-config "^24.5.0" jest-docblock "^24.3.0" - jest-haste-map "^24.3.1" - jest-jasmine2 "^24.3.1" - jest-leak-detector "^24.3.1" - jest-message-util "^24.3.0" - jest-resolve "^24.3.1" - jest-runtime "^24.3.1" - jest-util "^24.3.0" - jest-worker "^24.3.1" + jest-haste-map "^24.5.0" + jest-jasmine2 "^24.5.0" + jest-leak-detector "^24.5.0" + jest-message-util "^24.5.0" + jest-resolve "^24.5.0" + jest-runtime "^24.5.0" + jest-util "^24.5.0" + jest-worker "^24.4.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.3.1.tgz#2798230b4fbed594b375a13e395278694d4751e2" - integrity sha512-Qz/tJWbZ2naFJ2Kvy1p+RhhRgsPYh4e6wddVRy6aHBr32FTt3Ja33bfV7pkMFWXFbVuAsJMJVdengbvdhWzq4A== +jest-runtime@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.5.0.tgz#3a76e0bfef4db3896d5116e9e518be47ba771aa2" + integrity sha512-GTFHzfLdwpaeoDPilNpBrorlPoNZuZrwKKzKJs09vWwHo+9TOsIIuszK8cWOuKC7ss07aN1922Ge8fsGdsqCuw== dependencies: "@jest/console" "^24.3.0" - "@jest/environment" "^24.3.1" + "@jest/environment" "^24.5.0" "@jest/source-map" "^24.3.0" - "@jest/transform" "^24.3.1" - "@jest/types" "^24.3.0" + "@jest/transform" "^24.5.0" + "@jest/types" "^24.5.0" "@types/yargs" "^12.0.2" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.1.15" - jest-config "^24.3.1" - jest-haste-map "^24.3.1" - jest-message-util "^24.3.0" - jest-mock "^24.3.0" + jest-config "^24.5.0" + jest-haste-map "^24.5.0" + jest-message-util "^24.5.0" + jest-mock "^24.5.0" jest-regex-util "^24.3.0" - jest-resolve "^24.3.1" - jest-snapshot "^24.3.1" - jest-util "^24.3.0" - jest-validate "^24.3.1" + jest-resolve "^24.5.0" + jest-snapshot "^24.5.0" + jest-util "^24.5.0" + jest-validate "^24.5.0" realpath-native "^1.1.0" slash "^2.0.0" strip-bom "^3.0.0" yargs "^12.0.2" -jest-serializer@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.3.0.tgz#074e307300d1451617cf2630d11543ee4f74a1c8" - integrity sha512-RiSpqo2OFbVLJN/PgAOwQIUeHDfss6NBUDTLhjiJM8Bb5rMrwRqHfkaqahIsOf9cXXB5UjcqDCzbQ7AIoMqWkg== - jest-serializer@^24.4.0: version "24.4.0" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== -jest-snapshot@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.3.1.tgz#0f22a86c1b8c87e823f5ad095e82c19d9ed93d72" - integrity sha512-7wbNJWh0sBjmoaexTOWqS7nleTQME7o2W9XKU6CHCxG49Thjct4aVPC/QPNF5NHnvf4M/VDmudIDbwz6noJTRA== +jest-snapshot@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.5.0.tgz#e5d224468a759fd19e36f01217aac912f500f779" + integrity sha512-eBEeJb5ROk0NcpodmSKnCVgMOo+Qsu5z9EDl3tGffwPzK1yV37mjGWF2YeIz1NkntgTzP+fUL4s09a0+0dpVWA== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" chalk "^2.0.1" - expect "^24.3.1" - jest-diff "^24.3.1" - jest-matcher-utils "^24.3.1" - jest-message-util "^24.3.0" - jest-resolve "^24.3.1" + expect "^24.5.0" + jest-diff "^24.5.0" + jest-matcher-utils "^24.5.0" + jest-message-util "^24.5.0" + jest-resolve "^24.5.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.3.1" + pretty-format "^24.5.0" semver "^5.5.0" -jest-util@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.3.0.tgz#a549ae9910fedbd4c5912b204bb1bcc122ea0057" - integrity sha512-eKIAC+MTKWZthUUVOwZ3Tc5a0cKMnxalQHr6qZ4kPzKn6k09sKvsmjCygqZ1SxVVfUKoa8Sfn6XDv9uTJ1iXTg== - dependencies: - "@jest/console" "^24.3.0" - "@jest/fake-timers" "^24.3.0" - "@jest/source-map" "^24.3.0" - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" - "@types/node" "*" - callsites "^3.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.15" - is-ci "^2.0.0" - mkdirp "^0.5.1" - slash "^2.0.0" - source-map "^0.6.0" - jest-util@^24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.5.0.tgz#9d9cb06d9dcccc8e7cc76df91b1635025d7baa84" @@ -4584,41 +4511,32 @@ jest-util@^24.5.0: slash "^2.0.0" source-map "^0.6.0" -jest-validate@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.3.1.tgz#9359eea5a767a3d20b4fa7a5764fd78330ba8312" - integrity sha512-ww3+IPNCOEMi1oKlrHdSnBXetXtdrrdSh0bqLNTVkWglduhORf94RJWd1ko9oEPU2TcEQS5QIPacYziQIUzc4A== +jest-validate@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.5.0.tgz#62fd93d81214c070bb2d7a55f329a79d8057c7de" + integrity sha512-gg0dYszxjgK2o11unSIJhkOFZqNRQbWOAB2/LOUdsd2LfD9oXiMeuee8XsT0iRy5EvSccBgB4h/9HRbIo3MHgQ== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" camelcase "^5.0.0" chalk "^2.0.1" jest-get-type "^24.3.0" leven "^2.1.0" - pretty-format "^24.3.1" + pretty-format "^24.5.0" -jest-watcher@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.3.0.tgz#ee51c6afbe4b35a12fcf1107556db6756d7b9290" - integrity sha512-EpJS/aUG8D3DMuy9XNA4fnkKWy3DQdoWhY92ZUdlETIeEn1xya4Np/96MBSh4II5YvxwKe6JKwbu3Bnzfwa7vA== +jest-watcher@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.5.0.tgz#da7bd9cb5967e274889b42078c8f501ae1c47761" + integrity sha512-/hCpgR6bg0nKvD3nv4KasdTxuhwfViVMHUATJlnGCD0r1QrmIssimPbmc5KfAQblAVxkD8xrzuij9vfPUk1/rA== dependencies: - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" + "@jest/test-result" "^24.5.0" + "@jest/types" "^24.5.0" "@types/node" "*" "@types/yargs" "^12.0.9" ansi-escapes "^3.0.0" chalk "^2.0.1" - jest-util "^24.3.0" + jest-util "^24.5.0" string-length "^2.0.0" -jest-worker@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.3.1.tgz#c1759dd2b1d5541b09a2e5e1bc3288de6c9d8632" - integrity sha512-ZCoAe/iGLzTJvWHrO8fyx3bmEQhpL16SILJmWHKe8joHhyF3z00psF1sCRT54DoHw5GJG0ZpUtGy+ylvwA4haA== - dependencies: - "@types/node" "*" - merge-stream "^1.0.1" - supports-color "^6.1.0" - jest-worker@^24.4.0: version "24.4.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.4.0.tgz#fbc452b0120bb5c2a70cdc88fa132b48eeb11dd0" @@ -4628,13 +4546,13 @@ jest-worker@^24.4.0: merge-stream "^1.0.1" supports-color "^6.1.0" -jest@~24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.3.1.tgz#81959de0d57b2df923510f4fafe266712d37dcca" - integrity sha512-SqZguEbYNcZ3r0KUUBN+IkKfyPS1VBbIUiK4Wrc0AiGUR52gJa0fmlWSOCL3x25908QrfoQwkVDu5jCsfXb2ig== +jest@~24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.4.0.tgz#688b71a2dadd41e26d0cfc04e1ddcacf30a1efbb" + integrity sha512-gAGfjvu8hHN0N6/aDyCBpncWWBcpY6wq69Msq/I6Xd763q/ZYBEMh0SKUomrViFoJ/dyistA6b4aJh8e+5QMyw== dependencies: import-local "^2.0.0" - jest-cli "^24.3.1" + jest-cli "^24.4.0" jmespath@0.15.0: version "0.15.0" @@ -5884,12 +5802,12 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -pretty-format@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.3.1.tgz#ae4a98e93d73d86913a8a7dd1a7c3c900f8fda59" - integrity sha512-NZGH1NWS6o4i9pvRWLsxIK00JB9pqOUzVrO7yWT6vjI2thdxwvxefBJO6O5T24UAhI8P5dMceZ7x5wphgVI7Mg== +pretty-format@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.5.0.tgz#cc69a0281a62cd7242633fc135d6930cd889822d" + integrity sha512-/3RuSghukCf8Riu5Ncve0iI+BzVkbRU5EeUoArKARZobREycuH5O4waxvaNIloEXdb0qwgmEAed5vTpX1HNROQ== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.5.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" react-is "^16.8.4" From 41ee83a9a873360bf659d0b5fbe0d29d329772fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 14 Mar 2019 04:16:57 +0000 Subject: [PATCH 05/14] Bump apollo-link-http from 1.5.12 to 1.5.13 Bumps [apollo-link-http](https://github.com/apollographql/apollo-link) from 1.5.12 to 1.5.13. - [Release notes](https://github.com/apollographql/apollo-link/releases) - [Changelog](https://github.com/apollographql/apollo-link/blob/master/CHANGELOG.md) - [Commits](https://github.com/apollographql/apollo-link/compare/apollo-link-http@1.5.12...apollo-link-http@1.5.13) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 254b55e5d..140fdc616 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "dependencies": { "apollo-cache-inmemory": "~1.5.1", "apollo-client": "~2.5.1", - "apollo-link-http": "~1.5.12", + "apollo-link-http": "~1.5.13", "apollo-server": "~2.4.8", "bcryptjs": "~2.4.3", "cheerio": "~1.0.0-rc.2", diff --git a/yarn.lock b/yarn.lock index 24b54ead3..c978f7a5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1307,33 +1307,33 @@ apollo-link-dedup@^1.0.0: dependencies: apollo-link "^1.2.4" -apollo-link-http-common@^0.2.11: - version "0.2.11" - resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.11.tgz#d4e494ed1e45ea0e0c0ed60f3df64541d0de682d" - integrity sha512-FjtzEDiG6blH/2MR4fpVNoxdZUFmddP0sez34qnoLaYz6ABFbTDlmRE/dVN79nPExM4Spfs/DtW7KRqyjJ3tOg== +apollo-link-http-common@^0.2.12: + version "0.2.12" + resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.12.tgz#30cb42b6417076872d3e9e7699dbf79a9c9d7bee" + integrity sha512-jMgvp8ZURiaSivKLsB7J0uVKLNit5nPeFaxr85r6CsdS0HQB0tH+aqzblPQeMQ0zpR/EqX8YrogXFZ08y9kjYQ== dependencies: - apollo-link "^1.2.9" + apollo-link "^1.2.10" ts-invariant "^0.3.2" tslib "^1.9.3" -apollo-link-http@~1.5.12: - version "1.5.12" - resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.12.tgz#878d48bf9d8ae091752710529a222c4a5548118e" - integrity sha512-2tS36RIU6OdxzoWYTPrjvDTF2sCrnlaJ6SL7j0ILPn1Lmw4y6YLwKDsv/SWLwtodtVe9v1dLCGKIGMRMM/SdyA== +apollo-link-http@~1.5.13: + version "1.5.13" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.13.tgz#f7d6e1fda0009e0b623df1cbd83902fd71d34f67" + integrity sha512-e8pU/omWPy3pI3v+UKktFuG5YcjbA4jT0jUHo59U51vKszqw5xsYjCOQhw7IPoixYN651vkn122CQEFgL6MuvA== dependencies: - apollo-link "^1.2.9" - apollo-link-http-common "^0.2.11" + apollo-link "^1.2.10" + apollo-link-http-common "^0.2.12" tslib "^1.9.3" -apollo-link@^1.0.0, apollo-link@^1.2.3, apollo-link@^1.2.4, apollo-link@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.9.tgz#40a8f0b90716ce3fd6beb27b7eae1108b92e0054" - integrity sha512-ZLUwthOFZq4lxchQ2jeBfVqS/UDdcVmmh8aUw6Ar9awZH4r+RgkcDeu2ooFLUfodWE3mZr7wIZuYsBas/MaNVA== +apollo-link@^1.0.0, apollo-link@^1.2.10, apollo-link@^1.2.3, apollo-link@^1.2.4: + version "1.2.10" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.10.tgz#98cf24c46c0d75cb878804143e39dcf9813f0c20" + integrity sha512-vQ5u+jEHyLJaV+eUoVKFYYiJcCY9dBNSNhf7Ve9YxeFf84ZDt5NNOPXQEygF39qdoqFRYJb7OkAOJptydteOvw== dependencies: apollo-utilities "^1.2.1" ts-invariant "^0.3.2" tslib "^1.9.3" - zen-observable-ts "^0.8.16" + zen-observable-ts "^0.8.17" apollo-server-caching@0.3.1: version "0.3.1" @@ -7513,10 +7513,10 @@ yup@^0.26.10: synchronous-promise "^2.0.5" toposort "^2.0.2" -zen-observable-ts@^0.8.16: - version "0.8.16" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.16.tgz#969367299074fe17422fe2f46ee417e9a30cf3fa" - integrity sha512-pQl75N7qwgybKVsh6WFO+WwPRijeQ52Gn1vSf4uvPFXald9CbVQXLa5QrOPEJhdZiC+CD4quqOVqSG+Ptz5XLA== +zen-observable-ts@^0.8.17: + version "0.8.17" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.17.tgz#b3183625fa55d3960c829e3a90061f82ec2d7863" + integrity sha512-eVQH3UG5h4lMlD9HMMIsiMk3vsCW66QVOPJQMCSJhP4THswDW7r/BPHO6oCZbA/LZzntv2t8W/bv3vYO9NYh/g== dependencies: tslib "^1.9.3" zen-observable "^0.8.0" From 6b5afe0520878154cde7ab2c25d0ab04f2aba5fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 14 Mar 2019 04:17:11 +0000 Subject: [PATCH 06/14] Bump jest from 24.4.0 to 24.5.0 Bumps [jest](https://github.com/facebook/jest) from 24.4.0 to 24.5.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/compare/v24.4.0...v24.5.0) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 254b55e5d..45d0737bd 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "eslint-plugin-promise": "~4.0.1", "eslint-plugin-standard": "~4.0.0", "graphql-request": "~1.8.2", - "jest": "~24.4.0", + "jest": "~24.5.0", "nodemon": "~1.18.10", "nyc": "~13.3.0", "supertest": "~4.0.0" diff --git a/yarn.lock b/yarn.lock index 24b54ead3..cad225d99 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4213,7 +4213,7 @@ jest-changed-files@^24.5.0: execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.4.0: +jest-cli@^24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.5.0.tgz#598139d3446d1942fb7dc93944b9ba766d756d4b" integrity sha512-P+Jp0SLO4KWN0cGlNtC7JV0dW1eSFR7eRpoOucP2UM0sqlzp/bVHeo71Omonvigrj9AvCKy7NtQANtqJ7FXz8g== @@ -4546,13 +4546,13 @@ jest-worker@^24.4.0: merge-stream "^1.0.1" supports-color "^6.1.0" -jest@~24.4.0: - version "24.4.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.4.0.tgz#688b71a2dadd41e26d0cfc04e1ddcacf30a1efbb" - integrity sha512-gAGfjvu8hHN0N6/aDyCBpncWWBcpY6wq69Msq/I6Xd763q/ZYBEMh0SKUomrViFoJ/dyistA6b4aJh8e+5QMyw== +jest@~24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.5.0.tgz#38f11ae2c2baa2f86c2bc4d8a91d2b51612cd19a" + integrity sha512-lxL+Fq5/RH7inxxmfS2aZLCf8MsS+YCUBfeiNO6BWz/MmjhDGaIEA/2bzEf9q4Q0X+mtFHiinHFvQ0u+RvW/qQ== dependencies: import-local "^2.0.0" - jest-cli "^24.4.0" + jest-cli "^24.5.0" jmespath@0.15.0: version "0.15.0" From 582d2e5c4ea42aba396e46e0711fdc89275cad23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 14 Mar 2019 11:57:44 +0000 Subject: [PATCH 07/14] Bump dotenv from 6.2.0 to 7.0.0 Bumps [dotenv](https://github.com/motdotla/dotenv) from 6.2.0 to 7.0.0. - [Release notes](https://github.com/motdotla/dotenv/releases) - [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md) - [Commits](https://github.com/motdotla/dotenv/compare/v6.2.0...v7.0.0) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 343251848..5c596b910 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "cheerio": "~1.0.0-rc.2", "cross-env": "~5.2.0", "date-fns": "2.0.0-alpha.27", - "dotenv": "~6.2.0", + "dotenv": "~7.0.0", "faker": "~4.1.0", "graphql": "~14.1.1", "graphql-custom-directives": "~0.2.14", diff --git a/yarn.lock b/yarn.lock index 15d79aede..591428412 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2580,10 +2580,10 @@ dotenv@^0.4.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-0.4.0.tgz#f6fb351363c2d92207245c737802c9ab5ae1495a" integrity sha1-9vs1E2PC2SIHJFxzeALJq1rhSVo= -dotenv@~6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" - integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== +dotenv@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-7.0.0.tgz#a2be3cd52736673206e8a85fb5210eea29628e7c" + integrity sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g== duplexer3@^0.1.4: version "0.1.4" From b04e922afc0ad2ce64c260d05bb166bbe8b5e53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Thu, 14 Mar 2019 16:24:16 +0100 Subject: [PATCH 08/14] Disabled users are unauthenticated --- src/jwt/decode.js | 3 ++- src/resolvers/user_management.spec.js | 29 ++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/jwt/decode.js b/src/jwt/decode.js index 0ab1e4529..6abc06dc1 100644 --- a/src/jwt/decode.js +++ b/src/jwt/decode.js @@ -13,7 +13,7 @@ export default async (driver, authorizationHeader) => { const session = driver.session() const query = ` MATCH (user:User {id: {id} }) - RETURN user {.id, .slug, .name, .avatar, .email, .role} as user + RETURN user {.id, .slug, .name, .avatar, .email, .role, .disabled} LIMIT 1 ` const result = await session.run(query, { id }) @@ -22,6 +22,7 @@ export default async (driver, authorizationHeader) => { return record.get('user') }) if (!currentUser) return null + if (currentUser.disabled) return null return { token, ...currentUser diff --git a/src/resolvers/user_management.spec.js b/src/resolvers/user_management.spec.js index c4b09df37..6df1b1626 100644 --- a/src/resolvers/user_management.spec.js +++ b/src/resolvers/user_management.spec.js @@ -73,11 +73,30 @@ describe('isLoggedIn', () => { }) describe('and a corresponding user in the database', () => { - it('returns true', async () => { - // see the decoded token above - await factory.create('User', { id: 'u3' }) - await expect(client.request(query)).resolves.toEqual({ - isLoggedIn: true + describe('user is enabled', () => { + it('returns true', async () => { + // see the decoded token above + await factory.create('User', { id: 'u3' }) + await expect(client.request(query)).resolves.toEqual({ + isLoggedIn: true + }) + }) + }) + + describe('user is disabled', () => { + beforeEach(async () => { + const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } + const asModerator = Factory() + await asModerator.create('User', moderatorParams) + await asModerator.authenticateAs(moderatorParams) + await factory.create('User', { id: 'u3' }) + await asModerator.mutate('mutation($id: ID!) { disable(id: $id) }', { id: 'u3' }) + }) + + it('returns false', async () => { + await expect(client.request(query)).resolves.toEqual({ + isLoggedIn: false + }) }) }) }) From b0ce023f49eb5c7c17d323ab7cec2c16a5e2d2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Thu, 14 Mar 2019 16:44:22 +0100 Subject: [PATCH 09/14] Create failing test @abdellani your turn :muscle: --- src/resolvers/user_management.spec.js | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/resolvers/user_management.spec.js b/src/resolvers/user_management.spec.js index 6df1b1626..1c21adac1 100644 --- a/src/resolvers/user_management.spec.js +++ b/src/resolvers/user_management.spec.js @@ -26,6 +26,14 @@ const jennyRostocksHeaders = { 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoidXNlciIsImxvY2F0aW9uTmFtZSI6bnVsbCwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJhYm91dCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9zYXNoYV9zaGVzdGFrb3YvMTI4LmpwZyIsImlkIjoidTMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5vcmciLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTU1MDg0NjY4MCwiZXhwIjoxNjM3MjQ2NjgwLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.eZ_mVKas4Wzoc_JrQTEWXyRn7eY64cdIg4vqQ-F_7Jc' } +const disable = async (id) => { + const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } + const asModerator = Factory() + await asModerator.create('User', moderatorParams) + await asModerator.authenticateAs(moderatorParams) + await asModerator.mutate('mutation($id: ID!) { disable(id: $id) }', { id }) +} + beforeEach(async () => { await factory.create('User', { avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg', @@ -85,12 +93,8 @@ describe('isLoggedIn', () => { describe('user is disabled', () => { beforeEach(async () => { - const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } - const asModerator = Factory() - await asModerator.create('User', moderatorParams) - await asModerator.authenticateAs(moderatorParams) await factory.create('User', { id: 'u3' }) - await asModerator.mutate('mutation($id: ID!) { disable(id: $id) }', { id: 'u3' }) + await disable('u3') }) it('returns false', async () => { @@ -187,6 +191,21 @@ describe('login', () => { }) }) + describe('valid email/password but user is disabled', () => { + it('responds with "Your account has been disabled."', async () => { + await disable('acb2d923-f3af-479e-9f00-61b12e864666') + await expect( + request( + host, + mutation({ + email: 'test@example.org', + password: '1234' + }) + ) + ).rejects.toThrow('Your account has been disabled.') + }) + }) + describe('with a valid email but incorrect password', () => { it('responds with "Incorrect email address or password."', async () => { await expect( From b4372dff36562c61b8c49da9751b809e9bd7ddbb Mon Sep 17 00:00:00 2001 From: abdellani Date: Fri, 15 Mar 2019 14:59:36 +0100 Subject: [PATCH 10/14] Show error message when a disabled user tries to authenticate --- src/resolvers/user_management.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index 36865646f..ebb50f0b1 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -32,7 +32,7 @@ export default { const session = driver.session() const result = await session.run( 'MATCH (user:User {email: $userEmail}) ' + - 'RETURN user {.id, .slug, .name, .avatar, .email, .password, .role} as user LIMIT 1', + 'RETURN user {.id, .slug, .name, .avatar, .email, .password, .role, .disabled} as user LIMIT 1', { userEmail: email } @@ -45,11 +45,18 @@ export default { if ( currentUser && - (await bcrypt.compareSync(password, currentUser.password)) + (await bcrypt.compareSync(password, currentUser.password)) && + currentUser.disabled == false ) { delete currentUser.password return encode(currentUser) - } else { + } + else if (currentUser && + currentUser.disabled + ){ + throw new AuthenticationError('Your account has been disabled.') + } + else { throw new AuthenticationError('Incorrect email address or password.') } }, From b7cc18ee98e568cdf31ba41d3eafd21344a421db Mon Sep 17 00:00:00 2001 From: abdellani Date: Fri, 15 Mar 2019 18:33:07 +0100 Subject: [PATCH 11/14] Show error message when a disabled user tries to authenticate --- src/resolvers/user_management.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index ebb50f0b1..c81d12c37 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -46,17 +46,15 @@ export default { if ( currentUser && (await bcrypt.compareSync(password, currentUser.password)) && - currentUser.disabled == false + !currentUser.disabled ) { delete currentUser.password return encode(currentUser) - } - else if (currentUser && + } else if (currentUser && currentUser.disabled - ){ + ) { throw new AuthenticationError('Your account has been disabled.') - } - else { + } else { throw new AuthenticationError('Incorrect email address or password.') } }, From eacb0a452e8fd6bc7f44e056a5373189376d6e84 Mon Sep 17 00:00:00 2001 From: abdellani Date: Fri, 15 Mar 2019 18:33:07 +0100 Subject: [PATCH 12/14] Show error message when a disabled user tries to authenticate --- src/resolvers/user_management.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index ebb50f0b1..26dfb81db 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -46,17 +46,15 @@ export default { if ( currentUser && (await bcrypt.compareSync(password, currentUser.password)) && - currentUser.disabled == false + !currentUser.disabled ) { delete currentUser.password return encode(currentUser) - } - else if (currentUser && + } else if (currentUser && currentUser.disabled - ){ + ) { throw new AuthenticationError('Your account has been disabled.') - } - else { + } else { throw new AuthenticationError('Incorrect email address or password.') } }, From d0fd20e790efdf6805ed74f3997e98f519a51e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Fri, 15 Mar 2019 20:36:18 +0100 Subject: [PATCH 13/14] Obfuscate user name and use a neutral replacement --- src/middleware/softDeleteMiddleware.js | 13 +++++------ src/middleware/softDeleteMiddleware.spec.js | 24 +++++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/middleware/softDeleteMiddleware.js b/src/middleware/softDeleteMiddleware.js index 24105c435..53beca219 100644 --- a/src/middleware/softDeleteMiddleware.js +++ b/src/middleware/softDeleteMiddleware.js @@ -15,12 +15,13 @@ const setDefaultFilters = (resolve, root, args, context, info) => { const obfuscateDisabled = async (resolve, root, args, context, info) => { if (!isModerator(context) && root.disabled) { - root.content = 'DELETED' - root.contentExcerpt = 'DELETED' - root.title = 'DELETED' - root.image = 'DELETED' - root.avatar = 'DELETED' - root.about = 'DELETED' + root.content = 'UNAVAILABLE' + root.contentExcerpt = 'UNAVAILABLE' + root.title = 'UNAVAILABLE' + root.image = 'UNAVAILABLE' + root.avatar = 'UNAVAILABLE' + root.about = 'UNAVAILABLE' + root.name = 'UNAVAILABLE' } return resolve(root, args, context, info) } diff --git a/src/middleware/softDeleteMiddleware.spec.js b/src/middleware/softDeleteMiddleware.spec.js index 6b8b4bc49..46005a4ff 100644 --- a/src/middleware/softDeleteMiddleware.spec.js +++ b/src/middleware/softDeleteMiddleware.spec.js @@ -12,7 +12,7 @@ beforeAll(async () => { await Promise.all([ factory.create('User', { id: 'u1', role: 'user', email: 'user@example.org', password: '1234' }), factory.create('User', { id: 'm1', role: 'moderator', email: 'moderator@example.org', password: '1234' }), - factory.create('User', { id: 'u2', role: 'user', avatar: '/some/offensive/avatar.jpg', about: 'This self description is very offensive', email: 'troll@example.org', password: '1234' }) + factory.create('User', { id: 'u2', role: 'user', name: 'Offensive Name', avatar: '/some/offensive/avatar.jpg', about: 'This self description is very offensive', email: 'troll@example.org', password: '1234' }) ]) await factory.authenticateAs({ email: 'user@example.org', password: '1234' }) @@ -62,7 +62,7 @@ describe('softDeleteMiddleware', () => { comment = response.User[0].following[0].comments[0] } const beforeUser = async () => { - query = '{ User(id: "u1") { following { about avatar } } }' + query = '{ User(id: "u1") { following { name about avatar } } }' const response = await action() user = response.User[0].following[0] } @@ -85,6 +85,7 @@ describe('softDeleteMiddleware', () => { describe('User', () => { beforeEach(beforeUser) + it('displays name', () => expect(user.name).toEqual('Offensive Name')) it('displays about', () => expect(user.about).toEqual('This self description is very offensive')) it('displays avatar', () => expect(user.avatar).toEqual('/some/offensive/avatar.jpg')) }) @@ -115,24 +116,25 @@ describe('softDeleteMiddleware', () => { describe('User', () => { beforeEach(beforeUser) - it('obfuscates about', () => expect(user.about).toEqual('DELETED')) - it('obfuscates avatar', () => expect(user.avatar).toEqual('DELETED')) + it('displays name', () => expect(user.name).toEqual('UNAVAILABLE')) + it('obfuscates about', () => expect(user.about).toEqual('UNAVAILABLE')) + it('obfuscates avatar', () => expect(user.avatar).toEqual('UNAVAILABLE')) }) describe('Post', () => { beforeEach(beforePost) - it('obfuscates title', () => expect(post.title).toEqual('DELETED')) - it('obfuscates content', () => expect(post.content).toEqual('DELETED')) - it('obfuscates contentExcerpt', () => expect(post.contentExcerpt).toEqual('DELETED')) - it('obfuscates image', () => expect(post.image).toEqual('DELETED')) + it('obfuscates title', () => expect(post.title).toEqual('UNAVAILABLE')) + it('obfuscates content', () => expect(post.content).toEqual('UNAVAILABLE')) + it('obfuscates contentExcerpt', () => expect(post.contentExcerpt).toEqual('UNAVAILABLE')) + it('obfuscates image', () => expect(post.image).toEqual('UNAVAILABLE')) }) describe('Comment', () => { beforeEach(beforeComment) - it('obfuscates content', () => expect(comment.content).toEqual('DELETED')) - it('obfuscates contentExcerpt', () => expect(comment.contentExcerpt).toEqual('DELETED')) + it('obfuscates content', () => expect(comment.content).toEqual('UNAVAILABLE')) + it('obfuscates contentExcerpt', () => expect(comment.contentExcerpt).toEqual('UNAVAILABLE')) }) }) }) @@ -185,7 +187,7 @@ describe('softDeleteMiddleware', () => { it('conceals disabled comments', async () => { const expected = [ { content: 'Enabled comment on public post' }, - { content: 'DELETED' } + { content: 'UNAVAILABLE' } ] const { Post: [{ comments }] } = await action() await expect(comments).toEqual(expect.arrayContaining(expected)) From 71ed58de3aca7440e65216f5f9873ef3d5190fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Fri, 15 Mar 2019 20:47:33 +0100 Subject: [PATCH 14/14] Create a nice discussion on the most recent post --- src/seed/seed-db.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/seed/seed-db.js b/src/seed/seed-db.js index d526518b9..3de70e643 100644 --- a/src/seed/seed-db.js +++ b/src/seed/seed-db.js @@ -191,7 +191,12 @@ import Factory from './factories' f.create('Comment', { id: 'c4' }), f.create('Comment', { id: 'c5' }), f.create('Comment', { id: 'c6' }), - f.create('Comment', { id: 'c7' }) + f.create('Comment', { id: 'c7' }), + f.create('Comment', { id: 'c8' }), + f.create('Comment', { id: 'c9' }), + f.create('Comment', { id: 'c10' }), + f.create('Comment', { id: 'c11' }), + f.create('Comment', { id: 'c12' }) ]) await Promise.all([ @@ -208,7 +213,17 @@ import Factory from './factories' f.relate('Comment', 'Author', { from: 'u3', to: 'c6' }), f.relate('Comment', 'Post', { from: 'c6', to: 'p4' }), f.relate('Comment', 'Author', { from: 'u2', to: 'c7' }), - f.relate('Comment', 'Post', { from: 'c7', to: 'p2' }) + f.relate('Comment', 'Post', { from: 'c7', to: 'p2' }), + f.relate('Comment', 'Author', { from: 'u5', to: 'c8' }), + f.relate('Comment', 'Post', { from: 'c8', to: 'p15' }), + f.relate('Comment', 'Author', { from: 'u6', to: 'c9' }), + f.relate('Comment', 'Post', { from: 'c9', to: 'p15' }), + f.relate('Comment', 'Author', { from: 'u7', to: 'c10' }), + f.relate('Comment', 'Post', { from: 'c10', to: 'p15' }), + f.relate('Comment', 'Author', { from: 'u5', to: 'c11' }), + f.relate('Comment', 'Post', { from: 'c11', to: 'p15' }), + f.relate('Comment', 'Author', { from: 'u6', to: 'c12' }), + f.relate('Comment', 'Post', { from: 'c12', to: 'p15' }) ]) const disableMutation = 'mutation($id: ID!) { disable(id: $id) }'