diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 35457d215..9bbd6de90 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -5,7 +5,7 @@ before submitting a new issue. Following one of the issue templates will ensure
Thanks!
-->
-## Issue
+## 💬 Issue
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 58ca6b387..fbf7173fc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,7 +1,8 @@
---
name: 🐛 Bug report
about: Create a report to help us improve
-
+labels: bug
+title: 🐛 [Bug]
---
## :bug: Bugreport
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index ed30ba7ad..1fba3fa58 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,22 +1,12 @@
---
name: 🚀 Feature request
about: Suggest an idea for this project
-
+labels: feature
+title: 🚀 [Feature]
---
## :rocket: Feature
-
-
-
-### Is your feature request related to a problem? Please describe.
-
-
-
-### Describe the prefered solution and alternatives you've considered
-
-
+
### Design & Layout
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
index eb5a923dd..aabbc0f0a 100644
--- a/.github/ISSUE_TEMPLATE/question.md
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -1,6 +1,8 @@
---
name: 💬 Question
about: If you need help understanding HumanConnection.
+labels: question
+title: 💬 [Question]
---
+## 🍰 Pullrequest
+
### Issues
-- [X] None
-
-### Checklist
-
-- [X] None
-
-### How2Test
-
-
-- [X] None
+- None
### Todo
diff --git a/.gitignore b/.gitignore
index 07623b965..eb661fd6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
.env
.idea
*.iml
-.vscode
.DS_Store
npm-debug.log*
yarn-debug.log*
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 000000000..e2d92ff83
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ "recommendations": [
+ "dbaeumer.vscode-eslint",
+ "octref.vetur",
+ "gruntfuggly.todo-tree",
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..908252f41
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,12 @@
+{
+ "eslint.validate": [
+ "javascript",
+ "javascriptreact",
+ {
+ "language": "vue",
+ "autoFix": true
+ }
+ ],
+ "editor.formatOnSave": true,
+ "eslint.autoFixOnSave": true
+}
\ No newline at end of file
diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js
index 0fdbfd52d..0000bb066 100644
--- a/backend/.eslintrc.js
+++ b/backend/.eslintrc.js
@@ -1,20 +1,25 @@
module.exports = {
- "extends": "standard",
- "parser": "babel-eslint",
- "env": {
- "es6": true,
- "node": true,
- "jest/globals": true
+ env: {
+ es6: true,
+ node: true,
+ jest: true
},
- "rules": {
- "indent": [
- "error",
- 2
- ],
- "quotes": [
- "error",
- "single"
- ]
+ parserOptions: {
+ parser: 'babel-eslint'
+ },
+ extends: [
+ 'standard',
+ 'plugin:prettier/recommended'
+ ],
+ plugins: [
+ 'jest'
+ ],
+ rules: {
+ //'indent': [ 'error', 2 ],
+ //'quotes': [ "error", "single"],
+ // 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+ 'no-console': ['error'],
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+ 'prettier/prettier': ['error'],
},
- "plugins": ["jest"]
};
diff --git a/backend/.prettierrc.js b/backend/.prettierrc.js
new file mode 100644
index 000000000..e2cf91e91
--- /dev/null
+++ b/backend/.prettierrc.js
@@ -0,0 +1,9 @@
+
+module.exports = {
+ semi: false,
+ printWidth: 100,
+ singleQuote: true,
+ trailingComma: "all",
+ tabWidth: 2,
+ bracketSpacing: true
+};
diff --git a/backend/package.json b/backend/package.json
index d940937a8..b1739a4cb 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -44,7 +44,7 @@
},
"dependencies": {
"activitystrea.ms": "~2.1.3",
- "apollo-cache-inmemory": "~1.5.1",
+ "apollo-cache-inmemory": "~1.6.0",
"apollo-client": "~2.5.1",
"apollo-link-context": "~1.0.14",
"apollo-link-http": "~1.5.14",
@@ -58,7 +58,7 @@
"dotenv": "~8.0.0",
"express": "~4.17.0",
"faker": "~4.1.0",
- "graphql": "~14.3.0",
+ "graphql": "~14.3.1",
"graphql-custom-directives": "~0.2.14",
"graphql-iso-date": "~3.6.1",
"graphql-middleware": "~3.0.2",
@@ -71,7 +71,7 @@
"lodash": "~4.17.11",
"ms": "~2.1.1",
"neo4j-driver": "~1.7.4",
- "neo4j-graphql-js": "~2.6.0",
+ "neo4j-graphql-js": "~2.6.1",
"node-fetch": "~2.6.0",
"npm-run-all": "~4.1.5",
"request": "~2.88.0",
@@ -83,10 +83,10 @@
},
"devDependencies": {
"@babel/cli": "~7.4.4",
- "@babel/core": "~7.4.4",
- "@babel/node": "~7.2.2",
+ "@babel/core": "~7.4.5",
+ "@babel/node": "~7.4.5",
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
- "@babel/preset-env": "~7.4.4",
+ "@babel/preset-env": "~7.4.5",
"@babel/register": "~7.4.4",
"apollo-server-testing": "~2.5.0",
"babel-core": "~7.0.0-0",
@@ -96,14 +96,17 @@
"cucumber": "~5.1.0",
"eslint": "~5.16.0",
"eslint-config-standard": "~12.0.0",
+ "eslint-config-prettier": "~4.3.0",
"eslint-plugin-import": "~2.17.2",
- "eslint-plugin-jest": "~22.5.1",
- "eslint-plugin-node": "~9.0.1",
+ "eslint-plugin-jest": "~22.6.4",
+ "eslint-plugin-node": "~9.1.0",
+ "eslint-plugin-prettier": "~3.1.0",
"eslint-plugin-promise": "~4.1.1",
"eslint-plugin-standard": "~4.0.0",
"graphql-request": "~1.8.2",
"jest": "~24.8.0",
"nodemon": "~1.19.0",
+ "prettier": "~1.14.3",
"supertest": "~4.0.2"
}
}
\ No newline at end of file
diff --git a/backend/src/activitypub/ActivityPub.js b/backend/src/activitypub/ActivityPub.js
index 3ce27e109..da1056362 100644
--- a/backend/src/activitypub/ActivityPub.js
+++ b/backend/src/activitypub/ActivityPub.js
@@ -1,13 +1,5 @@
-import {
- extractNameFromId,
- extractDomainFromUrl,
- signAndSend
-} from './utils'
-import {
- isPublicAddressed,
- sendAcceptActivity,
- sendRejectActivity
-} from './utils/activity'
+import { extractNameFromId, extractDomainFromUrl, signAndSend } from './utils'
+import { isPublicAddressed, sendAcceptActivity, sendRejectActivity } from './utils/activity'
import request from 'request'
import as from 'activitystrea.ms'
import NitroDataSource from './NitroDataSource'
@@ -22,182 +14,203 @@ let activityPub = null
export { activityPub }
export default class ActivityPub {
- constructor (activityPubEndpointUri, internalGraphQlUri) {
+ constructor(activityPubEndpointUri, internalGraphQlUri) {
this.endpoint = activityPubEndpointUri
this.dataSource = new NitroDataSource(internalGraphQlUri)
this.collections = new Collections(this.dataSource)
}
- static init (server) {
+ static init(server) {
if (!activityPub) {
dotenv.config()
- activityPub = new ActivityPub(process.env.CLIENT_URI || 'http://localhost:3000', process.env.GRAPHQL_URI || 'http://localhost:4000')
+ activityPub = new ActivityPub(
+ process.env.CLIENT_URI || 'http://localhost:3000',
+ process.env.GRAPHQL_URI || 'http://localhost:4000',
+ )
// integrate into running graphql express server
server.express.set('ap', activityPub)
server.express.use(router)
- console.log('-> ActivityPub middleware added to the graphql express server')
+ console.log('-> ActivityPub middleware added to the graphql express server') // eslint-disable-line no-console
} else {
- console.log('-> ActivityPub middleware already added to the graphql express server')
+ console.log('-> ActivityPub middleware already added to the graphql express server') // eslint-disable-line no-console
}
}
- handleFollowActivity (activity) {
+ handleFollowActivity(activity) {
debug(`inside FOLLOW ${activity.actor}`)
let toActorName = extractNameFromId(activity.object)
let fromDomain = extractDomainFromUrl(activity.actor)
const dataSource = this.dataSource
return new Promise((resolve, reject) => {
- request({
- url: activity.actor,
- headers: {
- 'Accept': 'application/activity+json'
- }
- }, async (err, response, toActorObject) => {
- if (err) return reject(err)
- // save shared inbox
- toActorObject = JSON.parse(toActorObject)
- await this.dataSource.addSharedInboxEndpoint(toActorObject.endpoints.sharedInbox)
+ request(
+ {
+ url: activity.actor,
+ headers: {
+ Accept: 'application/activity+json',
+ },
+ },
+ async (err, response, toActorObject) => {
+ if (err) return reject(err)
+ // save shared inbox
+ toActorObject = JSON.parse(toActorObject)
+ await this.dataSource.addSharedInboxEndpoint(toActorObject.endpoints.sharedInbox)
- let followersCollectionPage = await this.dataSource.getFollowersCollectionPage(activity.object)
+ let followersCollectionPage = await this.dataSource.getFollowersCollectionPage(
+ activity.object,
+ )
- const followActivity = as.follow()
- .id(activity.id)
- .actor(activity.actor)
- .object(activity.object)
+ const followActivity = as
+ .follow()
+ .id(activity.id)
+ .actor(activity.actor)
+ .object(activity.object)
- // add follower if not already in collection
- if (followersCollectionPage.orderedItems.includes(activity.actor)) {
- debug('follower already in collection!')
+ // add follower if not already in collection
+ if (followersCollectionPage.orderedItems.includes(activity.actor)) {
+ debug('follower already in collection!')
+ debug(`inbox = ${toActorObject.inbox}`)
+ resolve(
+ sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox),
+ )
+ } else {
+ followersCollectionPage.orderedItems.push(activity.actor)
+ }
+ debug(`toActorObject = ${toActorObject}`)
+ toActorObject =
+ typeof toActorObject !== 'object' ? JSON.parse(toActorObject) : toActorObject
+ debug(`followers = ${JSON.stringify(followersCollectionPage.orderedItems, null, 2)}`)
debug(`inbox = ${toActorObject.inbox}`)
- resolve(sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox))
- } else {
- followersCollectionPage.orderedItems.push(activity.actor)
- }
- debug(`toActorObject = ${toActorObject}`)
- toActorObject = typeof toActorObject !== 'object' ? JSON.parse(toActorObject) : toActorObject
- debug(`followers = ${JSON.stringify(followersCollectionPage.orderedItems, null, 2)}`)
- debug(`inbox = ${toActorObject.inbox}`)
- debug(`outbox = ${toActorObject.outbox}`)
- debug(`followers = ${toActorObject.followers}`)
- debug(`following = ${toActorObject.following}`)
+ debug(`outbox = ${toActorObject.outbox}`)
+ debug(`followers = ${toActorObject.followers}`)
+ debug(`following = ${toActorObject.following}`)
- try {
- await dataSource.saveFollowersCollectionPage(followersCollectionPage)
- debug('follow activity saved')
- resolve(sendAcceptActivity(followActivity, toActorName, fromDomain, toActorObject.inbox))
- } catch (e) {
- debug('followers update error!', e)
- resolve(sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox))
- }
- })
+ try {
+ await dataSource.saveFollowersCollectionPage(followersCollectionPage)
+ debug('follow activity saved')
+ resolve(
+ sendAcceptActivity(followActivity, toActorName, fromDomain, toActorObject.inbox),
+ )
+ } catch (e) {
+ debug('followers update error!', e)
+ resolve(
+ sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox),
+ )
+ }
+ },
+ )
})
}
- handleUndoActivity (activity) {
+ handleUndoActivity(activity) {
debug('inside UNDO')
switch (activity.object.type) {
- case 'Follow':
- const followActivity = activity.object
- return this.dataSource.undoFollowActivity(followActivity.actor, followActivity.object)
- case 'Like':
- return this.dataSource.deleteShouted(activity)
- default:
+ case 'Follow':
+ const followActivity = activity.object
+ return this.dataSource.undoFollowActivity(followActivity.actor, followActivity.object)
+ case 'Like':
+ return this.dataSource.deleteShouted(activity)
+ default:
}
}
- handleCreateActivity (activity) {
+ handleCreateActivity(activity) {
debug('inside create')
switch (activity.object.type) {
- case 'Article':
- case 'Note':
- const articleObject = activity.object
- if (articleObject.inReplyTo) {
- return this.dataSource.createComment(activity)
- } else {
- return this.dataSource.createPost(activity)
- }
- default:
+ case 'Article':
+ case 'Note':
+ const articleObject = activity.object
+ if (articleObject.inReplyTo) {
+ return this.dataSource.createComment(activity)
+ } else {
+ return this.dataSource.createPost(activity)
+ }
+ default:
}
}
- handleDeleteActivity (activity) {
+ handleDeleteActivity(activity) {
debug('inside delete')
switch (activity.object.type) {
- case 'Article':
- case 'Note':
- return this.dataSource.deletePost(activity)
- default:
+ case 'Article':
+ case 'Note':
+ return this.dataSource.deletePost(activity)
+ default:
}
}
- handleUpdateActivity (activity) {
+ handleUpdateActivity(activity) {
debug('inside update')
switch (activity.object.type) {
- case 'Note':
- case 'Article':
- return this.dataSource.updatePost(activity)
- default:
+ case 'Note':
+ case 'Article':
+ return this.dataSource.updatePost(activity)
+ default:
}
}
- handleLikeActivity (activity) {
+ handleLikeActivity(activity) {
// TODO differ if activity is an Article/Note/etc.
return this.dataSource.createShouted(activity)
}
- handleDislikeActivity (activity) {
+ handleDislikeActivity(activity) {
// TODO differ if activity is an Article/Note/etc.
return this.dataSource.deleteShouted(activity)
}
- async handleAcceptActivity (activity) {
+ async handleAcceptActivity(activity) {
debug('inside accept')
switch (activity.object.type) {
- case 'Follow':
- const followObject = activity.object
- const followingCollectionPage = await this.collections.getFollowingCollectionPage(followObject.actor)
- followingCollectionPage.orderedItems.push(followObject.object)
- await this.dataSource.saveFollowingCollectionPage(followingCollectionPage)
+ case 'Follow':
+ const followObject = activity.object
+ const followingCollectionPage = await this.collections.getFollowingCollectionPage(
+ followObject.actor,
+ )
+ followingCollectionPage.orderedItems.push(followObject.object)
+ await this.dataSource.saveFollowingCollectionPage(followingCollectionPage)
}
}
- getActorObject (url) {
+ getActorObject(url) {
return new Promise((resolve, reject) => {
- request({
- url: url,
- headers: {
- 'Accept': 'application/json'
- }
- }, (err, response, body) => {
- if (err) {
- reject(err)
- }
- resolve(JSON.parse(body))
- })
+ request(
+ {
+ url: url,
+ headers: {
+ Accept: 'application/json',
+ },
+ },
+ (err, response, body) => {
+ if (err) {
+ reject(err)
+ }
+ resolve(JSON.parse(body))
+ },
+ )
})
}
- generateStatusId (slug) {
+ generateStatusId(slug) {
return `https://${this.host}/activitypub/users/${slug}/status/${uuid()}`
}
- async sendActivity (activity) {
+ async sendActivity(activity) {
delete activity.send
const fromName = extractNameFromId(activity.actor)
if (Array.isArray(activity.to) && isPublicAddressed(activity)) {
debug('is public addressed')
const sharedInboxEndpoints = await this.dataSource.getSharedInboxEndpoints()
// serve shared inbox endpoints
- sharedInboxEndpoints.map((sharedInbox) => {
+ sharedInboxEndpoints.map(sharedInbox => {
return this.trySend(activity, fromName, new URL(sharedInbox).host, sharedInbox)
})
- activity.to = activity.to.filter((recipient) => {
- return !(isPublicAddressed({ to: recipient }))
+ activity.to = activity.to.filter(recipient => {
+ return !isPublicAddressed({ to: recipient })
})
// serve the rest
- activity.to.map(async (recipient) => {
+ activity.to.map(async recipient => {
debug('serve rest')
const actorObject = await this.getActorObject(recipient)
return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox)
@@ -207,18 +220,18 @@ export default class ActivityPub {
const actorObject = await this.getActorObject(activity.to)
return this.trySend(activity, fromName, new URL(activity.to).host, actorObject.inbox)
} else if (Array.isArray(activity.to)) {
- activity.to.map(async (recipient) => {
+ activity.to.map(async recipient => {
const actorObject = await this.getActorObject(recipient)
return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox)
})
}
}
- async trySend (activity, fromName, host, url, tries = 5) {
+ async trySend(activity, fromName, host, url, tries = 5) {
try {
return await signAndSend(activity, fromName, host, url)
} catch (e) {
if (tries > 0) {
- setTimeout(function () {
+ setTimeout(function() {
return this.trySend(activity, fromName, host, url, --tries)
}, 20000)
}
diff --git a/backend/src/activitypub/Collections.js b/backend/src/activitypub/Collections.js
index 227e1717b..641db596a 100644
--- a/backend/src/activitypub/Collections.js
+++ b/backend/src/activitypub/Collections.js
@@ -1,28 +1,28 @@
export default class Collections {
- constructor (dataSource) {
+ constructor(dataSource) {
this.dataSource = dataSource
}
- getFollowersCollection (actorId) {
+ getFollowersCollection(actorId) {
return this.dataSource.getFollowersCollection(actorId)
}
- getFollowersCollectionPage (actorId) {
+ getFollowersCollectionPage(actorId) {
return this.dataSource.getFollowersCollectionPage(actorId)
}
- getFollowingCollection (actorId) {
+ getFollowingCollection(actorId) {
return this.dataSource.getFollowingCollection(actorId)
}
- getFollowingCollectionPage (actorId) {
+ getFollowingCollectionPage(actorId) {
return this.dataSource.getFollowingCollectionPage(actorId)
}
- getOutboxCollection (actorId) {
+ getOutboxCollection(actorId) {
return this.dataSource.getOutboxCollection(actorId)
}
- getOutboxCollectionPage (actorId) {
+ getOutboxCollectionPage(actorId) {
return this.dataSource.getOutboxCollectionPage(actorId)
}
}
diff --git a/backend/src/activitypub/NitroDataSource.js b/backend/src/activitypub/NitroDataSource.js
index 0ab6db091..eea37337a 100644
--- a/backend/src/activitypub/NitroDataSource.js
+++ b/backend/src/activitypub/NitroDataSource.js
@@ -2,16 +2,10 @@ import {
throwErrorIfApolloErrorOccurred,
extractIdFromActivityId,
extractNameFromId,
- constructIdFromName
+ constructIdFromName,
} from './utils'
-import {
- createOrderedCollection,
- createOrderedCollectionPage
-} from './utils/collection'
-import {
- createArticleObject,
- isPublicAddressed
-} from './utils/activity'
+import { createOrderedCollection, createOrderedCollectionPage } from './utils/collection'
+import { createArticleObject, isPublicAddressed } from './utils/activity'
import crypto from 'crypto'
import gql from 'graphql-tag'
import { createHttpLink } from 'apollo-link-http'
@@ -23,35 +17,36 @@ import trunc from 'trunc-html'
const debug = require('debug')('ea:nitro-datasource')
export default class NitroDataSource {
- constructor (uri) {
+ constructor(uri) {
this.uri = uri
const defaultOptions = {
query: {
fetchPolicy: 'network-only',
- errorPolicy: 'all'
- }
+ errorPolicy: 'all',
+ },
}
const link = createHttpLink({ uri: this.uri, fetch: fetch }) // eslint-disable-line
const cache = new InMemoryCache()
const authLink = setContext((_, { headers }) => {
// generate the authentication token (maybe from env? Which user?)
- const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJuYW1lIjoiUGV0ZXIgTHVzdGlnIiwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9qb2huY2FmYXp6YS8xMjguanBnIiwiaWQiOiJ1MSIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJzbHVnIjoicGV0ZXItbHVzdGlnIiwiaWF0IjoxNTUyNDIwMTExLCJleHAiOjE2Mzg4MjAxMTEsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMCIsInN1YiI6InUxIn0.G7An1yeQUViJs-0Qj-Tc-zm0WrLCMB3M02pfPnm6xzw'
+ const token =
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJuYW1lIjoiUGV0ZXIgTHVzdGlnIiwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9qb2huY2FmYXp6YS8xMjguanBnIiwiaWQiOiJ1MSIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJzbHVnIjoicGV0ZXItbHVzdGlnIiwiaWF0IjoxNTUyNDIwMTExLCJleHAiOjE2Mzg4MjAxMTEsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMCIsInN1YiI6InUxIn0.G7An1yeQUViJs-0Qj-Tc-zm0WrLCMB3M02pfPnm6xzw'
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
- Authorization: token ? `Bearer ${token}` : ''
- }
+ Authorization: token ? `Bearer ${token}` : '',
+ },
}
})
this.client = new ApolloClient({
link: authLink.concat(link),
cache: cache,
- defaultOptions
+ defaultOptions,
})
}
- async getFollowersCollection (actorId) {
+ async getFollowersCollection(actorId) {
const slug = extractNameFromId(actorId)
debug(`slug= ${slug}`)
const result = await this.client.query({
@@ -61,7 +56,7 @@ export default class NitroDataSource {
followedByCount
}
}
- `
+ `,
})
debug('successfully fetched followers')
debug(result.data)
@@ -78,7 +73,7 @@ export default class NitroDataSource {
}
}
- async getFollowersCollectionPage (actorId) {
+ async getFollowersCollectionPage(actorId) {
const slug = extractNameFromId(actorId)
debug(`getFollowersPage slug = ${slug}`)
const result = await this.client.query({
@@ -91,7 +86,7 @@ export default class NitroDataSource {
followedByCount
}
}
- `
+ `,
})
debug(result.data)
@@ -104,9 +99,9 @@ export default class NitroDataSource {
followersCollection.totalItems = followersCount
debug(`followers = ${JSON.stringify(followers, null, 2)}`)
await Promise.all(
- followers.map(async (follower) => {
+ followers.map(async follower => {
followersCollection.orderedItems.push(constructIdFromName(follower.slug))
- })
+ }),
)
return followersCollection
@@ -115,7 +110,7 @@ export default class NitroDataSource {
}
}
- async getFollowingCollection (actorId) {
+ async getFollowingCollection(actorId) {
const slug = extractNameFromId(actorId)
const result = await this.client.query({
query: gql`
@@ -124,7 +119,7 @@ export default class NitroDataSource {
followingCount
}
}
- `
+ `,
})
debug(result.data)
@@ -141,7 +136,7 @@ export default class NitroDataSource {
}
}
- async getFollowingCollectionPage (actorId) {
+ async getFollowingCollectionPage(actorId) {
const slug = extractNameFromId(actorId)
const result = await this.client.query({
query: gql`
@@ -153,7 +148,7 @@ export default class NitroDataSource {
followingCount
}
}
- `
+ `,
})
debug(result.data)
@@ -166,9 +161,9 @@ export default class NitroDataSource {
followingCollection.totalItems = followingCount
await Promise.all(
- following.map(async (user) => {
+ following.map(async user => {
followingCollection.orderedItems.push(await constructIdFromName(user.slug))
- })
+ }),
)
return followingCollection
@@ -177,7 +172,7 @@ export default class NitroDataSource {
}
}
- async getOutboxCollection (actorId) {
+ async getOutboxCollection(actorId) {
const slug = extractNameFromId(actorId)
const result = await this.client.query({
query: gql`
@@ -192,7 +187,7 @@ export default class NitroDataSource {
}
}
}
- `
+ `,
})
debug(result.data)
@@ -209,7 +204,7 @@ export default class NitroDataSource {
}
}
- async getOutboxCollectionPage (actorId) {
+ async getOutboxCollectionPage(actorId) {
const slug = extractNameFromId(actorId)
debug(`inside getting outbox collection page => ${slug}`)
const result = await this.client.query({
@@ -232,7 +227,7 @@ export default class NitroDataSource {
}
}
}
- `
+ `,
})
debug(result.data)
@@ -243,9 +238,18 @@ export default class NitroDataSource {
const outboxCollection = createOrderedCollectionPage(slug, 'outbox')
outboxCollection.totalItems = posts.length
await Promise.all(
- posts.map(async (post) => {
- outboxCollection.orderedItems.push(await createArticleObject(post.activityId, post.objectId, post.content, post.author.slug, post.id, post.createdAt))
- })
+ posts.map(async post => {
+ outboxCollection.orderedItems.push(
+ await createArticleObject(
+ post.activityId,
+ post.objectId,
+ post.content,
+ post.author.slug,
+ post.id,
+ post.createdAt,
+ ),
+ )
+ }),
)
debug('after createNote')
@@ -255,7 +259,7 @@ export default class NitroDataSource {
}
}
- async undoFollowActivity (fromActorId, toActorId) {
+ async undoFollowActivity(fromActorId, toActorId) {
const fromUserId = await this.ensureUser(fromActorId)
const toUserId = await this.ensureUser(toActorId)
const result = await this.client.mutate({
@@ -265,13 +269,13 @@ export default class NitroDataSource {
from { name }
}
}
- `
+ `,
})
debug(`undoFollowActivity result = ${JSON.stringify(result, null, 2)}`)
throwErrorIfApolloErrorOccurred(result)
}
- async saveFollowersCollectionPage (followersCollection, onlyNewestItem = true) {
+ async saveFollowersCollectionPage(followersCollection, onlyNewestItem = true) {
debug('inside saveFollowers')
let orderedItems = followersCollection.orderedItems
const toUserName = extractNameFromId(followersCollection.id)
@@ -279,7 +283,7 @@ export default class NitroDataSource {
orderedItems = onlyNewestItem ? [orderedItems.pop()] : orderedItems
return Promise.all(
- orderedItems.map(async (follower) => {
+ orderedItems.map(async follower => {
debug(`follower = ${follower}`)
const fromUserId = await this.ensureUser(follower)
debug(`fromUserId = ${fromUserId}`)
@@ -291,22 +295,22 @@ export default class NitroDataSource {
from { name }
}
}
- `
+ `,
})
debug(`addUserFollowedBy edge = ${JSON.stringify(result, null, 2)}`)
throwErrorIfApolloErrorOccurred(result)
debug('saveFollowers: added follow edge successfully')
- })
+ }),
)
}
- async saveFollowingCollectionPage (followingCollection, onlyNewestItem = true) {
+ async saveFollowingCollectionPage(followingCollection, onlyNewestItem = true) {
debug('inside saveFollowers')
let orderedItems = followingCollection.orderedItems
const fromUserName = extractNameFromId(followingCollection.id)
const fromUserId = await this.ensureUser(constructIdFromName(fromUserName))
orderedItems = onlyNewestItem ? [orderedItems.pop()] : orderedItems
return Promise.all(
- orderedItems.map(async (following) => {
+ orderedItems.map(async following => {
debug(`follower = ${following}`)
const toUserId = await this.ensureUser(following)
debug(`fromUserId = ${fromUserId}`)
@@ -318,33 +322,45 @@ export default class NitroDataSource {
from { name }
}
}
- `
+ `,
})
debug(`addUserFollowing edge = ${JSON.stringify(result, null, 2)}`)
throwErrorIfApolloErrorOccurred(result)
debug('saveFollowing: added follow edge successfully')
- })
+ }),
)
}
- async createPost (activity) {
+ async createPost(activity) {
// TODO how to handle the to field? Now the post is just created, doesn't matter who is the recipient
// createPost
const postObject = activity.object
if (!isPublicAddressed(postObject)) {
- return debug('createPost: not send to public (sending to specific persons is not implemented yet)')
+ return debug(
+ 'createPost: not send to public (sending to specific persons is not implemented yet)',
+ )
}
- const title = postObject.summary ? postObject.summary : postObject.content.split(' ').slice(0, 5).join(' ')
+ const title = postObject.summary
+ ? postObject.summary
+ : postObject.content
+ .split(' ')
+ .slice(0, 5)
+ .join(' ')
const postId = extractIdFromActivityId(postObject.id)
debug('inside create post')
let result = await this.client.mutate({
mutation: gql`
mutation {
- CreatePost(content: "${postObject.content}", contentExcerpt: "${trunc(postObject.content, 120)}", title: "${title}", id: "${postId}", objectId: "${postObject.id}", activityId: "${activity.id}") {
+ CreatePost(content: "${postObject.content}", contentExcerpt: "${trunc(
+ postObject.content,
+ 120,
+ )}", title: "${title}", id: "${postId}", objectId: "${postObject.id}", activityId: "${
+ activity.id
+ }") {
id
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
@@ -362,13 +378,13 @@ export default class NitroDataSource {
}
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
}
- async deletePost (activity) {
+ async deletePost(activity) {
const result = await this.client.mutate({
mutation: gql`
mutation {
@@ -376,28 +392,30 @@ export default class NitroDataSource {
title
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
}
- async updatePost (activity) {
+ async updatePost(activity) {
const postObject = activity.object
const postId = extractIdFromActivityId(postObject.id)
const date = postObject.updated ? postObject.updated : new Date().toISOString()
const result = await this.client.mutate({
mutation: gql`
mutation {
- UpdatePost(content: "${postObject.content}", contentExcerpt: "${trunc(postObject.content, 120).html}", id: "${postId}", updatedAt: "${date}") {
+ UpdatePost(content: "${postObject.content}", contentExcerpt: "${
+ trunc(postObject.content, 120).html
+ }", id: "${postId}", updatedAt: "${date}") {
title
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
}
- async createShouted (activity) {
+ async createShouted(activity) {
const userId = await this.ensureUser(activity.actor)
const postId = extractIdFromActivityId(activity.object)
const result = await this.client.mutate({
@@ -409,7 +427,7 @@ export default class NitroDataSource {
}
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
if (!result.data.AddUserShouted) {
@@ -418,7 +436,7 @@ export default class NitroDataSource {
}
}
- async deleteShouted (activity) {
+ async deleteShouted(activity) {
const userId = await this.ensureUser(activity.actor)
const postId = extractIdFromActivityId(activity.object)
const result = await this.client.mutate({
@@ -430,7 +448,7 @@ export default class NitroDataSource {
}
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
if (!result.data.AddUserShouted) {
@@ -439,27 +457,27 @@ export default class NitroDataSource {
}
}
- async getSharedInboxEndpoints () {
+ async getSharedInboxEndpoints() {
const result = await this.client.query({
query: gql`
query {
- SharedInboxEndpoint {
- uri
- }
+ SharedInboxEndpoint {
+ uri
+ }
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
return result.data.SharedInboxEnpoint
}
- async addSharedInboxEndpoint (uri) {
+ async addSharedInboxEndpoint(uri) {
try {
const result = await this.client.mutate({
mutation: gql`
mutation {
CreateSharedInboxEndpoint(uri: "${uri}")
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
return true
@@ -468,16 +486,18 @@ export default class NitroDataSource {
}
}
- async createComment (activity) {
+ async createComment(activity) {
const postObject = activity.object
let result = await this.client.mutate({
mutation: gql`
mutation {
- CreateComment(content: "${postObject.content}", activityId: "${extractIdFromActivityId(activity.id)}") {
+ CreateComment(content: "${
+ postObject.content
+ }", activityId: "${extractIdFromActivityId(activity.id)}") {
id
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
@@ -485,11 +505,13 @@ export default class NitroDataSource {
const result2 = await this.client.mutate({
mutation: gql`
mutation {
- AddCommentAuthor(from: {id: "${result.data.CreateComment.id}"}, to: {id: "${toUserId}"}) {
+ AddCommentAuthor(from: {id: "${
+ result.data.CreateComment.id
+ }"}, to: {id: "${toUserId}"}) {
id
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result2)
@@ -497,11 +519,13 @@ export default class NitroDataSource {
result = await this.client.mutate({
mutation: gql`
mutation {
- AddCommentPost(from: { id: "${result.data.CreateComment.id}", to: { id: "${postId}" }}) {
+ AddCommentPost(from: { id: "${
+ result.data.CreateComment.id
+ }", to: { id: "${postId}" }}) {
id
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
@@ -513,7 +537,7 @@ export default class NitroDataSource {
* @param actorId
* @returns {Promise<*>}
*/
- async ensureUser (actorId) {
+ async ensureUser(actorId) {
debug(`inside ensureUser = ${actorId}`)
const name = extractNameFromId(actorId)
const queryResult = await this.client.query({
@@ -523,10 +547,14 @@ export default class NitroDataSource {
id
}
}
- `
+ `,
})
- if (queryResult.data && Array.isArray(queryResult.data.User) && queryResult.data.User.length > 0) {
+ if (
+ queryResult.data &&
+ Array.isArray(queryResult.data.User) &&
+ queryResult.data.User.length > 0
+ ) {
debug('ensureUser: user exists.. return id')
// user already exists.. return the id
return queryResult.data.User[0].id
@@ -534,7 +562,10 @@ export default class NitroDataSource {
debug('ensureUser: user not exists.. createUser')
// user does not exist.. create it
const pw = crypto.randomBytes(16).toString('hex')
- const slug = name.toLowerCase().split(' ').join('-')
+ const slug = name
+ .toLowerCase()
+ .split(' ')
+ .join('-')
const result = await this.client.mutate({
mutation: gql`
mutation {
@@ -542,7 +573,7 @@ export default class NitroDataSource {
id
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
diff --git a/backend/src/activitypub/routes/inbox.js b/backend/src/activitypub/routes/inbox.js
index f9cfb3794..b31b89ed4 100644
--- a/backend/src/activitypub/routes/inbox.js
+++ b/backend/src/activitypub/routes/inbox.js
@@ -7,24 +7,24 @@ const router = express.Router()
// Shared Inbox endpoint (federated Server)
// For now its only able to handle Note Activities!!
-router.post('/', async function (req, res, next) {
+router.post('/', async function(req, res, next) {
debug(`Content-Type = ${req.get('Content-Type')}`)
debug(`body = ${JSON.stringify(req.body, null, 2)}`)
debug(`Request headers = ${JSON.stringify(req.headers, null, 2)}`)
switch (req.body.type) {
- case 'Create':
- await activityPub.handleCreateActivity(req.body).catch(next)
- break
- case 'Undo':
- await activityPub.handleUndoActivity(req.body).catch(next)
- break
- case 'Follow':
- await activityPub.handleFollowActivity(req.body).catch(next)
- break
- case 'Delete':
- await activityPub.handleDeleteActivity(req.body).catch(next)
- break
- /* eslint-disable */
+ case 'Create':
+ await activityPub.handleCreateActivity(req.body).catch(next)
+ break
+ case 'Undo':
+ await activityPub.handleUndoActivity(req.body).catch(next)
+ break
+ case 'Follow':
+ await activityPub.handleFollowActivity(req.body).catch(next)
+ break
+ case 'Delete':
+ await activityPub.handleDeleteActivity(req.body).catch(next)
+ break
+ /* eslint-disable */
case 'Update':
await activityPub.handleUpdateActivity(req.body).catch(next)
break
diff --git a/backend/src/activitypub/routes/index.js b/backend/src/activitypub/routes/index.js
index 24898e766..c7d31f1c4 100644
--- a/backend/src/activitypub/routes/index.js
+++ b/backend/src/activitypub/routes/index.js
@@ -7,23 +7,21 @@ import verify from './verify'
const router = express.Router()
-router.use('/.well-known/webFinger',
- cors(),
- express.urlencoded({ extended: true }),
- webFinger
-)
-router.use('/activitypub/users',
+router.use('/.well-known/webFinger', cors(), express.urlencoded({ extended: true }), webFinger)
+router.use(
+ '/activitypub/users',
cors(),
express.json({ type: ['application/activity+json', 'application/ld+json', 'application/json'] }),
express.urlencoded({ extended: true }),
- user
+ user,
)
-router.use('/activitypub/inbox',
+router.use(
+ '/activitypub/inbox',
cors(),
express.json({ type: ['application/activity+json', 'application/ld+json', 'application/json'] }),
express.urlencoded({ extended: true }),
verify,
- inbox
+ inbox,
)
export default router
diff --git a/backend/src/activitypub/routes/serveUser.js b/backend/src/activitypub/routes/serveUser.js
index f65876741..6f4472235 100644
--- a/backend/src/activitypub/routes/serveUser.js
+++ b/backend/src/activitypub/routes/serveUser.js
@@ -2,7 +2,7 @@ import { createActor } from '../utils/actor'
const gql = require('graphql-tag')
const debug = require('debug')('ea:serveUser')
-export async function serveUser (req, res, next) {
+export async function serveUser(req, res, next) {
let name = req.params.name
if (name.startsWith('@')) {
@@ -10,21 +10,32 @@ export async function serveUser (req, res, next) {
}
debug(`name = ${name}`)
- const result = await req.app.get('ap').dataSource.client.query({
- query: gql`
+ const result = await req.app
+ .get('ap')
+ .dataSource.client.query({
+ query: gql`
query {
User(slug: "${name}") {
publicKey
}
}
- `
- }).catch(reason => { debug(`serveUser User fetch error: ${reason}`) })
+ `,
+ })
+ .catch(reason => {
+ debug(`serveUser User fetch error: ${reason}`)
+ })
if (result.data && Array.isArray(result.data.User) && result.data.User.length > 0) {
const publicKey = result.data.User[0].publicKey
const actor = createActor(name, publicKey)
debug(`actor = ${JSON.stringify(actor, null, 2)}`)
- debug(`accepts json = ${req.accepts(['application/activity+json', 'application/ld+json', 'application/json'])}`)
+ debug(
+ `accepts json = ${req.accepts([
+ 'application/activity+json',
+ 'application/ld+json',
+ 'application/json',
+ ])}`,
+ )
if (req.accepts(['application/activity+json', 'application/ld+json', 'application/json'])) {
return res.json(actor)
} else if (req.accepts('text/html')) {
diff --git a/backend/src/activitypub/routes/user.js b/backend/src/activitypub/routes/user.js
index 017891e61..9dc9b5071 100644
--- a/backend/src/activitypub/routes/user.js
+++ b/backend/src/activitypub/routes/user.js
@@ -7,7 +7,7 @@ import verify from './verify'
const router = express.Router()
const debug = require('debug')('ea:user')
-router.get('/:name', async function (req, res, next) {
+router.get('/:name', async function(req, res, next) {
debug('inside user.js -> serveUser')
await serveUser(req, res, next)
})
@@ -45,24 +45,24 @@ router.get('/:name/outbox', (req, res) => {
}
})
-router.post('/:name/inbox', verify, async function (req, res, next) {
+router.post('/:name/inbox', verify, async function(req, res, next) {
debug(`body = ${JSON.stringify(req.body, null, 2)}`)
debug(`actorId = ${req.body.actor}`)
// const result = await saveActorId(req.body.actor)
switch (req.body.type) {
- case 'Create':
- await activityPub.handleCreateActivity(req.body).catch(next)
- break
- case 'Undo':
- await activityPub.handleUndoActivity(req.body).catch(next)
- break
- case 'Follow':
- await activityPub.handleFollowActivity(req.body).catch(next)
- break
- case 'Delete':
- await activityPub.handleDeleteActivity(req.body).catch(next)
- break
- /* eslint-disable */
+ case 'Create':
+ await activityPub.handleCreateActivity(req.body).catch(next)
+ break
+ case 'Undo':
+ await activityPub.handleUndoActivity(req.body).catch(next)
+ break
+ case 'Follow':
+ await activityPub.handleFollowActivity(req.body).catch(next)
+ break
+ case 'Delete':
+ await activityPub.handleDeleteActivity(req.body).catch(next)
+ break
+ /* eslint-disable */
case 'Update':
await activityPub.handleUpdateActivity(req.body).catch(next)
break
diff --git a/backend/src/activitypub/routes/verify.js b/backend/src/activitypub/routes/verify.js
index bb5850b3e..33603805f 100644
--- a/backend/src/activitypub/routes/verify.js
+++ b/backend/src/activitypub/routes/verify.js
@@ -4,7 +4,12 @@ const debug = require('debug')('ea:verify')
export default async (req, res, next) => {
debug(`actorId = ${req.body.actor}`)
// TODO stop if signature validation fails
- if (await verifySignature(`${req.protocol}://${req.hostname}:${req.app.get('port')}${req.originalUrl}`, req.headers)) {
+ if (
+ await verifySignature(
+ `${req.protocol}://${req.hostname}:${req.app.get('port')}${req.originalUrl}`,
+ req.headers,
+ )
+ ) {
debug('verify = true')
next()
} else {
diff --git a/backend/src/activitypub/routes/webFinger.js b/backend/src/activitypub/routes/webFinger.js
index 8def32328..7d52c69cd 100644
--- a/backend/src/activitypub/routes/webFinger.js
+++ b/backend/src/activitypub/routes/webFinger.js
@@ -4,10 +4,14 @@ import gql from 'graphql-tag'
const router = express.Router()
-router.get('/', async function (req, res) {
+router.get('/', async function(req, res) {
const resource = req.query.resource
if (!resource || !resource.includes('acct:')) {
- return res.status(400).send('Bad request. Please make sure "acct:USER@DOMAIN" is what you are sending as the "resource" query parameter.')
+ return res
+ .status(400)
+ .send(
+ 'Bad request. Please make sure "acct:USER@DOMAIN" is what you are sending as the "resource" query parameter.',
+ )
} else {
const nameAndDomain = resource.replace('acct:', '')
const name = nameAndDomain.split('@')[0]
@@ -21,7 +25,7 @@ router.get('/', async function (req, res) {
slug
}
}
- `
+ `,
})
} catch (error) {
return res.status(500).json({ error })
diff --git a/backend/src/activitypub/security/httpSignature.spec.js b/backend/src/activitypub/security/httpSignature.spec.js
index d40c38242..0c6fbb8b5 100644
--- a/backend/src/activitypub/security/httpSignature.spec.js
+++ b/backend/src/activitypub/security/httpSignature.spec.js
@@ -14,9 +14,9 @@ describe('activityPub/security', () => {
privateKey = pair.privateKey
publicKey = pair.publicKey
headers = {
- 'Date': '2019-03-08T14:35:45.759Z',
- 'Host': 'democracy-app.de',
- 'Content-Type': 'application/json'
+ Date: '2019-03-08T14:35:45.759Z',
+ Host: 'democracy-app.de',
+ 'Content-Type': 'application/json',
}
})
@@ -27,13 +27,23 @@ describe('activityPub/security', () => {
beforeEach(() => {
const signer = crypto.createSign('rsa-sha256')
- signer.update('(request-target): post /activitypub/users/max/inbox\ndate: 2019-03-08T14:35:45.759Z\nhost: democracy-app.de\ncontent-type: application/json')
+ signer.update(
+ '(request-target): post /activitypub/users/max/inbox\ndate: 2019-03-08T14:35:45.759Z\nhost: democracy-app.de\ncontent-type: application/json',
+ )
signatureB64 = signer.sign({ key: privateKey, passphrase }, 'base64')
- httpSignature = createSignature({ privateKey, keyId: 'https://human-connection.org/activitypub/users/lea#main-key', url: 'https://democracy-app.de/activitypub/users/max/inbox', headers, passphrase })
+ httpSignature = createSignature({
+ privateKey,
+ keyId: 'https://human-connection.org/activitypub/users/lea#main-key',
+ url: 'https://democracy-app.de/activitypub/users/max/inbox',
+ headers,
+ passphrase,
+ })
})
it('contains keyId', () => {
- expect(httpSignature).toContain('keyId="https://human-connection.org/activitypub/users/lea#main-key"')
+ expect(httpSignature).toContain(
+ 'keyId="https://human-connection.org/activitypub/users/lea#main-key"',
+ )
})
it('contains default algorithm "rsa-sha256"', () => {
@@ -54,13 +64,19 @@ describe('activityPub/security', () => {
let httpSignature
beforeEach(() => {
- httpSignature = createSignature({ privateKey, keyId: 'http://localhost:4001/activitypub/users/test-user#main-key', url: 'https://democracy-app.de/activitypub/users/max/inbox', headers, passphrase })
+ httpSignature = createSignature({
+ privateKey,
+ keyId: 'http://localhost:4001/activitypub/users/test-user#main-key',
+ url: 'https://democracy-app.de/activitypub/users/max/inbox',
+ headers,
+ passphrase,
+ })
const body = {
- 'publicKey': {
- 'id': 'https://localhost:4001/activitypub/users/test-user#main-key',
- 'owner': 'https://localhost:4001/activitypub/users/test-user',
- 'publicKeyPem': publicKey
- }
+ publicKey: {
+ id: 'https://localhost:4001/activitypub/users/test-user#main-key',
+ owner: 'https://localhost:4001/activitypub/users/test-user',
+ publicKeyPem: publicKey,
+ },
}
const mockedRequest = jest.fn((_, callback) => callback(null, null, JSON.stringify(body)))
@@ -68,7 +84,9 @@ describe('activityPub/security', () => {
})
it('resolves false', async () => {
- await expect(verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers)).resolves.toEqual(false)
+ await expect(
+ verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers),
+ ).resolves.toEqual(false)
})
describe('valid signature', () => {
@@ -77,7 +95,9 @@ describe('activityPub/security', () => {
})
it('resolves true', async () => {
- await expect(verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers)).resolves.toEqual(true)
+ await expect(
+ verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers),
+ ).resolves.toEqual(true)
})
})
})
diff --git a/backend/src/activitypub/security/index.js b/backend/src/activitypub/security/index.js
index fdb1e27c6..7f619acbe 100644
--- a/backend/src/activitypub/security/index.js
+++ b/backend/src/activitypub/security/index.js
@@ -6,42 +6,48 @@ const debug = require('debug')('ea:security')
dotenv.config({ path: resolve('src', 'activitypub', '.env') })
-export function generateRsaKeyPair (options = {}) {
+export function generateRsaKeyPair(options = {}) {
const { passphrase = process.env.PRIVATE_KEY_PASSPHRASE } = options
return crypto.generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
- format: 'pem'
+ format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
- passphrase
- }
+ passphrase,
+ },
})
}
// signing
-export function createSignature (options) {
+export function createSignature(options) {
const {
- privateKey, keyId, url,
+ privateKey,
+ keyId,
+ url,
headers = {},
algorithm = 'rsa-sha256',
- passphrase = process.env.PRIVATE_KEY_PASSPHRASE
+ passphrase = process.env.PRIVATE_KEY_PASSPHRASE,
} = options
- if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) { throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`) }
+ if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) {
+ throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`)
+ }
const signer = crypto.createSign(algorithm)
const signingString = constructSigningString(url, headers)
signer.update(signingString)
const signatureB64 = signer.sign({ key: privateKey, passphrase }, 'base64')
- const headersString = Object.keys(headers).reduce((result, key) => { return result + ' ' + key.toLowerCase() }, '')
+ const headersString = Object.keys(headers).reduce((result, key) => {
+ return result + ' ' + key.toLowerCase()
+ }, '')
return `keyId="${keyId}",algorithm="${algorithm}",headers="(request-target)${headersString}",signature="${signatureB64}"`
}
// verifying
-export function verifySignature (url, headers) {
+export function verifySignature(url, headers) {
return new Promise((resolve, reject) => {
const signatureHeader = headers['signature'] ? headers['signature'] : headers['Signature']
if (!signatureHeader) {
@@ -61,40 +67,47 @@ export function verifySignature (url, headers) {
const usedHeaders = headersString.split(' ')
const verifyHeaders = {}
- Object.keys(headers).forEach((key) => {
+ Object.keys(headers).forEach(key => {
if (usedHeaders.includes(key.toLowerCase())) {
verifyHeaders[key.toLowerCase()] = headers[key]
}
})
const signingString = constructSigningString(url, verifyHeaders)
debug(`keyId= ${keyId}`)
- request({
- url: keyId,
- headers: {
- 'Accept': 'application/json'
- }
- }, (err, response, body) => {
- if (err) reject(err)
- debug(`body = ${body}`)
- const actor = JSON.parse(body)
- const publicKeyPem = actor.publicKey.publicKeyPem
- resolve(httpVerify(publicKeyPem, signature, signingString, algorithm))
- })
+ request(
+ {
+ url: keyId,
+ headers: {
+ Accept: 'application/json',
+ },
+ },
+ (err, response, body) => {
+ if (err) reject(err)
+ debug(`body = ${body}`)
+ const actor = JSON.parse(body)
+ const publicKeyPem = actor.publicKey.publicKeyPem
+ resolve(httpVerify(publicKeyPem, signature, signingString, algorithm))
+ },
+ )
})
}
// private: signing
-function constructSigningString (url, headers) {
+function constructSigningString(url, headers) {
const urlObj = new URL(url)
- let signingString = `(request-target): post ${urlObj.pathname}${urlObj.search !== '' ? urlObj.search : ''}`
+ let signingString = `(request-target): post ${urlObj.pathname}${
+ urlObj.search !== '' ? urlObj.search : ''
+ }`
return Object.keys(headers).reduce((result, key) => {
return result + `\n${key.toLowerCase()}: ${headers[key]}`
}, signingString)
}
// private: verifying
-function httpVerify (pubKey, signature, signingString, algorithm) {
- if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) { throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`) }
+function httpVerify(pubKey, signature, signingString, algorithm) {
+ if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) {
+ throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`)
+ }
const verifier = crypto.createVerify(algorithm)
verifier.update(signingString)
return verifier.verify(pubKey, signature, 'base64')
@@ -103,14 +116,16 @@ function httpVerify (pubKey, signature, signingString, algorithm) {
// private: verifying
// This function can be used to extract the signature,headers,algorithm etc. out of the Signature Header.
// Just pass what you want as key
-function extractKeyValueFromSignatureHeader (signatureHeader, key) {
- const keyString = signatureHeader.split(',').filter((el) => {
+function extractKeyValueFromSignatureHeader(signatureHeader, key) {
+ const keyString = signatureHeader.split(',').filter(el => {
return !!el.startsWith(key)
})[0]
let firstEqualIndex = keyString.search('=')
// When headers are requested add 17 to the index to remove "(request-target) " from the string
- if (key === 'headers') { firstEqualIndex += 17 }
+ if (key === 'headers') {
+ firstEqualIndex += 17
+ }
return keyString.substring(firstEqualIndex + 2, keyString.length - 1)
}
@@ -151,4 +166,5 @@ export const SUPPORTED_HASH_ALGORITHMS = [
'sha512WithRSAEncryption',
'ssl3-md5',
'ssl3-sha1',
- 'whirlpool']
+ 'whirlpool',
+]
diff --git a/backend/src/activitypub/utils/activity.js b/backend/src/activitypub/utils/activity.js
index 57b6dfb83..baf13e1bf 100644
--- a/backend/src/activitypub/utils/activity.js
+++ b/backend/src/activitypub/utils/activity.js
@@ -6,45 +6,45 @@ import as from 'activitystrea.ms'
import gql from 'graphql-tag'
const debug = require('debug')('ea:utils:activity')
-export function createNoteObject (text, name, id, published) {
+export function createNoteObject(text, name, id, published) {
const createUuid = crypto.randomBytes(16).toString('hex')
return {
'@context': 'https://www.w3.org/ns/activitystreams',
- 'id': `${activityPub.endpoint}/activitypub/users/${name}/status/${createUuid}`,
- 'type': 'Create',
- 'actor': `${activityPub.endpoint}/activitypub/users/${name}`,
- 'object': {
- 'id': `${activityPub.endpoint}/activitypub/users/${name}/status/${id}`,
- 'type': 'Note',
- 'published': published,
- 'attributedTo': `${activityPub.endpoint}/activitypub/users/${name}`,
- 'content': text,
- 'to': 'https://www.w3.org/ns/activitystreams#Public'
- }
+ id: `${activityPub.endpoint}/activitypub/users/${name}/status/${createUuid}`,
+ type: 'Create',
+ actor: `${activityPub.endpoint}/activitypub/users/${name}`,
+ object: {
+ id: `${activityPub.endpoint}/activitypub/users/${name}/status/${id}`,
+ type: 'Note',
+ published: published,
+ attributedTo: `${activityPub.endpoint}/activitypub/users/${name}`,
+ content: text,
+ to: 'https://www.w3.org/ns/activitystreams#Public',
+ },
}
}
-export async function createArticleObject (activityId, objectId, text, name, id, published) {
+export async function createArticleObject(activityId, objectId, text, name, id, published) {
const actorId = await getActorId(name)
return {
'@context': 'https://www.w3.org/ns/activitystreams',
- 'id': `${activityId}`,
- 'type': 'Create',
- 'actor': `${actorId}`,
- 'object': {
- 'id': `${objectId}`,
- 'type': 'Article',
- 'published': published,
- 'attributedTo': `${actorId}`,
- 'content': text,
- 'to': 'https://www.w3.org/ns/activitystreams#Public'
- }
+ id: `${activityId}`,
+ type: 'Create',
+ actor: `${actorId}`,
+ object: {
+ id: `${objectId}`,
+ type: 'Article',
+ published: published,
+ attributedTo: `${actorId}`,
+ content: text,
+ to: 'https://www.w3.org/ns/activitystreams#Public',
+ },
}
}
-export async function getActorId (name) {
+export async function getActorId(name) {
const result = await activityPub.dataSource.client.query({
query: gql`
query {
@@ -52,7 +52,7 @@ export async function getActorId (name) {
actorId
}
}
- `
+ `,
})
throwErrorIfApolloErrorOccurred(result)
if (Array.isArray(result.data.User) && result.data.User[0]) {
@@ -62,9 +62,12 @@ export async function getActorId (name) {
}
}
-export function sendAcceptActivity (theBody, name, targetDomain, url) {
+export function sendAcceptActivity(theBody, name, targetDomain, url) {
as.accept()
- .id(`${activityPub.endpoint}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex'))
+ .id(
+ `${activityPub.endpoint}/activitypub/users/${name}/status/` +
+ crypto.randomBytes(16).toString('hex'),
+ )
.actor(`${activityPub.endpoint}/activitypub/users/${name}`)
.object(theBody)
.prettyWrite((err, doc) => {
@@ -77,9 +80,12 @@ export function sendAcceptActivity (theBody, name, targetDomain, url) {
})
}
-export function sendRejectActivity (theBody, name, targetDomain, url) {
+export function sendRejectActivity(theBody, name, targetDomain, url) {
as.reject()
- .id(`${activityPub.endpoint}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex'))
+ .id(
+ `${activityPub.endpoint}/activitypub/users/${name}/status/` +
+ crypto.randomBytes(16).toString('hex'),
+ )
.actor(`${activityPub.endpoint}/activitypub/users/${name}`)
.object(theBody)
.prettyWrite((err, doc) => {
@@ -92,7 +98,7 @@ export function sendRejectActivity (theBody, name, targetDomain, url) {
})
}
-export function isPublicAddressed (postObject) {
+export function isPublicAddressed(postObject) {
if (typeof postObject.to === 'string') {
postObject.to = [postObject.to]
}
@@ -102,7 +108,9 @@ export function isPublicAddressed (postObject) {
if (Array.isArray(postObject)) {
postObject.to = postObject
}
- return postObject.to.includes('Public') ||
+ return (
+ postObject.to.includes('Public') ||
postObject.to.includes('as:Public') ||
postObject.to.includes('https://www.w3.org/ns/activitystreams#Public')
+ )
}
diff --git a/backend/src/activitypub/utils/actor.js b/backend/src/activitypub/utils/actor.js
index 27612517b..a08065778 100644
--- a/backend/src/activitypub/utils/actor.js
+++ b/backend/src/activitypub/utils/actor.js
@@ -1,41 +1,38 @@
import { activityPub } from '../ActivityPub'
-export function createActor (name, pubkey) {
+export function createActor(name, pubkey) {
return {
- '@context': [
- 'https://www.w3.org/ns/activitystreams',
- 'https://w3id.org/security/v1'
- ],
- 'id': `${activityPub.endpoint}/activitypub/users/${name}`,
- 'type': 'Person',
- 'preferredUsername': `${name}`,
- 'name': `${name}`,
- 'following': `${activityPub.endpoint}/activitypub/users/${name}/following`,
- 'followers': `${activityPub.endpoint}/activitypub/users/${name}/followers`,
- 'inbox': `${activityPub.endpoint}/activitypub/users/${name}/inbox`,
- 'outbox': `${activityPub.endpoint}/activitypub/users/${name}/outbox`,
- 'url': `${activityPub.endpoint}/activitypub/@${name}`,
- 'endpoints': {
- 'sharedInbox': `${activityPub.endpoint}/activitypub/inbox`
+ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'],
+ id: `${activityPub.endpoint}/activitypub/users/${name}`,
+ type: 'Person',
+ preferredUsername: `${name}`,
+ name: `${name}`,
+ following: `${activityPub.endpoint}/activitypub/users/${name}/following`,
+ followers: `${activityPub.endpoint}/activitypub/users/${name}/followers`,
+ inbox: `${activityPub.endpoint}/activitypub/users/${name}/inbox`,
+ outbox: `${activityPub.endpoint}/activitypub/users/${name}/outbox`,
+ url: `${activityPub.endpoint}/activitypub/@${name}`,
+ endpoints: {
+ sharedInbox: `${activityPub.endpoint}/activitypub/inbox`,
+ },
+ publicKey: {
+ id: `${activityPub.endpoint}/activitypub/users/${name}#main-key`,
+ owner: `${activityPub.endpoint}/activitypub/users/${name}`,
+ publicKeyPem: pubkey,
},
- 'publicKey': {
- 'id': `${activityPub.endpoint}/activitypub/users/${name}#main-key`,
- 'owner': `${activityPub.endpoint}/activitypub/users/${name}`,
- 'publicKeyPem': pubkey
- }
}
}
-export function createWebFinger (name) {
+export function createWebFinger(name) {
const { host } = new URL(activityPub.endpoint)
return {
- 'subject': `acct:${name}@${host}`,
- 'links': [
+ subject: `acct:${name}@${host}`,
+ links: [
{
- 'rel': 'self',
- 'type': 'application/activity+json',
- 'href': `${activityPub.endpoint}/activitypub/users/${name}`
- }
- ]
+ rel: 'self',
+ type: 'application/activity+json',
+ href: `${activityPub.endpoint}/activitypub/users/${name}`,
+ },
+ ],
}
}
diff --git a/backend/src/activitypub/utils/collection.js b/backend/src/activitypub/utils/collection.js
index e3a63c74d..29cf69ac2 100644
--- a/backend/src/activitypub/utils/collection.js
+++ b/backend/src/activitypub/utils/collection.js
@@ -2,68 +2,71 @@ import { activityPub } from '../ActivityPub'
import { constructIdFromName } from './index'
const debug = require('debug')('ea:utils:collections')
-export function createOrderedCollection (name, collectionName) {
+export function createOrderedCollection(name, collectionName) {
return {
'@context': 'https://www.w3.org/ns/activitystreams',
- 'id': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`,
- 'summary': `${name}s ${collectionName} collection`,
- 'type': 'OrderedCollection',
- 'first': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`,
- 'totalItems': 0
+ id: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`,
+ summary: `${name}s ${collectionName} collection`,
+ type: 'OrderedCollection',
+ first: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`,
+ totalItems: 0,
}
}
-export function createOrderedCollectionPage (name, collectionName) {
+export function createOrderedCollectionPage(name, collectionName) {
return {
'@context': 'https://www.w3.org/ns/activitystreams',
- 'id': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`,
- 'summary': `${name}s ${collectionName} collection`,
- 'type': 'OrderedCollectionPage',
- 'totalItems': 0,
- 'partOf': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`,
- 'orderedItems': []
+ id: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`,
+ summary: `${name}s ${collectionName} collection`,
+ type: 'OrderedCollectionPage',
+ totalItems: 0,
+ partOf: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`,
+ orderedItems: [],
}
}
-export function sendCollection (collectionName, req, res) {
+export function sendCollection(collectionName, req, res) {
const name = req.params.name
const id = constructIdFromName(name)
switch (collectionName) {
- case 'followers':
- attachThenCatch(activityPub.collections.getFollowersCollection(id), res)
- break
+ case 'followers':
+ attachThenCatch(activityPub.collections.getFollowersCollection(id), res)
+ break
- case 'followersPage':
- attachThenCatch(activityPub.collections.getFollowersCollectionPage(id), res)
- break
+ case 'followersPage':
+ attachThenCatch(activityPub.collections.getFollowersCollectionPage(id), res)
+ break
- case 'following':
- attachThenCatch(activityPub.collections.getFollowingCollection(id), res)
- break
+ case 'following':
+ attachThenCatch(activityPub.collections.getFollowingCollection(id), res)
+ break
- case 'followingPage':
- attachThenCatch(activityPub.collections.getFollowingCollectionPage(id), res)
- break
+ case 'followingPage':
+ attachThenCatch(activityPub.collections.getFollowingCollectionPage(id), res)
+ break
- case 'outbox':
- attachThenCatch(activityPub.collections.getOutboxCollection(id), res)
- break
+ case 'outbox':
+ attachThenCatch(activityPub.collections.getOutboxCollection(id), res)
+ break
- case 'outboxPage':
- attachThenCatch(activityPub.collections.getOutboxCollectionPage(id), res)
- break
+ case 'outboxPage':
+ attachThenCatch(activityPub.collections.getOutboxCollectionPage(id), res)
+ break
- default:
- res.status(500).end()
+ default:
+ res.status(500).end()
}
}
-function attachThenCatch (promise, res) {
+function attachThenCatch(promise, res) {
return promise
- .then((collection) => {
- res.status(200).contentType('application/activity+json').send(collection)
+ .then(collection => {
+ res
+ .status(200)
+ .contentType('application/activity+json')
+ .send(collection)
})
- .catch((err) => {
+ .catch(err => {
debug(`error getting a Collection: = ${err}`)
res.status(500).end()
})
diff --git a/backend/src/activitypub/utils/index.js b/backend/src/activitypub/utils/index.js
index a83dcc829..ee7ae2606 100644
--- a/backend/src/activitypub/utils/index.js
+++ b/backend/src/activitypub/utils/index.js
@@ -4,7 +4,7 @@ import { createSignature } from '../security'
import request from 'request'
const debug = require('debug')('ea:utils')
-export function extractNameFromId (uri) {
+export function extractNameFromId(uri) {
const urlObject = new URL(uri)
const pathname = urlObject.pathname
const splitted = pathname.split('/')
@@ -12,28 +12,30 @@ export function extractNameFromId (uri) {
return splitted[splitted.indexOf('users') + 1]
}
-export function extractIdFromActivityId (uri) {
+export function extractIdFromActivityId(uri) {
const urlObject = new URL(uri)
const pathname = urlObject.pathname
const splitted = pathname.split('/')
return splitted[splitted.indexOf('status') + 1]
}
-export function constructIdFromName (name, fromDomain = activityPub.endpoint) {
+export function constructIdFromName(name, fromDomain = activityPub.endpoint) {
return `${fromDomain}/activitypub/users/${name}`
}
-export function extractDomainFromUrl (url) {
+export function extractDomainFromUrl(url) {
return new URL(url).host
}
-export function throwErrorIfApolloErrorOccurred (result) {
+export function throwErrorIfApolloErrorOccurred(result) {
if (result.error && (result.error.message || result.error.errors)) {
- throw new Error(`${result.error.message ? result.error.message : result.error.errors[0].message}`)
+ throw new Error(
+ `${result.error.message ? result.error.message : result.error.errors[0].message}`,
+ )
}
}
-export function signAndSend (activity, fromName, targetDomain, url) {
+export function signAndSend(activity, fromName, targetDomain, url) {
// fix for development: replace with http
url = url.indexOf('localhost') > -1 ? url.replace('https', 'http') : url
debug(`passhprase = ${process.env.PRIVATE_KEY_PASSPHRASE}`)
@@ -47,7 +49,7 @@ export function signAndSend (activity, fromName, targetDomain, url) {
privateKey
}
}
- `
+ `,
})
if (result.error) {
@@ -69,34 +71,38 @@ export function signAndSend (activity, fromName, targetDomain, url) {
const date = new Date().toUTCString()
debug(`url = ${url}`)
- request({
- url: url,
- headers: {
- 'Host': targetDomain,
- 'Date': date,
- 'Signature': createSignature({ privateKey,
- keyId: `${activityPub.endpoint}/activitypub/users/${fromName}#main-key`,
- url,
- headers: {
- 'Host': targetDomain,
- 'Date': date,
- 'Content-Type': 'application/activity+json'
- }
- }),
- 'Content-Type': 'application/activity+json'
+ request(
+ {
+ url: url,
+ headers: {
+ Host: targetDomain,
+ Date: date,
+ Signature: createSignature({
+ privateKey,
+ keyId: `${activityPub.endpoint}/activitypub/users/${fromName}#main-key`,
+ url,
+ headers: {
+ Host: targetDomain,
+ Date: date,
+ 'Content-Type': 'application/activity+json',
+ },
+ }),
+ 'Content-Type': 'application/activity+json',
+ },
+ method: 'POST',
+ body: JSON.stringify(parsedActivity),
},
- method: 'POST',
- body: JSON.stringify(parsedActivity)
- }, (error, response) => {
- if (error) {
- debug(`Error = ${JSON.stringify(error, null, 2)}`)
- reject(error)
- } else {
- debug('Response Headers:', JSON.stringify(response.headers, null, 2))
- debug('Response Body:', JSON.stringify(response.body, null, 2))
- resolve()
- }
- })
+ (error, response) => {
+ if (error) {
+ debug(`Error = ${JSON.stringify(error, null, 2)}`)
+ reject(error)
+ } else {
+ debug('Response Headers:', JSON.stringify(response.headers, null, 2))
+ debug('Response Body:', JSON.stringify(response.body, null, 2))
+ resolve()
+ }
+ },
+ )
}
})
}
diff --git a/backend/src/bootstrap/directives.js b/backend/src/bootstrap/directives.js
index 8c392ed46..93a7574fb 100644
--- a/backend/src/bootstrap/directives.js
+++ b/backend/src/bootstrap/directives.js
@@ -1,15 +1,11 @@
import {
GraphQLLowerCaseDirective,
GraphQLTrimDirective,
- GraphQLDefaultToDirective
+ GraphQLDefaultToDirective,
} from 'graphql-custom-directives'
-export default function applyDirectives (augmentedSchema) {
- const directives = [
- GraphQLLowerCaseDirective,
- GraphQLTrimDirective,
- GraphQLDefaultToDirective
- ]
+export default function applyDirectives(augmentedSchema) {
+ const directives = [GraphQLLowerCaseDirective, GraphQLTrimDirective, GraphQLDefaultToDirective]
augmentedSchema._directives.push.apply(augmentedSchema._directives, directives)
return augmentedSchema
diff --git a/backend/src/bootstrap/neo4j.js b/backend/src/bootstrap/neo4j.js
index 935449a0a..292983359 100644
--- a/backend/src/bootstrap/neo4j.js
+++ b/backend/src/bootstrap/neo4j.js
@@ -5,11 +5,11 @@ dotenv.config()
let driver
-export function getDriver (options = {}) {
+export function getDriver(options = {}) {
const {
uri = process.env.NEO4J_URI || 'bolt://localhost:7687',
username = process.env.NEO4J_USERNAME || 'neo4j',
- password = process.env.NEO4J_PASSWORD || 'neo4j'
+ password = process.env.NEO4J_PASSWORD || 'neo4j',
} = options
if (!driver) {
driver = neo4j.driver(uri, neo4j.auth.basic(username, password))
diff --git a/backend/src/bootstrap/scalars.js b/backend/src/bootstrap/scalars.js
index 813bd5051..eb6d3739b 100644
--- a/backend/src/bootstrap/scalars.js
+++ b/backend/src/bootstrap/scalars.js
@@ -1,10 +1,6 @@
-import {
- GraphQLDate,
- GraphQLTime,
- GraphQLDateTime
-} from 'graphql-iso-date'
+import { GraphQLDate, GraphQLTime, GraphQLDateTime } from 'graphql-iso-date'
-export default function applyScalars (augmentedSchema) {
+export default function applyScalars(augmentedSchema) {
augmentedSchema._typeMap.Date = GraphQLDate
augmentedSchema._typeMap.Time = GraphQLTime
augmentedSchema._typeMap.DateTime = GraphQLDateTime
diff --git a/backend/src/graphql-schema.js b/backend/src/graphql-schema.js
index bad277721..0942b2381 100644
--- a/backend/src/graphql-schema.js
+++ b/backend/src/graphql-schema.js
@@ -14,9 +14,7 @@ import notifications from './resolvers/notifications'
import comments from './resolvers/comments'
export const typeDefs = fs
- .readFileSync(
- process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql')
- )
+ .readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
.toString('utf-8')
export const resolvers = {
@@ -24,7 +22,7 @@ export const resolvers = {
...statistics.Query,
...userManagement.Query,
...notifications.Query,
- ...comments.Query
+ ...comments.Query,
},
Mutation: {
...userManagement.Mutation,
@@ -36,6 +34,6 @@ export const resolvers = {
...rewards.Mutation,
...socialMedia.Mutation,
...notifications.Mutation,
- ...comments.Mutation
- }
+ ...comments.Mutation,
+ },
}
diff --git a/backend/src/helpers/asyncForEach.js b/backend/src/helpers/asyncForEach.js
index 1f05ea915..5577cce14 100644
--- a/backend/src/helpers/asyncForEach.js
+++ b/backend/src/helpers/asyncForEach.js
@@ -5,7 +5,7 @@
* @param callback
* @returns {Promise Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock. Something inspirational about @bob-der-baumeister and @jenny-rostock.
'
- )
+ .replace(/<\/(p|div|th|tr)>\s*(
\s*)+\s*<(p|div|th|tr)>/gim, '
')
// remove additional linebreaks inside p tags
- .replace(
- /<[a-z-]+>(<[a-z-]+>)*\s*(
\s*)+\s*(<\/[a-z-]+>)*<\/[a-z-]+>/gim,
- ''
- )
+ .replace(/<[a-z-]+>(<[a-z-]+>)*\s*(
\s*)+\s*(<\/[a-z-]+>)*<\/[a-z-]+>/gim, '')
// remove additional linebreaks when first child inside p tags
.replace(/
(\s*
\s*)+/gim, '
') // remove additional linebreaks when last child inside p tags @@ -138,5 +150,5 @@ export default { Query: async (resolve, root, args, context, info) => { const result = await resolve(root, args, context, info) return walkRecursive(result, fields, clean) - } + }, } diff --git a/backend/src/mocks/index.js b/backend/src/mocks/index.js index a87ccfbbc..7b453c8c6 100644 --- a/backend/src/mocks/index.js +++ b/backend/src/mocks/index.js @@ -1,15 +1,14 @@ - import faker from 'faker' export default { User: () => ({ name: () => `${faker.name.firstName()} ${faker.name.lastName()}`, - email: () => `${faker.internet.email()}` + email: () => `${faker.internet.email()}`, }), Post: () => ({ title: () => faker.lorem.lines(1), slug: () => faker.lorem.slug(3), content: () => faker.lorem.paragraphs(5), - contentExcerpt: () => faker.lorem.paragraphs(1) - }) + contentExcerpt: () => faker.lorem.paragraphs(1), + }), } diff --git a/backend/src/resolvers/badges.spec.js b/backend/src/resolvers/badges.spec.js index 1966ce241..f5e15f4a2 100644 --- a/backend/src/resolvers/badges.spec.js +++ b/backend/src/resolvers/badges.spec.js @@ -10,17 +10,17 @@ describe('badges', () => { await factory.create('User', { email: 'user@example.org', role: 'user', - password: '1234' + password: '1234', }) await factory.create('User', { id: 'u2', role: 'moderator', - email: 'moderator@example.org' + email: 'moderator@example.org', }) await factory.create('User', { id: 'u3', role: 'admin', - email: 'admin@example.org' + email: 'admin@example.org', }) }) @@ -34,7 +34,7 @@ describe('badges', () => { key: 'indiegogo_en_racoon', type: 'crowdfunding', status: 'permanent', - icon: '/img/badges/indiegogo_en_racoon.svg' + icon: '/img/badges/indiegogo_en_racoon.svg', } const mutation = ` @@ -58,9 +58,7 @@ describe('badges', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { client = new GraphQLClient(host) - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -76,8 +74,8 @@ describe('badges', () => { id: 'b1', key: 'indiegogo_en_racoon', status: 'permanent', - type: 'crowdfunding' - } + type: 'crowdfunding', + }, } await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) @@ -90,9 +88,7 @@ describe('badges', () => { }) it('throws authorization error', async () => { - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) }) @@ -104,7 +100,7 @@ describe('badges', () => { }) const variables = { id: 'b1', - key: 'whatever' + key: 'whatever', } const mutation = ` @@ -119,9 +115,7 @@ describe('badges', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { client = new GraphQLClient(host) - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -132,9 +126,7 @@ describe('badges', () => { }) it('throws authorization error', async () => { - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -147,8 +139,8 @@ describe('badges', () => { const expected = { UpdateBadge: { id: 'b1', - key: 'whatever' - } + key: 'whatever', + }, } await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) @@ -161,7 +153,7 @@ describe('badges', () => { await factory.create('Badge', { id: 'b1' }) }) const variables = { - id: 'b1' + id: 'b1', } const mutation = ` @@ -175,9 +167,7 @@ describe('badges', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { client = new GraphQLClient(host) - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -188,9 +178,7 @@ describe('badges', () => { }) it('throws authorization error', async () => { - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -202,8 +190,8 @@ describe('badges', () => { it('deletes a badge', async () => { const expected = { DeleteBadge: { - id: 'b1' - } + id: 'b1', + }, } await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index d4775b235..949b77041 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -23,11 +23,13 @@ export default { } const session = context.driver.session() - const postQueryRes = await session.run(` + const postQueryRes = await session.run( + ` MATCH (post:Post {id: $postId}) - RETURN post`, { - postId - } + RETURN post`, + { + postId, + }, ) const [post] = postQueryRes.records.map(record => { return record.get('post') @@ -38,18 +40,20 @@ export default { } const comment = await neo4jgraphql(object, params, context, resolveInfo, false) - await session.run(` + await session.run( + ` MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}), (author:User {id: $userId}) MERGE (post)<-[:COMMENTS]-(comment)<-[:WROTE]-(author) - RETURN post`, { - userId: context.user.id, - postId, - commentId: comment.id - } + RETURN post`, + { + userId: context.user.id, + postId, + commentId: comment.id, + }, ) session.close() return comment - } - } + }, + }, } diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index 87a0df270..451c559f1 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -12,7 +12,7 @@ let createCommentVariablesWithNonExistentPost beforeEach(async () => { await factory.create('User', { email: 'test@example.org', - password: '1234' + password: '1234', }) }) @@ -47,10 +47,12 @@ describe('CreateComment', () => { it('throws authorization error', async () => { createCommentVariables = { postId: 'p1', - content: 'I\'m not authorised to comment' + content: "I'm not authorised to comment", } client = new GraphQLClient(host) - await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow('Not Authorised') + await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow( + 'Not Authorised', + ) }) }) @@ -61,12 +63,12 @@ describe('CreateComment', () => { client = new GraphQLClient(host, { headers }) createCommentVariables = { postId: 'p1', - content: 'I\'m authorised to comment' + content: "I'm authorised to comment", } createPostVariables = { id: 'p1', title: 'post to comment on', - content: 'please comment on me' + content: 'please comment on me', } await client.request(createPostMutation, createPostVariables) }) @@ -74,11 +76,13 @@ describe('CreateComment', () => { it('creates a comment', async () => { const expected = { CreateComment: { - content: 'I\'m authorised to comment' - } + content: "I'm authorised to comment", + }, } - await expect(client.request(createCommentMutation, createCommentVariables)).resolves.toMatchObject(expected) + await expect( + client.request(createCommentMutation, createCommentVariables), + ).resolves.toMatchObject(expected) }) it('assigns the authenticated user as author', async () => { @@ -92,86 +96,96 @@ describe('CreateComment', () => { } }`) - expect(User).toEqual([ { comments: [ { content: 'I\'m authorised to comment' } ] } ]) + expect(User).toEqual([{ comments: [{ content: "I'm authorised to comment" }] }]) }) it('throw an error if an empty string is sent from the editor as content', async () => { createCommentVariables = { postId: 'p1', - content: '
' + content: '', } - await expect(client.request(createCommentMutation, createCommentVariables)) - .rejects.toThrow('Comment must be at least 1 character long!') + await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow( + 'Comment must be at least 1 character long!', + ) }) it('throws an error if a comment sent from the editor does not contain a single character', async () => { createCommentVariables = { postId: 'p1', - content: '' + content: '
', } - await expect(client.request(createCommentMutation, createCommentVariables)) - .rejects.toThrow('Comment must be at least 1 character long!') + await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow( + 'Comment must be at least 1 character long!', + ) }) it('throws an error if postId is sent as an empty string', async () => { createCommentVariables = { postId: 'p1', - content: '' + content: '', } - await expect(client.request(createCommentMutation, createCommentVariables)) - .rejects.toThrow('Comment must be at least 1 character long!') + await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow( + 'Comment must be at least 1 character long!', + ) }) it('throws an error if content is sent as an string of empty characters', async () => { createCommentVariables = { postId: 'p1', - content: ' ' + content: ' ', } - await expect(client.request(createCommentMutation, createCommentVariables)) - .rejects.toThrow('Comment must be at least 1 character long!') + await expect(client.request(createCommentMutation, createCommentVariables)).rejects.toThrow( + 'Comment must be at least 1 character long!', + ) }) it('throws an error if postId is sent as an empty string', async () => { createCommentVariablesSansPostId = { postId: '', - content: 'this comment should not be created' + content: 'this comment should not be created', } - await expect(client.request(createCommentMutation, createCommentVariablesSansPostId)) - .rejects.toThrow('Comment cannot be created without a post!') + await expect( + client.request(createCommentMutation, createCommentVariablesSansPostId), + ).rejects.toThrow('Comment cannot be created without a post!') }) it('throws an error if postId is sent as an string of empty characters', async () => { createCommentVariablesSansPostId = { postId: ' ', - content: 'this comment should not be created' + content: 'this comment should not be created', } - await expect(client.request(createCommentMutation, createCommentVariablesSansPostId)) - .rejects.toThrow('Comment cannot be created without a post!') + await expect( + client.request(createCommentMutation, createCommentVariablesSansPostId), + ).rejects.toThrow('Comment cannot be created without a post!') }) it('throws an error if the post does not exist in the database', async () => { createCommentVariablesWithNonExistentPost = { postId: 'p2', - content: 'comment should not be created cause the post doesn\'t exist' + content: "comment should not be created cause the post doesn't exist", } - await expect(client.request(createCommentMutation, createCommentVariablesWithNonExistentPost)) - .rejects.toThrow('Comment cannot be created without a post!') + await expect( + client.request(createCommentMutation, createCommentVariablesWithNonExistentPost), + ).rejects.toThrow('Comment cannot be created without a post!') }) it('does not create the comment with the postId as an attribute', async () => { const commentQueryVariablesByContent = { - content: 'I\'m authorised to comment' + content: "I'm authorised to comment", } await client.request(createCommentMutation, createCommentVariables) - const { Comment } = await client.request(commentQueryForPostId, commentQueryVariablesByContent) + const { Comment } = await client.request( + commentQueryForPostId, + commentQueryVariablesByContent, + ) expect(Comment).toEqual([{ postId: null }]) }) }) diff --git a/backend/src/resolvers/follow.js b/backend/src/resolvers/follow.js index df7b58891..4e9a3b27d 100644 --- a/backend/src/resolvers/follow.js +++ b/backend/src/resolvers/follow.js @@ -12,8 +12,8 @@ export default { { id, type, - userId: context.user.id - } + userId: context.user.id, + }, ) const [isFollowed] = transactionRes.records.map(record => { @@ -37,8 +37,8 @@ export default { { id, type, - userId: context.user.id - } + userId: context.user.id, + }, ) const [isFollowed] = transactionRes.records.map(record => { return record.get('isFollowed') @@ -46,6 +46,6 @@ export default { session.close() return isFollowed - } - } + }, + }, } diff --git a/backend/src/resolvers/follow.spec.js b/backend/src/resolvers/follow.spec.js index 081e49081..4a361b03d 100644 --- a/backend/src/resolvers/follow.spec.js +++ b/backend/src/resolvers/follow.spec.js @@ -6,12 +6,12 @@ const factory = Factory() let clientUser1 let headersUser1 -const mutationFollowUser = (id) => ` +const mutationFollowUser = id => ` mutation { follow(id: "${id}", type: User) } ` -const mutationUnfollowUser = (id) => ` +const mutationUnfollowUser = id => ` mutation { unfollow(id: "${id}", type: User) } @@ -21,12 +21,12 @@ beforeEach(async () => { await factory.create('User', { id: 'u1', email: 'test@example.org', - password: '1234' + password: '1234', }) await factory.create('User', { id: 'u2', email: 'test2@example.org', - password: '1234' + password: '1234', }) headersUser1 = await login({ email: 'test@example.org', password: '1234' }) @@ -43,18 +43,14 @@ describe('follow', () => { it('throws authorization error', async () => { let client client = new GraphQLClient(host) - await expect( - client.request(mutationFollowUser('u2')) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutationFollowUser('u2'))).rejects.toThrow('Not Authorised') }) }) it('I can follow another user', async () => { - const res = await clientUser1.request( - mutationFollowUser('u2') - ) + const res = await clientUser1.request(mutationFollowUser('u2')) const expected = { - follow: true + follow: true, } expect(res).toMatchObject(expected) @@ -65,20 +61,16 @@ describe('follow', () => { } }`) const expected2 = { - followedBy: [ - { id: 'u1' } - ], - followedByCurrentUser: true + followedBy: [{ id: 'u1' }], + followedByCurrentUser: true, } expect(User[0]).toMatchObject(expected2) }) it('I can`t follow myself', async () => { - const res = await clientUser1.request( - mutationFollowUser('u1') - ) + const res = await clientUser1.request(mutationFollowUser('u1')) const expected = { - follow: false + follow: false, } expect(res).toMatchObject(expected) @@ -90,7 +82,7 @@ describe('follow', () => { }`) const expected2 = { followedBy: [], - followedByCurrentUser: false + followedByCurrentUser: false, } expect(User[0]).toMatchObject(expected2) }) @@ -99,26 +91,20 @@ describe('follow', () => { describe('unauthenticated follow', () => { it('throws authorization error', async () => { // follow - await clientUser1.request( - mutationFollowUser('u2') - ) + await clientUser1.request(mutationFollowUser('u2')) // unfollow let client client = new GraphQLClient(host) - await expect( - client.request(mutationUnfollowUser('u2')) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutationUnfollowUser('u2'))).rejects.toThrow('Not Authorised') }) }) it('I can unfollow a user', async () => { // follow - await clientUser1.request( - mutationFollowUser('u2') - ) + await clientUser1.request(mutationFollowUser('u2')) // unfollow const expected = { - unfollow: true + unfollow: true, } const res = await clientUser1.request(mutationUnfollowUser('u2')) expect(res).toMatchObject(expected) @@ -131,7 +117,7 @@ describe('follow', () => { }`) const expected2 = { followedBy: [], - followedByCurrentUser: false + followedByCurrentUser: false, } expect(User[0]).toMatchObject(expected2) }) diff --git a/backend/src/resolvers/moderation.js b/backend/src/resolvers/moderation.js index 7bc1227ff..d61df7545 100644 --- a/backend/src/resolvers/moderation.js +++ b/backend/src/resolvers/moderation.js @@ -14,7 +14,7 @@ export default { const session = driver.session() const res = await session.run(cypher, { id, userId }) session.close() - const [resource] = res.records.map((record) => { + const [resource] = res.records.map(record => { return record.get('resource') }) if (!resource) return null @@ -31,11 +31,11 @@ export default { const session = driver.session() const res = await session.run(cypher, { id }) session.close() - const [resource] = res.records.map((record) => { + const [resource] = res.records.map(record => { return record.get('resource') }) if (!resource) return null return resource.id - } - } + }, + }, } diff --git a/backend/src/resolvers/moderation.spec.js b/backend/src/resolvers/moderation.spec.js index 28f4dc322..835e9e535 100644 --- a/backend/src/resolvers/moderation.spec.js +++ b/backend/src/resolvers/moderation.spec.js @@ -5,7 +5,7 @@ import { host, login } from '../jest/helpers' const factory = Factory() let client -const setupAuthenticateClient = (params) => { +const setupAuthenticateClient = params => { const authenticateClient = async () => { await factory.create('User', params) const headers = await login(params) @@ -46,7 +46,7 @@ describe('disable', () => { beforeEach(() => { // our defaul set of variables variables = { - id: 'blabla' + id: 'blabla', } }) @@ -63,7 +63,7 @@ describe('disable', () => { beforeEach(() => { authenticateClient = setupAuthenticateClient({ email: 'user@example.org', - password: '1234' + password: '1234', }) }) @@ -78,19 +78,17 @@ describe('disable', () => { id: 'u7', email: 'moderator@example.org', password: '1234', - role: 'moderator' + role: 'moderator', }) }) describe('on something that is not a (Comment|Post|User) ', () => { beforeEach(async () => { variables = { - id: 't23' + id: 't23', } createResource = () => { - return Promise.all([ - factory.create('Tag', { id: 't23' }) - ]) + return Promise.all([factory.create('Tag', { id: 't23' })]) } }) @@ -104,21 +102,28 @@ describe('disable', () => { describe('on a comment', () => { beforeEach(async () => { variables = { - id: 'c47' + id: 'c47', } createPostVariables = { id: 'p3', title: 'post to comment on', - content: 'please comment on me' + content: 'please comment on me', } createCommentVariables = { id: 'c47', postId: 'p3', - content: 'this comment was created for this post' + content: 'this comment was created for this post', } createResource = async () => { - await factory.create('User', { id: 'u45', email: 'commenter@example.org', password: '1234' }) - const asAuthenticatedUser = await factory.authenticateAs({ email: 'commenter@example.org', password: '1234' }) + await factory.create('User', { + id: 'u45', + email: 'commenter@example.org', + password: '1234', + }) + const asAuthenticatedUser = await factory.authenticateAs({ + email: 'commenter@example.org', + password: '1234', + }) await asAuthenticatedUser.create('Post', createPostVariables) await asAuthenticatedUser.create('Comment', createCommentVariables) } @@ -135,41 +140,39 @@ describe('disable', () => { const expected = { Comment: [{ id: 'c47', disabledBy: { id: 'u7' } }] } await setup() - await expect(client.request( - '{ Comment { id, disabledBy { id } } }' - )).resolves.toEqual(before) + await expect(client.request('{ Comment { id, disabledBy { id } } }')).resolves.toEqual( + before, + ) await action() - await expect(client.request( - '{ Comment(disabled: true) { id, disabledBy { id } } }' - )).resolves.toEqual(expected) + await expect( + client.request('{ Comment(disabled: true) { id, disabledBy { id } } }'), + ).resolves.toEqual(expected) }) it('updates .disabled on comment', async () => { - const before = { Comment: [ { id: 'c47', disabled: false } ] } - const expected = { Comment: [ { id: 'c47', disabled: true } ] } + const before = { Comment: [{ id: 'c47', disabled: false }] } + const expected = { Comment: [{ id: 'c47', disabled: true }] } await setup() - await expect(client.request( - '{ Comment { id disabled } }' - )).resolves.toEqual(before) + await expect(client.request('{ Comment { id disabled } }')).resolves.toEqual(before) await action() - await expect(client.request( - '{ Comment(disabled: true) { id disabled } }' - )).resolves.toEqual(expected) + await expect( + client.request('{ Comment(disabled: true) { id disabled } }'), + ).resolves.toEqual(expected) }) }) describe('on a post', () => { beforeEach(async () => { variables = { - id: 'p9' + id: 'p9', } createResource = async () => { await factory.create('User', { email: 'author@example.org', password: '1234' }) await factory.authenticateAs({ email: 'author@example.org', password: '1234' }) await factory.create('Post', { - id: 'p9' // that's the ID we will look for + id: 'p9', // that's the ID we will look for }) } }) @@ -185,27 +188,25 @@ describe('disable', () => { const expected = { Post: [{ id: 'p9', disabledBy: { id: 'u7' } }] } await setup() - await expect(client.request( - '{ Post { id, disabledBy { id } } }' - )).resolves.toEqual(before) + await expect(client.request('{ Post { id, disabledBy { id } } }')).resolves.toEqual( + before, + ) await action() - await expect(client.request( - '{ Post(disabled: true) { id, disabledBy { id } } }' - )).resolves.toEqual(expected) + await expect( + client.request('{ Post(disabled: true) { id, disabledBy { id } } }'), + ).resolves.toEqual(expected) }) it('updates .disabled on post', async () => { - const before = { Post: [ { id: 'p9', disabled: false } ] } - const expected = { Post: [ { id: 'p9', disabled: true } ] } + const before = { Post: [{ id: 'p9', disabled: false }] } + const expected = { Post: [{ id: 'p9', disabled: true }] } await setup() - await expect(client.request( - '{ Post { id disabled } }' - )).resolves.toEqual(before) + await expect(client.request('{ Post { id disabled } }')).resolves.toEqual(before) await action() - await expect(client.request( - '{ Post(disabled: true) { id disabled } }' - )).resolves.toEqual(expected) + await expect(client.request('{ Post(disabled: true) { id disabled } }')).resolves.toEqual( + expected, + ) }) }) }) @@ -227,7 +228,7 @@ describe('enable', () => { beforeEach(() => { // our defaul set of variables variables = { - id: 'blabla' + id: 'blabla', } }) @@ -240,7 +241,7 @@ describe('enable', () => { beforeEach(() => { authenticateClient = setupAuthenticateClient({ email: 'user@example.org', - password: '1234' + password: '1234', }) }) @@ -254,20 +255,18 @@ describe('enable', () => { authenticateClient = setupAuthenticateClient({ role: 'moderator', email: 'someUser@example.org', - password: '1234' + password: '1234', }) }) describe('on something that is not a (Comment|Post|User) ', () => { beforeEach(async () => { variables = { - id: 't23' + id: 't23', } createResource = () => { // we cannot create a :DISABLED relationship here - return Promise.all([ - factory.create('Tag', { id: 't23' }) - ]) + return Promise.all([factory.create('Tag', { id: 't23' })]) } }) @@ -281,21 +280,28 @@ describe('enable', () => { describe('on a comment', () => { beforeEach(async () => { variables = { - id: 'c456' + id: 'c456', } createPostVariables = { id: 'p9', title: 'post to comment on', - content: 'please comment on me' + content: 'please comment on me', } createCommentVariables = { id: 'c456', postId: 'p9', - content: 'this comment was created for this post' + content: 'this comment was created for this post', } createResource = async () => { - await factory.create('User', { id: 'u123', email: 'author@example.org', password: '1234' }) - const asAuthenticatedUser = await factory.authenticateAs({ email: 'author@example.org', password: '1234' }) + await factory.create('User', { + id: 'u123', + email: 'author@example.org', + password: '1234', + }) + const asAuthenticatedUser = await factory.authenticateAs({ + email: 'author@example.org', + password: '1234', + }) await asAuthenticatedUser.create('Post', createPostVariables) await asAuthenticatedUser.create('Comment', createCommentVariables) @@ -319,41 +325,43 @@ describe('enable', () => { const expected = { Comment: [{ id: 'c456', disabledBy: null }] } await setup() - await expect(client.request( - '{ Comment(disabled: true) { id, disabledBy { id } } }' - )).resolves.toEqual(before) + await expect( + client.request('{ Comment(disabled: true) { id, disabledBy { id } } }'), + ).resolves.toEqual(before) await action() - await expect(client.request( - '{ Comment { id, disabledBy { id } } }' - )).resolves.toEqual(expected) + await expect(client.request('{ Comment { id, disabledBy { id } } }')).resolves.toEqual( + expected, + ) }) it('updates .disabled on post', async () => { - const before = { Comment: [ { id: 'c456', disabled: true } ] } - const expected = { Comment: [ { id: 'c456', disabled: false } ] } + const before = { Comment: [{ id: 'c456', disabled: true }] } + const expected = { Comment: [{ id: 'c456', disabled: false }] } await setup() - await expect(client.request( - '{ Comment(disabled: true) { id disabled } }' - )).resolves.toEqual(before) + await expect( + client.request('{ Comment(disabled: true) { id disabled } }'), + ).resolves.toEqual(before) await action() // this updates .disabled - await expect(client.request( - '{ Comment { id disabled } }' - )).resolves.toEqual(expected) + await expect(client.request('{ Comment { id disabled } }')).resolves.toEqual(expected) }) }) describe('on a post', () => { beforeEach(async () => { variables = { - id: 'p9' + id: 'p9', } createResource = async () => { - await factory.create('User', { id: 'u123', email: 'author@example.org', password: '1234' }) + await factory.create('User', { + id: 'u123', + email: 'author@example.org', + password: '1234', + }) await factory.authenticateAs({ email: 'author@example.org', password: '1234' }) await factory.create('Post', { - id: 'p9' // that's the ID we will look for + id: 'p9', // that's the ID we will look for }) const disableMutation = ` @@ -376,27 +384,25 @@ describe('enable', () => { const expected = { Post: [{ id: 'p9', disabledBy: null }] } await setup() - await expect(client.request( - '{ Post(disabled: true) { id, disabledBy { id } } }' - )).resolves.toEqual(before) + await expect( + client.request('{ Post(disabled: true) { id, disabledBy { id } } }'), + ).resolves.toEqual(before) await action() - await expect(client.request( - '{ Post { id, disabledBy { id } } }' - )).resolves.toEqual(expected) + await expect(client.request('{ Post { id, disabledBy { id } } }')).resolves.toEqual( + expected, + ) }) it('updates .disabled on post', async () => { - const before = { Post: [ { id: 'p9', disabled: true } ] } - const expected = { Post: [ { id: 'p9', disabled: false } ] } + const before = { Post: [{ id: 'p9', disabled: true }] } + const expected = { Post: [{ id: 'p9', disabled: false }] } await setup() - await expect(client.request( - '{ Post(disabled: true) { id disabled } }' - )).resolves.toEqual(before) + await expect(client.request('{ Post(disabled: true) { id disabled } }')).resolves.toEqual( + before, + ) await action() // this updates .disabled - await expect(client.request( - '{ Post { id disabled } }' - )).resolves.toEqual(expected) + await expect(client.request('{ Post { id disabled } }')).resolves.toEqual(expected) }) }) }) diff --git a/backend/src/resolvers/notifications.js b/backend/src/resolvers/notifications.js index bc3da0acf..ddc1985cf 100644 --- a/backend/src/resolvers/notifications.js +++ b/backend/src/resolvers/notifications.js @@ -4,11 +4,11 @@ export default { Query: { Notification: (object, params, context, resolveInfo) => { return neo4jgraphql(object, params, context, resolveInfo, false) - } + }, }, Mutation: { UpdateNotification: (object, params, context, resolveInfo) => { return neo4jgraphql(object, params, context, resolveInfo, false) - } - } + }, + }, } diff --git a/backend/src/resolvers/notifications.spec.js b/backend/src/resolvers/notifications.spec.js index 799bc1594..37d8c83ff 100644 --- a/backend/src/resolvers/notifications.spec.js +++ b/backend/src/resolvers/notifications.spec.js @@ -1,4 +1,3 @@ - import Factory from '../seed/factories' import { GraphQLClient } from 'graphql-request' import { host, login } from '../jest/helpers' @@ -8,7 +7,7 @@ let client let userParams = { id: 'you', email: 'test@example.org', - password: '1234' + password: '1234', } beforeEach(async () => { @@ -49,12 +48,12 @@ describe('currentUser { notifications }', () => { const neighborParams = { email: 'neighbor@example.org', password: '1234', - id: 'neighbor' + id: 'neighbor', } await Promise.all([ factory.create('User', neighborParams), factory.create('Notification', { id: 'not-for-you' }), - factory.create('Notification', { id: 'already-seen', read: true }) + factory.create('Notification', { id: 'already-seen', read: true }), ]) await factory.create('Notification', { id: 'unseen' }) await factory.authenticateAs(neighborParams) @@ -65,7 +64,7 @@ describe('currentUser { notifications }', () => { factory.relate('Notification', 'User', { from: 'unseen', to: 'you' }), factory.relate('Notification', 'Post', { from: 'p1', to: 'unseen' }), factory.relate('Notification', 'User', { from: 'already-seen', to: 'you' }), - factory.relate('Notification', 'Post', { from: 'p1', to: 'already-seen' }) + factory.relate('Notification', 'Post', { from: 'p1', to: 'already-seen' }), ]) }) @@ -84,10 +83,8 @@ describe('currentUser { notifications }', () => { it('returns only unread notifications of current user', async () => { const expected = { currentUser: { - notifications: [ - { id: 'unseen', post: { id: 'p1' } } - ] - } + notifications: [{ id: 'unseen', post: { id: 'p1' } }], + }, } await expect(client.request(query, variables)).resolves.toEqual(expected) }) @@ -109,9 +106,9 @@ describe('currentUser { notifications }', () => { currentUser: { notifications: [ { id: 'unseen', post: { id: 'p1' } }, - { id: 'already-seen', post: { id: 'p1' } } - ] - } + { id: 'already-seen', post: { id: 'p1' } }, + ], + }, } await expect(client.request(query, variables)).resolves.toEqual(expected) }) @@ -136,7 +133,7 @@ describe('UpdateNotification', () => { id: 'mentioned-1', email: 'mentioned@example.org', password: '1234', - slug: 'mentioned' + slug: 'mentioned', } await factory.create('User', mentionedParams) await factory.create('Notification', { id: 'to-be-updated' }) @@ -144,7 +141,7 @@ describe('UpdateNotification', () => { await factory.create('Post', { id: 'p1' }) await Promise.all([ factory.relate('Notification', 'User', { from: 'to-be-updated', to: 'mentioned-1' }), - factory.relate('Notification', 'Post', { from: 'p1', to: 'to-be-updated' }) + factory.relate('Notification', 'Post', { from: 'p1', to: 'to-be-updated' }), ]) }) diff --git a/backend/src/resolvers/posts.js b/backend/src/resolvers/posts.js index 5b06c38fa..e4d0d6876 100644 --- a/backend/src/resolvers/posts.js +++ b/backend/src/resolvers/posts.js @@ -8,15 +8,16 @@ export default { const session = context.driver.session() await session.run( 'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' + - 'MERGE (post)<-[:WROTE]-(author) ' + - 'RETURN author', { + 'MERGE (post)<-[:WROTE]-(author) ' + + 'RETURN author', + { userId: context.user.id, - postId: result.id - } + postId: result.id, + }, ) session.close() return result - } - } + }, + }, } diff --git a/backend/src/resolvers/posts.spec.js b/backend/src/resolvers/posts.spec.js index 5603683eb..e4175ff09 100644 --- a/backend/src/resolvers/posts.spec.js +++ b/backend/src/resolvers/posts.spec.js @@ -8,7 +8,7 @@ let client beforeEach(async () => { await factory.create('User', { email: 'test@example.org', - password: '1234' + password: '1234', }) }) @@ -47,22 +47,25 @@ describe('CreatePost', () => { const expected = { CreatePost: { title: 'I am a title', - content: 'Some content' - } + content: 'Some content', + }, } await expect(client.request(mutation)).resolves.toMatchObject(expected) }) it('assigns the authenticated user as author', async () => { await client.request(mutation) - const { User } = await client.request(`{ + const { User } = await client.request( + `{ User(email:"test@example.org") { contributions { title } } - }`, { headers }) - expect(User).toEqual([ { contributions: [ { title: 'I am a title' } ] } ]) + }`, + { headers }, + ) + expect(User).toEqual([{ contributions: [{ title: 'I am a title' }] }]) }) describe('disabled and deleted', () => { @@ -86,22 +89,22 @@ describe('UpdatePost', () => { let variables = { id: 'p1', - content: 'New content' + content: 'New content', } beforeEach(async () => { const asAuthor = Factory() await asAuthor.create('User', { email: 'author@example.org', - password: '1234' + password: '1234', }) await asAuthor.authenticateAs({ email: 'author@example.org', - password: '1234' + password: '1234', }) await asAuthor.create('Post', { id: 'p1', - content: 'Old content' + content: 'Old content', }) }) @@ -149,22 +152,22 @@ describe('DeletePost', () => { ` let variables = { - id: 'p1' + id: 'p1', } beforeEach(async () => { const asAuthor = Factory() await asAuthor.create('User', { email: 'author@example.org', - password: '1234' + password: '1234', }) await asAuthor.authenticateAs({ email: 'author@example.org', - password: '1234' + password: '1234', }) await asAuthor.create('Post', { id: 'p1', - content: 'To be deleted' + content: 'To be deleted', }) }) diff --git a/backend/src/resolvers/reports.js b/backend/src/resolvers/reports.js index fb912a557..2c0fbfc75 100644 --- a/backend/src/resolvers/reports.js +++ b/backend/src/resolvers/reports.js @@ -7,11 +7,12 @@ export default { const session = driver.session() const reportData = { id: reportId, - createdAt: (new Date()).toISOString(), - description: description + createdAt: new Date().toISOString(), + description: description, } - const res = await session.run(` + const res = await session.run( + ` MATCH (submitter:User {id: $userId}) MATCH (resource {id: $resourceId}) WHERE resource:User OR resource:Comment OR resource:Post @@ -19,11 +20,12 @@ export default { MERGE (resource)<-[:REPORTED]-(report) MERGE (report)<-[:REPORTED]-(submitter) RETURN report, submitter, resource, labels(resource)[0] as type - `, { - resourceId: id, - userId: user.id, - reportData - } + `, + { + resourceId: id, + userId: user.id, + reportData, + }, ) session.close() @@ -32,7 +34,7 @@ export default { report: r.get('report'), submitter: r.get('submitter'), resource: r.get('resource'), - type: r.get('type') + type: r.get('type'), } }) if (!dbResponse) return null @@ -44,20 +46,20 @@ export default { comment: null, user: null, submitter: submitter.properties, - type + type, } switch (type) { - case 'Post': - response.post = resource.properties - break - case 'Comment': - response.comment = resource.properties - break - case 'User': - response.user = resource.properties - break + case 'Post': + response.post = resource.properties + break + case 'Comment': + response.comment = resource.properties + break + case 'User': + response.user = resource.properties + break } return response - } - } + }, + }, } diff --git a/backend/src/resolvers/reports.spec.js b/backend/src/resolvers/reports.spec.js index 9bd1fe753..19b5e6f9e 100644 --- a/backend/src/resolvers/reports.spec.js +++ b/backend/src/resolvers/reports.spec.js @@ -18,13 +18,13 @@ describe('report', () => { await factory.create('User', { id: 'u1', email: 'test@example.org', - password: '1234' + password: '1234', }) await factory.create('User', { id: 'u2', name: 'abusive-user', role: 'user', - email: 'abusive-user@example.org' + email: 'abusive-user@example.org', }) }) @@ -59,7 +59,7 @@ describe('report', () => { describe('invalid resource id', () => { it('returns null', async () => { await expect(action()).resolves.toEqual({ - report: null + report: null, }) }) }) @@ -71,14 +71,14 @@ describe('report', () => { it('creates a report', async () => { await expect(action()).resolves.toEqual({ - report: { description: 'Violates code of conduct' } + report: { description: 'Violates code of conduct' }, }) }) it('returns the submitter', async () => { returnedObject = '{ submitter { email } }' await expect(action()).resolves.toEqual({ - report: { submitter: { email: 'test@example.org' } } + report: { submitter: { email: 'test@example.org' } }, }) }) @@ -86,14 +86,14 @@ describe('report', () => { it('returns type "User"', async () => { returnedObject = '{ type }' await expect(action()).resolves.toEqual({ - report: { type: 'User' } + report: { type: 'User' }, }) }) it('returns resource in user attribute', async () => { returnedObject = '{ user { name } }' await expect(action()).resolves.toEqual({ - report: { user: { name: 'abusive-user' } } + report: { user: { name: 'abusive-user' } }, }) }) }) @@ -101,28 +101,31 @@ describe('report', () => { describe('reported resource is a post', () => { beforeEach(async () => { await factory.authenticateAs({ email: 'test@example.org', password: '1234' }) - await factory.create('Post', { id: 'p23', title: 'Matt and Robert having a pair-programming' }) + await factory.create('Post', { + id: 'p23', + title: 'Matt and Robert having a pair-programming', + }) variables = { id: 'p23' } }) it('returns type "Post"', async () => { returnedObject = '{ type }' await expect(action()).resolves.toEqual({ - report: { type: 'Post' } + report: { type: 'Post' }, }) }) it('returns resource in post attribute', async () => { returnedObject = '{ post { title } }' await expect(action()).resolves.toEqual({ - report: { post: { title: 'Matt and Robert having a pair-programming' } } + report: { post: { title: 'Matt and Robert having a pair-programming' } }, }) }) it('returns null in user attribute', async () => { returnedObject = '{ user { name } }' await expect(action()).resolves.toEqual({ - report: { user: null } + report: { user: null }, }) }) }) @@ -132,25 +135,32 @@ describe('report', () => { createPostVariables = { id: 'p1', title: 'post to comment on', - content: 'please comment on me' + content: 'please comment on me', } - const asAuthenticatedUser = await factory.authenticateAs({ email: 'test@example.org', password: '1234' }) + const asAuthenticatedUser = await factory.authenticateAs({ + email: 'test@example.org', + password: '1234', + }) await asAuthenticatedUser.create('Post', createPostVariables) - await asAuthenticatedUser.create('Comment', { postId: 'p1', id: 'c34', content: 'Robert getting tired.' }) + await asAuthenticatedUser.create('Comment', { + postId: 'p1', + id: 'c34', + content: 'Robert getting tired.', + }) variables = { id: 'c34' } }) it('returns type "Comment"', async () => { returnedObject = '{ type }' await expect(action()).resolves.toEqual({ - report: { type: 'Comment' } + report: { type: 'Comment' }, }) }) it('returns resource in comment attribute', async () => { returnedObject = '{ comment { content } }' await expect(action()).resolves.toEqual({ - report: { comment: { content: 'Robert getting tired.' } } + report: { comment: { content: 'Robert getting tired.' } }, }) }) }) diff --git a/backend/src/resolvers/rewards.js b/backend/src/resolvers/rewards.js index a7a8c1ab7..ec5043da3 100644 --- a/backend/src/resolvers/rewards.js +++ b/backend/src/resolvers/rewards.js @@ -10,8 +10,8 @@ export default { RETURN rewardedUser {.id}`, { badgeId: fromBadgeId, - rewardedUserId: toUserId - } + rewardedUserId: toUserId, + }, ) const [rewardedUser] = transactionRes.records.map(record => { @@ -33,8 +33,8 @@ export default { RETURN rewardedUser {.id}`, { badgeId: fromBadgeId, - rewardedUserId: toUserId - } + rewardedUserId: toUserId, + }, ) const [rewardedUser] = transactionRes.records.map(record => { return record.get('rewardedUser') @@ -42,6 +42,6 @@ export default { session.close() return rewardedUser.id - } - } + }, + }, } diff --git a/backend/src/resolvers/rewards.spec.js b/backend/src/resolvers/rewards.spec.js index 567228eca..e2b67b25d 100644 --- a/backend/src/resolvers/rewards.spec.js +++ b/backend/src/resolvers/rewards.spec.js @@ -10,24 +10,24 @@ describe('rewards', () => { id: 'u1', role: 'user', email: 'user@example.org', - password: '1234' + password: '1234', }) await factory.create('User', { id: 'u2', role: 'moderator', - email: 'moderator@example.org' + email: 'moderator@example.org', }) await factory.create('User', { id: 'u3', role: 'admin', - email: 'admin@example.org' + email: 'admin@example.org', }) await factory.create('Badge', { id: 'b6', key: 'indiegogo_en_rhino', type: 'crowdfunding', status: 'permanent', - icon: '/img/badges/indiegogo_en_rhino.svg' + icon: '/img/badges/indiegogo_en_rhino.svg', }) }) @@ -48,15 +48,13 @@ describe('rewards', () => { describe('unauthenticated', () => { const variables = { from: 'b6', - to: 'u1' + to: 'u1', } let client it('throws authorization error', async () => { client = new GraphQLClient(host) - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -70,14 +68,12 @@ describe('rewards', () => { it('rewards a badge to user', async () => { const variables = { from: 'b6', - to: 'u1' + to: 'u1', } const expected = { - reward: 'u1' + reward: 'u1', } - await expect( - client.request(mutation, variables) - ).resolves.toEqual(expected) + await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) it('rewards a second different badge to same user', async () => { await factory.create('Badge', { @@ -85,41 +81,37 @@ describe('rewards', () => { key: 'indiegogo_en_racoon', type: 'crowdfunding', status: 'permanent', - icon: '/img/badges/indiegogo_en_racoon.svg' + icon: '/img/badges/indiegogo_en_racoon.svg', }) const variables = { from: 'b1', - to: 'u1' + to: 'u1', } const expected = { - reward: 'u1' + reward: 'u1', } - await expect( - client.request(mutation, variables) - ).resolves.toEqual(expected) + await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) it('rewards the same badge as well to another user', async () => { const variables1 = { from: 'b6', - to: 'u1' + to: 'u1', } await client.request(mutation, variables1) const variables2 = { from: 'b6', - to: 'u2' + to: 'u2', } const expected = { - reward: 'u2' + reward: 'u2', } - await expect( - client.request(mutation, variables2) - ).resolves.toEqual(expected) + await expect(client.request(mutation, variables2)).resolves.toEqual(expected) }) it('returns the original reward if a reward is attempted a second time', async () => { const variables = { from: 'b6', - to: 'u1' + to: 'u1', } await client.request(mutation, variables) await client.request(mutation, variables) @@ -132,16 +124,14 @@ describe('rewards', () => { ` const expected = { User: [{ badgesCount: 1 }] } - await expect( - client.request(query) - ).resolves.toEqual(expected) + await expect(client.request(query)).resolves.toEqual(expected) }) }) describe('authenticated moderator', () => { const variables = { from: 'b6', - to: 'u1' + to: 'u1', } let client beforeEach(async () => { @@ -151,9 +141,7 @@ describe('rewards', () => { describe('rewards bage to user', () => { it('throws authorization error', async () => { - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) }) @@ -165,10 +153,10 @@ describe('rewards', () => { }) const variables = { from: 'b6', - to: 'u1' + to: 'u1', } const expected = { - unreward: 'u1' + unreward: 'u1', } const mutation = ` @@ -185,9 +173,7 @@ describe('rewards', () => { it('throws authorization error', async () => { client = new GraphQLClient(host) - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) @@ -199,17 +185,15 @@ describe('rewards', () => { }) it('removes a badge from user', async () => { - await expect( - client.request(mutation, variables) - ).resolves.toEqual(expected) + await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) it('fails to remove a not existing badge from user', async () => { await client.request(mutation, variables) - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Cannot read property \'id\' of undefined') + await expect(client.request(mutation, variables)).rejects.toThrow( + "Cannot read property 'id' of undefined", + ) }) }) @@ -222,9 +206,7 @@ describe('rewards', () => { describe('removes bage from user', () => { it('throws authorization error', async () => { - await expect( - client.request(mutation, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') }) }) }) diff --git a/backend/src/resolvers/shout.js b/backend/src/resolvers/shout.js index 69c39a3a9..d2d7f652e 100644 --- a/backend/src/resolvers/shout.js +++ b/backend/src/resolvers/shout.js @@ -12,8 +12,8 @@ export default { { id, type, - userId: context.user.id - } + userId: context.user.id, + }, ) const [isShouted] = transactionRes.records.map(record => { @@ -37,8 +37,8 @@ export default { { id, type, - userId: context.user.id - } + userId: context.user.id, + }, ) const [isShouted] = transactionRes.records.map(record => { return record.get('isShouted') @@ -46,6 +46,6 @@ export default { session.close() return isShouted - } - } + }, + }, } diff --git a/backend/src/resolvers/shout.spec.js b/backend/src/resolvers/shout.spec.js index 88866a74f..46570efa0 100644 --- a/backend/src/resolvers/shout.spec.js +++ b/backend/src/resolvers/shout.spec.js @@ -6,12 +6,12 @@ const factory = Factory() let clientUser1, clientUser2 let headersUser1, headersUser2 -const mutationShoutPost = (id) => ` +const mutationShoutPost = id => ` mutation { shout(id: "${id}", type: Post) } ` -const mutationUnshoutPost = (id) => ` +const mutationUnshoutPost = id => ` mutation { unshout(id: "${id}", type: Post) } @@ -21,12 +21,12 @@ beforeEach(async () => { await factory.create('User', { id: 'u1', email: 'test@example.org', - password: '1234' + password: '1234', }) await factory.create('User', { id: 'u2', email: 'test2@example.org', - password: '1234' + password: '1234', }) headersUser1 = await login({ email: 'test@example.org', password: '1234' }) @@ -62,18 +62,14 @@ describe('shout', () => { it('throws authorization error', async () => { let client client = new GraphQLClient(host) - await expect( - client.request(mutationShoutPost('p1')) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutationShoutPost('p1'))).rejects.toThrow('Not Authorised') }) }) it('I shout a post of another user', async () => { - const res = await clientUser1.request( - mutationShoutPost('p2') - ) + const res = await clientUser1.request(mutationShoutPost('p2')) const expected = { - shout: true + shout: true, } expect(res).toMatchObject(expected) @@ -83,17 +79,15 @@ describe('shout', () => { } }`) const expected2 = { - shoutedByCurrentUser: true + shoutedByCurrentUser: true, } expect(Post[0]).toMatchObject(expected2) }) it('I can`t shout my own post', async () => { - const res = await clientUser1.request( - mutationShoutPost('p1') - ) + const res = await clientUser1.request(mutationShoutPost('p1')) const expected = { - shout: false + shout: false, } expect(res).toMatchObject(expected) @@ -103,7 +97,7 @@ describe('shout', () => { } }`) const expected2 = { - shoutedByCurrentUser: false + shoutedByCurrentUser: false, } expect(Post[0]).toMatchObject(expected2) }) @@ -113,25 +107,19 @@ describe('shout', () => { describe('unauthenticated shout', () => { it('throws authorization error', async () => { // shout - await clientUser1.request( - mutationShoutPost('p2') - ) + await clientUser1.request(mutationShoutPost('p2')) // unshout let client client = new GraphQLClient(host) - await expect( - client.request(mutationUnshoutPost('p2')) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutationUnshoutPost('p2'))).rejects.toThrow('Not Authorised') }) }) it('I unshout a post of another user', async () => { // shout - await clientUser1.request( - mutationShoutPost('p2') - ) + await clientUser1.request(mutationShoutPost('p2')) const expected = { - unshout: true + unshout: true, } // unshout const res = await clientUser1.request(mutationUnshoutPost('p2')) @@ -143,7 +131,7 @@ describe('shout', () => { } }`) const expected2 = { - shoutedByCurrentUser: false + shoutedByCurrentUser: false, } expect(Post[0]).toMatchObject(expected2) }) diff --git a/backend/src/resolvers/socialMedia.js b/backend/src/resolvers/socialMedia.js index ef143a478..0bc03ea74 100644 --- a/backend/src/resolvers/socialMedia.js +++ b/backend/src/resolvers/socialMedia.js @@ -5,16 +5,17 @@ export default { CreateSocialMedia: async (object, params, context, resolveInfo) => { /** * TODO?: Creates double Nodes! - */ + */ const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, false) const session = context.driver.session() await session.run( `MATCH (owner:User {id: $userId}), (socialMedia:SocialMedia {id: $socialMediaId}) MERGE (socialMedia)<-[:OWNED]-(owner) - RETURN owner`, { + RETURN owner`, + { userId: context.user.id, - socialMediaId: socialMedia.id - } + socialMediaId: socialMedia.id, + }, ) session.close() @@ -24,6 +25,6 @@ export default { const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, false) return socialMedia - } - } + }, + }, } diff --git a/backend/src/resolvers/socialMedia.spec.js b/backend/src/resolvers/socialMedia.spec.js index 9d1d76726..5143587b1 100644 --- a/backend/src/resolvers/socialMedia.spec.js +++ b/backend/src/resolvers/socialMedia.spec.js @@ -31,7 +31,7 @@ describe('CreateSocialMedia', () => { slug: 'matilde-hermiston', role: 'user', email: 'test@example.org', - password: '1234' + password: '1234', }) }) @@ -43,9 +43,7 @@ describe('CreateSocialMedia', () => { it('throws authorization error', async () => { client = new GraphQLClient(host) const variables = { url: 'http://nsosp.org' } - await expect( - client.request(mutationC, variables) - ).rejects.toThrow('Not Authorised') + await expect(client.request(mutationC, variables)).rejects.toThrow('Not Authorised') }) }) @@ -57,14 +55,14 @@ describe('CreateSocialMedia', () => { it('creates social media with correct URL', async () => { const variables = { url: 'http://nsosp.org' } - await expect( - client.request(mutationC, variables) - ).resolves.toEqual(expect.objectContaining({ - CreateSocialMedia: { - id: expect.any(String), - url: 'http://nsosp.org' - } - })) + await expect(client.request(mutationC, variables)).resolves.toEqual( + expect.objectContaining({ + CreateSocialMedia: { + id: expect.any(String), + url: 'http://nsosp.org', + }, + }), + ) }) it('deletes social media', async () => { @@ -76,26 +74,20 @@ describe('CreateSocialMedia', () => { const expected = { DeleteSocialMedia: { id: id, - url: 'http://nsosp.org' - } + url: 'http://nsosp.org', + }, } - await expect( - client.request(mutationD, deletionVariables) - ).resolves.toEqual(expected) + await expect(client.request(mutationD, deletionVariables)).resolves.toEqual(expected) }) it('rejects empty string', async () => { const variables = { url: '' } - await expect( - client.request(mutationC, variables) - ).rejects.toThrow('Input is not a URL') + await expect(client.request(mutationC, variables)).rejects.toThrow('Input is not a URL') }) it('validates URLs', async () => { const variables = { url: 'not-a-url' } - await expect( - client.request(mutationC, variables) - ).rejects.toThrow('Input is not a URL') + await expect(client.request(mutationC, variables)).rejects.toThrow('Input is not a URL') }) }) }) diff --git a/backend/src/resolvers/statistics.js b/backend/src/resolvers/statistics.js index 17c4be956..f09b7219d 100644 --- a/backend/src/resolvers/statistics.js +++ b/backend/src/resolvers/statistics.js @@ -1,24 +1,22 @@ export const query = (cypher, session) => { return new Promise((resolve, reject) => { let data = [] - session - .run(cypher) - .subscribe({ - onNext: function (record) { - let item = {} - record.keys.forEach(key => { - item[key] = record.get(key) - }) - data.push(item) - }, - onCompleted: function () { - session.close() - resolve(data) - }, - onError: function (error) { - reject(error) - } - }) + session.run(cypher).subscribe({ + onNext: function(record) { + let item = {} + record.keys.forEach(key => { + item[key] = record.get(key) + }) + data.push(item) + }, + onCompleted: function() { + session.close() + resolve(data) + }, + onError: function(error) { + reject(error) + }, + }) }) } const queryOne = (cypher, session) => { @@ -36,32 +34,41 @@ const queryOne = (cypher, session) => { export default { Query: { statistics: async (parent, args, { driver, user }) => { - return new Promise(async (resolve) => { + return new Promise(async resolve => { const session = driver.session() const queries = { - countUsers: 'MATCH (r:User) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countUsers', - countPosts: 'MATCH (r:Post) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countPosts', - countComments: 'MATCH (r:Comment) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countComments', - countNotifications: 'MATCH (r:Notification) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countNotifications', - countOrganizations: 'MATCH (r:Organization) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countOrganizations', - countProjects: 'MATCH (r:Project) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countProjects', - countInvites: 'MATCH (r:Invite) WHERE r.wasUsed <> true OR NOT exists(r.wasUsed) RETURN COUNT(r) AS countInvites', + countUsers: + 'MATCH (r:User) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countUsers', + countPosts: + 'MATCH (r:Post) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countPosts', + countComments: + 'MATCH (r:Comment) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countComments', + countNotifications: + 'MATCH (r:Notification) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countNotifications', + countOrganizations: + 'MATCH (r:Organization) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countOrganizations', + countProjects: + 'MATCH (r:Project) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countProjects', + countInvites: + 'MATCH (r:Invite) WHERE r.wasUsed <> true OR NOT exists(r.wasUsed) RETURN COUNT(r) AS countInvites', countFollows: 'MATCH (:User)-[r:FOLLOWS]->(:User) RETURN COUNT(r) AS countFollows', - countShouts: 'MATCH (:User)-[r:SHOUTED]->(:Post) RETURN COUNT(r) AS countShouts' + countShouts: 'MATCH (:User)-[r:SHOUTED]->(:Post) RETURN COUNT(r) AS countShouts', } let data = { countUsers: (await queryOne(queries.countUsers, session)).countUsers.low, countPosts: (await queryOne(queries.countPosts, session)).countPosts.low, countComments: (await queryOne(queries.countComments, session)).countComments.low, - countNotifications: (await queryOne(queries.countNotifications, session)).countNotifications.low, - countOrganizations: (await queryOne(queries.countOrganizations, session)).countOrganizations.low, + countNotifications: (await queryOne(queries.countNotifications, session)) + .countNotifications.low, + countOrganizations: (await queryOne(queries.countOrganizations, session)) + .countOrganizations.low, countProjects: (await queryOne(queries.countProjects, session)).countProjects.low, countInvites: (await queryOne(queries.countInvites, session)).countInvites.low, countFollows: (await queryOne(queries.countFollows, session)).countFollows.low, - countShouts: (await queryOne(queries.countShouts, session)).countShouts.low + countShouts: (await queryOne(queries.countShouts, session)).countShouts.low, } resolve(data) }) - } - } + }, + }, } diff --git a/backend/src/resolvers/user_management.js b/backend/src/resolvers/user_management.js index 26dfb81db..e2fd5acf1 100644 --- a/backend/src/resolvers/user_management.js +++ b/backend/src/resolvers/user_management.js @@ -12,7 +12,7 @@ export default { const { user } = ctx if (!user) return null return neo4jgraphql(object, { id: user.id }, ctx, resolveInfo, false) - } + }, }, Mutation: { signup: async (parent, { email, password }, { req }) => { @@ -34,12 +34,12 @@ export default { 'MATCH (user:User {email: $userEmail}) ' + 'RETURN user {.id, .slug, .name, .avatar, .email, .password, .role, .disabled} as user LIMIT 1', { - userEmail: email - } + userEmail: email, + }, ) session.close() - const [currentUser] = await result.records.map(function (record) { + const [currentUser] = await result.records.map(function(record) { return record.get('user') }) @@ -50,29 +50,23 @@ export default { ) { delete currentUser.password return encode(currentUser) - } else if (currentUser && - currentUser.disabled - ) { + } else if (currentUser && currentUser.disabled) { throw new AuthenticationError('Your account has been disabled.') } else { throw new AuthenticationError('Incorrect email address or password.') } }, - changePassword: async ( - _, - { oldPassword, newPassword }, - { driver, user } - ) => { + changePassword: async (_, { oldPassword, newPassword }, { driver, user }) => { const session = driver.session() let result = await session.run( `MATCH (user:User {email: $userEmail}) RETURN user {.id, .email, .password}`, { - userEmail: user.email - } + userEmail: user.email, + }, ) - const [currentUser] = result.records.map(function (record) { + const [currentUser] = result.records.map(function(record) { return record.get('user') }) @@ -81,9 +75,7 @@ export default { } if (await bcrypt.compareSync(newPassword, currentUser.password)) { - throw new AuthenticationError( - 'Old password and new password should be different' - ) + throw new AuthenticationError('Old password and new password should be different') } else { const newHashedPassword = await bcrypt.hashSync(newPassword, 10) session.run( @@ -93,13 +85,13 @@ export default { `, { userEmail: user.email, - newHashedPassword - } + newHashedPassword, + }, ) session.close() return encode(currentUser) } - } - } + }, + }, } diff --git a/backend/src/resolvers/user_management.spec.js b/backend/src/resolvers/user_management.spec.js index 7c0be08f3..9dff9e388 100644 --- a/backend/src/resolvers/user_management.spec.js +++ b/backend/src/resolvers/user_management.spec.js @@ -24,10 +24,10 @@ const factory = Factory() // } const jennyRostocksHeaders = { authorization: - 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoidXNlciIsImxvY2F0aW9uTmFtZSI6bnVsbCwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJhYm91dCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9zYXNoYV9zaGVzdGFrb3YvMTI4LmpwZyIsImlkIjoidTMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5vcmciLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTU1MDg0NjY4MCwiZXhwIjoxNjM3MjQ2NjgwLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.eZ_mVKas4Wzoc_JrQTEWXyRn7eY64cdIg4vqQ-F_7Jc' + 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoidXNlciIsImxvY2F0aW9uTmFtZSI6bnVsbCwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJhYm91dCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9zYXNoYV9zaGVzdGFrb3YvMTI4LmpwZyIsImlkIjoidTMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5vcmciLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTU1MDg0NjY4MCwiZXhwIjoxNjM3MjQ2NjgwLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.eZ_mVKas4Wzoc_JrQTEWXyRn7eY64cdIg4vqQ-F_7Jc', } -const disable = async (id) => { +const disable = async id => { const moderatorParams = { email: 'moderator@example.org', role: 'moderator', password: '1234' } const asModerator = Factory() await asModerator.create('User', moderatorParams) @@ -43,7 +43,7 @@ beforeEach(async () => { slug: 'matilde-hermiston', role: 'user', email: 'test@example.org', - password: '1234' + password: '1234', }) }) @@ -56,7 +56,7 @@ describe('isLoggedIn', () => { describe('unauthenticated', () => { it('returns false', async () => { await expect(request(host, query)).resolves.toEqual({ - isLoggedIn: false + isLoggedIn: false, }) }) }) @@ -67,7 +67,7 @@ describe('isLoggedIn', () => { it('returns false', async () => { await expect(client.request(query)).resolves.toEqual({ - isLoggedIn: false + isLoggedIn: false, }) }) }) @@ -77,7 +77,7 @@ describe('isLoggedIn', () => { it('returns false', async () => { await expect(client.request(query)).resolves.toEqual({ - isLoggedIn: false + isLoggedIn: false, }) }) @@ -87,7 +87,7 @@ describe('isLoggedIn', () => { // see the decoded token above await factory.create('User', { id: 'u3' }) await expect(client.request(query)).resolves.toEqual({ - isLoggedIn: true + isLoggedIn: true, }) }) }) @@ -100,7 +100,7 @@ describe('isLoggedIn', () => { it('returns false', async () => { await expect(client.request(query)).resolves.toEqual({ - isLoggedIn: false + isLoggedIn: false, }) }) }) @@ -156,8 +156,8 @@ describe('currentUser', () => { id: 'acb2d923-f3af-479e-9f00-61b12e864666', name: 'Matilde Hermiston', slug: 'matilde-hermiston', - role: 'user' - } + role: 'user', + }, } await expect(client.request(query)).resolves.toEqual(expected) }) @@ -181,8 +181,8 @@ describe('login', () => { host, mutation({ email: 'test@example.org', - password: '1234' - }) + password: '1234', + }), ) const token = data.login jwt.verify(token, process.env.JWT_SECRET, (err, data) => { @@ -200,9 +200,9 @@ describe('login', () => { host, mutation({ email: 'test@example.org', - password: '1234' - }) - ) + password: '1234', + }), + ), ).rejects.toThrow('Your account has been disabled.') }) }) @@ -214,9 +214,9 @@ describe('login', () => { host, mutation({ email: 'test@example.org', - password: 'wrong' - }) - ) + password: 'wrong', + }), + ), ).rejects.toThrow('Incorrect email address or password.') }) }) @@ -228,9 +228,9 @@ describe('login', () => { host, mutation({ email: 'non-existent@example.org', - password: 'wrong' - }) - ) + password: 'wrong', + }), + ), ).rejects.toThrow('Incorrect email address or password.') }) }) @@ -261,9 +261,9 @@ describe('change password', () => { host, mutation({ oldPassword: '1234', - newPassword: '1234' - }) - ) + newPassword: '1234', + }), + ), ).rejects.toThrow('Not Authorised!') }) }) @@ -274,9 +274,9 @@ describe('change password', () => { client.request( mutation({ oldPassword: '1234', - newPassword: '1234' - }) - ) + newPassword: '1234', + }), + ), ).rejects.toThrow('Old password and new password should be different') }) }) @@ -287,9 +287,9 @@ describe('change password', () => { client.request( mutation({ oldPassword: 'notOldPassword', - newPassword: '12345' - }) - ) + newPassword: '12345', + }), + ), ).rejects.toThrow('Old password is not correct') }) }) @@ -299,14 +299,14 @@ describe('change password', () => { let response = await client.request( mutation({ oldPassword: '1234', - newPassword: '12345' - }) + newPassword: '12345', + }), + ) + await expect(response).toEqual( + expect.objectContaining({ + changePassword: expect.any(String), + }), ) - await expect( - response - ).toEqual(expect.objectContaining({ - changePassword: expect.any(String) - })) }) }) }) @@ -320,14 +320,16 @@ describe('do not expose private RSA key', () => { id publicKey } - }` + } + ` const queryUserPrivateKey = gql` query($queriedUserSlug: String) { User(slug: $queriedUserSlug) { id privateKey } - }` + } + ` const actionGenUserWithKeys = async () => { // Generate user with "privateKey" via 'CreateUser' mutation instead of using the factories "factory.create('User', {...})", see above. @@ -336,14 +338,17 @@ describe('do not expose private RSA key', () => { password: 'xYz', slug: 'apfel-strudel', name: 'Apfel Strudel', - email: 'apfel-strudel@test.org' + email: 'apfel-strudel@test.org', } - await client.request(gql` - mutation($id: ID, $password: String!, $slug: String, $name: String, $email: String!) { - CreateUser(id: $id, password: $password, slug: $slug, name: $name, email: $email) { - id + await client.request( + gql` + mutation($id: ID, $password: String!, $slug: String, $name: String, $email: String!) { + CreateUser(id: $id, password: $password, slug: $slug, name: $name, email: $email) { + id + } } - }`, variables + `, + variables, ) } @@ -356,13 +361,17 @@ describe('do not expose private RSA key', () => { it('returns publicKey', async () => { await actionGenUserWithKeys() await expect( - await client.request(queryUserPuplicKey, { queriedUserSlug: 'apfel-strudel' }) - ).toEqual(expect.objectContaining({ - User: [{ - id: 'bcb2d923-f3af-479e-9f00-61b12e864667', - publicKey: expect.any(String) - }] - })) + await client.request(queryUserPuplicKey, { queriedUserSlug: 'apfel-strudel' }), + ).toEqual( + expect.objectContaining({ + User: [ + { + id: 'bcb2d923-f3af-479e-9f00-61b12e864667', + publicKey: expect.any(String), + }, + ], + }), + ) }) }) @@ -370,7 +379,7 @@ describe('do not expose private RSA key', () => { it('throws "Not Authorised!"', async () => { await actionGenUserWithKeys() await expect( - client.request(queryUserPrivateKey, { queriedUserSlug: 'apfel-strudel' }) + client.request(queryUserPrivateKey, { queriedUserSlug: 'apfel-strudel' }), ).rejects.toThrow('Not Authorised') }) }) @@ -385,13 +394,17 @@ describe('do not expose private RSA key', () => { it('returns publicKey', async () => { await actionGenUserWithKeys() await expect( - await client.request(queryUserPuplicKey, { queriedUserSlug: 'apfel-strudel' }) - ).toEqual(expect.objectContaining({ - User: [{ - id: 'bcb2d923-f3af-479e-9f00-61b12e864667', - publicKey: expect.any(String) - }] - })) + await client.request(queryUserPuplicKey, { queriedUserSlug: 'apfel-strudel' }), + ).toEqual( + expect.objectContaining({ + User: [ + { + id: 'bcb2d923-f3af-479e-9f00-61b12e864667', + publicKey: expect.any(String), + }, + ], + }), + ) }) }) @@ -399,7 +412,7 @@ describe('do not expose private RSA key', () => { it('throws "Not Authorised!"', async () => { await actionGenUserWithKeys() await expect( - client.request(queryUserPrivateKey, { queriedUserSlug: 'apfel-strudel' }) + client.request(queryUserPrivateKey, { queriedUserSlug: 'apfel-strudel' }), ).rejects.toThrow('Not Authorised') }) }) diff --git a/backend/src/resolvers/users.spec.js b/backend/src/resolvers/users.spec.js index 48e4741d7..bf55784fd 100644 --- a/backend/src/resolvers/users.spec.js +++ b/backend/src/resolvers/users.spec.js @@ -24,15 +24,14 @@ describe('users', () => { const variables = { name: 'John Doe', password: '123', - email: '123@123.de' + email: '123@123.de', } const expected = { CreateUser: { - id: expect.any(String) - } + id: expect.any(String), + }, } - await expect(client.request(mutation, variables)) - .resolves.toEqual(expected) + await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) }) @@ -54,35 +53,32 @@ describe('users', () => { it('name within specifications', async () => { const variables = { id: 'u47', - name: 'James Doe' + name: 'James Doe', } const expected = { UpdateUser: { id: 'u47', - name: 'James Doe' - } + name: 'James Doe', + }, } - await expect(client.request(mutation, variables)) - .resolves.toEqual(expected) + await expect(client.request(mutation, variables)).resolves.toEqual(expected) }) it('with no name', async () => { const variables = { - id: 'u47' + id: 'u47', } const expected = 'Username must be at least 3 characters long!' - await expect(client.request(mutation, variables)) - .rejects.toThrow(expected) + await expect(client.request(mutation, variables)).rejects.toThrow(expected) }) it('with too short name', async () => { const variables = { id: 'u47', - name: ' ' + name: ' ', } const expected = 'Username must be at least 3 characters long!' - await expect(client.request(mutation, variables)) - .rejects.toThrow(expected) + await expect(client.request(mutation, variables)).rejects.toThrow(expected) }) }) }) diff --git a/backend/src/seed/factories/badges.js b/backend/src/seed/factories/badges.js index 6f5f8d69a..52fa9da33 100644 --- a/backend/src/seed/factories/badges.js +++ b/backend/src/seed/factories/badges.js @@ -1,12 +1,12 @@ import uuid from 'uuid/v4' -export default function (params) { +export default function(params) { const { id = uuid(), key = '', type = 'crowdfunding', status = 'permanent', - icon = '/img/badges/indiegogo_en_panda.svg' + icon = '/img/badges/indiegogo_en_panda.svg', } = params return { @@ -23,6 +23,6 @@ export default function (params) { } } `, - variables: { id, key, type, status, icon } + variables: { id, key, type, status, icon }, } } diff --git a/backend/src/seed/factories/categories.js b/backend/src/seed/factories/categories.js index 5c1b3ce10..341f1b1fd 100644 --- a/backend/src/seed/factories/categories.js +++ b/backend/src/seed/factories/categories.js @@ -1,12 +1,7 @@ import uuid from 'uuid/v4' -export default function (params) { - const { - id = uuid(), - name, - slug, - icon - } = params +export default function(params) { + const { id = uuid(), name, slug, icon } = params return { mutation: ` @@ -17,6 +12,6 @@ export default function (params) { } } `, - variables: { id, name, slug, icon } + variables: { id, name, slug, icon }, } } diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index ba3a85840..b1079e392 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -1,14 +1,11 @@ import faker from 'faker' import uuid from 'uuid/v4' -export default function (params) { +export default function(params) { const { id = uuid(), postId = 'p6', - content = [ - faker.lorem.sentence(), - faker.lorem.sentence() - ].join('. ') + content = [faker.lorem.sentence(), faker.lorem.sentence()].join('. '), } = params return { @@ -19,6 +16,6 @@ export default function (params) { } } `, - variables: { id, postId, content } + variables: { id, postId, content }, } } diff --git a/backend/src/seed/factories/index.js b/backend/src/seed/factories/index.js index a0cb310ab..211edf87e 100644 --- a/backend/src/seed/factories/index.js +++ b/backend/src/seed/factories/index.js @@ -19,7 +19,7 @@ const authenticatedHeaders = async ({ email, password }, host) => { }` const response = await request(host, mutation) return { - authorization: `Bearer ${response.login}` + authorization: `Bearer ${response.login}`, } } const factories = { @@ -31,7 +31,7 @@ const factories = { Category: createCategory, Tag: createTag, Report: createReport, - Notification: createNotification + Notification: createNotification, } export const cleanDatabase = async (options = {}) => { @@ -47,11 +47,8 @@ export const cleanDatabase = async (options = {}) => { } } -export default function Factory (options = {}) { - const { - neo4jDriver = getDriver(), - seedServerHost = 'http://127.0.0.1:4001' - } = options +export default function Factory(options = {}) { + const { neo4jDriver = getDriver(), seedServerHost = 'http://127.0.0.1:4001' } = options const graphQLClient = new GraphQLClient(seedServerHost) @@ -61,21 +58,18 @@ export default function Factory (options = {}) { graphQLClient, factories, lastResponse: null, - async authenticateAs ({ email, password }) { - const headers = await authenticatedHeaders( - { email, password }, - seedServerHost - ) + async authenticateAs({ email, password }) { + const headers = await authenticatedHeaders({ email, password }, seedServerHost) this.lastResponse = headers this.graphQLClient = new GraphQLClient(seedServerHost, { headers }) return this }, - async create (node, properties) { + async create(node, properties) { const { mutation, variables } = this.factories[node](properties) this.lastResponse = await this.graphQLClient.request(mutation, variables) return this }, - async relate (node, relationship, properties) { + async relate(node, relationship, properties) { const { from, to } = properties const mutation = ` mutation { @@ -88,11 +82,11 @@ export default function Factory (options = {}) { this.lastResponse = await this.graphQLClient.request(mutation) return this }, - async mutate (mutation, variables) { + async mutate(mutation, variables) { this.lastResponse = await this.graphQLClient.request(mutation, variables) return this }, - async shout (properties) { + async shout(properties) { const { id, type } = properties const mutation = ` mutation { @@ -105,7 +99,7 @@ export default function Factory (options = {}) { this.lastResponse = await this.graphQLClient.request(mutation) return this }, - async follow (properties) { + async follow(properties) { const { id, type } = properties const mutation = ` mutation { @@ -118,10 +112,10 @@ export default function Factory (options = {}) { this.lastResponse = await this.graphQLClient.request(mutation) return this }, - async cleanDatabase () { + async cleanDatabase() { this.lastResponse = await cleanDatabase({ driver: this.neo4jDriver }) return this - } + }, } result.authenticateAs.bind(result) result.create.bind(result) diff --git a/backend/src/seed/factories/notifications.js b/backend/src/seed/factories/notifications.js index f7797200f..d14d4294a 100644 --- a/backend/src/seed/factories/notifications.js +++ b/backend/src/seed/factories/notifications.js @@ -1,10 +1,7 @@ import uuid from 'uuid/v4' -export default function (params) { - const { - id = uuid(), - read = false - } = params +export default function(params) { + const { id = uuid(), read = false } = params return { mutation: ` @@ -15,6 +12,6 @@ export default function (params) { } } `, - variables: { id, read } + variables: { id, read }, } } diff --git a/backend/src/seed/factories/organizations.js b/backend/src/seed/factories/organizations.js index dd4100b26..536de1597 100644 --- a/backend/src/seed/factories/organizations.js +++ b/backend/src/seed/factories/organizations.js @@ -1,11 +1,11 @@ import faker from 'faker' import uuid from 'uuid/v4' -export default function create (params) { +export default function create(params) { const { id = uuid(), name = faker.company.companyName(), - description = faker.company.catchPhrase() + description = faker.company.catchPhrase(), } = params return { @@ -16,6 +16,6 @@ export default function create (params) { } } `, - variables: { id, name, description } + variables: { id, name, description }, } } diff --git a/backend/src/seed/factories/posts.js b/backend/src/seed/factories/posts.js index cbc73dbf8..1468b05d7 100644 --- a/backend/src/seed/factories/posts.js +++ b/backend/src/seed/factories/posts.js @@ -1,7 +1,7 @@ import faker from 'faker' import uuid from 'uuid/v4' -export default function (params) { +export default function(params) { const { id = uuid(), slug = '', @@ -11,11 +11,11 @@ export default function (params) { faker.lorem.sentence(), faker.lorem.sentence(), faker.lorem.sentence(), - faker.lorem.sentence() + faker.lorem.sentence(), ].join('. '), image = faker.image.image(), visibility = 'public', - deleted = false + deleted = false, } = params return { @@ -43,6 +43,6 @@ export default function (params) { } } `, - variables: { id, slug, title, content, image, visibility, deleted } + variables: { id, slug, title, content, image, visibility, deleted }, } } diff --git a/backend/src/seed/factories/reports.js b/backend/src/seed/factories/reports.js index 130c20c37..40d0e6179 100644 --- a/backend/src/seed/factories/reports.js +++ b/backend/src/seed/factories/reports.js @@ -1,10 +1,7 @@ import faker from 'faker' -export default function create (params) { - const { - description = faker.lorem.sentence(), - id - } = params +export default function create(params) { + const { description = faker.lorem.sentence(), id } = params return { mutation: ` @@ -15,6 +12,6 @@ export default function create (params) { } } `, - variables: { id, description } + variables: { id, description }, } } diff --git a/backend/src/seed/factories/tags.js b/backend/src/seed/factories/tags.js index 558b68957..15ded1986 100644 --- a/backend/src/seed/factories/tags.js +++ b/backend/src/seed/factories/tags.js @@ -1,10 +1,7 @@ import uuid from 'uuid/v4' -export default function (params) { - const { - id = uuid(), - name = '#human-connection' - } = params +export default function(params) { + const { id = uuid(), name = '#human-connection' } = params return { mutation: ` @@ -14,6 +11,6 @@ export default function (params) { } } `, - variables: { id, name } + variables: { id, name }, } } diff --git a/backend/src/seed/factories/users.js b/backend/src/seed/factories/users.js index a088b4c54..1ab362ce2 100644 --- a/backend/src/seed/factories/users.js +++ b/backend/src/seed/factories/users.js @@ -1,7 +1,7 @@ import faker from 'faker' import uuid from 'uuid/v4' -export default function create (params) { +export default function create(params) { const { id = uuid(), name = faker.name.findName(), @@ -10,7 +10,7 @@ export default function create (params) { password = '1234', role = 'user', avatar = faker.internet.avatar(), - about = faker.lorem.paragraph() + about = faker.lorem.paragraph(), } = params return { @@ -46,6 +46,6 @@ export default function create (params) { } } `, - variables: { id, name, slug, password, email, avatar, about, role } + variables: { id, name, slug, password, email, avatar, about, role }, } } diff --git a/backend/src/seed/reset-db.js b/backend/src/seed/reset-db.js index 4075489f9..3197a6e18 100644 --- a/backend/src/seed/reset-db.js +++ b/backend/src/seed/reset-db.js @@ -7,13 +7,13 @@ if (process.env.NODE_ENV === 'production') { throw new Error(`YOU CAN'T CLEAN THE DATABASE WITH NODE_ENV=${process.env.NODE_ENV}`) } -(async function () { +;(async function() { try { await cleanDatabase() - console.log('Successfully deleted all nodes and relations!') + console.log('Successfully deleted all nodes and relations!') // eslint-disable-line no-console process.exit(0) } catch (err) { - console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`) + console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`) // eslint-disable-line no-console process.exit(1) } })() diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js index 8694a7948..27af1106a 100644 --- a/backend/src/seed/seed-db.js +++ b/backend/src/seed/seed-db.js @@ -2,126 +2,247 @@ import faker from 'faker' import Factory from './factories' /* eslint-disable no-multi-spaces */ -(async function () { +;(async function() { try { const f = Factory() await Promise.all([ - f.create('Badge', { id: 'b1', key: 'indiegogo_en_racoon', type: 'crowdfunding', status: 'permanent', icon: '/img/badges/indiegogo_en_racoon.svg' }), - f.create('Badge', { id: 'b2', key: 'indiegogo_en_rabbit', type: 'crowdfunding', status: 'permanent', icon: '/img/badges/indiegogo_en_rabbit.svg' }), - f.create('Badge', { id: 'b3', key: 'indiegogo_en_wolf', type: 'crowdfunding', status: 'permanent', icon: '/img/badges/indiegogo_en_wolf.svg' }), - f.create('Badge', { id: 'b4', key: 'indiegogo_en_bear', type: 'crowdfunding', status: 'permanent', icon: '/img/badges/indiegogo_en_bear.svg' }), - f.create('Badge', { id: 'b5', key: 'indiegogo_en_turtle', type: 'crowdfunding', status: 'permanent', icon: '/img/badges/indiegogo_en_turtle.svg' }), - f.create('Badge', { id: 'b6', key: 'indiegogo_en_rhino', type: 'crowdfunding', status: 'permanent', icon: '/img/badges/indiegogo_en_rhino.svg' }) + f.create('Badge', { + id: 'b1', + key: 'indiegogo_en_racoon', + type: 'crowdfunding', + status: 'permanent', + icon: '/img/badges/indiegogo_en_racoon.svg', + }), + f.create('Badge', { + id: 'b2', + key: 'indiegogo_en_rabbit', + type: 'crowdfunding', + status: 'permanent', + icon: '/img/badges/indiegogo_en_rabbit.svg', + }), + f.create('Badge', { + id: 'b3', + key: 'indiegogo_en_wolf', + type: 'crowdfunding', + status: 'permanent', + icon: '/img/badges/indiegogo_en_wolf.svg', + }), + f.create('Badge', { + id: 'b4', + key: 'indiegogo_en_bear', + type: 'crowdfunding', + status: 'permanent', + icon: '/img/badges/indiegogo_en_bear.svg', + }), + f.create('Badge', { + id: 'b5', + key: 'indiegogo_en_turtle', + type: 'crowdfunding', + status: 'permanent', + icon: '/img/badges/indiegogo_en_turtle.svg', + }), + f.create('Badge', { + id: 'b6', + key: 'indiegogo_en_rhino', + type: 'crowdfunding', + status: 'permanent', + icon: '/img/badges/indiegogo_en_rhino.svg', + }), ]) await Promise.all([ - f.create('User', { id: 'u1', name: 'Peter Lustig', role: 'admin', email: 'admin@example.org' }), - f.create('User', { id: 'u2', name: 'Bob der Baumeister', role: 'moderator', email: 'moderator@example.org' }), - f.create('User', { id: 'u3', name: 'Jenny Rostock', role: 'user', email: 'user@example.org' }), - f.create('User', { id: 'u4', name: 'Tick', role: 'user', email: 'tick@example.org' }), - f.create('User', { id: 'u5', name: 'Trick', role: 'user', email: 'trick@example.org' }), - f.create('User', { id: 'u6', name: 'Track', role: 'user', email: 'track@example.org' }), - f.create('User', { id: 'u7', name: 'Dagobert', role: 'user', email: 'dagobert@example.org' }) + f.create('User', { + id: 'u1', + name: 'Peter Lustig', + role: 'admin', + email: 'admin@example.org', + }), + f.create('User', { + id: 'u2', + name: 'Bob der Baumeister', + role: 'moderator', + email: 'moderator@example.org', + }), + f.create('User', { + id: 'u3', + name: 'Jenny Rostock', + role: 'user', + email: 'user@example.org', + }), + f.create('User', { id: 'u4', name: 'Tick', role: 'user', email: 'tick@example.org' }), + f.create('User', { id: 'u5', name: 'Trick', role: 'user', email: 'trick@example.org' }), + f.create('User', { id: 'u6', name: 'Track', role: 'user', email: 'track@example.org' }), + f.create('User', { id: 'u7', name: 'Dagobert', role: 'user', email: 'dagobert@example.org' }), ]) - const [ asAdmin, asModerator, asUser, asTick, asTrick, asTrack ] = await Promise.all([ - Factory().authenticateAs({ email: 'admin@example.org', password: '1234' }), + const [asAdmin, asModerator, asUser, asTick, asTrick, asTrack] = await Promise.all([ + Factory().authenticateAs({ email: 'admin@example.org', password: '1234' }), Factory().authenticateAs({ email: 'moderator@example.org', password: '1234' }), - Factory().authenticateAs({ email: 'user@example.org', password: '1234' }), - Factory().authenticateAs({ email: 'tick@example.org', password: '1234' }), - Factory().authenticateAs({ email: 'trick@example.org', password: '1234' }), - Factory().authenticateAs({ email: 'track@example.org', password: '1234' }) + Factory().authenticateAs({ email: 'user@example.org', password: '1234' }), + Factory().authenticateAs({ email: 'tick@example.org', password: '1234' }), + Factory().authenticateAs({ email: 'trick@example.org', password: '1234' }), + Factory().authenticateAs({ email: 'track@example.org', password: '1234' }), ]) await Promise.all([ - f.relate('User', 'Badges', { from: 'b6', to: 'u1' }), - f.relate('User', 'Badges', { from: 'b5', to: 'u2' }), - f.relate('User', 'Badges', { from: 'b4', to: 'u3' }), - f.relate('User', 'Badges', { from: 'b3', to: 'u4' }), - f.relate('User', 'Badges', { from: 'b2', to: 'u5' }), - f.relate('User', 'Badges', { from: 'b1', to: 'u6' }), - f.relate('User', 'Friends', { from: 'u1', to: 'u2' }), - f.relate('User', 'Friends', { from: 'u1', to: 'u3' }), - f.relate('User', 'Friends', { from: 'u2', to: 'u3' }), + f.relate('User', 'Badges', { from: 'b6', to: 'u1' }), + f.relate('User', 'Badges', { from: 'b5', to: 'u2' }), + f.relate('User', 'Badges', { from: 'b4', to: 'u3' }), + f.relate('User', 'Badges', { from: 'b3', to: 'u4' }), + f.relate('User', 'Badges', { from: 'b2', to: 'u5' }), + f.relate('User', 'Badges', { from: 'b1', to: 'u6' }), + f.relate('User', 'Friends', { from: 'u1', to: 'u2' }), + f.relate('User', 'Friends', { from: 'u1', to: 'u3' }), + f.relate('User', 'Friends', { from: 'u2', to: 'u3' }), f.relate('User', 'Blacklisted', { from: 'u7', to: 'u4' }), f.relate('User', 'Blacklisted', { from: 'u7', to: 'u5' }), - f.relate('User', 'Blacklisted', { from: 'u7', to: 'u6' }) + f.relate('User', 'Blacklisted', { from: 'u7', to: 'u6' }), ]) await Promise.all([ - asAdmin - .follow({ id: 'u3', type: 'User' }), - asModerator - .follow({ id: 'u4', type: 'User' }), - asUser - .follow({ id: 'u4', type: 'User' }), - asTick - .follow({ id: 'u6', type: 'User' }), - asTrick - .follow({ id: 'u4', type: 'User' }), - asTrack - .follow({ id: 'u3', type: 'User' }) + asAdmin.follow({ id: 'u3', type: 'User' }), + asModerator.follow({ id: 'u4', type: 'User' }), + asUser.follow({ id: 'u4', type: 'User' }), + asTick.follow({ id: 'u6', type: 'User' }), + asTrick.follow({ id: 'u4', type: 'User' }), + asTrack.follow({ id: 'u3', type: 'User' }), ]) await Promise.all([ - f.create('Category', { id: 'cat1', name: 'Just For Fun', slug: 'justforfun', icon: 'smile' }), - f.create('Category', { id: 'cat2', name: 'Happyness & Values', slug: 'happyness-values', icon: 'heart-o' }), - f.create('Category', { id: 'cat3', name: 'Health & Wellbeing', slug: 'health-wellbeing', icon: 'medkit' }), - f.create('Category', { id: 'cat4', name: 'Environment & Nature', slug: 'environment-nature', icon: 'tree' }), - f.create('Category', { id: 'cat5', name: 'Animal Protection', slug: 'animalprotection', icon: 'paw' }), - f.create('Category', { id: 'cat6', name: 'Humanrights Justice', slug: 'humanrights-justice', icon: 'balance-scale' }), - f.create('Category', { id: 'cat7', name: 'Education & Sciences', slug: 'education-sciences', icon: 'graduation-cap' }), - f.create('Category', { id: 'cat8', name: 'Cooperation & Development', slug: 'cooperation-development', icon: 'users' }), - f.create('Category', { id: 'cat9', name: 'Democracy & Politics', slug: 'democracy-politics', icon: 'university' }), - f.create('Category', { id: 'cat10', name: 'Economy & Finances', slug: 'economy-finances', icon: 'money' }), - f.create('Category', { id: 'cat11', name: 'Energy & Technology', slug: 'energy-technology', icon: 'flash' }), - f.create('Category', { id: 'cat12', name: 'IT, Internet & Data Privacy', slug: 'it-internet-dataprivacy', icon: 'mouse-pointer' }), - f.create('Category', { id: 'cat13', name: 'Art, Curlure & Sport', slug: 'art-culture-sport', icon: 'paint-brush' }), - f.create('Category', { id: 'cat14', name: 'Freedom of Speech', slug: 'freedomofspeech', icon: 'bullhorn' }), - f.create('Category', { id: 'cat15', name: 'Consumption & Sustainability', slug: 'consumption-sustainability', icon: 'shopping-cart' }), - f.create('Category', { id: 'cat16', name: 'Global Peace & Nonviolence', slug: 'globalpeace-nonviolence', icon: 'angellist' }) + f.create('Category', { id: 'cat1', name: 'Just For Fun', slug: 'justforfun', icon: 'smile' }), + f.create('Category', { + id: 'cat2', + name: 'Happyness & Values', + slug: 'happyness-values', + icon: 'heart-o', + }), + f.create('Category', { + id: 'cat3', + name: 'Health & Wellbeing', + slug: 'health-wellbeing', + icon: 'medkit', + }), + f.create('Category', { + id: 'cat4', + name: 'Environment & Nature', + slug: 'environment-nature', + icon: 'tree', + }), + f.create('Category', { + id: 'cat5', + name: 'Animal Protection', + slug: 'animalprotection', + icon: 'paw', + }), + f.create('Category', { + id: 'cat6', + name: 'Humanrights Justice', + slug: 'humanrights-justice', + icon: 'balance-scale', + }), + f.create('Category', { + id: 'cat7', + name: 'Education & Sciences', + slug: 'education-sciences', + icon: 'graduation-cap', + }), + f.create('Category', { + id: 'cat8', + name: 'Cooperation & Development', + slug: 'cooperation-development', + icon: 'users', + }), + f.create('Category', { + id: 'cat9', + name: 'Democracy & Politics', + slug: 'democracy-politics', + icon: 'university', + }), + f.create('Category', { + id: 'cat10', + name: 'Economy & Finances', + slug: 'economy-finances', + icon: 'money', + }), + f.create('Category', { + id: 'cat11', + name: 'Energy & Technology', + slug: 'energy-technology', + icon: 'flash', + }), + f.create('Category', { + id: 'cat12', + name: 'IT, Internet & Data Privacy', + slug: 'it-internet-dataprivacy', + icon: 'mouse-pointer', + }), + f.create('Category', { + id: 'cat13', + name: 'Art, Curlure & Sport', + slug: 'art-culture-sport', + icon: 'paint-brush', + }), + f.create('Category', { + id: 'cat14', + name: 'Freedom of Speech', + slug: 'freedomofspeech', + icon: 'bullhorn', + }), + f.create('Category', { + id: 'cat15', + name: 'Consumption & Sustainability', + slug: 'consumption-sustainability', + icon: 'shopping-cart', + }), + f.create('Category', { + id: 'cat16', + name: 'Global Peace & Nonviolence', + slug: 'globalpeace-nonviolence', + icon: 'angellist', + }), ]) await Promise.all([ f.create('Tag', { id: 't1', name: 'Umwelt' }), f.create('Tag', { id: 't2', name: 'Naturschutz' }), f.create('Tag', { id: 't3', name: 'Demokratie' }), - f.create('Tag', { id: 't4', name: 'Freiheit' }) + f.create('Tag', { id: 't4', name: 'Freiheit' }), ]) const mention1 = 'Hey @jenny-rostock, what\'s up?' - const mention2 = 'Hey @jenny-rostock, here is another notification for you!' + const mention2 = + 'Hey @jenny-rostock, here is another notification for you!' await Promise.all([ - asAdmin.create('Post', { id: 'p0' }), + asAdmin.create('Post', { id: 'p0' }), asModerator.create('Post', { id: 'p1' }), - asUser.create('Post', { id: 'p2' }), - asTick.create('Post', { id: 'p3' }), - asTrick.create('Post', { id: 'p4' }), - asTrack.create('Post', { id: 'p5' }), - asAdmin.create('Post', { id: 'p6' }), + asUser.create('Post', { id: 'p2' }), + asTick.create('Post', { id: 'p3' }), + asTrick.create('Post', { id: 'p4' }), + asTrack.create('Post', { id: 'p5' }), + asAdmin.create('Post', { id: 'p6' }), asModerator.create('Post', { id: 'p7', content: `${mention1} ${faker.lorem.paragraph()}` }), - asUser.create('Post', { id: 'p8' }), - asTick.create('Post', { id: 'p9' }), - asTrick.create('Post', { id: 'p10' }), - asTrack.create('Post', { id: 'p11' }), - asAdmin.create('Post', { id: 'p12', content: `${mention2} ${faker.lorem.paragraph()}` }), + asUser.create('Post', { id: 'p8' }), + asTick.create('Post', { id: 'p9' }), + asTrick.create('Post', { id: 'p10' }), + asTrack.create('Post', { id: 'p11' }), + asAdmin.create('Post', { id: 'p12', content: `${mention2} ${faker.lorem.paragraph()}` }), asModerator.create('Post', { id: 'p13' }), - asUser.create('Post', { id: 'p14' }), - asTick.create('Post', { id: 'p15' }) + asUser.create('Post', { id: 'p14' }), + asTick.create('Post', { id: 'p15' }), ]) await Promise.all([ - f.relate('Post', 'Categories', { from: 'p0', to: 'cat16' }), - f.relate('Post', 'Categories', { from: 'p1', to: 'cat1' }), - f.relate('Post', 'Categories', { from: 'p2', to: 'cat2' }), - f.relate('Post', 'Categories', { from: 'p3', to: 'cat3' }), - f.relate('Post', 'Categories', { from: 'p4', to: 'cat4' }), - f.relate('Post', 'Categories', { from: 'p5', to: 'cat5' }), - f.relate('Post', 'Categories', { from: 'p6', to: 'cat6' }), - f.relate('Post', 'Categories', { from: 'p7', to: 'cat7' }), - f.relate('Post', 'Categories', { from: 'p8', to: 'cat8' }), - f.relate('Post', 'Categories', { from: 'p9', to: 'cat9' }), + f.relate('Post', 'Categories', { from: 'p0', to: 'cat16' }), + f.relate('Post', 'Categories', { from: 'p1', to: 'cat1' }), + f.relate('Post', 'Categories', { from: 'p2', to: 'cat2' }), + f.relate('Post', 'Categories', { from: 'p3', to: 'cat3' }), + f.relate('Post', 'Categories', { from: 'p4', to: 'cat4' }), + f.relate('Post', 'Categories', { from: 'p5', to: 'cat5' }), + f.relate('Post', 'Categories', { from: 'p6', to: 'cat6' }), + f.relate('Post', 'Categories', { from: 'p7', to: 'cat7' }), + f.relate('Post', 'Categories', { from: 'p8', to: 'cat8' }), + f.relate('Post', 'Categories', { from: 'p9', to: 'cat9' }), f.relate('Post', 'Categories', { from: 'p10', to: 'cat10' }), f.relate('Post', 'Categories', { from: 'p11', to: 'cat11' }), f.relate('Post', 'Categories', { from: 'p12', to: 'cat12' }), @@ -129,63 +250,45 @@ import Factory from './factories' f.relate('Post', 'Categories', { from: 'p14', to: 'cat14' }), f.relate('Post', 'Categories', { from: 'p15', to: 'cat15' }), - f.relate('Post', 'Tags', { from: 'p0', to: 't4' }), - f.relate('Post', 'Tags', { from: 'p1', to: 't1' }), - f.relate('Post', 'Tags', { from: 'p2', to: 't2' }), - f.relate('Post', 'Tags', { from: 'p3', to: 't3' }), - f.relate('Post', 'Tags', { from: 'p4', to: 't4' }), - f.relate('Post', 'Tags', { from: 'p5', to: 't1' }), - f.relate('Post', 'Tags', { from: 'p6', to: 't2' }), - f.relate('Post', 'Tags', { from: 'p7', to: 't3' }), - f.relate('Post', 'Tags', { from: 'p8', to: 't4' }), - f.relate('Post', 'Tags', { from: 'p9', to: 't1' }), + f.relate('Post', 'Tags', { from: 'p0', to: 't4' }), + f.relate('Post', 'Tags', { from: 'p1', to: 't1' }), + f.relate('Post', 'Tags', { from: 'p2', to: 't2' }), + f.relate('Post', 'Tags', { from: 'p3', to: 't3' }), + f.relate('Post', 'Tags', { from: 'p4', to: 't4' }), + f.relate('Post', 'Tags', { from: 'p5', to: 't1' }), + f.relate('Post', 'Tags', { from: 'p6', to: 't2' }), + f.relate('Post', 'Tags', { from: 'p7', to: 't3' }), + f.relate('Post', 'Tags', { from: 'p8', to: 't4' }), + f.relate('Post', 'Tags', { from: 'p9', to: 't1' }), f.relate('Post', 'Tags', { from: 'p10', to: 't2' }), f.relate('Post', 'Tags', { from: 'p11', to: 't3' }), f.relate('Post', 'Tags', { from: 'p12', to: 't4' }), f.relate('Post', 'Tags', { from: 'p13', to: 't1' }), f.relate('Post', 'Tags', { from: 'p14', to: 't2' }), - f.relate('Post', 'Tags', { from: 'p15', to: 't3' }) + f.relate('Post', 'Tags', { from: 'p15', to: 't3' }), ]) await Promise.all([ - asAdmin - .shout({ id: 'p2', type: 'Post' }), - asAdmin - .shout({ id: 'p6', type: 'Post' }), - asModerator - .shout({ id: 'p0', type: 'Post' }), - asModerator - .shout({ id: 'p6', type: 'Post' }), - asUser - .shout({ id: 'p6', type: 'Post' }), - asUser - .shout({ id: 'p7', type: 'Post' }), - asTick - .shout({ id: 'p8', type: 'Post' }), - asTick - .shout({ id: 'p9', type: 'Post' }), - asTrack - .shout({ id: 'p10', type: 'Post' }) + asAdmin.shout({ id: 'p2', type: 'Post' }), + asAdmin.shout({ id: 'p6', type: 'Post' }), + asModerator.shout({ id: 'p0', type: 'Post' }), + asModerator.shout({ id: 'p6', type: 'Post' }), + asUser.shout({ id: 'p6', type: 'Post' }), + asUser.shout({ id: 'p7', type: 'Post' }), + asTick.shout({ id: 'p8', type: 'Post' }), + asTick.shout({ id: 'p9', type: 'Post' }), + asTrack.shout({ id: 'p10', type: 'Post' }), ]) await Promise.all([ - asAdmin - .shout({ id: 'p2', type: 'Post' }), - asAdmin - .shout({ id: 'p6', type: 'Post' }), - asModerator - .shout({ id: 'p0', type: 'Post' }), - asModerator - .shout({ id: 'p6', type: 'Post' }), - asUser - .shout({ id: 'p6', type: 'Post' }), - asUser - .shout({ id: 'p7', type: 'Post' }), - asTick - .shout({ id: 'p8', type: 'Post' }), - asTick - .shout({ id: 'p9', type: 'Post' }), - asTrack - .shout({ id: 'p10', type: 'Post' }) + asAdmin.shout({ id: 'p2', type: 'Post' }), + asAdmin.shout({ id: 'p6', type: 'Post' }), + asModerator.shout({ id: 'p0', type: 'Post' }), + asModerator.shout({ id: 'p6', type: 'Post' }), + asUser.shout({ id: 'p6', type: 'Post' }), + asUser.shout({ id: 'p7', type: 'Post' }), + asTick.shout({ id: 'p8', type: 'Post' }), + asTick.shout({ id: 'p9', type: 'Post' }), + asTrack.shout({ id: 'p10', type: 'Post' }), ]) await Promise.all([ @@ -200,33 +303,49 @@ import Factory from './factories' asTrick.create('Comment', { id: 'c9', postId: 'p15' }), asTrack.create('Comment', { id: 'c10', postId: 'p15' }), asUser.create('Comment', { id: 'c11', postId: 'p15' }), - asUser.create('Comment', { id: 'c12', postId: 'p15' }) + asUser.create('Comment', { id: 'c12', postId: 'p15' }), ]) const disableMutation = 'mutation($id: ID!) { disable(id: $id) }' await Promise.all([ asModerator.mutate(disableMutation, { id: 'p11' }), - asModerator.mutate(disableMutation, { id: 'c5' }) + 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' }), - asTrack.create('Report', { description: 'I don\'t like this user', id: 'u1' }) + asTick.create('Report', { description: "I don't like this comment", id: 'c1' }), + asTrick.create('Report', { description: "I don't like this post", id: 'p1' }), + asTrack.create('Report', { description: "I don't like this user", id: 'u1' }), ]) await Promise.all([ - f.create('Organization', { id: 'o1', name: 'Democracy Deutschland', description: 'Description for democracy-deutschland.' }), - f.create('Organization', { id: 'o2', name: 'Human-Connection', description: 'Description for human-connection.' }), - f.create('Organization', { id: 'o3', name: 'Pro Veg', description: 'Description for pro-veg.' }), - f.create('Organization', { id: 'o4', name: 'Greenpeace', description: 'Description for greenpeace.' }) + f.create('Organization', { + id: 'o1', + name: 'Democracy Deutschland', + description: 'Description for democracy-deutschland.', + }), + f.create('Organization', { + id: 'o2', + name: 'Human-Connection', + description: 'Description for human-connection.', + }), + f.create('Organization', { + id: 'o3', + name: 'Pro Veg', + description: 'Description for pro-veg.', + }), + f.create('Organization', { + id: 'o4', + name: 'Greenpeace', + description: 'Description for greenpeace.', + }), ]) await Promise.all([ f.relate('Organization', 'CreatedBy', { from: 'u1', to: 'o1' }), f.relate('Organization', 'CreatedBy', { from: 'u1', to: 'o2' }), - f.relate('Organization', 'OwnedBy', { from: 'u2', to: 'o2' }), - f.relate('Organization', 'OwnedBy', { from: 'u2', to: 'o3' }) + f.relate('Organization', 'OwnedBy', { from: 'u2', to: 'o2' }), + f.relate('Organization', 'OwnedBy', { from: 'u2', to: 'o3' }), ]) /* eslint-disable-next-line no-console */ console.log('Seeded Data...') diff --git a/backend/src/seed/seed-helpers.js b/backend/src/seed/seed-helpers.js index 23bde40ae..399d06670 100644 --- a/backend/src/seed/seed-helpers.js +++ b/backend/src/seed/seed-helpers.js @@ -19,7 +19,7 @@ const unsplashTopics = [ 'face', 'people', 'portrait', - 'amazing' + 'amazing', ] let unsplashTopicsTmp = [] @@ -30,7 +30,7 @@ const ngoLogos = [ 'https://dcassetcdn.com/design_img/10133/25833/25833_303600_10133_image.jpg', 'https://cdn.tutsplus.com/vector/uploads/legacy/articles/08bad_ngologos/20.jpg', 'https://cdn.tutsplus.com/vector/uploads/legacy/articles/08bad_ngologos/33.jpg', - null + null, ] const difficulties = ['easy', 'medium', 'hard'] @@ -38,8 +38,7 @@ const difficulties = ['easy', 'medium', 'hard'] export default { randomItem: (items, filter) => { let ids = filter - ? Object.keys(items) - .filter(id => { + ? Object.keys(items).filter(id => { return filter(items[id]) }) : _.keys(items) @@ -61,7 +60,7 @@ export default { } return res }, - random: (items) => { + random: items => { return _.shuffle(items).pop() }, randomDifficulty: () => { @@ -78,7 +77,9 @@ export default { if (unsplashTopicsTmp.length < 2) { unsplashTopicsTmp = _.shuffle(unsplashTopics) } - return 'https://source.unsplash.com/daily?' + unsplashTopicsTmp.pop() + ',' + unsplashTopicsTmp.pop() + return ( + 'https://source.unsplash.com/daily?' + unsplashTopicsTmp.pop() + ',' + unsplashTopicsTmp.pop() + ) }, randomCategories: (seederstore, allowEmpty = false) => { let count = Math.round(Math.random() * 3) @@ -101,8 +102,8 @@ export default { zipCode: faker.address.zipCode(), street: faker.address.streetAddress(), country: faker.address.countryCode(), - lat: 54.032726 - (Math.random() * 10), - lng: 6.558838 + (Math.random() * 10) + lat: 54.032726 - Math.random() * 10, + lng: 6.558838 + Math.random() * 10, }) } return addresses @@ -129,5 +130,5 @@ export default { code += chars.substr(n, 1) } return code - } + }, } diff --git a/backend/src/server.js b/backend/src/server.js index fe0d4ee1d..59261302f 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -28,17 +28,17 @@ let schema = makeAugmentedSchema({ resolvers, config: { query: { - exclude: ['Notfication', 'Statistics', 'LoggedInUser'] + exclude: ['Notfication', 'Statistics', 'LoggedInUser'], }, mutation: { - exclude: ['Notfication', 'Statistics', 'LoggedInUser'] + exclude: ['Notfication', 'Statistics', 'LoggedInUser'], }, - debug: debug - } + debug: debug, + }, }) schema = applyScalars(applyDirectives(schema)) -const createServer = (options) => { +const createServer = options => { const defaults = { context: async ({ request }) => { const authorizationHeader = request.headers.authorization || '' @@ -48,15 +48,15 @@ const createServer = (options) => { user, req: request, cypherParams: { - currentUserId: user ? user.id : null - } + currentUserId: user ? user.id : null, + }, } }, schema: schema, debug: debug, tracing: debug, middlewares: middleware(schema), - mocks: (process.env.MOCK === 'true') ? mocks : false + mocks: process.env.MOCK === 'true' ? mocks : false, } const server = new GraphQLServer(Object.assign({}, defaults, options)) diff --git a/backend/yarn.lock b/backend/yarn.lock index 7a24e16ca..c486f174d 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -38,17 +38,17 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@^7.1.0", "@babel/core@~7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.4.tgz#84055750b05fcd50f9915a826b44fa347a825250" - integrity sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ== +"@babel/core@^7.1.0", "@babel/core@~7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.5.tgz#081f97e8ffca65a9b4b0fdc7e274e703f000c06a" + integrity sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA== dependencies: "@babel/code-frame" "^7.0.0" "@babel/generator" "^7.4.4" "@babel/helpers" "^7.4.4" - "@babel/parser" "^7.4.4" + "@babel/parser" "^7.4.5" "@babel/template" "^7.4.4" - "@babel/traverse" "^7.4.4" + "@babel/traverse" "^7.4.5" "@babel/types" "^7.4.4" convert-source-map "^1.1.0" debug "^4.1.0" @@ -278,21 +278,22 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/node@~7.2.2": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.2.2.tgz#1557dd23545b38d7b1d030a9c0e8fb225dbf70ab" - integrity sha512-jPqgTycE26uFsuWpLika9Ohz9dmLQHWjOnMNxBOjYb1HXO+eLKxEr5FfKSXH/tBvFwwaw+pzke3gagnurGOfCA== +"@babel/node@~7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.4.5.tgz#bce71bb44d902bfdd4da0b9c839a8a90fc084056" + integrity sha512-nDXPT0KwYMycDHhFG9wKlkipCR+iXzzoX9bD2aF2UABLhQ13AKhNi5Y61W8ASGPPll/7p9GrHesmlOgTUJVcfw== dependencies: "@babel/polyfill" "^7.0.0" "@babel/register" "^7.0.0" commander "^2.8.1" - lodash "^4.17.10" + lodash "^4.17.11" + node-environment-flags "^1.0.5" v8flags "^3.1.1" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.4.tgz#5977129431b8fe33471730d255ce8654ae1250b6" - integrity sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.4", "@babel/parser@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872" + integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew== "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" @@ -524,12 +525,12 @@ "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-named-capturing-groups-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.4.tgz#5611d96d987dfc4a3a81c4383bb173361037d68d" - integrity sha512-Ki+Y9nXBlKfhD+LXaRS7v95TtTGYRAf9Y1rTDiE75zf8YQz4GDaWRXosMfJBXxnk88mGFjWdCRIeqDbon7spYA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" + integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== dependencies: - regexp-tree "^0.1.0" + regexp-tree "^0.1.6" "@babel/plugin-transform-new-target@^7.4.4": version "7.4.4" @@ -562,12 +563,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-regenerator@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.4.tgz#5b4da4df79391895fca9e28f99e87e22cfc02072" - integrity sha512-Zz3w+pX1SI0KMIiqshFZkwnVGUhDZzpX2vtPzfJBKQQq8WsP/Xy9DNdELWivxcKOCX/Pywge4SiEaPaLtoDT4g== +"@babel/plugin-transform-regenerator@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" + integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== dependencies: - regenerator-transform "^0.13.4" + regenerator-transform "^0.14.0" "@babel/plugin-transform-reserved-words@^7.2.0": version "7.2.0" @@ -622,15 +623,7 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" -"@babel/polyfill@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.0.0.tgz#c8ff65c9ec3be6a1ba10113ebd40e8750fb90bff" - integrity sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q== - dependencies: - core-js "^2.5.7" - regenerator-runtime "^0.11.1" - -"@babel/polyfill@^7.2.3": +"@babel/polyfill@^7.0.0", "@babel/polyfill@^7.2.3": version "7.2.5" resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d" integrity sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug== @@ -638,10 +631,10 @@ core-js "^2.5.7" regenerator-runtime "^0.12.0" -"@babel/preset-env@~7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.4.tgz#b6f6825bfb27b3e1394ca3de4f926482722c1d6f" - integrity sha512-FU1H+ACWqZZqfw1x2G1tgtSSYSfxJLkpaUQL37CenULFARDo+h4xJoVHzRoHbK+85ViLciuI7ME4WTIhFRBBlw== +"@babel/preset-env@~7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" + integrity sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -672,12 +665,12 @@ "@babel/plugin-transform-modules-commonjs" "^7.4.4" "@babel/plugin-transform-modules-systemjs" "^7.4.4" "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.5" "@babel/plugin-transform-new-target" "^7.4.4" "@babel/plugin-transform-object-super" "^7.2.0" "@babel/plugin-transform-parameters" "^7.4.4" "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.4.4" + "@babel/plugin-transform-regenerator" "^7.4.5" "@babel/plugin-transform-reserved-words" "^7.2.0" "@babel/plugin-transform-shorthand-properties" "^7.2.0" "@babel/plugin-transform-spread" "^7.2.0" @@ -686,8 +679,8 @@ "@babel/plugin-transform-typeof-symbol" "^7.2.0" "@babel/plugin-transform-unicode-regex" "^7.4.4" "@babel/types" "^7.4.4" - browserslist "^4.5.2" - core-js-compat "^3.0.0" + browserslist "^4.6.0" + core-js-compat "^3.1.1" invariant "^2.2.2" js-levenshtein "^1.1.3" semver "^5.5.0" @@ -720,16 +713,16 @@ "@babel/parser" "^7.4.4" "@babel/types" "^7.4.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.4.tgz#0776f038f6d78361860b6823887d4f3937133fe8" - integrity sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216" + integrity sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A== dependencies: "@babel/code-frame" "^7.0.0" "@babel/generator" "^7.4.4" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.4.4" + "@babel/parser" "^7.4.5" "@babel/types" "^7.4.4" debug "^4.1.0" globals "^11.1.0" @@ -1141,6 +1134,13 @@ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== +"@wry/context@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.0.tgz#8a8718408e4dd0514a0f8f4231bb4b87130b34e3" + integrity sha512-rVjwzFjVYXJ8pWJ8ZRCHv6meOebQvfTlvnUYUNX93Ce0KNeMTqCkf0GiOJc6BNVB96s7qfvwoLN3nUgDnSFOOg== + dependencies: + tslib "^1.9.3" + abab@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" @@ -1296,18 +1296,18 @@ apollo-cache-control@^0.1.0: dependencies: graphql-extensions "^0.0.x" -apollo-cache-inmemory@~1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.5.1.tgz#265d1ee67b0bf0aca9c37629d410bfae44e62953" - integrity sha512-D3bdpPmWfaKQkWy8lfwUg+K8OBITo3sx0BHLs1B/9vIdOIZ7JNCKq3EUcAgAfInomJUdN0QG1yOfi8M8hxkN1g== +apollo-cache-inmemory@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.0.tgz#a106cdc520f0a043be2575372d5dbb7e4790254c" + integrity sha512-Mr86ucMsXnRH9YRvcuuy6kc3dtyRBuVSo8gdxp2sJVuUAtvQ6r/8E+ok2qX84em9ZBAYxoyvPnKeShhvcKiiDw== dependencies: - apollo-cache "^1.2.1" - apollo-utilities "^1.2.1" - optimism "^0.6.9" - ts-invariant "^0.2.1" + apollo-cache "^1.3.0" + apollo-utilities "^1.3.0" + optimism "^0.9.0" + ts-invariant "^0.4.0" tslib "^1.9.3" -apollo-cache@1.2.1, apollo-cache@^1.2.1: +apollo-cache@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.2.1.tgz#aae71eb4a11f1f7322adc343f84b1a39b0693644" integrity sha512-nzFmep/oKlbzUuDyz6fS6aYhRmfpcHWqNkkA9Bbxwk18RD6LXC4eZkuE0gXRX0IibVBHNjYVK+Szi0Yied4SpQ== @@ -1315,6 +1315,14 @@ apollo-cache@1.2.1, apollo-cache@^1.2.1: apollo-utilities "^1.2.1" tslib "^1.9.3" +apollo-cache@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.0.tgz#de5c907cbd329440c9b0aafcbe8436391b9e6142" + integrity sha512-voPlvSIDA2pY3+7QwtXPs7o5uSNAVjUKwimyHWoiW0MIZtPxawtOV/Y+BL85R227JqcjPic1El+QToVR8l4ytQ== + dependencies: + apollo-utilities "^1.3.0" + tslib "^1.9.3" + apollo-client@~2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.5.1.tgz#36126ed1d32edd79c3713c6684546a3bea80e6d1" @@ -1567,7 +1575,7 @@ apollo-upload-server@^7.0.0: http-errors "^1.7.0" object-path "^0.11.4" -apollo-utilities@1.2.1, apollo-utilities@^1.0.1, apollo-utilities@^1.2.1: +apollo-utilities@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.2.1.tgz#1c3a1ebf5607d7c8efe7636daaf58e7463b41b3c" integrity sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg== @@ -1576,6 +1584,15 @@ apollo-utilities@1.2.1, apollo-utilities@^1.0.1, apollo-utilities@^1.2.1: ts-invariant "^0.2.1" tslib "^1.9.3" +apollo-utilities@^1.0.1, apollo-utilities@^1.2.1, apollo-utilities@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.0.tgz#9803724c07ac94ca11dc26397edb58735d2b0211" + integrity sha512-wQjV+FdWcTWmWUFlChG5rS0vHKy5OsXC6XlV9STRstQq6VbXANwHy6DHnTEQAfLXWAbNcPgBu+nBUpR3dFhwrA== + dependencies: + fast-json-stable-stringify "^2.0.0" + ts-invariant "^0.4.0" + tslib "^1.9.3" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -2012,14 +2029,14 @@ browser-resolve@^1.11.3: dependencies: resolve "1.1.7" -browserslist@^4.5.1, browserslist@^4.5.2: - version "4.5.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.4.tgz#166c4ecef3b51737a42436ea8002aeea466ea2c7" - integrity sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag== +browserslist@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.0.tgz#5274028c26f4d933d5b1323307c1d1da5084c9ff" + integrity sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg== dependencies: - caniuse-lite "^1.0.30000955" - electron-to-chromium "^1.3.122" - node-releases "^1.1.13" + caniuse-lite "^1.0.30000967" + electron-to-chromium "^1.3.133" + node-releases "^1.1.19" bs58@=2.0.0: version "2.0.0" @@ -2110,10 +2127,10 @@ camelize@1.0.0: resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= -caniuse-lite@^1.0.30000955: - version "1.0.30000956" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000956.tgz#fe56d8727fab96e0304ffbde6c4e538c9ad2a741" - integrity sha512-3o7L6XkQ01Oney+x2fS5UVbQXJ7QQkYxrSfaLmFlgQabcKfploI8bhS2nmQ8Unh5MpMONAMeDEdEXG9t9AK6uA== +caniuse-lite@^1.0.30000967: + version "1.0.30000971" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz#d1000e4546486a6977756547352bc96a4cfd2b13" + integrity sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g== capture-exit@^1.2.0: version "1.2.0" @@ -2230,7 +2247,7 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-table3@^0.5.0, cli-table3@^0.5.1: +cli-table3@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== @@ -2394,25 +2411,19 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.0.0.tgz#cd9810b8000742535a4a43773866185e310bd4f7" - integrity sha512-W/Ppz34uUme3LmXWjMgFlYyGnbo1hd9JvA0LNQ4EmieqVjg2GPYbj3H6tcdP2QGPGWdRKUqZVbVKLNIFVs/HiA== +core-js-compat@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.1.2.tgz#c29ab9722517094b98622175e2218c3b7398176d" + integrity sha512-X0Ch5f6itrHxhg5HSJucX6nNLNAGr+jq+biBh6nPGc3YAWz2a8p/ZIZY8cUkDzSRNG54omAuu3hoEF8qZbu/6Q== dependencies: - browserslist "^4.5.1" - core-js "3.0.0" - core-js-pure "3.0.0" - semver "^5.6.0" + browserslist "^4.6.0" + core-js-pure "3.1.2" + semver "^6.0.0" -core-js-pure@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.0.0.tgz#a5679adb4875427c8c0488afc93e6f5b7125859b" - integrity sha512-yPiS3fQd842RZDgo/TAKGgS0f3p2nxssF1H65DIZvZv0Od5CygP8puHXn3IQiM/39VAvgCbdaMQpresrbGgt9g== - -core-js@3.0.0, core-js@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.0.tgz#a8dbfa978d29bfc263bfb66c556d0ca924c28957" - integrity sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ== +core-js-pure@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.2.tgz#62fc435f35b7374b9b782013cdcb2f97e9f6dffa" + integrity sha512-5ckIdBF26B3ldK9PM177y2ZcATP2oweam9RskHSoqfZCrJ2As6wVg8zJ1zTriFsZf6clj/N1ThDFRGaomMsh9w== core-js@3.0.0-beta.13: version "3.0.0-beta.13" @@ -2424,6 +2435,11 @@ core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.2.tgz#267988d7268323b349e20b4588211655f0e83944" integrity sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g== +core-js@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.0.tgz#a8dbfa978d29bfc263bfb66c556d0ca924c28957" + integrity sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2845,10 +2861,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.122: - version "1.3.122" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.122.tgz#b32a0805f48557bd3c3b8104eadc7fa511b14a9a" - integrity sha512-3RKoIyCN4DhP2dsmleuFvpJAIDOseWH88wFYBzb22CSwoFDSWRc4UAMfrtc9h8nBdJjTNIN3rogChgOy6eFInw== +electron-to-chromium@^1.3.133: + version "1.3.137" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.137.tgz#ba7c88024984c038a5c5c434529aabcea7b42944" + integrity sha512-kGi32g42a8vS/WnYE7ELJyejRT7hbr3UeOOu0WeuYuQ29gCpg9Lrf6RdcTQVXSt/v0bjCfnlb/EWOOsiKpTmkw== elliptic@=3.0.3: version "3.0.3" @@ -2991,6 +3007,13 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" +eslint-config-prettier@~4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-4.3.0.tgz#c55c1fcac8ce4518aeb77906984e134d9eb5a4f0" + integrity sha512-sZwhSTHVVz78+kYD3t5pCWSYEdVSBR0PXnwjDRsUs8ytIrK8PLXw+6FKp8r3Z7rx4ZszdetWlXYKOHoUrrwPlA== + dependencies: + get-stdin "^6.0.0" + eslint-config-standard@~12.0.0: version "12.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz#638b4c65db0bd5a41319f96bba1f15ddad2107d9" @@ -3037,22 +3060,29 @@ eslint-plugin-import@~2.17.2: read-pkg-up "^2.0.0" resolve "^1.10.0" -eslint-plugin-jest@~22.5.1: - version "22.5.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.5.1.tgz#a31dfe9f9513c6af7c17ece4c65535a1370f060b" - integrity sha512-c3WjZR/HBoi4GedJRwo2OGHa8Pzo1EbSVwQ2HFzJ+4t2OoYM7Alx646EH/aaxZ+9eGcPiq0FT0UGkRuFFx2FHg== +eslint-plugin-jest@~22.6.4: + version "22.6.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.6.4.tgz#2895b047dd82f90f43a58a25cf136220a21c9104" + integrity sha512-36OqnZR/uMCDxXGmTsqU4RwllR0IiB/XF8GW3ODmhsjiITKuI0GpgultWFt193ipN3HARkaIcKowpE6HBvRHNg== -eslint-plugin-node@~9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.0.1.tgz#93e44626fa62bcb6efea528cee9687663dc03b62" - integrity sha512-fljT5Uyy3lkJzuqhxrYanLSsvaILs9I7CmQ31atTtZ0DoIzRbbvInBh4cQ1CrthFHInHYBQxfPmPt6KLHXNXdw== +eslint-plugin-node@~9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.1.0.tgz#f2fd88509a31ec69db6e9606d76dabc5adc1b91a" + integrity sha512-ZwQYGm6EoV2cfLpE1wxJWsfnKUIXfM/KM09/TlorkukgCAwmkgajEJnPCmyzoFPQQkmvo5DrW/nyKutNIw36Mw== dependencies: eslint-plugin-es "^1.4.0" eslint-utils "^1.3.1" ignore "^5.1.1" minimatch "^3.0.4" resolve "^1.10.1" - semver "^6.0.0" + semver "^6.1.0" + +eslint-plugin-prettier@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#8695188f95daa93b0dc54b249347ca3b79c4686d" + integrity sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA== + dependencies: + prettier-linter-helpers "^1.0.0" eslint-plugin-promise@~4.1.1: version "4.1.1" @@ -3360,6 +3390,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -3571,6 +3606,11 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3821,10 +3861,10 @@ graphql-yoga@~1.17.4: graphql-tools "^4.0.0" subscriptions-transport-ws "^0.9.8" -"graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0", graphql@^14.2.1, graphql@~14.3.0: - version "14.3.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.3.0.tgz#34dd36faa489ff642bcd25df6c3b4f988a1a2f3e" - integrity sha512-MdfI4v7kSNC3NhB7cF8KNijDsifuWO2XOtzpyququqaclO8wVuChYv+KogexDwgP5sp7nFI9Z6N4QHgoLkfjrg== +"graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0", graphql@^14.2.1, graphql@~14.3.1: + version "14.3.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.3.1.tgz#b3aa50e61a841ada3c1f9ccda101c483f8e8c807" + integrity sha512-FZm7kAa3FqKdXy8YSSpAoTtyDFMIYSpCDOr+3EqlI1bxmtHu+Vv/I2vrSeT1sBOEnEniX3uo4wFhFdS/8XN6gA== dependencies: iterall "^1.2.2" @@ -4092,11 +4132,6 @@ ignore@^5.1.1: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.1.tgz#2fc6b8f518aff48fef65a7f348ed85632448e4a5" integrity sha512-DWjnQIFLenVrwyRCKZT+7a7/U4Cqgar4WG8V++K3hw+lrW1hc/SIwdiGmtxKCVACmHULTuGeBbHJmbwW7/sAvA== -immutable-tuple@^0.4.9: - version "0.4.9" - resolved "https://registry.yarnpkg.com/immutable-tuple/-/immutable-tuple-0.4.9.tgz#473ebdd6c169c461913a454bf87ef8f601a20ff0" - integrity sha512-LWbJPZnidF8eczu7XmcnLBsumuyRBkpwIRPCZxlojouhBo5jEBO4toj6n7hMy6IxHU/c+MqDSWkvaTpPlMQcyA== - import-fresh@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" @@ -5564,10 +5599,10 @@ neo4j-driver@^1.7.3, neo4j-driver@~1.7.4: text-encoding "^0.6.4" uri-js "^4.2.1" -neo4j-graphql-js@~2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.6.0.tgz#1c418c5e4de384bd0992f99538d3d056d0602669" - integrity sha512-YStuqeBg6sjXQvQjICz+jpG4W58yHz3Fi1Gjw9HsVYeCSr97ARbGn4Sl02970IKpBeRYqKt1N1Xp3QIvO3OMIw== +neo4j-graphql-js@~2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.6.1.tgz#fc25d44d875a73114b6df08259985b555704b9bb" + integrity sha512-bPqzKumlCoHtS2qfPoTcZXrTkdXky210Kdu6Ubh5GhT+84wf+mo4Dzj4nxgDP2UgB77uA/caesIUImrSTLM8yQ== dependencies: graphql "^14.2.1" graphql-auth-directives "^2.1.0" @@ -5596,6 +5631,14 @@ nocache@2.1.0: resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== +node-environment-flags@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-fetch@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -5647,10 +5690,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.13.tgz#8c03296b5ae60c08e2ff4f8f22ae45bd2f210083" - integrity sha512-fKZGviSXR6YvVPyc011NHuJDSD8gFQvLPmc2d2V3BS4gr52ycyQ1Xzs7a8B+Ax3Ni/W+5h1h4SqmzeoA8WZRmA== +node-releases@^1.1.19: + version "1.1.21" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.21.tgz#46c86f9adaceae4d63c75d3c2f2e6eee618e55f3" + integrity sha512-TwnURTCjc8a+ElJUjmDqU6+12jhli1Q61xOQmdZ7ECZVBZuQpN/1UnembiIHDM1wCcfLvh5wrWXUF5H6ufX64Q== dependencies: semver "^5.3.0" @@ -5851,12 +5894,12 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -optimism@^0.6.9: - version "0.6.9" - resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.9.tgz#19258ff8b3be0cea29ac35f06bff818e026e30bb" - integrity sha512-xoQm2lvXbCA9Kd7SCx6y713Y7sZ6fUc5R6VYpoL5M6svKJbTuvtNopexK8sO8K4s0EOUYHuPN2+yAEsNyRggkQ== +optimism@^0.9.0: + version "0.9.5" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.9.5.tgz#b8b5dc9150e97b79ddbf2d2c6c0e44de4d255527" + integrity sha512-lNvmuBgONAGrUbj/xpH69FjMOz1d0jvMNoOCKyVynUPzq2jgVlGL4jFYJqrUHzUfBv+jAFSCP61x5UkfbduYJA== dependencies: - immutable-tuple "^0.4.9" + "@wry/context" "^0.4.0" optimist@^0.6.1: version "0.6.1" @@ -6184,6 +6227,18 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@~1.14.3: + version "1.14.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" + integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== + pretty-format@^24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" @@ -6476,7 +6531,7 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: +regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== @@ -6491,10 +6546,10 @@ regenerator-runtime@^0.13.2: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== -regenerator-transform@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb" - integrity sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A== +regenerator-transform@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.0.tgz#2ca9aaf7a2c239dd32e4761218425b8c7a86ecaf" + integrity sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w== dependencies: private "^0.1.6" @@ -6506,14 +6561,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.1.tgz#27b455f9b138ca2e84c090e9aff1ffe2a04d97fa" - integrity sha512-HwRjOquc9QOwKTgbxvZTcddS5mlNlwePMQ3NFL8broajMLD5CXDAqas8Y5yxJH5QtZp5iRor3YCILd5pz71Cgw== - dependencies: - cli-table3 "^0.5.0" - colors "^1.1.2" - yargs "^12.0.5" +regexp-tree@^0.1.6: + version "0.1.10" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" + integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== regexpp@^2.0.1: version "2.0.1" @@ -6797,15 +6848,15 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== -semver@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65" - integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ== +semver@^6.0.0, semver@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.0.tgz#e95dc415d45ecf03f2f9f83b264a6b11f49c0cca" + integrity sha512-kCqEOOHoBcFs/2Ccuk4Xarm/KiWRSLEX9CAZF8xkJ6ZPlIoTZ8V5f7J16vYLJqDbR7KrxTJpR2lqjIEm2Qx9cQ== send@0.17.1: version "0.17.1" @@ -7510,6 +7561,13 @@ ts-invariant@^0.3.2: dependencies: tslib "^1.9.3" +ts-invariant@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.2.tgz#8685131b8083e67c66d602540e78763408be9113" + integrity sha512-PTAAn8lJPEdRBJJEs4ig6MVZWfO12yrFzV7YaPslmyhG7+4MA279y4BXT3f72gXeVl0mC1aAWq2rMX4eKTWU/Q== + dependencies: + tslib "^1.9.3" + tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -8035,7 +8093,7 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^12.0.2, yargs@^12.0.5: +yargs@^12.0.2: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== diff --git a/package.json b/package.json index 29950b65c..0c2e47271 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "devDependencies": { "codecov": "^3.5.0", "cross-env": "^5.2.0", - "cypress": "^3.2.0", - "cypress-cucumber-preprocessor": "^1.11.0", - "cypress-plugin-retries": "^1.2.1", + "cypress": "^3.3.1", + "cypress-cucumber-preprocessor": "^1.11.2", + "cypress-plugin-retries": "^1.2.2", "dotenv": "^8.0.0", "faker": "^4.1.0", "graphql-request": "^1.8.2", diff --git a/webapp/.eslintrc.js b/webapp/.eslintrc.js index fdc9bfb5e..0400fe5f2 100644 --- a/webapp/.eslintrc.js +++ b/webapp/.eslintrc.js @@ -2,24 +2,30 @@ module.exports = { root: true, env: { browser: true, - node: true + node: true, + jest: true }, parserOptions: { parser: 'babel-eslint' }, extends: [ + 'standard', 'plugin:vue/recommended', 'plugin:prettier/recommended' ], // required to lint *.vue files plugins: [ 'vue', - 'prettier' + 'prettier', + 'jest' ], // add your custom rules here rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + //'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'no-console': ['error'], 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', - 'vue/component-name-in-template-casing': ['error', 'kebab-case'] + 'vue/component-name-in-template-casing': ['error', 'kebab-case'], + 'prettier/prettier': ['error'], + // 'newline-per-chained-call': [2] } } diff --git a/webapp/.prettierrc b/webapp/.prettierrc deleted file mode 100644 index 7dc4f8263..000000000 --- a/webapp/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "semi": false, - "singleQuote": true, - "tabWidth": 2, - "bracketSpacing": true -} diff --git a/webapp/.prettierrc.js b/webapp/.prettierrc.js new file mode 100644 index 000000000..e2cf91e91 --- /dev/null +++ b/webapp/.prettierrc.js @@ -0,0 +1,9 @@ + +module.exports = { + semi: false, + printWidth: 100, + singleQuote: true, + trailingComma: "all", + tabWidth: 2, + bracketSpacing: true +}; diff --git a/webapp/components/Badges.vue b/webapp/components/Badges.vue index b28412abe..ff8a2bd35 100644 --- a/webapp/components/Badges.vue +++ b/webapp/components/Badges.vue @@ -23,14 +23,14 @@ import HcImage from './Image' export default { components: { - HcImage + HcImage, }, props: { badges: { type: Array, - default: () => [] - } - } + default: () => [], + }, + }, } diff --git a/webapp/components/Category/index.spec.js b/webapp/components/Category/index.spec.js index 149f96189..7ce0b7243 100644 --- a/webapp/components/Category/index.spec.js +++ b/webapp/components/Category/index.spec.js @@ -14,8 +14,8 @@ describe('Category', () => { localVue, propsData: { icon, - name - } + name, + }, }) } diff --git a/webapp/components/Category/index.vue b/webapp/components/Category/index.vue index af602d4d0..31c1aa97b 100644 --- a/webapp/components/Category/index.vue +++ b/webapp/components/Category/index.vue @@ -13,7 +13,7 @@ export default { name: 'HcCategory', props: { icon: { type: String, required: true }, - name: { type: String, required: true } - } + name: { type: String, default: '' }, + }, } diff --git a/webapp/components/Comment.spec.js b/webapp/components/Comment.spec.js index 83a738956..ebb9b8bf8 100644 --- a/webapp/components/Comment.spec.js +++ b/webapp/components/Comment.spec.js @@ -1,6 +1,5 @@ -import { config, shallowMount, mount, createLocalVue } from '@vue/test-utils' +import { config, shallowMount, createLocalVue } from '@vue/test-utils' import Comment from './Comment.vue' -import Vue from 'vue' import Vuex from 'vuex' import Styleguide from '@human-connection/styleguide' @@ -12,8 +11,6 @@ localVue.use(Styleguide) config.stubs['no-ssr'] = '
'
- )
+ .replace(/<\/(p|div|th|tr)>\s*(
\s*)+\s*<(p|div|th|tr)>/gim, '
')
// remove additional linebreaks inside p tags
- .replace(
- /<[a-z-]+>(<[a-z-]+>)*\s*(
\s*)+\s*(<\/[a-z-]+>)*<\/[a-z-]+>/gim,
- ''
- )
+ .replace(/<[a-z-]+>(<[a-z-]+>)*\s*(
\s*)+\s*(<\/[a-z-]+>)*<\/[a-z-]+>/gim, '')
// remove additional linebreaks when first child inside p tags
.replace(/
(\s*
\s*)+/gim, '
')
// remove additional linebreaks when last child inside p tags
.replace(/(\s*
\s*)+<\/p>/gim, '