diff --git a/.travis.yml b/.travis.yml index 6ba9d7f12..42b427a11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,8 @@ before_install: install: - docker-compose -f docker-compose.yml -f docker-compose.travis.yml up --build -d - - wait-on http://localhost:7474 && docker-compose exec neo4j migrate + # avoid "Database constraints have changed after this transaction started" + - wait-on http://localhost:7474 script: # Backend diff --git a/SUMMARY.md b/SUMMARY.md index fdf3600b4..701eac2d0 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -3,6 +3,7 @@ * [Introduction](README.md) * [Edit this Documentation](edit-this-documentation.md) * [Installation](installation.md) +* [Neo4J](neo4j/README.md) * [Backend](backend/README.md) * [GraphQL](backend/graphql.md) * [Webapp](webapp/README.md) diff --git a/backend/README.md b/backend/README.md index 7c4d3a3e9..3cce123ac 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1,8 +1,6 @@ # Backend -## Installation -{% tabs %} -{% tab title="Docker" %} +## Installation with Docker Run the following command to install everything through docker. @@ -14,28 +12,15 @@ $ docker-compose up # rebuild the containers for a cleanup $ docker-compose up --build ``` -Open another terminal and create unique indices with: -```bash -$ docker-compose exec neo4j migrate -``` +Wait a little until your backend is up and running at [http://localhost:4000/](http://localhost:4000/). -{% endtab %} - -{% tab title="Without Docker" %} +## Installation without Docker For the local installation you need a recent version of [node](https://nodejs.org/en/) -(>= `v10.12.0`) and [Neo4J](https://neo4j.com/) along with -[Apoc](https://github.com/neo4j-contrib/neo4j-apoc-procedures) plugin installed -on your system. +(>= `v10.12.0`). -Download [Neo4j Community Edition](https://neo4j.com/download-center/#releases) and unpack the files. - -Download [Neo4j Apoc](https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases) and drop the file into the `plugins` folder of the just extracted Neo4j-Server -Note that grand-stack-starter does not currently bundle a distribution of Neo4j. You can download [Neo4j Desktop](https://neo4j.com/download/) and run locally for development, spin up a [hosted Neo4j Sandbox instance](https://neo4j.com/download/), run Neo4j in one of the [many cloud options](https://neo4j.com/developer/guide-cloud-deployment/), [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`. -Start Neo4J and confirm the database is running at [http://localhost:7474](http://localhost:7474). - -Now install node dependencies with [yarn](https://yarnpkg.com/en/): +Install node dependencies with [yarn](https://yarnpkg.com/en/): ```bash $ cd backend $ yarn install @@ -46,14 +31,8 @@ Copy Environment Variables: # in backend/ $ cp .env.template .env ``` - -Configure the new files according to your needs and your local setup. - -Create unique indices with: - -```bash -$ ./neo4j/migrate.sh -``` +Configure the new file according to your needs and your local setup. Make sure +a [local Neo4J](http://localhost:7474) instance is up and running. Start the backend for development with: ```bash @@ -65,17 +44,12 @@ or start the backend in production environment with: yarn run start ``` -{% endtab %} -{% endtabs %} - Your backend is up and running at [http://localhost:4000/](http://localhost:4000/) -This will start the GraphQL service \(by default on localhost:4000\) where you can issue GraphQL requests or access GraphQL Playground in the browser. +This will start the GraphQL service \(by default on localhost:4000\) where you +can issue GraphQL requests or access GraphQL Playground in the browser. ![GraphQL Playground](../.gitbook/assets/graphql-playground.png) -You can access Neo4J through [http://localhost:7474/](http://localhost:7474/) -for an interactive `cypher` shell and a visualization of the graph. - #### Seed Database @@ -114,7 +88,8 @@ $ yarn run db:reset # Testing -**Beware**: We have no multiple database setup at the moment. We clean the database after each test, running the tests will wipe out all your data! +**Beware**: We have no multiple database setup at the moment. We clean the +database after each test, running the tests will wipe out all your data! {% tabs %} diff --git a/neo4j/.env.template b/neo4j/.env.template new file mode 100644 index 000000000..c58edee0e --- /dev/null +++ b/neo4j/.env.template @@ -0,0 +1,2 @@ +NEO4J_USERNAME=neo4j +NEO4J_PASSWORD=letmein diff --git a/neo4j/.gitignore b/neo4j/.gitignore new file mode 100644 index 000000000..4c49bd78f --- /dev/null +++ b/neo4j/.gitignore @@ -0,0 +1 @@ +.env diff --git a/neo4j/Dockerfile b/neo4j/Dockerfile index e94a89431..2c106882f 100644 --- a/neo4j/Dockerfile +++ b/neo4j/Dockerfile @@ -1,3 +1,11 @@ FROM neo4j:3.5.5 +LABEL Description="Neo4J database of the Social Network Human-Connection.org with preinstalled database constraints and indices" Vendor="Human Connection gGmbH" Version="0.0.1" Maintainer="Human Connection gGmbH (developer@human-connection.org)" + +ARG BUILD_COMMIT +ENV BUILD_COMMIT=$BUILD_COMMIT + 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/ -COPY migrate.sh /usr/local/bin/migrate +RUN apk add --no-cache --quiet procps +COPY db_setup.sh /usr/local/bin/db_setup +COPY entrypoint.sh /docker-entrypoint-wrapper.sh +ENTRYPOINT ["/docker-entrypoint-wrapper.sh"] diff --git a/neo4j/README.md b/neo4j/README.md new file mode 100644 index 000000000..379a89eec --- /dev/null +++ b/neo4j/README.md @@ -0,0 +1,64 @@ +# Neo4J + +Human Connection is a social network. Using a graph based database which can +model nodes and edges natively - a network - feels like an obvious choice. We +decided to use [Neo4j](https://neo4j.com/), the currently most used graph +database available. The community edition of Neo4J is Free and Open Source and +we try our best to keep our application compatible with the community edition +only. + +## Installation with Docker + +Run: + +```bash +docker-compose up +``` + +You can access Neo4J through [http://localhost:7474/](http://localhost:7474/) +for an interactive cypher shell and a visualization of the graph. + +## Installation without Docker + +Install community edition of [Neo4J]() along with the plugin +[Apoc](https://github.com/neo4j-contrib/neo4j-apoc-procedures) on your system. + +To do so, go to [releases](https://neo4j.com/download-center/#releases), choose +"Community Server", download the installation files for you operation system +and unpack the files. + +Download [Neo4j Apoc](https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases) +and drop the file into the `plugins` folder of the just extracted Neo4j-Server. + +### Alternatives + +You can download [Neo4j Desktop](https://neo4j.com/download/) and run locally +for development, spin up a +[hosted Neo4j Sandbox instance](https://neo4j.com/download/), run Neo4j in one +of the [many cloud options](https://neo4j.com/developer/guide-cloud-deployment/), +[spin up Neo4j in a Docker container](https://neo4j.com/developer/docker/), +on Archlinux you can install [neo4j-community from AUR](https://aur.archlinux.org/packages/neo4j-community/) +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 `backend/.env`. + +Start Neo4J and confirm the database is running at [http://localhost:7474](http://localhost:7474). + +## Database Indices and Constraints + +If you are not running our dedicated Neo4J [docker image](https://hub.docker.com/r/humanconnection/neo4j), +which is the case if you setup Neo4J locally without docker, then you have to +setup unique indices and database constraints manually. + +If you have `cypher-shell` available with your local installation of neo4j you +can run: + +```bash +# in folder neo4j/ +$ cp .env.template .env +$ ./db_setup.sh +``` + +Otherwise if you don't have `cypher-shell` available, simply copy the cypher +statements [from the script](./neo4j/db_setup.sh) and paste the scripts into your +database [browser frontend](http://localhost:7474). diff --git a/neo4j/db_setup.sh b/neo4j/db_setup.sh new file mode 100755 index 000000000..21ed54571 --- /dev/null +++ b/neo4j/db_setup.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +ENV_FILE=$(dirname "$0")/.env +[[ -f "$ENV_FILE" ]] && source "$ENV_FILE" + +if [ -z "$NEO4J_USERNAME" ] || [ -z "$NEO4J_PASSWORD" ]; then + echo "Please set NEO4J_USERNAME and NEO4J_PASSWORD environment variables." + echo "Setting up database constraints and indexes will probably fail because of authentication errors." + echo "E.g. you could \`cp .env.template .env\` unless you run the script in a docker container" +fi + +until echo 'RETURN "Connection successful" as info;' | cypher-shell +do + echo "Connecting to neo4j failed, trying again..." + sleep 1 +done + +echo ' +RETURN "Here is a list of indexes and constraints BEFORE THE SETUP:" as info; +CALL db.indexes(); +' | cypher-shell + +echo ' +CALL db.index.fulltext.createNodeIndex("full_text_search",["Post"],["title", "content"]); +CREATE CONSTRAINT ON (p:Post) ASSERT p.id IS UNIQUE; +CREATE CONSTRAINT ON (c:Comment) ASSERT c.id IS UNIQUE; +CREATE CONSTRAINT ON (c:Category) ASSERT c.id IS UNIQUE; +CREATE CONSTRAINT ON (u:User) ASSERT u.id IS UNIQUE; +CREATE CONSTRAINT ON (o:Organization) ASSERT o.id IS UNIQUE; +CREATE CONSTRAINT ON (t:Tag) ASSERT t.id IS UNIQUE; + + +CREATE CONSTRAINT ON (p:Post) ASSERT p.slug IS UNIQUE; +CREATE CONSTRAINT ON (c:Category) ASSERT c.slug IS UNIQUE; +CREATE CONSTRAINT ON (u:User) ASSERT u.slug IS UNIQUE; +CREATE CONSTRAINT ON (o:Organization) ASSERT o.slug IS UNIQUE; +' | cypher-shell + +echo ' +RETURN "Setting up all the indexes and constraints seems to have been successful. Here is a list AFTER THE SETUP:" as info; +CALL db.indexes(); +' | cypher-shell diff --git a/neo4j/entrypoint.sh b/neo4j/entrypoint.sh new file mode 100755 index 000000000..f9c1afbe1 --- /dev/null +++ b/neo4j/entrypoint.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# credits: https://github.com/javamonkey79 +# https://github.com/neo4j/docker-neo4j/issues/166 + +# turn on bash's job control +set -m + +# Start the primary process and put it in the background +/docker-entrypoint.sh neo4j & + +# Start the helper process +db_setup + +# the my_helper_process might need to know how to wait on the +# primary process to start before it does its work and returns + + +# now we bring the primary process back into the foreground +# and leave it there +fg %1 diff --git a/neo4j/migrate.sh b/neo4j/migrate.sh deleted file mode 100755 index 6f3361b8a..000000000 --- a/neo4j/migrate.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -# If the user has the password `neo4j` this is a strong indicator, that we are -# the initial default user. Before we can create constraints, we have to change -# the default password. This is a security feature of neo4j. -if echo ":exit" | cypher-shell --password neo4j 2> /dev/null ; then - if [[ -z "${NEO4J_PASSWORD}" ]]; then - echo "NEO4J_PASSWORD environment variable is undefined. I cannot set the initial password." - else - echo "CALL dbms.security.changePassword('${NEO4J_PASSWORD}');" | cypher-shell --password neo4j - fi -fi - -set -e - -echo ' -CALL db.index.fulltext.createNodeIndex("full_text_search",["Post"],["title", "content"]); -CREATE CONSTRAINT ON (p:Post) ASSERT p.id IS UNIQUE; -CREATE CONSTRAINT ON (c:Comment) ASSERT c.id IS UNIQUE; -CREATE CONSTRAINT ON (c:Category) ASSERT c.id IS UNIQUE; -CREATE CONSTRAINT ON (u:User) ASSERT u.id IS UNIQUE; -CREATE CONSTRAINT ON (o:Organization) ASSERT o.id IS UNIQUE; -CREATE CONSTRAINT ON (t:Tag) ASSERT t.id IS UNIQUE; - - -CREATE CONSTRAINT ON (p:Post) ASSERT p.slug IS UNIQUE; -CREATE CONSTRAINT ON (c:Category) ASSERT c.slug IS UNIQUE; -CREATE CONSTRAINT ON (u:User) ASSERT u.slug IS UNIQUE; -CREATE CONSTRAINT ON (o:Organization) ASSERT o.slug IS UNIQUE; -' | cypher-shell - -echo "Successfully created all indices and unique constraints:" -echo 'CALL db.indexes();' | cypher-shell diff --git a/scripts/docker_push.sh b/scripts/docker_push.sh index 6cd33ddd4..c70367005 100755 --- a/scripts/docker_push.sh +++ b/scripts/docker_push.sh @@ -2,7 +2,9 @@ echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin docker build --build-arg BUILD_COMMIT=$TRAVIS_COMMIT --target production -t humanconnection/nitro-backend:latest $TRAVIS_BUILD_DIR/backend docker build --build-arg BUILD_COMMIT=$TRAVIS_COMMIT --target production -t humanconnection/nitro-web:latest $TRAVIS_BUILD_DIR/webapp +docker build --build-arg BUILD_COMMIT=$TRAVIS_COMMIT -t humanconnection/neo4j:latest $TRAVIS_BUILD_DIR/neo4j docker build -t humanconnection/maintenance-worker:latest $TRAVIS_BUILD_DIR/deployment/legacy-migration/maintenance-worker docker push humanconnection/nitro-backend:latest docker push humanconnection/nitro-web:latest -docker push humanconnection/maintenance-worker:latest +docker push humanconnection/neo4j:latest +docker push humanconnection/maintenance-worker:latest \ No newline at end of file