merged master in

This commit is contained in:
Grzegorz Leoniec 2018-12-10 12:37:07 +01:00
commit 1f62e1d3f3
No known key found for this signature in database
GPG Key ID: 3AA43686D4EB1377
26 changed files with 1358 additions and 1416 deletions

18
.eslintrc.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
"extends": "standard",
"parser": "babel-eslint",
"env": {
"es6": true,
"node": true,
},
"rules": {
"indent": [
"error",
2
],
"quotes": [
"error",
"single"
]
}
};

View File

@ -1,24 +1,36 @@
language: node_js
node_js:
- "10"
services:
- docker
cache:
yarn: true
directories:
- node_modules
services:
- docker
env:
- DOCKER_COMPOSE_VERSION=1.23.2
before_install:
- sudo rm /usr/local/bin/docker-compose
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
install:
- docker build --build-arg BUILD_COMMIT=$TRAVIS_COMMIT -t humanconnection/nitro-backend .
- docker build --build-arg BUILD_COMMIT=$TRAVIS_COMMIT -t humanconnection/nitro-backend:latest .
- docker-compose up -d
script:
# TODO: re-add when testing is setup properly
# - docker run humanconnection/nitro-backend yarn run db:seed
- docker-compose exec backend yarn run eslint
- docker-compose exec backend yarn run mocha
- docker-compose exec backend yarn run db:reset
- docker-compose exec backend yarn run db:seed
after_success:
# - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
# - chmod +x send.sh
# - ./send.sh success $WEBHOOK_URL
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
- chmod +x send.sh
- ./send.sh success $WEBHOOK_URL
- if [ $TRAVIS_BRANCH == "master" ] && [ $TRAVIS_EVENT_TYPE == "push" ]; then
docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD";
docker tag humanconnection/nitro-backend humanconnection/nitro-backend:latest;
@ -29,3 +41,19 @@ after_failure:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
- chmod +x send.sh
- ./send.sh failure $WEBHOOK_URL
deploy:
- provider: script
script: scripts/deploy.sh nitro.human-connection.org
on:
branch: master
tags: true
- provider: script
script: scripts/deploy.sh nitro-staging.human-connection.org
on:
branch: master
- provider: script
script: scripts/deploy.sh "nitro-$(git rev-parse --short HEAD).human-connection.org"
on:
tags: true
all_branches: true

View File

@ -1,2 +1,2 @@
FROM neo4j:3.4
RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/3.4.0.3/apoc-3.4.0.3-all.jar -P plugins/
FROM neo4j:3.5.0
RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/3.5.0.1/apoc-3.5.0.1-all.jar -P plugins/

View File

@ -21,6 +21,9 @@
> We still need to evaluate the drawbacks and estimate the development
> cost of such an approach
## How to get in touch
Connect with other developers over [Discord](https://discord.gg/6ub73U3)
## Quick Start
### Installation with Docker
@ -30,7 +33,7 @@ Run:
docker-compose up
# if you want seed data
# open another terminal and run
docker-compose exec backend yarn run seedDb
docker-compose exec backend yarn run db:seed
```
App is [running on port 4000](http://localhost:4000/)
@ -92,24 +95,39 @@ run Neo4j in one of the [many cloud options](https://neo4j.com/developer/guide-c
[spin up Neo4j in a Docker container](https://neo4j.com/developer/docker/) or on Debian-based systems install [Neo4j from the Debian Repository](http://debian.neo4j.org/).
Just be sure to update the Neo4j connection string and credentials accordingly in `.env`.
## Mocking API Results
## Mock API Results
Alternatively you can just mock all responses from the api which let
you build a frontend application without running a neo4j instance.
Just set `MOCK=true` inside `.env` or pass it on application start.
## Seeding The Database
## Seed and Reset the Database
Optionally you can seed the GraphQL service by executing mutations that
will write sample data to the database:
```bash
yarn db:seed
yarn run db:seed
# -or-
npm run db:seed
```
For a reset you can use the reset script:
```bash
yarn db:reset
# -or-
npm run db:reset
```
## Run Tests
```bash
yarn run test
# -or-
npm run test
```
## Todo`s
- [x] add jwt authentication

View File

@ -2,15 +2,10 @@ version: "3.7"
services:
backend:
container_name: backend.127.0.0.1.xip.io
volumes:
- .:/backend
- /backend/node_modules
- .:/nitro-backend
- /nitro-backend/node_modules
neo4j:
ports:
- 7687:7687
- 7474:7474
networks:
hc-network:
name: hc-network

View File

@ -32,6 +32,7 @@ services:
networks:
hc-network:
name: hc-network
volumes:
neo4j-data:

View File

@ -6,14 +6,15 @@ First of all start minikube on your machine:
```sh
minikube start
```
[troubleshoot] If you get an error message along th lines of 'The vboxdrv kernel module is not loaded.' - then you have the same issue i had. to solve this you need to install the propper linux kernel host modules package. Here an example for Manjaro:
**[troubleshoot]** If you get an error message along th lines of 'The vboxdrv kernel module is not loaded.' - then you have the same issue i had. to solve this you need to install the propper linux kernel host modules package. Here an example for Manjaro:
https://forum.manjaro.org/t/installing-virtualbox-kernel-modules/6999
**[troubleshoot]** When you can not start minikube, try also to remove the cluster with `minikube delete` and start again with `minikube start`. Sometimes this fix startup problems of the cluster.
You can always get an overview and see what's going on with your minikube:
```sh
minikube dashboard
```
[troubleshoot] now again you might run into trouble with an error like 'kubectl could not be found on your path.' In this case run the following command:
**[troubleshoot]** now again you might run into trouble with an error like 'kubectl could not be found on your path.' In this case run the following command:
```sh
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/amd64/kubectl && chmod +x kubectl && sudo cp kubectl /usr/local/bin/ && rm kubectl
```

View File

@ -3,53 +3,70 @@
"version": "0.0.1",
"description": "GraphQL Backend for Human Connection",
"main": "src/index.js",
"config": {
"no_auth": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 PERMISSIONS=disabled"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 0",
"mocha": "./node_modules/.bin/mocha --require @babel/register src/**/*.test.js",
"eslint": "eslint src --config .eslintrc.js",
"start": "./node_modules/.bin/nodemon --exec babel-node src/index.js",
"start:debug": "./node_modules/.bin/nodemon --exec babel-node --inspect=0.0.0.0:9229 src/index.js",
"db:seed": "concurrently --kill-others --success first 'cross-env GRAPHQL_URI=http://localhost:4001 PERMISSIONS=disabled GRAPHQL_PORT=4001 yarn run start' 'wait-on tcp:4001 && cross-env GRAPHQL_URI=http://localhost:4001 ./node_modules/.bin/babel-node src/seed/seed-db.js'"
"db:script:seed": "wait-on tcp:4001 && ./node_modules/.bin/babel-node src/seed/seed-db.js",
"db:script:reset": "wait-on tcp:4001 && ./node_modules/.bin/babel-node src/seed/reset-db.js",
"db:seed": "$npm_package_config_no_auth run-p --race start db:script:seed",
"db:reset": "$npm_package_config_no_auth run-p --race start db:script:reset"
},
"author": "Human Connection gGmbH",
"license": "MIT",
"dependencies": {
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
"@babel/node": "^7.0.0",
"@babel/preset-env": "^7.1.6",
"@babel/register": "^7.0.0",
"apollo-cache-inmemory": "^1.2.5",
"apollo-client": "^2.3.2",
"apollo-link-http": "^1.5.4",
"apollo-server": "^2.0.4",
"bcryptjs": "^2.4.3",
"cheerio": "^1.0.0-rc.2",
"date-fns": "^2.0.0-alpha.24",
"dotenv": "^6.0.0",
"graphql-custom-directives": "^0.2.13",
"graphql-iso-date": "^3.6.1",
"graphql-middleware": "1.7.6",
"graphql-shield": "^4.0.1",
"graphql-tag": "^2.9.2",
"graphql-yoga": "1.16.2",
"jsonwebtoken": "^8.3.0",
"linkifyjs": "^2.1.7",
"lodash": "^4.17.11",
"ms": "^2.1.1",
"neo4j-driver": "^1.6.1",
"neo4j-graphql-js": "1.0.5",
"node-fetch": "^2.1.2",
"passport": "^0.4.0",
"passport-jwt": "^4.0.0",
"request": "^2.88.0",
"sanitize-html": "^1.19.1",
"slug": "^0.9.1",
"trunc-html": "^1.1.2"
"@babel/cli": "~7.2.0",
"@babel/core": "~7.2.0",
"@babel/node": "~7.2.0",
"@babel/preset-env": "~7.2.0",
"@babel/register": "~7.0.0",
"apollo-cache-inmemory": "~1.3.11",
"apollo-client": "~2.4.7",
"apollo-link-http": "~1.5.7",
"apollo-server": "~2.2.6",
"bcryptjs": "~2.4.3",
"cheerio": "~1.0.0-rc.2",
"cross-env": "~5.2.0",
"date-fns": "^2.0.0-alpha.25",
"dotenv": "~6.2.0",
"graphql": "~0.13.0",
"graphql-custom-directives": "~0.2.14",
"graphql-iso-date": "~3.6.1",
"graphql-middleware": "2.0.2",
"graphql-shield": "~4.1.0",
"graphql-tag": "~2.10.0",
"graphql-yoga": "~1.16.7",
"jsonwebtoken": "~8.4.0",
"linkifyjs": "~2.1.7",
"lodash": "~4.17.11",
"ms": "~2.1.1",
"neo4j-driver": "~1.7.2",
"neo4j-graphql-js": "2.0.1",
"node-fetch": "~2.3.0",
"passport": "~0.4.0",
"passport-jwt": "~4.0.0",
"sanitize-html": "~1.19.3",
"slug": "~0.9.2",
"trunc-html": "~1.1.2"
},
"devDependencies": {
"concurrently": "^4.1.0",
"cross-env": "^5.2.0",
"faker": "^4.1.0",
"nodemon": "^1.18.7",
"wait-on": "^3.2.0"
"apollo-server-testing": "~2.2.6",
"babel-eslint": "~10.0.1",
"chai": "~4.2.0",
"eslint": "~5.9.0",
"eslint-config-standard": "~12.0.0",
"eslint-plugin-import": "~2.14.0",
"eslint-plugin-node": "~8.0.0",
"eslint-plugin-promise": "~4.0.1",
"eslint-plugin-standard": "~4.0.0",
"faker": "~4.1.0",
"mocha": "^5.2.0",
"nodemon": "~1.18.7",
"npm-run-all": "~4.1.5",
"wait-on": "~3.2.0"
}
}

4
scripts/deploy.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
echo "See me deployed at $1 :)"

View File

@ -4,7 +4,7 @@ import {
GraphQLDefaultToDirective
} from 'graphql-custom-directives'
export default function applyDirectives(augmentedSchema) {
export default function applyDirectives (augmentedSchema) {
const directives = [
GraphQLLowerCaseDirective,
GraphQLTrimDirective,

View File

@ -4,7 +4,7 @@ let driver
export default function () {
return {
getDriver() {
getDriver () {
if (!driver) {
driver = neo4j.driver(
process.env.NEO4J_URI || 'bolt://localhost:7687',

View File

@ -4,7 +4,7 @@ import {
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

View File

@ -7,10 +7,10 @@ import generateJwt from './jwt/generateToken'
import { fixUrl } from './middleware/fixImageUrlsMiddleware'
export const typeDefs =
fs.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, "schema.graphql"))
fs.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
.toString('utf-8')
const query = (cypher, session) => {
export const query = (cypher, session) => {
return new Promise((resolve, reject) => {
let data = []
session
@ -54,15 +54,15 @@ export const resolvers = {
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`,
countFollows: `MATCH (:User)-[r:FOLLOWS]->(:User) RETURN COUNT(r) AS countFollows`,
countShouts: `MATCH (:User)-[r:SHOUTED]->(:Post) RETURN COUNT(r) AS countShouts`
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'
}
let data = {
countUsers: (await queryOne(queries.countUsers, session)).countUsers,

View File

@ -1,64 +1,4 @@
import { GraphQLServer } from 'graphql-yoga'
import { makeExecutableSchema } from 'apollo-server'
import { augmentSchema } from 'neo4j-graphql-js'
import { typeDefs, resolvers } from './graphql-schema'
import dotenv from 'dotenv'
import mocks from './mocks'
import middleware from './middleware'
import applyDirectives from './bootstrap/directives'
import applyScalars from './bootstrap/scalars'
import neo4j from './bootstrap/neo4j'
import passport from 'passport'
import jwtStrategy from './jwt/strategy'
import jwt from 'jsonwebtoken'
dotenv.config()
let schema = makeExecutableSchema({
typeDefs,
resolvers
})
const driver = neo4j().getDriver()
const MOCK = (process.env.MOCK === 'true')
console.log('MOCK:', MOCK)
schema = augmentSchema(schema, {
query: {
exclude: ['Statistics', 'LoggedInUser']
},
mutation: {
exclude: ['Statistics', 'LoggedInUser']
}
})
schema = applyScalars(applyDirectives(schema))
const server = new GraphQLServer({
context: async (req) => {
const payload = {
driver,
user: null,
req: req.request
}
try {
const token = payload.req.headers.authorization.replace('Bearer ', '')
payload.user = await jwt.verify(token, process.env.JWT_SECRET)
} catch (err) {}
return payload
},
schema: schema,
tracing: true,
middlewares: middleware(schema),
mocks: MOCK ? mocks : false
})
passport.use('jwt', jwtStrategy())
server.express.use(passport.initialize())
server.express.post('/graphql', passport.authenticate(['jwt'], { session: false }))
import server from './server'
const serverConfig = {
port: process.env.GRAPHQL_PORT || 4000
@ -68,6 +8,6 @@ const serverConfig = {
// }
}
server.start(serverConfig, options => {
console.log(`Server ready at ${process.env.GRAPHQL_URI} 🚀`);
server.start(serverConfig, options => {
console.log(`Server ready at ${process.env.GRAPHQL_URI} 🚀`)
})

View File

@ -3,7 +3,7 @@ import jwt from 'jsonwebtoken'
import ms from 'ms'
// Generate an Access Token for the given User ID
export default function generateJwt(user) {
export default function generateJwt (user) {
const token = jwt.sign(user, process.env.JWT_SECRET, {
expiresIn: ms('1d'),
issuer: process.env.GRAPHQL_URI,

View File

@ -20,7 +20,10 @@ export default () => {
(JWTPayload, next) => {
// usually this would be a database call:
// var user = users[_.findIndex(users, {id: JWTPayload.id})]
// TODO: fix https://github.com/Human-Connection/Nitro-Backend/issues/41
/* eslint-disable */
if (true) {
/* eslint-enable */
next(null, {})
} else {
next(null, false)

View File

@ -1,17 +1,22 @@
import { rule, shield, and, or, not, allow } from 'graphql-shield'
import { rule, shield, allow } from 'graphql-shield'
/*
* TODO: implement
* See: https://github.com/Human-Connection/Nitro-Backend/pull/40#pullrequestreview-180898363
const isAuthenticated = rule()(async (parent, args, ctx, info) => {
return ctx.user !== null
})
const isOwner = rule()(async (parent, args, ctx, info) => {
return ctx.user.id === parent.id
})
const isAdmin = rule()(async (parent, args, ctx, info) => {
return ctx.user.role === 'ADMIN'
})
const isModerator = rule()(async (parent, args, ctx, info) => {
return ctx.user.role === 'MODERATOR'
})
*/
const isOwner = rule()(async (parent, args, ctx, info) => {
return ctx.user.id === parent.id
})
// Permissions
const permissions = shield({

View File

@ -0,0 +1,17 @@
import { describe, it } from 'mocha'
describe('query', () => {
describe('statistics', () => {
describe('authenticated user', () => {
describe('read', () => {
it('is forbidden')
})
})
describe('admin', () => {
describe('read', () => {
it('is permitted')
})
})
})
})

View File

@ -1,5 +1,4 @@
import walkRecursive from './helpers/walkRecursive'
import trunc from 'trunc-html'
// import { getByDot, setByDot, getItems, replaceItems } from 'feathers-hooks-common'
import sanitizeHtml from 'sanitize-html'
// import { isEmpty, intersection } from 'lodash'

View File

@ -1,5 +1,3 @@
import faker from 'faker'
export default () => {
return `mutation {
o1: CreateOrganization(

View File

@ -6,7 +6,7 @@ export default function (data) {
p1: CreatePost(
id: "p1",
title: "Gedanken eines Polizisten zum Einsatz im Hambacher Forst",
content: "<p><strong>Diese Zukunftsstadt ist real und keine Computer-Animation</strong> sondern sie ist das Lebenswerk des mittlerweile über 100 Jahre alten Futuristen und Architekten Jacque Fresco aus Florida. In 35 Jahren (seit seinem 13. Lebensjahr) hat dieser zusammen mit seiner Frau seinen futuristischen Traum von einer besonderen Zukunftsstadt auf 85.000 Quadratmetern realisiert. In den Gebäuden und Gärten befinden sich u.a. ein Forschungszentrum, Vortragsräume und unzählige seiner Modelle &amp; Architekturentwürfe.</p><br /><p>Sein zentrales Anliegen ist eine resourcenbasierte Wirtschaft und die Abschaffung von Geld und Privatbesitz. Mit Hilfe von Roboterarbeit und dem Bedingungslosen Grundeinkommen (da nach seiner Ansicht in den kommenden Jahren fast alle Jobs automatisiert werden), möchte er eine ökologische Landwirtschaft mit Permakulturen etc. und eine effiziente Energiegewinnung (ausschließlich durch regenerative Energien) schaffen. Wenige kompatible Formen in einer sparsamen Modulbauweise (in die u.a. bereits variable Service- und Reparaturelemente integriert sind) sollen insgesamt eine soziale &amp; ökologische Utopie im Einklang mit der Natur ermöglichen.</p><br /><p>Nachfolgend der Direkt-Link auf den interessanten Artikel von Zoltan Istvan, der den Architekten und seine Frau in Florida besuchen durfte und seinen Artikel Ende 2016 auf „MOTHERBOARD“ veröffentlicht hatte:</p><br /><p>https://motherboard.vice.com/de/article/vv34nb/ich-habe-die-zukunft-besucht-in-der-wir-ohne-geld-steuern-und-besitz-leben </p><br /><p>Da soll noch jemand behaupten, es gäbe keine Utopien mehr bzw. keine Futuristen, die ihre kreativen und zukunftsfähigen Ideen (auch in ganz großem Stil) selbst in die Tat umsetzen. LG @all :) </p><br /><p><strong>Wir sind eine Menschheitsfamilie. • Wir sind eins. • Wir sind HUMAN CONNECTION</strong> ❤️</p>",
content: "<p><strong>Diese Zukunftsstadt ist real und keine Computer-Animation</strong> sondern sie ist das Lebenswerk des mittlerweile über 100 Jahre alten Futuristen und Architekten Jacque Fresco aus Florida. In 35 Jahren (seit seinem 13. Lebensjahr) hat dieser zusammen mit seiner Frau seinen futuristischen Traum von einer besonderen Zukunftsstadt auf 85.000 Quadratmetern realisiert. In den Gebäuden und Gärten befinden sich u.a. ein Forschungszentrum, Vortragsräume und unzählige seiner Modelle &amp; Architekturentwürfe.</p><br /><p>Sein zentrales Anliegen ist eine resourcenbasierte Wirtschaft und die Abschaffung von Geld und Privatbesitz. Mit Hilfe von Roboterarbeit und dem Bedingungslosen Grundeinkommen (da nach seiner Ansicht in den kommenden Jahren fast alle Jobs automatisiert werden), möchte er eine ökologische Landwirtschaft mit Permakulturen etc. und eine effiziente Energiegewinnung (ausschließlich durch regenerative Energien) schaffen. Wenige kompatible Formen in einer sparsamen Modulbauweise (in die u.a. bereits variable Service- und Reparaturelemente integriert sind) sollen insgesamt eine soziale &amp; ökologische Utopie im Einklang mit der Natur ermöglichen.</p><br /><p>Nachfolgend der Direkt-Link auf den interessanten Artikel von Zoltan Istvan, der den Architekten und seine Frau in Florida besuchen durfte und seinen Artikel Ende 2016 auf „MOTHERBOARD“ veröffentlicht hatte:</p><br /><p>https://motherboard.vice.com/de/article/vv34nb/ich-habe-die-zukunft-besucht-in-der-wir-ohne-geld-steuern-und-besitz-leben</p><br /><p>Da soll noch jemand behaupten, es gäbe keine Utopien mehr bzw. keine Futuristen, die ihre kreativen und zukunftsfähigen Ideen (auch in ganz großem Stil) selbst in die Tat umsetzen. LG @all :)</p><br /><p><strong>Wir sind eine Menschheitsfamilie. • Wir sind eins. • Wir sind HUMAN CONNECTION</strong>❤️</p>",
image: "https://picsum.photos/1280/1024?image=352",
visibility: public,
disabled: false,
@ -31,7 +31,7 @@ export default function (data) {
p2: CreatePost(
id: "p2",
title: "Julian Assange",
content: "<p><strong>Diese Zukunftsstadt ist real und keine Computer-Animation</strong> sondern sie ist das Lebenswerk des mittlerweile über 100 Jahre alten Futuristen und Architekten Jacque Fresco aus Florida. In 35 Jahren (seit seinem 13. Lebensjahr) hat dieser zusammen mit seiner Frau seinen futuristischen Traum von einer besonderen Zukunftsstadt auf 85.000 Quadratmetern realisiert. In den Gebäuden und Gärten befinden sich u.a. ein Forschungszentrum, Vortragsräume und unzählige seiner Modelle &amp; Architekturentwürfe.</p><br /><p>Sein zentrales Anliegen ist eine resourcenbasierte Wirtschaft und die Abschaffung von Geld und Privatbesitz. Mit Hilfe von Roboterarbeit und dem Bedingungslosen Grundeinkommen (da nach seiner Ansicht in den kommenden Jahren fast alle Jobs automatisiert werden), möchte er eine ökologische Landwirtschaft mit Permakulturen etc. und eine effiziente Energiegewinnung (ausschließlich durch regenerative Energien) schaffen. Wenige kompatible Formen in einer sparsamen Modulbauweise (in die u.a. bereits variable Service- und Reparaturelemente integriert sind) sollen insgesamt eine soziale &amp; ökologische Utopie im Einklang mit der Natur ermöglichen.</p><br /><p>Nachfolgend der Direkt-Link auf den interessanten Artikel von Zoltan Istvan, der den Architekten und seine Frau in Florida besuchen durfte und seinen Artikel Ende 2016 auf „MOTHERBOARD“ veröffentlicht hatte:</p><br /><p>https://motherboard.vice.com/de/article/vv34nb/ich-habe-die-zukunft-besucht-in-der-wir-ohne-geld-steuern-und-besitz-leben </p><br /><p>Da soll noch jemand behaupten, es gäbe keine Utopien mehr bzw. keine Futuristen, die ihre kreativen und zukunftsfähigen Ideen (auch in ganz großem Stil) selbst in die Tat umsetzen. LG @all :) </p><br /><p><strong>Wir sind eine Menschheitsfamilie. • Wir sind eins. • Wir sind HUMAN CONNECTION</strong> ❤️</p>",
content: "<p><strong>Diese Zukunftsstadt ist real und keine Computer-Animation</strong> sondern sie ist das Lebenswerk des mittlerweile über 100 Jahre alten Futuristen und Architekten Jacque Fresco aus Florida. In 35 Jahren (seit seinem 13. Lebensjahr) hat dieser zusammen mit seiner Frau seinen futuristischen Traum von einer besonderen Zukunftsstadt auf 85.000 Quadratmetern realisiert. In den Gebäuden und Gärten befinden sich u.a. ein Forschungszentrum, Vortragsräume und unzählige seiner Modelle &amp; Architekturentwürfe.</p><br /><p>Sein zentrales Anliegen ist eine resourcenbasierte Wirtschaft und die Abschaffung von Geld und Privatbesitz. Mit Hilfe von Roboterarbeit und dem Bedingungslosen Grundeinkommen (da nach seiner Ansicht in den kommenden Jahren fast alle Jobs automatisiert werden), möchte er eine ökologische Landwirtschaft mit Permakulturen etc. und eine effiziente Energiegewinnung (ausschließlich durch regenerative Energien) schaffen. Wenige kompatible Formen in einer sparsamen Modulbauweise (in die u.a. bereits variable Service- und Reparaturelemente integriert sind) sollen insgesamt eine soziale &amp; ökologische Utopie im Einklang mit der Natur ermöglichen.</p><br /><p>Nachfolgend der Direkt-Link auf den interessanten Artikel von Zoltan Istvan, der den Architekten und seine Frau in Florida besuchen durfte und seinen Artikel Ende 2016 auf „MOTHERBOARD“ veröffentlicht hatte:</p><br /><p>https://motherboard.vice.com/de/article/vv34nb/ich-habe-die-zukunft-besucht-in-der-wir-ohne-geld-steuern-und-besitz-leben</p><br /><p>Da soll noch jemand behaupten, es gäbe keine Utopien mehr bzw. keine Futuristen, die ihre kreativen und zukunftsfähigen Ideen (auch in ganz großem Stil) selbst in die Tat umsetzen. LG @all :)</p><br /><p><strong>Wir sind eine Menschheitsfamilie. • Wir sind eins. • Wir sind HUMAN CONNECTION</strong>❤️</p>",
image: "https://picsum.photos/1280/1024?image=72",
visibility: public,
disabled: false,

23
src/seed/reset-db.js Normal file
View File

@ -0,0 +1,23 @@
import { query } from '../graphql-schema'
import dotenv from 'dotenv'
import neo4j from '../bootstrap/neo4j'
dotenv.config()
if (process.env.NODE_ENV === 'production') {
throw new Error('YOU CAN`T UNSEED IN PRODUCTION MODE')
}
const driver = neo4j().getDriver()
const session = driver.session()
query('MATCH (n) DETACH DELETE n', session).then(() => {
console.log('Successfully deleted all nodes and relations!')
}).catch((err) => {
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`)
}).finally(() => {
if (session) {
session.close()
}
process.exit(0)
})

View File

@ -1,12 +1,11 @@
import ApolloClient from "apollo-client";
import dotenv from "dotenv";
import gql from 'graphql-tag'
import fetch from "node-fetch";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from 'apollo-client'
import dotenv from 'dotenv'
import fetch from 'node-fetch'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import Seed from './data/index'
dotenv.config();
dotenv.config()
if (process.env.NODE_ENV === 'production') {
throw new Error('YOU CAN`T SEED IN PRODUCTION MODE')
@ -15,6 +14,6 @@ if (process.env.NODE_ENV === 'production') {
const client = new ApolloClient({
link: new HttpLink({ uri: process.env.GRAPHQL_URI, fetch }),
cache: new InMemoryCache()
});
})
Seed(client)

View File

@ -137,7 +137,7 @@ export default {
const chars = '23456789abcdefghkmnpqrstuvwxyzABCDEFGHJKLMNPRSTUVWXYZ'
let code = ''
for (let i = 0; i < 8; i++) {
const n = _.random(0, chars.length-1)
const n = _.random(0, chars.length - 1)
code += chars.substr(n, 1)
}
return code

63
src/server.js Normal file
View File

@ -0,0 +1,63 @@
import { GraphQLServer } from 'graphql-yoga'
import { makeExecutableSchema } from 'apollo-server'
import { augmentSchema } from 'neo4j-graphql-js'
import { typeDefs, resolvers } from './graphql-schema'
import dotenv from 'dotenv'
import mocks from './mocks'
import middleware from './middleware'
import applyDirectives from './bootstrap/directives'
import applyScalars from './bootstrap/scalars'
import neo4j from './bootstrap/neo4j'
import passport from 'passport'
import jwtStrategy from './jwt/strategy'
import jwt from 'jsonwebtoken'
dotenv.config()
let schema = makeExecutableSchema({
typeDefs,
resolvers
})
const driver = neo4j().getDriver()
const MOCK = (process.env.MOCK === 'true')
console.log('MOCK:', MOCK)
schema = augmentSchema(schema, {
query: {
exclude: ['Statistics', 'LoggedInUser']
},
mutation: {
exclude: ['Statistics', 'LoggedInUser']
}
})
schema = applyScalars(applyDirectives(schema))
const server = new GraphQLServer({
context: async (req) => {
const payload = {
driver,
user: null,
req: req.request
}
try {
const token = payload.req.headers.authorization.replace('Bearer ', '')
payload.user = await jwt.verify(token, process.env.JWT_SECRET)
} catch (err) {}
return payload
},
schema: schema,
tracing: true,
middlewares: middleware(schema),
mocks: MOCK ? mocks : false
})
passport.use('jwt', jwtStrategy())
server.express.use(passport.initialize())
server.express.post('/graphql', passport.authenticate(['jwt'], { session: false }))
export default server

2329
yarn.lock

File diff suppressed because it is too large Load Diff