mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge pull request #1513 from Human-Connection/bugfix_about_me_not_saved_on_signup_verification
Bugfix: `about me` not saved on signup
This commit is contained in:
commit
3712a5d2cf
@ -1,62 +1,81 @@
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import Factory from '../seed/factories'
|
||||
import { host, login, gql } from '../jest/helpers'
|
||||
import { neode } from '../bootstrap/neo4j'
|
||||
import { gql } from '../jest/helpers'
|
||||
import { neode as getNeode, getDriver } from '../bootstrap/neo4j'
|
||||
import createServer from '../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
|
||||
let authenticatedClient
|
||||
let headers
|
||||
const factory = Factory()
|
||||
const instance = neode()
|
||||
const categoryIds = ['cat9']
|
||||
const createPostMutation = gql`
|
||||
mutation($title: String!, $content: String!, $categoryIds: [ID]!, $slug: String) {
|
||||
CreatePost(title: $title, content: $content, categoryIds: $categoryIds, slug: $slug) {
|
||||
slug
|
||||
}
|
||||
}
|
||||
`
|
||||
let createPostVariables = {
|
||||
title: 'I am a brand new post',
|
||||
content: 'Some content',
|
||||
categoryIds,
|
||||
}
|
||||
|
||||
let mutate
|
||||
let authenticatedUser
|
||||
let variables
|
||||
|
||||
const driver = getDriver()
|
||||
const neode = getNeode()
|
||||
|
||||
beforeAll(() => {
|
||||
const { server } = createServer({
|
||||
context: () => {
|
||||
return {
|
||||
driver,
|
||||
neode,
|
||||
user: authenticatedUser,
|
||||
}
|
||||
},
|
||||
})
|
||||
mutate = createTestClient(server).mutate
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const adminParams = { role: 'admin', email: 'admin@example.org', password: '1234' }
|
||||
await factory.create('User', adminParams)
|
||||
variables = {}
|
||||
const admin = await factory.create('User', { role: 'admin' })
|
||||
await factory.create('User', {
|
||||
email: 'someone@example.org',
|
||||
password: '1234',
|
||||
})
|
||||
await instance.create('Category', {
|
||||
await factory.create('Category', {
|
||||
id: 'cat9',
|
||||
name: 'Democracy & Politics',
|
||||
icon: 'university',
|
||||
})
|
||||
// we need to be an admin, otherwise we're not authorized to create a user
|
||||
headers = await login(adminParams)
|
||||
authenticatedClient = new GraphQLClient(host, { headers })
|
||||
authenticatedUser = await admin.toJson()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('slugify', () => {
|
||||
describe('slugifyMiddleware', () => {
|
||||
describe('CreatePost', () => {
|
||||
const categoryIds = ['cat9']
|
||||
const createPostMutation = gql`
|
||||
mutation($title: String!, $content: String!, $categoryIds: [ID]!, $slug: String) {
|
||||
CreatePost(title: $title, content: $content, categoryIds: $categoryIds, slug: $slug) {
|
||||
slug
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
beforeEach(() => {
|
||||
variables = {
|
||||
...variables,
|
||||
title: 'I am a brand new post',
|
||||
content: 'Some content',
|
||||
categoryIds,
|
||||
}
|
||||
})
|
||||
|
||||
it('generates a slug based on title', async () => {
|
||||
const response = await authenticatedClient.request(createPostMutation, createPostVariables)
|
||||
expect(response).toEqual({
|
||||
CreatePost: { slug: 'i-am-a-brand-new-post' },
|
||||
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject({
|
||||
data: {
|
||||
CreatePost: { slug: 'i-am-a-brand-new-post' },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('if slug exists', () => {
|
||||
beforeEach(async () => {
|
||||
const asSomeoneElse = await Factory().authenticateAs({
|
||||
email: 'someone@example.org',
|
||||
password: '1234',
|
||||
})
|
||||
await asSomeoneElse.create('Post', {
|
||||
await factory.create('Post', {
|
||||
title: 'Pre-existing post',
|
||||
slug: 'pre-existing-post',
|
||||
content: 'as Someone else content',
|
||||
@ -65,72 +84,110 @@ describe('slugify', () => {
|
||||
})
|
||||
|
||||
it('chooses another slug', async () => {
|
||||
createPostVariables = { title: 'Pre-existing post', content: 'Some content', categoryIds }
|
||||
const response = await authenticatedClient.request(createPostMutation, createPostVariables)
|
||||
expect(response).toEqual({
|
||||
CreatePost: { slug: 'pre-existing-post-1' },
|
||||
variables = {
|
||||
...variables,
|
||||
title: 'Pre-existing post',
|
||||
content: 'Some content',
|
||||
categoryIds,
|
||||
}
|
||||
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject({
|
||||
data: { CreatePost: { slug: 'pre-existing-post-1' } },
|
||||
})
|
||||
})
|
||||
|
||||
describe('but if the client specifies a slug', () => {
|
||||
it('rejects CreatePost', async () => {
|
||||
createPostVariables = {
|
||||
variables = {
|
||||
...variables,
|
||||
title: 'Pre-existing post',
|
||||
content: 'Some content',
|
||||
slug: 'pre-existing-post',
|
||||
categoryIds,
|
||||
}
|
||||
await expect(
|
||||
authenticatedClient.request(createPostMutation, createPostVariables),
|
||||
).rejects.toThrow('already exists')
|
||||
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject({
|
||||
errors: [{ message: 'Post with this slug already exists!' }],
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('SignupVerification', () => {
|
||||
const mutation = `mutation($password: String!, $email: String!, $name: String!, $slug: String, $nonce: String!, $termsAndConditionsAgreedVersion: String!) {
|
||||
SignupVerification(email: $email, password: $password, name: $name, slug: $slug, nonce: $nonce, termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion) {
|
||||
slug
|
||||
const mutation = gql`
|
||||
mutation(
|
||||
$password: String!
|
||||
$email: String!
|
||||
$name: String!
|
||||
$slug: String
|
||||
$nonce: String!
|
||||
$termsAndConditionsAgreedVersion: String!
|
||||
) {
|
||||
SignupVerification(
|
||||
email: $email
|
||||
password: $password
|
||||
name: $name
|
||||
slug: $slug
|
||||
nonce: $nonce
|
||||
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
||||
) {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const action = async variables => {
|
||||
// required for SignupVerification
|
||||
await instance.create('EmailAddress', { email: '123@example.org', nonce: '123456' })
|
||||
|
||||
const defaultVariables = {
|
||||
beforeEach(() => {
|
||||
variables = {
|
||||
...variables,
|
||||
name: 'I am a user',
|
||||
nonce: '123456',
|
||||
password: 'yo',
|
||||
email: '123@example.org',
|
||||
termsAndConditionsAgreedVersion: '0.0.1',
|
||||
}
|
||||
return authenticatedClient.request(mutation, { ...defaultVariables, ...variables })
|
||||
}
|
||||
|
||||
it('generates a slug based on name', async () => {
|
||||
await expect(action({ name: 'I am a user' })).resolves.toEqual({
|
||||
SignupVerification: { slug: 'i-am-a-user' },
|
||||
})
|
||||
})
|
||||
|
||||
describe('if slug exists', () => {
|
||||
describe('given a user has signed up with their email address', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', { name: 'pre-existing user', slug: 'pre-existing-user' })
|
||||
})
|
||||
|
||||
it('chooses another slug', async () => {
|
||||
await expect(action({ name: 'pre-existing-user' })).resolves.toEqual({
|
||||
SignupVerification: { slug: 'pre-existing-user-1' },
|
||||
await factory.create('EmailAddress', {
|
||||
email: '123@example.org',
|
||||
nonce: '123456',
|
||||
verifiedAt: null,
|
||||
})
|
||||
})
|
||||
|
||||
describe('but if the client specifies a slug', () => {
|
||||
it('rejects SignupVerification', async () => {
|
||||
await expect(
|
||||
action({ name: 'Pre-existing user', slug: 'pre-existing-user' }),
|
||||
).rejects.toThrow('already exists')
|
||||
it('generates a slug based on name', async () => {
|
||||
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
|
||||
data: { SignupVerification: { slug: 'i-am-a-user' } },
|
||||
})
|
||||
})
|
||||
|
||||
describe('if slug exists', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', { name: 'I am a user', slug: 'i-am-a-user' })
|
||||
})
|
||||
|
||||
it('chooses another slug', async () => {
|
||||
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
|
||||
data: {
|
||||
SignupVerification: { slug: 'i-am-a-user-1' },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('but if the client specifies a slug', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, slug: 'i-am-a-user' }
|
||||
})
|
||||
|
||||
it('rejects SignupVerification', async () => {
|
||||
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'User with this slug already exists!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -3,6 +3,7 @@ import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
import fileUpload from './fileUpload'
|
||||
import { getBlockedUsers, getBlockedByUsers } from './users.js'
|
||||
import { mergeWith, isArray } from 'lodash'
|
||||
import { UserInputError } from 'apollo-server'
|
||||
import Resolver from './helpers/Resolver'
|
||||
|
||||
const filterForBlockedUsers = async (params, context) => {
|
||||
@ -78,6 +79,7 @@ export default {
|
||||
delete params.categoryIds
|
||||
params = await fileUpload(params, { file: 'imageUpload', url: 'image' })
|
||||
params.id = params.id || uuid()
|
||||
let post
|
||||
|
||||
const createPostCypher = `CREATE (post:Post {params})
|
||||
WITH post
|
||||
@ -92,15 +94,21 @@ export default {
|
||||
const createPostVariables = { userId: context.user.id, categoryIds, params }
|
||||
|
||||
const session = context.driver.session()
|
||||
const transactionRes = await session.run(createPostCypher, createPostVariables)
|
||||
try {
|
||||
const transactionRes = await session.run(createPostCypher, createPostVariables)
|
||||
const posts = transactionRes.records.map(record => {
|
||||
return record.get('post').properties
|
||||
})
|
||||
post = posts[0]
|
||||
} catch (e) {
|
||||
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||
throw new UserInputError('Post with this slug already exists!')
|
||||
throw new Error(e)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
|
||||
const [post] = transactionRes.records.map(record => {
|
||||
return record.get('post')
|
||||
})
|
||||
|
||||
session.close()
|
||||
|
||||
return post.properties
|
||||
return post
|
||||
},
|
||||
UpdatePost: async (object, params, context, resolveInfo) => {
|
||||
const { categoryIds } = params
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ForbiddenError, UserInputError } from 'apollo-server'
|
||||
import { UserInputError } from 'apollo-server'
|
||||
import uuid from 'uuid/v4'
|
||||
import { neode } from '../../bootstrap/neo4j'
|
||||
import fileUpload from './fileUpload'
|
||||
@ -80,7 +80,7 @@ export default {
|
||||
const { termsAndConditionsAgreedVersion } = args
|
||||
const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g)
|
||||
if (!regEx.test(termsAndConditionsAgreedVersion)) {
|
||||
throw new ForbiddenError('Invalid version format!')
|
||||
throw new UserInputError('Invalid version format!')
|
||||
}
|
||||
|
||||
let { nonce, email } = args
|
||||
@ -106,6 +106,8 @@ export default {
|
||||
])
|
||||
return user.toJson()
|
||||
} catch (e) {
|
||||
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||
throw new UserInputError('User with this slug already exists!')
|
||||
throw new UserInputError(e.message)
|
||||
}
|
||||
},
|
||||
|
||||
@ -327,6 +327,7 @@ describe('SignupVerification', () => {
|
||||
$password: String!
|
||||
$email: String!
|
||||
$nonce: String!
|
||||
$about: String
|
||||
$termsAndConditionsAgreedVersion: String!
|
||||
) {
|
||||
SignupVerification(
|
||||
@ -334,6 +335,7 @@ describe('SignupVerification', () => {
|
||||
password: $password
|
||||
email: $email
|
||||
nonce: $nonce
|
||||
about: $about
|
||||
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
||||
) {
|
||||
id
|
||||
@ -423,6 +425,15 @@ describe('SignupVerification', () => {
|
||||
expect(emails).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('sets `about` attribute of User', async () => {
|
||||
variables = { ...variables, about: 'Find this description in the user profile' }
|
||||
await mutate({ mutation, variables })
|
||||
const user = await neode.first('User', { name: 'John Doe' })
|
||||
await expect(user.toJson()).resolves.toMatchObject({
|
||||
about: 'Find this description in the user profile',
|
||||
})
|
||||
})
|
||||
|
||||
it('marks the EmailAddress as primary', async () => {
|
||||
const cypher = `
|
||||
MATCH(email:EmailAddress)<-[:PRIMARY_EMAIL]-(u:User {name: {name}})
|
||||
|
||||
17
backend/src/seed/factories/emailAddresses.js
Normal file
17
backend/src/seed/factories/emailAddresses.js
Normal file
@ -0,0 +1,17 @@
|
||||
import faker from 'faker'
|
||||
|
||||
export default function create() {
|
||||
return {
|
||||
factory: async ({ args, neodeInstance }) => {
|
||||
const defaults = {
|
||||
email: faker.internet.email(),
|
||||
verifiedAt: new Date().toISOString(),
|
||||
}
|
||||
args = {
|
||||
...defaults,
|
||||
...args,
|
||||
}
|
||||
return neodeInstance.create('EmailAddress', args)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ import createCategory from './categories.js'
|
||||
import createTag from './tags.js'
|
||||
import createSocialMedia from './socialMedia.js'
|
||||
import createLocation from './locations.js'
|
||||
import createEmailAddress from './emailAddresses.js'
|
||||
|
||||
export const seedServerHost = 'http://127.0.0.1:4001'
|
||||
|
||||
@ -30,6 +31,7 @@ const factories = {
|
||||
Tag: createTag,
|
||||
SocialMedia: createSocialMedia,
|
||||
Location: createLocation,
|
||||
EmailAddress: createEmailAddress,
|
||||
}
|
||||
|
||||
export const cleanDatabase = async (options = {}) => {
|
||||
|
||||
@ -5,7 +5,7 @@ import slugify from 'slug'
|
||||
|
||||
export default function create() {
|
||||
return {
|
||||
factory: async ({ args, neodeInstance }) => {
|
||||
factory: async ({ args, neodeInstance, factoryInstance }) => {
|
||||
const defaults = {
|
||||
id: uuid(),
|
||||
name: faker.name.findName(),
|
||||
@ -24,7 +24,7 @@ export default function create() {
|
||||
}
|
||||
args = await encryptPassword(args)
|
||||
const user = await neodeInstance.create('User', args)
|
||||
const email = await neodeInstance.create('EmailAddress', { email: args.email })
|
||||
const email = await factoryInstance.create('EmailAddress', { email: args.email })
|
||||
await user.relateTo(email, 'primaryEmail')
|
||||
await email.relateTo(user, 'belongsTo')
|
||||
return user
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { config, mount, createLocalVue } from '@vue/test-utils'
|
||||
import CreateUserAccount, { SignupVerificationMutation } from './CreateUserAccount'
|
||||
import CreateUserAccount from './CreateUserAccount'
|
||||
import { SignupVerificationMutation } from '~/graphql/Registration.js'
|
||||
import Styleguide from '@human-connection/styleguide'
|
||||
|
||||
const localVue = createLocalVue()
|
||||
@ -55,6 +56,7 @@ describe('CreateUserAccount', () => {
|
||||
wrapper = Wrapper()
|
||||
wrapper.find('input#name').setValue('John Doe')
|
||||
wrapper.find('input#password').setValue('hellopassword')
|
||||
wrapper.find('textarea#about').setValue('Hello I am the `about` attribute')
|
||||
wrapper.find('input#passwordConfirmation').setValue('hellopassword')
|
||||
wrapper.find('input#checkbox').setChecked()
|
||||
await wrapper.find('form').trigger('submit')
|
||||
@ -72,7 +74,7 @@ describe('CreateUserAccount', () => {
|
||||
await action()
|
||||
const expected = expect.objectContaining({
|
||||
variables: {
|
||||
about: '',
|
||||
about: 'Hello I am the `about` attribute',
|
||||
name: 'John Doe',
|
||||
email: 'sixseven@example.org',
|
||||
nonce: '666777',
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
:placeholder="$t('settings.data.namePlaceholder')"
|
||||
/>
|
||||
<ds-input
|
||||
id="bio"
|
||||
id="about"
|
||||
model="about"
|
||||
type="textarea"
|
||||
rows="3"
|
||||
@ -83,34 +83,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import PasswordStrength from '../Password/Strength'
|
||||
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
||||
import PasswordForm from '~/components/utils/PasswordFormHelper'
|
||||
import { VERSION } from '~/constants/terms-and-conditions-version.js'
|
||||
import { SignupVerificationMutation } from '~/graphql/Registration.js'
|
||||
|
||||
/* TODO: hier muss die version rein */
|
||||
export const SignupVerificationMutation = gql`
|
||||
mutation(
|
||||
$nonce: String!
|
||||
$name: String!
|
||||
$email: String!
|
||||
$password: String!
|
||||
$termsAndConditionsAgreedVersion: String!
|
||||
) {
|
||||
SignupVerification(
|
||||
nonce: $nonce
|
||||
email: $email
|
||||
name: $name
|
||||
password: $password
|
||||
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
||||
) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
`
|
||||
export default {
|
||||
components: {
|
||||
PasswordStrength,
|
||||
|
||||
24
webapp/graphql/Registration.js
Normal file
24
webapp/graphql/Registration.js
Normal file
@ -0,0 +1,24 @@
|
||||
import gql from 'graphql-tag'
|
||||
export const SignupVerificationMutation = gql`
|
||||
mutation(
|
||||
$nonce: String!
|
||||
$name: String!
|
||||
$email: String!
|
||||
$password: String!
|
||||
$about: String
|
||||
$termsAndConditionsAgreedVersion: String!
|
||||
) {
|
||||
SignupVerification(
|
||||
nonce: $nonce
|
||||
email: $email
|
||||
name: $name
|
||||
password: $password
|
||||
about: $about
|
||||
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
||||
) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
`
|
||||
Loading…
x
Reference in New Issue
Block a user