diff --git a/backend/README.md b/backend/README.md index 14e6d0ddd..5474c30d7 100644 --- a/backend/README.md +++ b/backend/README.md @@ -53,6 +53,27 @@ can issue GraphQL requests or access GraphQL Playground in the browser. ![GraphQL Playground](../.gitbook/assets/graphql-playground.png) +### Database Indices and Constraints + +Database indices and constraints need to be created when the database and the +backend is running: + +{% tabs %} +{% tab title="Docker" %} +```bash +docker-compose exec backend yarn run db:setup +``` +{% endtab %} + +{% tab title="Without Docker" %} +```bash +# in folder backend/ +# make sure your database is running on http://localhost:7474/browser/ +yarn run db:setup +``` +{% endtab %} +{% endtabs %} + #### Seed Database diff --git a/backend/package.json b/backend/package.json index cd8b3ea3f..acd0a9549 100644 --- a/backend/package.json +++ b/backend/package.json @@ -11,7 +11,9 @@ "lint": "eslint src --config .eslintrc.js", "test": "jest --forceExit --detectOpenHandles --runInBand", "db:reset": "babel-node src/seed/reset-db.js", - "db:seed": "babel-node src/seed/seed-db.js" + "db:seed": "babel-node src/seed/seed-db.js", + "db:setup": "babel-node src/migration/setup.js", + "db:migrate": "babel-node src/migration/migrate.js" }, "author": "Human Connection gGmbH", "license": "MIT", diff --git a/backend/src/migration/migrate.js b/backend/src/migration/migrate.js new file mode 100644 index 000000000..e69de29bb diff --git a/backend/src/migration/setup.js b/backend/src/migration/setup.js new file mode 100644 index 000000000..33667ff1b --- /dev/null +++ b/backend/src/migration/setup.js @@ -0,0 +1,7 @@ +import { getNeode } from '../bootstrap/neo4j' + +(async() => { + await getNeode().schema.install() + console.log('Schema installed!') + process.exit(0) +})() diff --git a/backend/src/models/Category.js b/backend/src/models/Category.js index faf5f189f..223bb4f87 100644 --- a/backend/src/models/Category.js +++ b/backend/src/models/Category.js @@ -3,7 +3,7 @@ import uuid from 'uuid/v4' export default { id: { type: 'string', primary: true, default: uuid }, name: { type: 'string', required: true, default: false }, - slug: { type: 'string' }, + slug: { type: 'string', unique: 'true' }, icon: { type: 'string', required: true, default: false }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, updatedAt: { diff --git a/backend/src/models/Post.js b/backend/src/models/Post.js index fd1e5b2ac..c29036009 100644 --- a/backend/src/models/Post.js +++ b/backend/src/models/Post.js @@ -11,7 +11,7 @@ export default { direction: 'in', }, title: { type: 'string', disallow: [null], min: 3 }, - slug: { type: 'string', allow: [null] }, + slug: { type: 'string', allow: [null], unique: 'true', }, content: { type: 'string', disallow: [null], min: 3 }, contentExcerpt: { type: 'string', allow: [null] }, image: { type: 'string', allow: [null] }, diff --git a/backend/src/models/UnverifiedEmailAddress.js b/backend/src/models/UnverifiedEmailAddress.js index 489e8517a..c582ed011 100644 --- a/backend/src/models/UnverifiedEmailAddress.js +++ b/backend/src/models/UnverifiedEmailAddress.js @@ -1,5 +1,5 @@ export default { - email: { type: 'string', primary: true, lowercase: true, email: true }, + email: { type: 'string', lowercase: true, email: true }, createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() }, nonce: { type: 'string', token: true }, belongsTo: { diff --git a/backend/src/models/User.js b/backend/src/models/User.js index fc352dccc..049611eb7 100644 --- a/backend/src/models/User.js +++ b/backend/src/models/User.js @@ -4,7 +4,7 @@ export default { id: { type: 'string', primary: true, default: uuid }, // TODO: should be type: 'uuid' but simplified for our tests actorId: { type: 'string', allow: [null] }, name: { type: 'string', disallow: [null], min: 3 }, - slug: { type: 'string', regex: /^[a-z0-9_-]+$/, lowercase: true }, + slug: { type: 'string', unique: 'true', regex: /^[a-z0-9_-]+$/, lowercase: true }, encryptedPassword: 'string', avatar: { type: 'string', allow: [null] }, coverImg: { type: 'string', allow: [null] }, diff --git a/neo4j/Dockerfile b/neo4j/Dockerfile index 22dabe114..b068b22b2 100644 --- a/neo4j/Dockerfile +++ b/neo4j/Dockerfile @@ -4,7 +4,5 @@ LABEL Description="Neo4J database of the Social Network Human-Connection.org wit ARG BUILD_COMMIT ENV BUILD_COMMIT=$BUILD_COMMIT -COPY db_setup.sh /usr/local/bin/db_setup - RUN apt-get update && apt-get -y install wget htop RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/3.5.0.4/apoc-3.5.0.4-all.jar -P plugins/ diff --git a/neo4j/README.md b/neo4j/README.md index fe8825734..5df01cc71 100644 --- a/neo4j/README.md +++ b/neo4j/README.md @@ -18,15 +18,6 @@ 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. -### Database Indices and Constraints - -Database indices and constraints need to be created when the database is -running. So start the container with the command above and run: - -```bash -docker-compose exec neo4j db_setup -``` - ## Installation without Docker diff --git a/neo4j/db_setup.sh b/neo4j/db_setup.sh deleted file mode 100755 index b7562d0c9..000000000 --- a/neo4j/db_setup.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/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("post_fulltext_search",["Post"],["title", "content"]); -CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"]); -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 (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 (e:EmailAddress) ASSERT e.email 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