diff --git a/README.md b/README.md index 1e305b201..b2f42c8b9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Codecov Coverage](https://img.shields.io/codecov/c/github/Human-Connection/Human-Connection/master.svg?style=flat-square)](https://codecov.io/gh/Human-Connection/Human-Connection/) [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Human-Connection/Nitro-Backend/blob/backend/LICENSE.md) [![Discord Channel](https://img.shields.io/discord/489522408076738561.svg)](https://discordapp.com/invite/DFSjPaX) +[![Open Source Helpers](https://www.codetriage.com/human-connection/human-connection/badges/users.svg)](https://www.codetriage.com/human-connection/human-connection) Human Connection is a nonprofit social, action and knowledge network that connects information to action and promotes positive local and global change in all areas of life. diff --git a/backend/package.json b/backend/package.json index 3806f9b8f..a7e35917e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -55,12 +55,12 @@ "cheerio": "~1.0.0-rc.3", "cors": "~2.8.5", "cross-env": "~5.2.1", - "date-fns": "2.1.0", + "date-fns": "2.2.1", "debug": "~4.1.1", "dotenv": "~8.1.0", "express": "^4.17.1", "faker": "Marak/faker.js#master", - "graphql": "^14.5.4", + "graphql": "^14.5.6", "graphql-custom-directives": "~0.2.14", "graphql-iso-date": "~3.6.1", "graphql-middleware": "~3.0.5", @@ -73,7 +73,7 @@ "lodash": "~4.17.14", "merge-graphql-schemas": "^1.7.0", "metascraper": "^4.10.3", - "metascraper-audio": "^5.6.5", + "metascraper-audio": "^5.7.4", "metascraper-author": "^5.6.5", "metascraper-clearbit-logo": "^5.3.0", "metascraper-date": "^5.7.4", @@ -82,9 +82,9 @@ "metascraper-lang": "^5.7.4", "metascraper-lang-detector": "^4.8.5", "metascraper-logo": "^5.7.4", - "metascraper-publisher": "^5.6.5", + "metascraper-publisher": "^5.7.4", "metascraper-soundcloud": "^5.7.4", - "metascraper-title": "^5.7.0", + "metascraper-title": "^5.7.4", "metascraper-url": "^5.7.4", "metascraper-video": "^5.7.4", "metascraper-youtube": "^5.7.4", @@ -116,7 +116,7 @@ "babel-jest": "~24.9.0", "chai": "~4.2.0", "cucumber": "~5.1.0", - "eslint": "~6.3.0", + "eslint": "~6.4.0", "eslint-config-prettier": "~6.3.0", "eslint-config-standard": "~14.1.0", "eslint-plugin-import": "~2.18.2", diff --git a/backend/src/middleware/hashtags/extractHashtags.js b/backend/src/middleware/hashtags/extractHashtags.js index c7782e59d..9a903e4fa 100644 --- a/backend/src/middleware/hashtags/extractHashtags.js +++ b/backend/src/middleware/hashtags/extractHashtags.js @@ -4,23 +4,23 @@ import { exec, build } from 'xregexp/xregexp-all.js' // https://en.wikipedia.org/w/index.php?title=Hashtag&oldid=905141980#Style // here: // 0. Search for whole string. -// 1. Hashtag has only all unicode characters and '0-9'. -// 2. If it starts with a digit '0-9' than a unicode character has to follow. -const regX = build('^/search/hashtag/((\\pL+[\\pL0-9]*)|([0-9]+\\pL+[\\pL0-9]*))$') +// 1. Hashtag has only all unicode letters and '0-9'. +// 2. If it starts with a digit '0-9' than a unicode letter has to follow. +const regX = build('^((\\pL+[\\pL0-9]*)|([0-9]+\\pL+[\\pL0-9]*))$') export default function(content) { if (!content) return [] const $ = cheerio.load(content) // We can not search for class '.hashtag', because the classes are removed at the 'xss' middleware. // But we have to know, which Hashtags are removed from the content as well, so we search for the 'a' html-tag. - const urls = $('a') + const ids = $('a[data-hashtag-id]') .map((_, el) => { - return $(el).attr('href') + return $(el).attr('data-hashtag-id') }) .get() const hashtags = [] - urls.forEach(url => { - const match = exec(url, regX) + ids.forEach(id => { + const match = exec(id, regX) if (match != null) { hashtags.push(match[1]) } diff --git a/backend/src/middleware/hashtags/extractHashtags.spec.js b/backend/src/middleware/hashtags/extractHashtags.spec.js index 2e1761718..739c7de54 100644 --- a/backend/src/middleware/hashtags/extractHashtags.spec.js +++ b/backend/src/middleware/hashtags/extractHashtags.spec.js @@ -8,9 +8,24 @@ describe('extractHashtags', () => { }) describe('searches through links', () => { - it('finds links with and without ".hashtag" class and extracts Hashtag names', () => { - const content = - '

#Elections#Democracy

' + it('without `class="hashtag"` but `data-hashtag-id="something"`, and extracts the Hashtag to make a Hashtag link', () => { + const content = ` +

+ + #Elections + + + #Democracy + +

+ ` expect(extractHashtags(content)).toEqual(['Elections', 'Democracy']) }) @@ -20,23 +35,57 @@ describe('extractHashtags', () => { expect(extractHashtags(content)).toEqual([]) }) - describe('handles links', () => { - it('ignores links with domains', () => { - const content = - '

#Elections#Democracy

' - expect(extractHashtags(content)).toEqual(['Democracy']) - }) - - it('ignores Hashtag links with not allowed character combinations', () => { - // Allowed are all unicode letters '\pL' and all digits '0-9'. There haveto be at least one letter in it. - const content = - '

Something inspirational about #AbcDefXyz0123456789!*(),2, #0123456789, #0123456789a, #AbcDefXyz0123456789, and #λαπ.

' - expect(extractHashtags(content).sort()).toEqual([ - '0123456789a', - 'AbcDefXyz0123456789', - 'λαπ', - ]) - }) + it('ignores hashtag links with unsupported character combinations', () => { + // Allowed are all unicode letters '\pL' and all digits '0-9'. There haveto be at least one letter in it. + const content = ` +

+ Something inspirational about + + #AbcDefXyz0123456789!*(),2 + , + + #0123456789 + , + + #0123456789a + , + + #AbcDefXyz0123456789 + , and + + #ħπαλ + . +

+ ` + expect(extractHashtags(content).sort()).toEqual([ + '0123456789a', + 'AbcDefXyz0123456789', + 'ħπαλ', + ]) }) describe('does not crash if', () => { diff --git a/backend/src/middleware/hashtags/hashtagsMiddleware.spec.js b/backend/src/middleware/hashtags/hashtagsMiddleware.spec.js index 3f101f778..89f1bdd86 100644 --- a/backend/src/middleware/hashtags/hashtagsMiddleware.spec.js +++ b/backend/src/middleware/hashtags/hashtagsMiddleware.spec.js @@ -69,8 +69,27 @@ afterEach(async () => { describe('hashtags', () => { const id = 'p135' const title = 'Two Hashtags' - const postContent = - '

Hey Dude, #Democracy should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone.

' + const postContent = ` +

+ Hey Dude, + + #Democracy + + should work equal for everybody!? That seems to be the only way to have + equal + + #Liberty + + for everyone. +

+ ` const postWithHastagsQuery = gql` query($id: ID) { Post(id: $id) { @@ -129,10 +148,29 @@ describe('hashtags', () => { ) }) - describe('afterwards update the Post by removing a Hashtag, leaving a Hashtag and add a Hashtag', () => { - // The already existing Hashtag has no class at this point. - const postContent = - '

Hey Dude, #Elections should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone.

' + describe('updates the Post by removing, keeping and adding one hashtag respectively', () => { + // The already existing hashtag has no class at this point. + const postContent = ` +

+ Hey Dude, + + #Elections + + should work equal for everybody!? That seems to be the only way to + have equal + + #Liberty + + for everyone. +

+ ` it('only one previous Hashtag and the new Hashtag exists', async () => { await mutate({ diff --git a/backend/src/schema/resolvers/registration.js b/backend/src/schema/resolvers/registration.js index fa7262f43..72e499038 100644 --- a/backend/src/schema/resolvers/registration.js +++ b/backend/src/schema/resolvers/registration.js @@ -6,14 +6,30 @@ import encryptPassword from '../../helpers/encryptPassword' const instance = neode() -/* - * TODO: remove this function as soon type `User` has no `email` property - * anymore - */ -const checkEmailDoesNotExist = async ({ email }) => { +const alreadyExistingMail = async (_parent, args, context) => { + let { email } = args email = email.toLowerCase() - const emails = await instance.all('EmailAddress', { email }) - if (emails.length > 0) throw new UserInputError('User account with this email already exists.') + const cypher = ` + MATCH (email:EmailAddress {email: $email}) + OPTIONAL MATCH (email)-[:PRIMARY_EMAIL]-(user) + RETURN email, user + ` + let transactionRes + const session = context.driver.session() + try { + transactionRes = await session.run(cypher, { email }) + } finally { + session.close() + } + const [result] = transactionRes.records.map(record => { + return { + alreadyExistingEmail: record.get('email').properties, + user: record.get('user') && record.get('user').properties, + } + }) + const { alreadyExistingEmail, user } = result || {} + if (user) throw new UserInputError('User account with this email already exists.') + return alreadyExistingEmail } export default { @@ -37,22 +53,24 @@ export default { } return response }, - Signup: async (_parent, args, _context, _resolveInfo) => { + Signup: async (_parent, args, context) => { const nonce = uuid().substring(0, 6) args.nonce = nonce - await checkEmailDoesNotExist({ email: args.email }) + let emailAddress = await alreadyExistingMail(_parent, args, context) + if (emailAddress) return emailAddress try { - const emailAddress = await instance.create('EmailAddress', args) + emailAddress = await instance.create('EmailAddress', args) return emailAddress.toJson() } catch (e) { throw new UserInputError(e.message) } }, - SignupByInvitation: async (_parent, args, _context, _resolveInfo) => { + SignupByInvitation: async (_parent, args, context) => { const { token } = args const nonce = uuid().substring(0, 6) args.nonce = nonce - await checkEmailDoesNotExist({ email: args.email }) + let emailAddress = await alreadyExistingMail(_parent, args, context) + if (emailAddress) return emailAddress try { const result = await instance.cypher( ` @@ -69,14 +87,14 @@ export default { ) if (!validInvitationCode) throw new UserInputError('Invitation code already used or does not exist.') - const emailAddress = await instance.create('EmailAddress', args) + emailAddress = await instance.create('EmailAddress', args) await validInvitationCode.relateTo(emailAddress, 'activated') return emailAddress.toJson() } catch (e) { throw new UserInputError(e) } }, - SignupVerification: async (_parent, args, _context, _resolveInfo) => { + SignupVerification: async (_parent, args) => { const { termsAndConditionsAgreedVersion } = args const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g) if (!regEx.test(termsAndConditionsAgreedVersion)) { diff --git a/backend/src/schema/resolvers/registration.spec.js b/backend/src/schema/resolvers/registration.spec.js index ca19f03c4..531eabea1 100644 --- a/backend/src/schema/resolvers/registration.spec.js +++ b/backend/src/schema/resolvers/registration.spec.js @@ -310,11 +310,60 @@ describe('Signup', () => { }) }) - it('creates a Signup with a cryptographic `nonce`', async () => { - await mutate({ mutation, variables }) - let emailAddress = await neode.first('EmailAddress', { email: 'someuser@example.org' }) - emailAddress = await emailAddress.toJson() - expect(emailAddress.nonce).toEqual(expect.any(String)) + describe('creates a EmailAddress node', () => { + it('with `createdAt` attribute', async () => { + await mutate({ mutation, variables }) + let emailAddress = await neode.first('EmailAddress', { email: 'someuser@example.org' }) + emailAddress = await emailAddress.toJson() + expect(emailAddress.createdAt).toBeTruthy() + expect(Date.parse(emailAddress.createdAt)).toEqual(expect.any(Number)) + }) + + it('with a cryptographic `nonce`', async () => { + await mutate({ mutation, variables }) + let emailAddress = await neode.first('EmailAddress', { email: 'someuser@example.org' }) + emailAddress = await emailAddress.toJson() + expect(emailAddress.nonce).toEqual(expect.any(String)) + }) + + describe('if the email already exists', () => { + let email + beforeEach(async () => { + email = await factory.create('EmailAddress', { + email: 'someuser@example.org', + verifiedAt: null, + }) + }) + + describe('and the user has registered already', () => { + beforeEach(async () => { + await factory.create('User', { email }) + }) + + it('throws UserInputError error because of unique constraint violation', async () => { + await expect(mutate({ mutation, variables })).resolves.toMatchObject({ + errors: [{ message: 'User account with this email already exists.' }], + }) + }) + }) + + describe('but the user has not yet registered', () => { + it('resolves with the already existing email', async () => { + await expect(mutate({ mutation, variables })).resolves.toMatchObject({ + data: { Signup: { email: 'someuser@example.org' } }, + }) + }) + + it('creates no additional `EmailAddress` node', async () => { + // admin account and the already existing user + await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) + await expect(mutate({ mutation, variables })).resolves.toMatchObject({ + data: { Signup: { email: 'someuser@example.org' } }, + }) + await expect(neode.all('EmailAddress')).resolves.toHaveLength(2) + }) + }) + }) }) }) }) diff --git a/backend/src/seed/factories/users.js b/backend/src/seed/factories/users.js index e0ec04fc0..962f92781 100644 --- a/backend/src/seed/factories/users.js +++ b/backend/src/seed/factories/users.js @@ -24,7 +24,15 @@ export default function create() { } args = await encryptPassword(args) const user = await neodeInstance.create('User', args) - const email = await factoryInstance.create('EmailAddress', { email: args.email }) + + let email + if (typeof args.email === 'object') { + // probably a neode node + email = args.email + } else { + email = await factoryInstance.create('EmailAddress', { email: args.email }) + } + await user.relateTo(email, 'primaryEmail') await email.relateTo(user, 'belongsTo') return user diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js index 48a739529..8c87a3214 100644 --- a/backend/src/seed/seed-db.js +++ b/backend/src/seed/seed-db.js @@ -413,9 +413,9 @@ import { gql } from '../jest/helpers' const mention2 = 'Hey @jenny-rostock, here is another notification for you!' const hashtag1 = - 'See #NaturphilosophieYoga can really help you!' + 'See #NaturphilosophieYoga, it can really help you!' const hashtagAndMention1 = - 'The new physics of #QuantenFlussTheorie can explain #QuantumGravity! @peter-lustig got that already. ;-)' + 'The new physics of #QuantenFlussTheorie can explain #QuantumGravity! @peter-lustig got that already. ;-)' const createPostMutation = gql` mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]) { CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) { @@ -470,9 +470,9 @@ import { gql } from '../jest/helpers' authenticatedUser = await dewey.toJson() const mentionInComment1 = - 'I heard @jenny-rostock, practice it since 3 years now.' + 'I heard @jenny-rostock has practiced it for 3 years now.' const mentionInComment2 = - 'Did @peter-lustig told you?' + 'Did @peter-lustig tell you?' const createCommentMutation = gql` mutation($id: ID, $postId: ID!, $content: String!) { CreateComment(id: $id, postId: $postId, content: $content) { @@ -661,21 +661,21 @@ import { gql } from '../jest/helpers' mutate({ mutation: reportMutation, variables: { - description: "I don't like this comment", + description: 'This comment is bigoted', id: 'c1', }, }), mutate({ mutation: reportMutation, variables: { - description: "I don't like this post", + description: 'This post is bigoted', id: 'p1', }, }), mutate({ mutation: reportMutation, variables: { - description: "I don't like this user", + description: 'This user is harassing me with bigoted remarks', id: 'u1', }, }), diff --git a/backend/yarn.lock b/backend/yarn.lock index ff33ff04d..3cf80a94d 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -971,7 +971,7 @@ url-regex "~4.1.1" video-extensions "~1.1.0" -"@metascraper/helpers@^5.6.6", "@metascraper/helpers@^5.7.0", "@metascraper/helpers@^5.7.4": +"@metascraper/helpers@^5.6.6", "@metascraper/helpers@^5.7.4": version "5.7.4" resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.7.4.tgz#c91c1b11ce585fa973a544a9d24c5d88d50a9354" integrity sha512-GMLFu8j7e65n04w+dfOVF8RWOqNHCqimITtTHYSa1XdLR8vSqE2PjvSOhGoS5ELU5fRlRQKy9EOrKDeRV3/K0w== @@ -2859,10 +2859,10 @@ data-urls@^1.0.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-fns@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.1.0.tgz#0d7e806c3cefe14a943532dbf968995ccfd46bd9" - integrity sha512-eKeLk3sLCnxB/0PN4t1+zqDtSs4jb4mXRSTZ2okmx/myfWyDqeO4r5nnmA5LClJiCwpuTMeK2v5UQPuE4uMaxA== +date-fns@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.2.1.tgz#b3f79cf56760af106050c686f4c72586a3383ee9" + integrity sha512-4V1i5CnTinjBvJpXTq7sDHD4NY6JPcl15112IeSNNLUWQOQ+kIuCvRGOFZMQZNvkadw8F9QTyZxz59rIRU6K+w== debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" @@ -3420,10 +3420,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@~6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.3.0.tgz#1f1a902f67bfd4c354e7288b81e40654d927eb6a" - integrity sha512-ZvZTKaqDue+N8Y9g0kp6UPZtS4FSY3qARxBs7p4f0H0iof381XHduqVerFWtK8DPtKmemqbqCFENWSQgPR/Gow== +eslint@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.4.0.tgz#5aa9227c3fbe921982b2eda94ba0d7fae858611a" + integrity sha512-WTVEzK3lSFoXUovDHEbkJqCVPEPwbhCq4trDktNI6ygs7aO41d4cDT0JFAT5MivzZeVLWlg7vHL+bgrQv/t3vA== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -4200,10 +4200,10 @@ graphql-upload@^8.0.2: http-errors "^1.7.2" object-path "^0.11.4" -graphql@^14.2.1, graphql@^14.5.4: - version "14.5.4" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.4.tgz#b33fe957854e90c10d4c07c7d26b6c8e9f159a13" - integrity sha512-dPLvHoxy5m9FrkqWczPPRnH0X80CyvRE6e7Fa5AWEqEAzg9LpxHvKh24po/482E6VWHigOkAmb4xCp6P9yT9gw== +graphql@^14.2.1, graphql@^14.5.6: + version "14.5.6" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.6.tgz#3fa12173b50e6ccdef953c31c82f37c50ef58bec" + integrity sha512-zJ6Oz8P1yptV4O4DYXdArSwvmirPetDOBnGFRBl0zQEC68vNW3Ny8qo8VzMgfr+iC8PKiRYJ+f2wub41oDCoQg== dependencies: iterall "^1.2.2" @@ -5859,12 +5859,12 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -metascraper-audio@^5.6.5: - version "5.6.6" - resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.6.6.tgz#1de5673e18fd9154fb0ead93a184d228514eaa26" - integrity sha512-wlpfJkZ2Bgc25Kf+XMFVSh9EwWKyJVUTfJ4nIkQ9XCYoUpEC2uwN2aHfF1TCZehCJKLioU6++zeuXEaq5APk9g== +metascraper-audio@^5.7.4: + version "5.7.4" + resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.7.4.tgz#a476ed484b2642060208243843dc7ef5c9eb7a3e" + integrity sha512-5M+C+tirJlR71PXymAkBnEXu8KG0+fkX3G0Dm2UO6jDEchIo+DhW2aGSgB8w9kQN80Ni8jaLjNH3+Mtwbsbbkw== dependencies: - "@metascraper/helpers" "^5.6.6" + "@metascraper/helpers" "^5.7.4" metascraper-author@^5.6.5: version "5.6.6" @@ -5925,12 +5925,12 @@ metascraper-logo@^5.7.4: dependencies: "@metascraper/helpers" "^5.7.4" -metascraper-publisher@^5.6.5: - version "5.6.6" - resolved "https://registry.yarnpkg.com/metascraper-publisher/-/metascraper-publisher-5.6.6.tgz#855515689e7d16870333e44af49ccb954bec45b3" - integrity sha512-micUEltrytzwKb1iJjnclJ/l5970xs0PWwoY/RFcIDviBVQ/EQNCW+DieK9P6gFJq3dSLPTJ9cv2QPHkDj+ORw== +metascraper-publisher@^5.7.4: + version "5.7.4" + resolved "https://registry.yarnpkg.com/metascraper-publisher/-/metascraper-publisher-5.7.4.tgz#5f69ad838636ef1fff015c45a66f683fcc2d3d37" + integrity sha512-l2FI63BC7cSQCvPD5OMKY4yRYpcxhhrrpsIrC0sIViKs6XrYRphb745NcNgFvKgi/PO0yw0bIEyhAroACaJKOA== dependencies: - "@metascraper/helpers" "^5.6.6" + "@metascraper/helpers" "^5.7.4" metascraper-soundcloud@^5.7.4: version "5.7.4" @@ -5941,12 +5941,12 @@ metascraper-soundcloud@^5.7.4: memoize-one "~5.1.1" tldts "~5.4.0" -metascraper-title@^5.7.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/metascraper-title/-/metascraper-title-5.7.0.tgz#4e37ec7cb914b70b60c9867fc05b14779d2199dd" - integrity sha512-+GwhBfw7P+S44DRak6H2oe/ESbYMfYpmFzBny2vR6a3vc8KnRivVkK8vF6PLYuTj2bteEcpvZbbPZ2w/H32CMQ== +metascraper-title@^5.7.4: + version "5.7.4" + resolved "https://registry.yarnpkg.com/metascraper-title/-/metascraper-title-5.7.4.tgz#1f9f05032c2abab2db9a6634b9f6abec5489c116" + integrity sha512-qrOw5uRmGVfqiaZxPF6dfXYM79RY13E+nITukPZsktiGMNIknRJmEVI/GSW+6Ek/+GxlW0gByvE+yqFOrgjCTw== dependencies: - "@metascraper/helpers" "^5.7.0" + "@metascraper/helpers" "^5.7.4" lodash "~4.17.15" metascraper-url@^5.7.4: diff --git a/deployment/legacy-migration/maintenance-worker/migration/mongo/export.sh b/deployment/legacy-migration/maintenance-worker/migration/mongo/export.sh index f9334ccd2..b56ace87a 100755 --- a/deployment/legacy-migration/maintenance-worker/migration/mongo/export.sh +++ b/deployment/legacy-migration/maintenance-worker/migration/mongo/export.sh @@ -44,7 +44,7 @@ export_collection_query "follows" '{"foreignService": "users"}' "users" # export_collection "settings" export_collection "shouts" # export_collection "status" -export_collection "users" +export_collection_query "users" '{"isVerified": true }' "verified" # export_collection "userscandos" # export_collection "usersettings" diff --git a/deployment/legacy-migration/maintenance-worker/migration/neo4j/import.sh b/deployment/legacy-migration/maintenance-worker/migration/neo4j/import.sh index cef2846a7..ccb22dafb 100755 --- a/deployment/legacy-migration/maintenance-worker/migration/neo4j/import.sh +++ b/deployment/legacy-migration/maintenance-worker/migration/neo4j/import.sh @@ -78,7 +78,7 @@ echo "DONE" echo "Start Importing Data" import_collection "badges" "badges/badges.cql" import_collection "categories" "categories/categories.cql" -import_collection "users" "users/users.cql" +import_collection "users_verified" "users/users.cql" import_collection "follows_users" "follows/follows.cql" #import_collection "follows_organizations" "follows/follows.cql" import_collection "contributions_post" "contributions/contributions.cql" diff --git a/webapp/components/Editor/ContentViewer.vue b/webapp/components/Editor/ContentViewer.vue index 993cf32b9..ab07d11d6 100644 --- a/webapp/components/Editor/ContentViewer.vue +++ b/webapp/components/Editor/ContentViewer.vue @@ -4,6 +4,7 @@ diff --git a/webapp/yarn.lock b/webapp/yarn.lock index b6ed88d73..d4a9592ae 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -1458,14 +1458,14 @@ webpack-node-externals "^1.7.2" webpackbar "^4.0.0" -"@nuxtjs/apollo@^4.0.0-rc12": - version "4.0.0-rc12" - resolved "https://registry.yarnpkg.com/@nuxtjs/apollo/-/apollo-4.0.0-rc12.tgz#4008c31a76b689b513292b39b9e4a6a04ef12edf" - integrity sha512-qHlDsvJoWYJAGt7ucWcFgPpFG89STyby8OoX07+mYCRV52tVaCdrLO95dFZx7k705hSYPzU8gBsMvJte3lEjjQ== +"@nuxtjs/apollo@^4.0.0-rc13": + version "4.0.0-rc13" + resolved "https://registry.yarnpkg.com/@nuxtjs/apollo/-/apollo-4.0.0-rc13.tgz#b18a5db3c9f1e5dac4be4848a469b84ae1833b62" + integrity sha512-JoIoexBz0AGkrWl3vkPN7+2hHSY0EJJaI04lfMhc5MQy4PjmYTtpOUFgxLHWSB/HUPeioQwyEdClzPTJrM4yxw== dependencies: cross-fetch "^3.0.4" universal-cookie "^4.0.2" - vue-apollo "^3.0.0-rc.2" + vue-apollo "^3.0.0-rc.5" vue-cli-plugin-apollo "^0.21.0" webpack-node-externals "^1.7.2" @@ -15110,10 +15110,10 @@ vscode-uri@^1.0.6: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59" integrity sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ== -vue-apollo@^3.0.0-rc.2: - version "3.0.0-rc.2" - resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.0-rc.2.tgz#3b59a93084cb37c19be46b9f18cd63214a782718" - integrity sha512-bYgC3sK77rBlLEHi4XFFAm9NTTB10/onAUzUIhioKM8BKnnFOagjykqBtA9xFRVmFvOcgZBNNbgJhzScBeTn4Q== +vue-apollo@^3.0.0-rc.5: + version "3.0.0-rc.5" + resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.0-rc.5.tgz#0280c0855318ca89439014c24f3a693a301fa25d" + integrity sha512-FuVP93Zq0cglj/S7xRJtmeuGa47BuE7PVEuEbmpGObhEu6sV8TzUMVI6UUTiOHMXYS02NvCAazyy4GAh8Duz8A== dependencies: chalk "^2.4.2" serialize-javascript "^1.7.0"