From e0e026a8b8c15347cd3adf0c160e267c2a51fa00 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Mon, 23 Mar 2020 18:46:28 +0100 Subject: [PATCH 1/3] fix(migration): return null for Image.url --- ...15-refactor_all_images_to_separate_type.js | 6 +-- ...emove_deleted_users_obsolete_attributes.js | 44 ++++++++++++++++++ ...emove_deleted_posts_obsolete_attributes.js | 46 +++++++++++++++++++ backend/src/schema/resolvers/images.js | 2 +- backend/src/schema/resolvers/users.js | 8 ++++ backend/src/schema/types/type/Image.gql | 2 +- webapp/graphql/PostMutations.js | 2 + 7 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 backend/src/db/migrations/20200323140300-remove_deleted_users_obsolete_attributes.js create mode 100644 backend/src/db/migrations/20200323160336-remove_deleted_posts_obsolete_attributes.js diff --git a/backend/src/db/migrations/20200320200315-refactor_all_images_to_separate_type.js b/backend/src/db/migrations/20200320200315-refactor_all_images_to_separate_type.js index d87a19827..9a0a5c30d 100644 --- a/backend/src/db/migrations/20200320200315-refactor_all_images_to_separate_type.js +++ b/backend/src/db/migrations/20200320200315-refactor_all_images_to_separate_type.js @@ -23,7 +23,7 @@ export async function up() { [ ` MATCH (post:Post) - WHERE post.image IS NOT NULL + WHERE post.image IS NOT NULL AND post.deleted = FALSE MERGE(image:Image {url: post.image}) CREATE (post)-[:HERO_IMAGE]->(image) SET @@ -36,14 +36,14 @@ export async function up() { `, ` MATCH (user:User) - WHERE user.avatar IS NOT NULL + WHERE user.avatar IS NOT NULL AND user.deleted = FALSE MERGE(avatar:Image {url: user.avatar}) CREATE (user)-[:AVATAR_IMAGE]->(avatar) REMOVE user.avatar `, ` MATCH (user:User) - WHERE user.coverImg IS NOT NULL + WHERE user.coverImg IS NOT NULL AND user.deleted = FALSE MERGE(coverImage:Image {url: user.coverImg}) CREATE (user)-[:COVER_IMAGE]->(coverImage) REMOVE user.coverImg diff --git a/backend/src/db/migrations/20200323140300-remove_deleted_users_obsolete_attributes.js b/backend/src/db/migrations/20200323140300-remove_deleted_users_obsolete_attributes.js new file mode 100644 index 000000000..8b2134dc5 --- /dev/null +++ b/backend/src/db/migrations/20200323140300-remove_deleted_users_obsolete_attributes.js @@ -0,0 +1,44 @@ +import { getDriver } from '../../db/neo4j' + +export const description = + 'We should not maintain obsolete attributes for users who have been deleted.' + +export async function up(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + const updateDeletedUserAttributes = await transaction.run(` + MATCH (user:User) + WHERE user.deleted = TRUE + SET user.createdAt = 'UNAVAILABLE' + SET user.updatedAt = 'UNAVAILABLE' + SET user.lastActiveAt = 'UNAVAILABLE' + SET user.termsAndConditionsAgreedVersion = 'UNAVAILABLE' + SET user.avatar = null + SET user.coverImg = null + RETURN user {.*}; + `) + try { + // Implement your migration here. + const users = await updateDeletedUserAttributes.records.map(record => record.get('user')) + // eslint-disable-next-line no-console + console.log(users) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} + +export async function down(next) { + // eslint-disable-next-line no-console + console.log('Irreversible migration') + next() +} diff --git a/backend/src/db/migrations/20200323160336-remove_deleted_posts_obsolete_attributes.js b/backend/src/db/migrations/20200323160336-remove_deleted_posts_obsolete_attributes.js new file mode 100644 index 000000000..07abf9aeb --- /dev/null +++ b/backend/src/db/migrations/20200323160336-remove_deleted_posts_obsolete_attributes.js @@ -0,0 +1,46 @@ +import { getDriver } from '../../db/neo4j' + +export const description = + 'We should not maintain obsolete attributes for posts which have been deleted.' + +export async function up(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + const updateDeletedPostsAttributes = await transaction.run(` + MATCH (post:Post) + WHERE post.deleted = TRUE + SET post.language = 'UNAVAILABLE' + SET post.createdAt = 'UNAVAILABLE' + SET post.updatedAt = 'UNAVAILABLE' + SET post.content = 'UNAVAILABLE' + SET post.title = 'UNAVAILABLE' + SET post.visibility = 'UNAVAILABLE' + SET post.contentExcerpt = 'UNAVAILABLE' + SET post.image = null + RETURN post {.*}; + `) + try { + // Implement your migration here. + const posts = await updateDeletedPostsAttributes.records.map(record => record.get('post')) + // eslint-disable-next-line no-console + console.log(posts) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} + +export async function down(next) { + // eslint-disable-next-line no-console + console.log('Irreversible migration') + next() +} diff --git a/backend/src/schema/resolvers/images.js b/backend/src/schema/resolvers/images.js index 8b3f4a3e8..1f025eda6 100644 --- a/backend/src/schema/resolvers/images.js +++ b/backend/src/schema/resolvers/images.js @@ -2,7 +2,7 @@ import Resolver from './helpers/Resolver' export default { Image: { ...Resolver('Image', { - undefinedToNull: ['sensitive', 'alt', 'aspectRatio'], + undefinedToNull: ['sensitive', 'alt', 'aspectRatio', 'url'], }), }, } diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index 252265ac3..b2f752143 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -192,6 +192,9 @@ export default { SET resource.deleted = true SET resource.content = 'UNAVAILABLE' SET resource.contentExcerpt = 'UNAVAILABLE' + SET resource.language = 'UNAVAILABLE' + SET resource.createdAt = 'UNAVAILABLE' + SET resource.updatedAt = 'UNAVAILABLE' SET comment.deleted = true RETURN resource {.*} `, @@ -214,6 +217,11 @@ export default { SET user.deleted = true SET user.name = 'UNAVAILABLE' SET user.about = 'UNAVAILABLE' + SET user.lastActiveAt = 'UNAVAILABLE' + SET user.createdAt = 'UNAVAILABLE' + SET user.updatedAt = 'UNAVAILABLE' + SET user.termsAndConditionsAgreedVersion = 'UNAVAILABLE' + SET user.encryptedPassword = null WITH user OPTIONAL MATCH (user)<-[:BELONGS_TO]-(email:EmailAddress) DETACH DELETE email diff --git a/backend/src/schema/types/type/Image.gql b/backend/src/schema/types/type/Image.gql index 41cc11eef..d4d9cf1b4 100644 --- a/backend/src/schema/types/type/Image.gql +++ b/backend/src/schema/types/type/Image.gql @@ -1,5 +1,5 @@ type Image { - url: ID!, + url: ID, # urlW34: String, # urlW160: String, # urlW320: String, diff --git a/webapp/graphql/PostMutations.js b/webapp/graphql/PostMutations.js index 9120b3e87..602256e01 100644 --- a/webapp/graphql/PostMutations.js +++ b/webapp/graphql/PostMutations.js @@ -23,6 +23,7 @@ export default () => { contentExcerpt language image { + url sensitive } } @@ -52,6 +53,7 @@ export default () => { contentExcerpt language image { + url sensitive aspectRatio } From 698c85b26229c95a683274750341fd22a16a319a Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Mon, 23 Mar 2020 19:16:10 +0100 Subject: [PATCH 2/3] fix(backend): Obfuscate avatar/image fix test - Then Image.url can be non-nullable because we return null if the resource is deleted. --- backend/src/middleware/softDelete/softDeleteMiddleware.js | 4 ++-- backend/src/schema/resolvers/images.js | 2 +- backend/src/schema/types/type/Image.gql | 2 +- backend/src/schema/types/type/Post.gql | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/src/middleware/softDelete/softDeleteMiddleware.js b/backend/src/middleware/softDelete/softDeleteMiddleware.js index 8be8c3d39..2e1f60251 100644 --- a/backend/src/middleware/softDelete/softDeleteMiddleware.js +++ b/backend/src/middleware/softDelete/softDeleteMiddleware.js @@ -17,10 +17,10 @@ const obfuscate = async (resolve, root, args, context, info) => { root.contentExcerpt = 'UNAVAILABLE' root.title = 'UNAVAILABLE' root.slug = 'UNAVAILABLE' - root.avatar = 'UNAVAILABLE' + root.avatar = null root.about = 'UNAVAILABLE' root.name = 'UNAVAILABLE' - root.image = null // avoid unecessary 500 errors + root.image = null } return resolve(root, args, context, info) } diff --git a/backend/src/schema/resolvers/images.js b/backend/src/schema/resolvers/images.js index 1f025eda6..8b3f4a3e8 100644 --- a/backend/src/schema/resolvers/images.js +++ b/backend/src/schema/resolvers/images.js @@ -2,7 +2,7 @@ import Resolver from './helpers/Resolver' export default { Image: { ...Resolver('Image', { - undefinedToNull: ['sensitive', 'alt', 'aspectRatio', 'url'], + undefinedToNull: ['sensitive', 'alt', 'aspectRatio'], }), }, } diff --git a/backend/src/schema/types/type/Image.gql b/backend/src/schema/types/type/Image.gql index d4d9cf1b4..41cc11eef 100644 --- a/backend/src/schema/types/type/Image.gql +++ b/backend/src/schema/types/type/Image.gql @@ -1,5 +1,5 @@ type Image { - url: ID, + url: ID!, # urlW34: String, # urlW160: String, # urlW320: String, diff --git a/backend/src/schema/types/type/Post.gql b/backend/src/schema/types/type/Post.gql index 01d8409ad..dc6a00a41 100644 --- a/backend/src/schema/types/type/Post.gql +++ b/backend/src/schema/types/type/Post.gql @@ -201,7 +201,6 @@ type Query { title: String slug: String content: String - image: String visibility: Visibility pinned: Boolean createdAt: String From 6e0459ca2da53b185c5d02ed07532c1e56a8975d Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Mon, 23 Mar 2020 20:43:31 +0100 Subject: [PATCH 3/3] fix(build): make locations spec more resilient --- .../schema/resolvers/users/location.spec.js | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/backend/src/schema/resolvers/users/location.spec.js b/backend/src/schema/resolvers/users/location.spec.js index 2e74e5c03..617951f01 100644 --- a/backend/src/schema/resolvers/users/location.spec.js +++ b/backend/src/schema/resolvers/users/location.spec.js @@ -19,48 +19,48 @@ const updateUserMutation = gql` const newlyCreatedNodesWithLocales = [ { city: { - lng: -74.5763, - lat: 41.1534, + id: expect.stringContaining('place'), + type: 'place', + name: 'Hamburg', + nameEN: 'Hamburg', + nameDE: 'Hamburg', + namePT: 'Hamburg', nameES: 'Hamburg', nameFR: 'Hamburg', nameIT: 'Hamburg', - nameEN: 'Hamburg', - type: 'place', - namePT: 'Hamburg', nameRU: 'Хамбург', - nameDE: 'Hamburg', nameNL: 'Hamburg', - name: 'Hamburg', namePL: 'Hamburg', - id: 'place.5977106083398860', + lng: -74.5763, + lat: 41.1534, }, state: { - namePT: 'Nova Jérsia', - nameRU: 'Нью-Джерси', - nameDE: 'New Jersey', - nameNL: 'New Jersey', - nameES: 'Nueva Jersey', + id: expect.stringContaining('region'), + type: 'region', name: 'New Jersey', - namePL: 'New Jersey', + nameEN: 'New Jersey', + nameDE: 'New Jersey', + namePT: 'Nova Jérsia', + nameES: 'Nueva Jersey', nameFR: 'New Jersey', nameIT: 'New Jersey', - id: 'region.14919479731700330', - nameEN: 'New Jersey', - type: 'region', + nameRU: 'Нью-Джерси', + nameNL: 'New Jersey', + namePL: 'New Jersey', }, country: { - namePT: 'Estados Unidos', - nameRU: 'Соединённые Штаты Америки', - nameDE: 'Vereinigte Staaten', - nameNL: 'Verenigde Staten van Amerika', - nameES: 'Estados Unidos', - namePL: 'Stany Zjednoczone', + id: expect.stringContaining('country'), + type: 'country', name: 'United States of America', + nameEN: 'United States of America', + nameDE: 'Vereinigte Staaten', + namePT: 'Estados Unidos', + nameES: 'Estados Unidos', nameFR: 'États-Unis', nameIT: "Stati Uniti d'America", - id: 'country.9053006287256050', - nameEN: 'United States of America', - type: 'country', + nameRU: 'Соединённые Штаты Америки', + nameNL: 'Verenigde Staten van Amerika', + namePL: 'Stany Zjednoczone', }, }, ]