Merge branch 'master' into feature/mark-all-notification-as-read

This commit is contained in:
Moriz Wahl 2023-03-08 16:50:02 +01:00
commit bdc1cb33da
461 changed files with 17572 additions and 5153 deletions

209
.github/dependabot.yml vendored
View File

@ -1,179 +1,68 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: "github-actions"
directory: "/"
rebase-strategy: "disabled"
schedule:
interval: weekly
day: "saturday"
timezone: "Europe/Berlin"
time: "03:00"
- package-ecosystem: npm - package-ecosystem: npm
directory: "/" directory: "/"
rebase-strategy: "disabled"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" day: "saturday"
open-pull-requests-limit: 10 timezone: "Europe/Berlin"
ignore: time: "03:00"
- dependency-name: cypress
versions:
- 6.3.0
- 6.4.0
- 6.5.0
- 6.6.0
- 6.7.1
- 6.8.0
- 7.0.0
- 7.0.1
- 7.1.0
- dependency-name: cypress-cucumber-preprocessor
versions:
- 4.0.0
- 4.0.1
- 4.0.3
- dependency-name: date-fns
versions:
- 2.16.1
- 2.17.0
- 2.18.0
- 2.19.0
- 2.20.0
- 2.20.1
- 2.20.2
- 2.20.3
- 2.21.0
- dependency-name: cypress-file-upload
versions:
- 5.0.2
- 5.0.3
- 5.0.4
- 5.0.5
- dependency-name: neo4j-driver
versions:
- 4.2.2
- package-ecosystem: npm - package-ecosystem: npm
directory: "/backend" directory: "/backend"
rebase-strategy: "disabled"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" day: "saturday"
open-pull-requests-limit: 10 timezone: "Europe/Berlin"
ignore: time: "03:00"
- dependency-name: y18n
versions:
- 4.0.1
- 4.0.2
- dependency-name: metascraper-publisher
versions:
- 5.16.16
- 5.18.1
- 5.18.12
- 5.18.2
- 5.18.4
- 5.18.5
- 5.18.6
- 5.18.9
- 5.20.0
- 5.21.0
- 5.21.2
- 5.21.3
- 5.21.4
- 5.21.5
- dependency-name: metascraper-author
versions:
- 5.16.16
- 5.18.1
- 5.18.12
- 5.18.2
- 5.18.4
- 5.18.5
- 5.18.6
- 5.18.9
- 5.20.0
- 5.21.0
- 5.21.2
- 5.21.3
- 5.21.4
- 5.21.5
- dependency-name: neo4j-driver
versions:
- 4.2.2
- dependency-name: neo4j-graphql-js
versions:
- 2.19.1
- dependency-name: mustache
versions:
- 4.1.0
- package-ecosystem: npm - package-ecosystem: npm
directory: "/webapp" directory: "/webapp"
rebase-strategy: "disabled"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" day: "saturday"
open-pull-requests-limit: 10 timezone: "Europe/Berlin"
ignore: time: "03:00"
- dependency-name: nuxt
versions:
- 2.14.12
- 2.15.0
- 2.15.1
- 2.15.2
- 2.15.3
- dependency-name: v-tooltip
versions:
- 2.1.2
- dependency-name: "@vue/server-test-utils"
versions:
- 1.1.2
- 1.1.3
- dependency-name: node-notifier
versions:
- 8.0.1
- package-ecosystem: docker
directory: "/webapp"
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
ignore:
- dependency-name: node
versions:
- ">= 15.5.a, < 15.6"
- dependency-name: node
versions:
- 15.10.0.pre.alpine3.10
- 15.11.0.pre.alpine3.10
- 15.12.0.pre.alpine3.10
- 15.13.0.pre.alpine3.10
- 15.7.0.pre.alpine3.10
- 15.8.0.pre.alpine3.10
- 15.9.0.pre.alpine3.10
- package-ecosystem: docker - package-ecosystem: docker
directory: "/backend" directory: "/backend"
rebase-strategy: "disabled"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" day: "saturday"
open-pull-requests-limit: 10 timezone: "Europe/Berlin"
ignore: time: "03:00"
- dependency-name: node - package-ecosystem: docker
versions: directory: "/webapp"
- ">= 15.4.a, < 15.5" rebase-strategy: "disabled"
- dependency-name: node schedule:
versions: interval: weekly
- ">= 15.5.a, < 15.6" day: "saturday"
- dependency-name: node timezone: "Europe/Berlin"
versions: time: "03:00"
- 15.10.0.pre.alpine3.10
- 15.11.0.pre.alpine3.10
- 15.12.0.pre.alpine3.10
- 15.13.0.pre.alpine3.10
- 15.7.0.pre.alpine3.10
- 15.8.0.pre.alpine3.10
- 15.9.0.pre.alpine3.10
- package-ecosystem: docker - package-ecosystem: docker
directory: "/neo4j" directory: "/neo4j"
rebase-strategy: "disabled"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" day: "saturday"
open-pull-requests-limit: 10 timezone: "Europe/Berlin"
ignore: time: "03:00"
- dependency-name: neo4j
versions:
- 4.2.3
- 4.2.4
- package-ecosystem: docker - package-ecosystem: docker
directory: "/deployment/legacy-migration/maintenance-worker" directory: "/deployment/src/docker"
rebase-strategy: "disabled"
schedule: schedule:
interval: daily interval: weekly
time: "04:00" day: "saturday"
open-pull-requests-limit: 10 timezone: "Europe/Berlin"
time: "03:00"

View File

@ -1,7 +1,6 @@
name: "ocelot.social lint pull request CI" name: "ocelot.social lint pull request CI"
on: on:
pull_request:
pull_request_target: pull_request_target:
types: types:
- opened - opened
@ -12,6 +11,7 @@ jobs:
main: main:
name: Validate PR title name: Validate PR title
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.actor != 'dependabot[bot]' }}
steps: steps:
- uses: amannn/action-semantic-pull-request@v5 - uses: amannn/action-semantic-pull-request@v5
env: env:

74
.github/workflows/publish-branded.yml vendored Normal file
View File

@ -0,0 +1,74 @@
name: publish-branded
on:
repository_dispatch:
types: [trigger-build-success]
jobs:
build_branded:
name: Docker Build Branded
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: ${{ github.event.client_payload.ref }}
- name: Setup env
run: echo "OCELOT_VERSION=${{ github.event.client_payload.BUILD_VERSION }}" >> $GITHUB_ENV
- name: Build branded images
run: |
deployment/scripts/branded-images.build.sh
docker save "ocelotsocialnetwork/backend-branded" > /tmp/backend-branded.tar
docker save "ocelotsocialnetwork/webapp-branded" > /tmp/webapp-branded.tar
docker save "ocelotsocialnetwork/maintenance-branded" > /tmp/maintenance-branded.tar
- name: Upload Artifact (Backend)
uses: actions/upload-artifact@v2
with:
name: docker-backend-branded
path: /tmp/backend-branded.tar
- name: Upload Artifact (Webapp)
uses: actions/upload-artifact@v2
with:
name: docker-webapp-branded
path: /tmp/webapp-branded.tar
- name: Upload Artifact (Maintenance)
uses: actions/upload-artifact@v2
with:
name: docker-maintenance-branded
path: /tmp/maintenance-branded.tar
upload_to_dockerhub:
name: Upload to Dockerhub
runs-on: ubuntu-latest
needs: [build_branded]
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps:
- name: Download Docker Image (Backend)
uses: actions/download-artifact@v2
with:
name: docker-backend-branded
path: /tmp
- name: Load Docker Image
run: docker load < /tmp/backend-branded.tar
- name: Download Docker Image (Webapp)
uses: actions/download-artifact@v2
with:
name: docker-webapp-branded
path: /tmp
- name: Load Docker Image
run: docker load < /tmp/webapp-branded.tar
- name: Download Docker Image (Maintenance)
uses: actions/download-artifact@v2
with:
name: docker-maintenance-branded
path: /tmp
- name: Load Docker Image
run: docker load < /tmp/maintenance-branded.tar
- name: Upload to dockerhub
run: deployment/scripts/branded-images.upload.sh

View File

@ -1,68 +1,40 @@
name: ocelot.social publish CI name: publish
on: on:
push: push:
branches: branches:
- master - master
# - 5059-epic-groups # for testing while developing
# template branches in repo
# - template--separate-branch-auto-deployment--5059-epic-groups
jobs: jobs:
##############################################################################
# JOB: PREPARE ###############################################################
##############################################################################
prepare:
name: Prepare
runs-on: ubuntu-latest
# needs: [nothing]
steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code
uses: actions/checkout@v2
##########################################################################
# TODO: DO STUFF ??? #####################################################
##########################################################################
- name: Check translation files
run: |
scripts/translations/sort.sh
scripts/translations/missing-keys.sh
############################################################################## ##############################################################################
# JOB: DOCKER BUILD COMMUNITY NEO4J ########################################## # JOB: DOCKER BUILD COMMUNITY NEO4J ##########################################
############################################################################## ##############################################################################
build_production_neo4j: build_production_neo4j:
name: Docker Build Production - Neo4J name: Docker Build Production - Neo4J
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [prepare]
steps: steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## - name: Setup env
# SET ENVS ############################################################### run: |
########################################################################## echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
- name: ENV - VERSION echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- name: ENV - BUILD_DATE - run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
run: echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
- name: ENV - BUILD_VERSION
run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: ENV - BUILD_COMMIT
run: echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
##########################################################################
# NEO4J ##################################################################
##########################################################################
- name: Neo4J | Build `community` image - name: Neo4J | Build `community` image
run: docker build --target community -t "ocelotsocialnetwork/neo4j-community:latest" -t "ocelotsocialnetwork/neo4j-community:${VERSION}" -t "ocelotsocialnetwork/neo4j-community:${BUILD_VERSION}" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT neo4j/ run: |
docker build --target community \
--tag "ocelotsocialnetwork/neo4j-community:latest" \
--tag "ocelotsocialnetwork/neo4j-community:${VERSION}" \
--tag "ocelotsocialnetwork/neo4j-community:${BUILD_VERSION}" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
neo4j/
- name: Neo4J | Save docker image - name: Neo4J | Save docker image
run: docker save "ocelotsocialnetwork/neo4j-community" > /tmp/neo4j.tar run: docker save "ocelotsocialnetwork/neo4j-community" > /tmp/neo4j.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-neo4j-community name: docker-neo4j-community
path: /tmp/neo4j.tar path: /tmp/neo4j.tar
@ -73,36 +45,45 @@ jobs:
build_production_backend: build_production_backend:
name: Docker Build Production - Backend name: Docker Build Production - Backend
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [prepare]
steps: steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## - name: Setup env
# SET ENVS ############################################################### run: |
########################################################################## echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
- name: ENV - VERSION echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- name: ENV - BUILD_DATE - run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
run: echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
- name: ENV - BUILD_VERSION
run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: ENV - BUILD_COMMIT
run: echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
##########################################################################
# BUILD BACKEND DOCKER IMAGE (production) ################################
##########################################################################
- name: Backend | Build `production` image - name: Backend | Build `production` image
run: | run: |
docker build --target base -t "ocelotsocialnetwork/backend:latest-base" -t "ocelotsocialnetwork/backend:${VERSION}-base" -t "ocelotsocialnetwork/backend:${BUILD_VERSION}-base" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT backend/ docker build --target base \
docker build --target code -t "ocelotsocialnetwork/backend:latest-code" -t "ocelotsocialnetwork/backend:${VERSION}-code" -t "ocelotsocialnetwork/backend:${BUILD_VERSION}-code" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT backend/ --tag "ocelotsocialnetwork/backend:latest-base" \
docker build --target production -t "ocelotsocialnetwork/backend:latest" -t "ocelotsocialnetwork/backend:${VERSION}" -t "ocelotsocialnetwork/backend:${BUILD_VERSION}" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT backend/ --tag "ocelotsocialnetwork/backend:${VERSION}-base" \
--tag "ocelotsocialnetwork/backend:${BUILD_VERSION}-base" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
backend/
docker build --target code \
--tag "ocelotsocialnetwork/backend:latest-code" \
--tag "ocelotsocialnetwork/backend:${VERSION}-code" \
--tag "ocelotsocialnetwork/backend:${BUILD_VERSION}-code" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
backend/
docker build --target production \
--tag "ocelotsocialnetwork/backend:latest" \
--tag "ocelotsocialnetwork/backend:${VERSION}" \
--tag "ocelotsocialnetwork/backend:${BUILD_VERSION}" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
backend/
- name: Backend | Save docker image - name: Backend | Save docker image
run: docker save "ocelotsocialnetwork/backend" > /tmp/backend.tar run: docker save "ocelotsocialnetwork/backend" > /tmp/backend.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-backend-production name: docker-backend-production
path: /tmp/backend.tar path: /tmp/backend.tar
@ -113,36 +94,45 @@ jobs:
build_production_webapp: build_production_webapp:
name: Docker Build Production - WebApp name: Docker Build Production - WebApp
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [prepare]
steps: steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## - name: Setup env
# SET ENVS ############################################################### run: |
########################################################################## echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
- name: ENV - VERSION echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- name: ENV - BUILD_DATE - run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
run: echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
- name: ENV - BUILD_VERSION
run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: ENV - BUILD_COMMIT
run: echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
##########################################################################
# BUILD WEBAPP DOCKER IMAGE (build) ######################################
##########################################################################
- name: Webapp | Build `production` image - name: Webapp | Build `production` image
run: | run: |
docker build --target base -t "ocelotsocialnetwork/webapp:latest-base" -t "ocelotsocialnetwork/webapp:${VERSION}-base" -t "ocelotsocialnetwork/webapp:${BUILD_VERSION}-base" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT webapp/ docker build --target base \
docker build --target code -t "ocelotsocialnetwork/webapp:latest-code" -t "ocelotsocialnetwork/webapp:${VERSION}-code" -t "ocelotsocialnetwork/webapp:${BUILD_VERSION}-code" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT webapp/ --tag "ocelotsocialnetwork/webapp:latest-base" \
docker build --target production -t "ocelotsocialnetwork/webapp:latest" -t "ocelotsocialnetwork/webapp:${VERSION}" -t "ocelotsocialnetwork/webapp:${BUILD_VERSION}" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT webapp/ --tag "ocelotsocialnetwork/webapp:${VERSION}-base" \
--tag "ocelotsocialnetwork/webapp:${BUILD_VERSION}-base" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
webapp/
docker build --target code \
--tag "ocelotsocialnetwork/webapp:latest-code" \
--tag "ocelotsocialnetwork/webapp:${VERSION}-code" \
--tag "ocelotsocialnetwork/webapp:${BUILD_VERSION}-code" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
webapp/
docker build --target production \
--tag "ocelotsocialnetwork/webapp:latest" \
--tag "ocelotsocialnetwork/webapp:${VERSION}" \
--tag "ocelotsocialnetwork/webapp:${BUILD_VERSION}" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
webapp/
- name: Webapp | Save docker image - name: Webapp | Save docker image
run: docker save "ocelotsocialnetwork/webapp" > /tmp/webapp.tar run: docker save "ocelotsocialnetwork/webapp" > /tmp/webapp.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-webapp-production name: docker-webapp-production
path: /tmp/webapp.tar path: /tmp/webapp.tar
@ -153,36 +143,48 @@ jobs:
build_production_maintenance: build_production_maintenance:
name: Docker Build Production - Maintenance name: Docker Build Production - Maintenance
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [prepare]
steps: steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## - name: Setup env
# SET ENVS ############################################################### run: |
########################################################################## echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
- name: ENV - VERSION echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- name: ENV - BUILD_DATE - run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
run: echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
- name: ENV - BUILD_VERSION
run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: ENV - BUILD_COMMIT
run: echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
##########################################################################
# BUILD MAINTENANCE DOCKER IMAGE (build) #################################
##########################################################################
- name: Maintenance | Build `production` image - name: Maintenance | Build `production` image
run: | run: |
docker build --target base -t "ocelotsocialnetwork/maintenance:latest-base" -t "ocelotsocialnetwork/maintenance:${VERSION}-base" -t "ocelotsocialnetwork/maintenance:${BUILD_VERSION}-base" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT webapp/ -f webapp/Dockerfile.maintenance docker build --target base \
docker build --target code -t "ocelotsocialnetwork/maintenance:latest-code" -t "ocelotsocialnetwork/maintenance:${VERSION}-code" -t "ocelotsocialnetwork/maintenance:${BUILD_VERSION}-code" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT webapp/ -f webapp/Dockerfile.maintenance --tag "ocelotsocialnetwork/maintenance:latest-base" \
docker build --target production -t "ocelotsocialnetwork/maintenance:latest" -t "ocelotsocialnetwork/maintenance:${VERSION}" -t "ocelotsocialnetwork/maintenance:${BUILD_VERSION}" --build-arg BBUILD_DATE=$BUILD_DATE --build-arg BBUILD_VERSION=$BUILD_VERSION --build-arg BBUILD_COMMIT=$BUILD_COMMIT webapp/ -f webapp/Dockerfile.maintenance --tag "ocelotsocialnetwork/maintenance:${VERSION}-base" \
--tag "ocelotsocialnetwork/maintenance:${BUILD_VERSION}-base" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
-f webapp/Dockerfile.maintenance \
webapp/
docker build --target code \
--tag "ocelotsocialnetwork/maintenance:latest-code" \
--tag "ocelotsocialnetwork/maintenance:${VERSION}-code" \
--tag "ocelotsocialnetwork/maintenance:${BUILD_VERSION}-code" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
-f webapp/Dockerfile.maintenance \
webapp/
docker build --target production \
--tag "ocelotsocialnetwork/maintenance:latest" \
--tag "ocelotsocialnetwork/maintenance:${VERSION}" \
--tag "ocelotsocialnetwork/maintenance:${BUILD_VERSION}" \
--build-arg BBUILD_DATE=$BUILD_DATE \
--build-arg BBUILD_VERSION=$BUILD_VERSION \
--build-arg BBUILD_COMMIT=$BUILD_COMMIT \
-f webapp/Dockerfile.maintenance \
webapp/
- name: Maintenance | Save docker image - name: Maintenance | Save docker image
run: docker save "ocelotsocialnetwork/maintenance" > /tmp/maintenance.tar run: docker save "ocelotsocialnetwork/maintenance" > /tmp/maintenance.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-maintenance-production name: docker-maintenance-production
path: /tmp/maintenance.tar path: /tmp/maintenance.tar
@ -198,130 +200,39 @@ jobs:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps: steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code
uses: actions/checkout@v2
##########################################################################
# DOWNLOAD DOCKER IMAGES #################################################
##########################################################################
- name: Download Docker Image (Neo4J) - name: Download Docker Image (Neo4J)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-neo4j-community name: docker-neo4j-community
path: /tmp path: /tmp
- name: Load Docker Image - run: docker load < /tmp/neo4j.tar
run: docker load < /tmp/neo4j.tar
- name: Download Docker Image (Backend) - name: Download Docker Image (Backend)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-backend-production name: docker-backend-production
path: /tmp path: /tmp
- name: Load Docker Image - run: docker load < /tmp/backend.tar
run: docker load < /tmp/backend.tar
- name: Download Docker Image (WebApp) - name: Download Docker Image (WebApp)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-webapp-production name: docker-webapp-production
path: /tmp path: /tmp
- name: Load Docker Image - run: docker load < /tmp/webapp.tar
run: docker load < /tmp/webapp.tar
- name: Download Docker Image (Maintenance) - name: Download Docker Image (Maintenance)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-maintenance-production name: docker-maintenance-production
path: /tmp path: /tmp
- name: Load Docker Image - run: docker load < /tmp/maintenance.tar
run: docker load < /tmp/maintenance.tar
##########################################################################
# Upload #################################################################
##########################################################################
- name: login to dockerhub - name: login to dockerhub
run: echo "${DOCKERHUB_TOKEN}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin run: echo "${DOCKERHUB_TOKEN}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin
- name: Push neo4j - name: Push images
run: docker push --all-tags ocelotsocialnetwork/neo4j-community
- name: Push backend
run: docker push --all-tags ocelotsocialnetwork/backend
- name: Push webapp
run: docker push --all-tags ocelotsocialnetwork/webapp
- name: Push maintenance
run: docker push --all-tags ocelotsocialnetwork/maintenance
##############################################################################
# JOB: KUBERNETES DEPLOY ACTUAL/LATEST VERSION ######################################
##############################################################################
kubernetes_deploy:
# see example https://github.com/do-community/example-doctl-action
# see example https://github.com/do-community/example-doctl-action/blob/main/.github/workflows/workflow.yaml
name: Kubernetes deploy of latest version to stage.ocelot.social cluster at DigitalOcean
runs-on: ubuntu-latest
needs: [upload_to_dockerhub]
steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code
uses: actions/checkout@v2
##########################################################################
# SET ENVS ###############################################################
##########################################################################
- name: ENV - VERSION
run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
- name: ENV - BUILD_VERSION
run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
##########################################################################
# Install DigitalOceans doctl and set kubeconfig #########################
##########################################################################
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Save DigitalOcean kubeconfig with short-lived credentials
run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 cluster-stage-ocelot-social
##########################################################################
# Deploy new Docker images to DigitalOcean Kubernetes cluster ############
##########################################################################
# - name: Deploy 'latest' to DigitalOcean Kubernetes
# run: |
# kubectl -n default set image deployment/ocelot-webapp container-ocelot-webapp=ocelotsocialnetwork/webapp:latest
# kubectl -n default rollout restart deployment/ocelot-webapp
# kubectl -n default set image deployment/ocelot-backend container-ocelot-backend=ocelotsocialnetwork/backend:latest
# kubectl -n default rollout restart deployment/ocelot-backend
# kubectl -n default set image deployment/ocelot-maintenance container-ocelot-maintenance=ocelotsocialnetwork/maintenance:latest
# kubectl -n default rollout restart deployment/ocelot-maintenance
# kubectl -n default set image deployment/ocelot-neo4j container-ocelot-neo4j=ocelotsocialnetwork/neo4j-community:latest
# kubectl -n default rollout restart deployment/ocelot-neo4j
- name: Deploy actual version '$BUILD_VERSION' to DigitalOcean Kubernetes
run: | run: |
kubectl -n default set image deployment/ocelot-webapp container-ocelot-webapp=ocelotsocialnetwork/webapp:$BUILD_VERSION docker push --all-tags ocelotsocialnetwork/neo4j-community
kubectl -n default rollout restart deployment/ocelot-webapp docker push --all-tags ocelotsocialnetwork/backend
kubectl -n default set image deployment/ocelot-backend container-ocelot-backend=ocelotsocialnetwork/backend:$BUILD_VERSION docker push --all-tags ocelotsocialnetwork/webapp
kubectl -n default rollout restart deployment/ocelot-backend docker push --all-tags ocelotsocialnetwork/maintenance
kubectl -n default set image deployment/ocelot-maintenance container-ocelot-maintenance=ocelotsocialnetwork/maintenance:$BUILD_VERSION
kubectl -n default rollout restart deployment/ocelot-maintenance
kubectl -n default set image deployment/ocelot-neo4j container-ocelot-neo4j=ocelotsocialnetwork/neo4j-community:$BUILD_VERSION
kubectl -n default rollout restart deployment/ocelot-neo4j
# because this step 'kubectl -n default rollout status deployment/* --timeout=600s' does not work as expected
# and we need the pods to be up again for cleaning and seeding the Neo4j database and the backend.
# !!! this is not a perfect solution !!!
# deployments are regularly up again after 3 minutes and 10 seconds
- name: Sleep for 4 minutes, means 240 seconds
run: sleep 240s
shell: bash
- name: Verify deployment and wait for the pods of each deployment to get ready for cleaning and seeding of the database
run: |
kubectl -n default rollout status deployment/ocelot-backend --timeout=600s
kubectl -n default rollout status deployment/ocelot-neo4j --timeout=600s
kubectl -n default rollout status deployment/ocelot-maintenance --timeout=600s
kubectl -n default rollout status deployment/ocelot-webapp --timeout=600s
- name: Run migrations for Neo4j database via backend for staging
run: |
kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "yarn prod:migrate up"
- name: Reset and seed Neo4j database via backend for staging
# db cleaning and seeding is only possible in production if env 'PRODUCTION_DB_CLEAN_ALLOW=true' is set in deployment
run: |
kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await dist/db/clean.js && node --experimental-repl-await dist/db/seed.js"
############################################################################## ##############################################################################
# JOB: GITHUB TAG LATEST VERSION ############################################# # JOB: GITHUB TAG LATEST VERSION #############################################
@ -331,39 +242,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [upload_to_dockerhub] needs: [upload_to_dockerhub]
steps: steps:
##########################################################################
# CHECKOUT CODE ##########################################################
##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
fetch-depth: 0 # Fetch full History for changelog fetch-depth: 0 # Fetch full History for changelog
########################################################################## - name: Setup env
# SET ENVS ############################################################### run: |
########################################################################## echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
- name: ENV - VERSION echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- name: ENV - BUILD_DATE - run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
run: echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
- name: ENV - BUILD_VERSION
run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: ENV - BUILD_COMMIT
run: echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
##########################################################################
# Push version tag to GitHub #############################################
##########################################################################
# TODO: this will error on duplicate
#- name: package-version-to-git-tag
# uses: pkgdeps/git-tag-action@v2
# with:
# github_token: ${{ secrets.GITHUB_TOKEN }}
# github_repo: ${{ github.repository }}
# version: ${{ env.VERSION }}
# git_commit_sha: ${{ github.sha }}
# git_tag_prefix: "v"
##########################################################################
# Push build tag to GitHub ###############################################
##########################################################################
- name: package-version-to-git-tag + build number - name: package-version-to-git-tag + build number
uses: pkgdeps/git-tag-action@v2 uses: pkgdeps/git-tag-action@v2
with: with:
@ -372,13 +260,10 @@ jobs:
version: ${{ env.BUILD_VERSION }} version: ${{ env.BUILD_VERSION }}
git_commit_sha: ${{ github.sha }} git_commit_sha: ${{ github.sha }}
git_tag_prefix: "b" git_tag_prefix: "b"
########################################################################## - name: Generate changelog
# Push release tag to GitHub ############################################# run: |
########################################################################## yarn install
- name: yarn install yarn auto-changelog --latest-version ${{ env.VERSION }} --unreleased-only
run: yarn install
- name: generate changelog
run: yarn auto-changelog --latest-version ${{ env.VERSION }} --unreleased-only
- name: package-version-to-git-release - name: package-version-to-git-release
continue-on-error: true # Will fail if tag exists continue-on-error: true # Will fail if tag exists
id: create_release id: create_release
@ -391,3 +276,101 @@ jobs:
body_path: ./CHANGELOG.md body_path: ./CHANGELOG.md
draft: false draft: false
prerelease: false prerelease: false
build_trigger:
name: Trigger successful build
runs-on: ubuntu-latest
needs: [github_tag]
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch full History for changelog
- name: Setup env
run: |
echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ github.token }}
event-type: trigger-build-success
repository: ${{ github.repository }}
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
# ##############################################################################
# # JOB: KUBERNETES DEPLOY ACTUAL/LATEST VERSION ######################################
# ##############################################################################
# kubernetes_deploy:
# # see example https://github.com/do-community/example-doctl-action
# # see example https://github.com/do-community/example-doctl-action/blob/main/.github/workflows/workflow.yaml
# name: Kubernetes deploy of latest version to stage.ocelot.social cluster at DigitalOcean
# runs-on: ubuntu-latest
# needs: [upload_to_dockerhub]
# steps:
# ##########################################################################
# # CHECKOUT CODE ##########################################################
# ##########################################################################
# - name: Checkout code
# uses: actions/checkout@v3
# ##########################################################################
# # SET ENVS ###############################################################
# ##########################################################################
# - name: ENV - VERSION
# run: echo "VERSION=$(node -p -e "require('./package.json').version")" >> $GITHUB_ENV
# - name: ENV - BUILD_VERSION
# run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
# ##########################################################################
# # Install DigitalOceans doctl and set kubeconfig #########################
# ##########################################################################
# - name: Install doctl
# uses: digitalocean/action-doctl@v2
# with:
# token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
# - name: Save DigitalOcean kubeconfig with short-lived credentials
# run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 cluster-stage-ocelot-social
# ##########################################################################
# # Deploy new Docker images to DigitalOcean Kubernetes cluster ############
# ##########################################################################
# # - name: Deploy 'latest' to DigitalOcean Kubernetes
# # run: |
# # kubectl -n default set image deployment/ocelot-webapp container-ocelot-webapp=ocelotsocialnetwork/webapp:latest
# # kubectl -n default rollout restart deployment/ocelot-webapp
# # kubectl -n default set image deployment/ocelot-backend container-ocelot-backend=ocelotsocialnetwork/backend:latest
# # kubectl -n default rollout restart deployment/ocelot-backend
# # kubectl -n default set image deployment/ocelot-maintenance container-ocelot-maintenance=ocelotsocialnetwork/maintenance:latest
# # kubectl -n default rollout restart deployment/ocelot-maintenance
# # kubectl -n default set image deployment/ocelot-neo4j container-ocelot-neo4j=ocelotsocialnetwork/neo4j-community:latest
# # kubectl -n default rollout restart deployment/ocelot-neo4j
# - name: Deploy actual version '$BUILD_VERSION' to DigitalOcean Kubernetes
# run: |
# kubectl -n default set image deployment/ocelot-webapp container-ocelot-webapp=ocelotsocialnetwork/webapp:$BUILD_VERSION
# kubectl -n default rollout restart deployment/ocelot-webapp
# kubectl -n default set image deployment/ocelot-backend container-ocelot-backend=ocelotsocialnetwork/backend:$BUILD_VERSION
# kubectl -n default rollout restart deployment/ocelot-backend
# kubectl -n default set image deployment/ocelot-maintenance container-ocelot-maintenance=ocelotsocialnetwork/maintenance:$BUILD_VERSION
# kubectl -n default rollout restart deployment/ocelot-maintenance
# kubectl -n default set image deployment/ocelot-neo4j container-ocelot-neo4j=ocelotsocialnetwork/neo4j-community:$BUILD_VERSION
# kubectl -n default rollout restart deployment/ocelot-neo4j
# # because this step 'kubectl -n default rollout status deployment/* --timeout=600s' does not work as expected
# # and we need the pods to be up again for cleaning and seeding the Neo4j database and the backend.
# # !!! this is not a perfect solution !!!
# # deployments are regularly up again after 3 minutes and 10 seconds
# - name: Sleep for 4 minutes, means 240 seconds
# run: sleep 240s
# shell: bash
# - name: Verify deployment and wait for the pods of each deployment to get ready for cleaning and seeding of the database
# run: |
# kubectl -n default rollout status deployment/ocelot-backend --timeout=600s
# kubectl -n default rollout status deployment/ocelot-neo4j --timeout=600s
# kubectl -n default rollout status deployment/ocelot-maintenance --timeout=600s
# kubectl -n default rollout status deployment/ocelot-webapp --timeout=600s
# - name: Run migrations for Neo4j database via backend for staging
# run: |
# kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "yarn prod:migrate up"
# - name: Reset and seed Neo4j database via backend for staging
# # db cleaning and seeding is only possible in production if env 'PRODUCTION_DB_CLEAN_ALLOW=true' is set in deployment
# run: |
# kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await dist/db/clean.js && node --experimental-repl-await dist/db/seed.js"

View File

@ -16,7 +16,7 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# TODO: DO STUFF ??? ##################################################### # TODO: DO STUFF ??? #####################################################
########################################################################## ##########################################################################
@ -37,7 +37,7 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# NEO4J ################################################################## # NEO4J ##################################################################
########################################################################## ##########################################################################
@ -46,7 +46,7 @@ jobs:
docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/ docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/
docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-neo4j-image name: docker-neo4j-image
path: /tmp/neo4j.tar path: /tmp/neo4j.tar
@ -63,7 +63,7 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# BUILD BACKEND DOCKER IMAGE (build) ##################################### # BUILD BACKEND DOCKER IMAGE (build) #####################################
########################################################################## ##########################################################################
@ -72,7 +72,7 @@ jobs:
docker build --target test -t "ocelotsocialnetwork/backend:test" backend/ docker build --target test -t "ocelotsocialnetwork/backend:test" backend/
docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-backend-test name: docker-backend-test
path: /tmp/backend.tar path: /tmp/backend.tar
@ -89,7 +89,7 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# BUILD WEBAPP DOCKER IMAGE (build) ###################################### # BUILD WEBAPP DOCKER IMAGE (build) ######################################
########################################################################## ##########################################################################
@ -98,7 +98,7 @@ jobs:
docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/ docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: docker-webapp-test name: docker-webapp-test
path: /tmp/webapp.tar path: /tmp/webapp.tar
@ -115,12 +115,12 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# DOWNLOAD DOCKER IMAGE ################################################## # DOWNLOAD DOCKER IMAGE ##################################################
########################################################################## ##########################################################################
- name: Download Docker Image (Backend) - name: Download Docker Image (Backend)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-backend-test name: docker-backend-test
path: /tmp path: /tmp
@ -144,12 +144,12 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# DOWNLOAD DOCKER IMAGE ################################################## # DOWNLOAD DOCKER IMAGE ##################################################
########################################################################## ##########################################################################
- name: Download Docker Image (Webapp) - name: Download Docker Image (Webapp)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-webapp-test name: docker-webapp-test
path: /tmp path: /tmp
@ -168,24 +168,26 @@ jobs:
name: Unit tests - backend name: Unit tests - backend
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build_test_neo4j,build_test_backend] needs: [build_test_neo4j,build_test_backend]
permissions:
checks: write
steps: steps:
########################################################################## ##########################################################################
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# DOWNLOAD DOCKER IMAGES ################################################# # DOWNLOAD DOCKER IMAGES #################################################
########################################################################## ##########################################################################
- name: Download Docker Image (Neo4J) - name: Download Docker Image (Neo4J)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-neo4j-image name: docker-neo4j-image
path: /tmp path: /tmp
- name: Load Docker Image - name: Load Docker Image
run: docker load < /tmp/neo4j.tar run: docker load < /tmp/neo4j.tar
- name: Download Docker Image (Backend) - name: Download Docker Image (Backend)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-backend-test name: docker-backend-test
path: /tmp path: /tmp
@ -225,17 +227,19 @@ jobs:
name: Unit tests - webapp name: Unit tests - webapp
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build_test_webapp] needs: [build_test_webapp]
permissions:
checks: write
steps: steps:
########################################################################## ##########################################################################
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# DOWNLOAD DOCKER IMAGES ################################################# # DOWNLOAD DOCKER IMAGES #################################################
########################################################################## ##########################################################################
- name: Download Docker Image (Webapp) - name: Download Docker Image (Webapp)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-webapp-test name: docker-webapp-test
path: /tmp path: /tmp
@ -269,7 +273,7 @@ jobs:
report_name: Coverage Webapp report_name: Coverage Webapp
type: lcov type: lcov
result_path: ./coverage/lcov.info result_path: ./coverage/lcov.info
min_coverage: 63 min_coverage: 83
token: ${{ github.token }} token: ${{ github.token }}
############################################################################## ##############################################################################
@ -290,26 +294,26 @@ jobs:
# CHECKOUT CODE ########################################################## # CHECKOUT CODE ##########################################################
########################################################################## ##########################################################################
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
########################################################################## ##########################################################################
# DOWNLOAD DOCKER IMAGES ################################################# # DOWNLOAD DOCKER IMAGES #################################################
########################################################################## ##########################################################################
- name: Download Docker Image (Neo4J) - name: Download Docker Image (Neo4J)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-neo4j-image name: docker-neo4j-image
path: /tmp path: /tmp
- name: Load Docker Image - name: Load Docker Image
run: docker load < /tmp/neo4j.tar run: docker load < /tmp/neo4j.tar
- name: Download Docker Image (Backend) - name: Download Docker Image (Backend)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-backend-test name: docker-backend-test
path: /tmp path: /tmp
- name: Load Docker Image - name: Load Docker Image
run: docker load < /tmp/backend.tar run: docker load < /tmp/backend.tar
- name: Download Docker Image (Webapp) - name: Download Docker Image (Webapp)
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: docker-webapp-test name: docker-webapp-test
path: /tmp path: /tmp
@ -332,12 +336,12 @@ jobs:
# UPLOAD SCREENSHOTS & VIDEO ############################################# # UPLOAD SCREENSHOTS & VIDEO #############################################
########################################################################## ##########################################################################
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: cypress-screenshots name: cypress-screenshots
path: cypress/screenshots/ path: cypress/screenshots/
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: cypress-videos name: cypress-videos
path: cypress/videos/ path: cypress/videos/

2
.nvmrc
View File

@ -1 +1 @@
v17.9.0 v19.4.0

View File

@ -4,8 +4,54 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
#### [2.2.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.1.0...2.2.0) #### [2.4.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.3.0...2.4.0)
- fix(webapp): post teaser width in mobile view [`#5958`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5958)
- fix(webapp): navbar disappears when scrolling to top [`#5957`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5957)
- fix(webapp): close mobile menu on all links [`#5956`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5956)
- feat(webapp): mark active filters on the posts [`#5952`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5952)
- refactor(webapp): refacchange postion add content button, refactor mobile filter menu [`#5943`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5943)
- refactor(webapp): set legend to map [`#5950`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5950)
- fix(webapp): small changes for deploy [`#5949`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5949)
- feat(webapp): hide navbar by scroll, filter button for content [`#5926`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5926)
- feat(webapp): map [`#5843`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5843)
- refactor(webapp): upgrade node version to 19.4 [`#5910`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5910)
- fix(webapp): texts for groups [`#5923`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5923)
- fix(webapp): add category name in tooltip [`#5884`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5884)
- refactor(webapp): 🍰 Refactor Social Media And `MySomethingList` [`#5138`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5138)
- fix(backend): do not expose registered emails on registration [`#5909`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5909)
- refactor(backend): node 19 with fixed image upload [`#5897`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5897)
- refactor(webapp): nump docker version to `16.19.0` in webapp & maintenance [`#5842`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5842)
- updated required packages for node19, fix fs-capacitator [`11087cb`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/11087cbaefde604668ac192b710666df09cb813c)
- fixed build error [`3889204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3889204f871df97b307401032900db7940913038)
- linting [`8bfe486`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8bfe486034badd55a8096982f81aba08207b9e83)
#### [2.3.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.2.0...2.3.0)
> 5 December 2022
- chore(release): v2.3.0 [`#5768`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5768)
- feat(webapp): 🍰 Sort Categories By Name [`#5709`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5709)
- fix(backend): sanitize group description [`#5707`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5707)
- fix(webapp): clean up webapp unit tests [`#5711`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5711)
- feat(webapp): 🍰 Search Users To Add To Group [`#5652`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5652)
- feat(webapp): 🍰 Params For Category Filter [`#5699`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5699)
- fix(backend): 🍰 Misspelled Notification [`#5703`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5703)
- test(other): jest coverage report in console [`#5637`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5637)
- fix(webapp): centralize mobile hamburger menu [`#5674`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5674)
- refactor(backend): 🍰 Move `db/graphql` Folder Content To `graphql` Folder [`#5661`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5661)
- feat(other): semantic pullrequest workflow [`#5634`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5634)
- fix: Cannot Add Group Members as New Members to Group [`#5635`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5635)
- fix: My Groups Count Includes Pending Membership [`#5631`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5631)
- frontend: jest coverage [`f57e11d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/f57e11dd021dbb156b33fbd5538cf5ca32df7334)
- reverted yarn lock [`a01aee8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a01aee89a92bbc9885e2895c577eb3c63042ba22)
- reverted all package updates [`a520089`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a5200893f4508d45619447231b6789178a51daf7)
#### [2.2.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.1.0...2.2.0)
> 28 October 2022
- chore: 🍰 Release v2.2.0 [`#5610`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5610)
- refactor: 🍰 Refactor Design Of Category Filter In Filter Menu [`#5597`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5597) - refactor: 🍰 Refactor Design Of Category Filter In Filter Menu [`#5597`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5597)
- feat: 🍰 Footer And Header Links Configurable To Have External Link Target [`#5590`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5590) - feat: 🍰 Footer And Header Links Configurable To Have External Link Target [`#5590`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5590)
- feat: 🍰 Header Menu To Component And Other Refinements [`#5546`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5546) - feat: 🍰 Header Menu To Component And Other Refinements [`#5546`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5546)
@ -19,10 +65,26 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- fix: 🍰 Fix Group Teaser [`#5584`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5584) - fix: 🍰 Fix Group Teaser [`#5584`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5584)
- feat: 🍰 List All Groups [`#5582`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5582) - feat: 🍰 List All Groups [`#5582`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5582)
- feat: 🍰 Header Logo Routing Update [`#5579`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5579) - feat: 🍰 Header Logo Routing Update [`#5579`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5579)
- add header menu to component, central variabl for screen width [`401f59a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/401f59ae8de5b1c27f0e26e1f71778d3257d2180)
- comment out LanguagesFilter, EmotionsFilter, fix tests, fix lint [`52dcd77`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/52dcd772fa81e02a0d95e89a9fc8232e70a09d28)
- fix lint [`15561cb`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/15561cb94f8768e93846c25945c935ae83977553)
#### [2.1.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.0.0...2.1.0)
> 25 October 2022
- chore: 🍰 Release v2.1.0 [`#5574`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5574) - chore: 🍰 Release v2.1.0 [`#5574`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5574)
- feat: 🍰 EPIC Groups [`#5132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5132) - feat: 🍰 EPIC Groups [`#5132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5132)
- chore: 🍰 Remove Group Branchs `5059-epic-groups` Separate Auto-Deployment [`#5552`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5552) - chore: 🍰 Remove Group Branchs `5059-epic-groups` Separate Auto-Deployment [`#5552`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5552)
- fix: [WIP] 🍰 Long Words Are Being Wrapped Now [`#5559`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5559) - fix: [WIP] 🍰 Long Words Are Being Wrapped Now [`#5559`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5559)
- Remove groups separate auto-deployment [`c8d8168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c8d816887b2d49293d1b8ee2805d452fe10d907e)
- Release v2.1.0 [`dc085e9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/dc085e9e69b288fce6dd06e8d7eb05ef34bd9a7b)
- Add database migration to auto-deployment on publish [`ef06f1a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ef06f1a67d2654aaeb55d0434d3324a3ac37a380)
### [2.0.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.1.1...2.0.0)
> 23 October 2022
- feat: 🍰 Search For Groups [`#5543`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5543) - feat: 🍰 Search For Groups [`#5543`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5543)
- feat: 🍰 Mobile Footer Menu To Header Menu [`#5524`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5524) - feat: 🍰 Mobile Footer Menu To Header Menu [`#5524`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5524)
- feat: 🍰 Implement `LOGO_HEADER_CLICK` As Configuration [`#5525`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5525) - feat: 🍰 Implement `LOGO_HEADER_CLICK` As Configuration [`#5525`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5525)
@ -39,25 +101,35 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- feat: 🍰 Group Members Management [`#5345`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5345) - feat: 🍰 Group Members Management [`#5345`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5345)
- feat: 🍰 Have My Groups In The User Menu And Configure Groups Button In Header [`#5411`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5411) - feat: 🍰 Have My Groups In The User Menu And Configure Groups Button In Header [`#5411`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5411)
- chore: 🍰 Implement Automatic Deployment For Groups Branch '5059-epic-groups' [`#5408`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5408) - chore: 🍰 Implement Automatic Deployment For Groups Branch '5059-epic-groups' [`#5408`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5408)
- Chore: 🍰 Release v1.1.1 Refactor Rebranding [`#5392`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5392)
- chore: 🍰 Refactor Rebranding [`#5390`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5390)
- feat: 🍰 Group Profile Description Etc [`#5368`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5368) - feat: 🍰 Group Profile Description Etc [`#5368`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5368)
- feat: 🍰 Tooltips For Topics [`#5350`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5350)
- feat: 🍰 Group Profile Members List Etc [`#5335`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5335) - feat: 🍰 Group Profile Members List Etc [`#5335`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5335)
- feat: 🍰 Implement Group Profile Visibility [`#5332`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5332) - feat: 🍰 Implement Group Profile Visibility [`#5332`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5332)
- feat: 🍰 Save Categories In Frontend [`#5284`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5284)
- feat: 🍰 Add New Yunite Icons [`#5319`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5319)
- chore: 🍰 Update Neode From v^0.4.7 To v^0.4.8 In Backend [`#5334`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5334)
- feat: 🍰 My Groups Page [`#5148`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5148) - feat: 🍰 My Groups Page [`#5148`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5148)
- feat: 🍰 Hidden Groups Shall Not Be Visible For None Or Pending Members In Backend [`#5317`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5317) - feat: 🍰 Hidden Groups Shall Not Be Visible For None Or Pending Members In Backend [`#5317`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5317)
- feat: 🍰 Implement Group Profile [`#5197`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5197) - feat: 🍰 Implement Group Profile [`#5197`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5197)
- feat: 🍰 Implement `UpdateGroup` Resolver [`#5224`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5224)
- feat: 🍰 Implement `JoinGroup`, `GroupMember`, `SwitchGroupMemberRole` Resolvers [`#5199`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5199)
- chore: 🍰 Add Groups To Seeding [`#5185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5185)
- feat: 🍰 Implement Group GQL Model And CRUD Resolvers First Step [`#5139`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5139)
- Refine design and functionality of group list and create, edit group [`7b11122`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7b11122bea4868624dd1c1641219e71070412e20)
- improved code and tests as suggested by @tirokk, thanks for the great review! [`631f34a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/631f34a2e5224d68279337a92e7535794b670d70)
- implement and test post visibilty when leaving or changing the role in a group [`76bfe48`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/76bfe484768cf9b20b2dced865d5d3e3eb999235)
#### [1.1.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.1.0...1.1.1)
> 22 September 2022
- Chore: 🍰 Release v1.1.1 Refactor Rebranding [`#5392`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5392)
- chore: 🍰 Refactor Rebranding [`#5390`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5390)
- feat: 🍰 Tooltips For Topics [`#5350`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5350)
- feat: 🍰 Save Categories In Frontend [`#5284`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5284)
- feat: 🍰 Add New Yunite Icons [`#5319`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5319)
- chore: 🍰 Update Neode From v^0.4.7 To v^0.4.8 In Backend [`#5334`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5334)
- fix: Category Filter Menu Client Only [`#5301`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5301) - fix: Category Filter Menu Client Only [`#5301`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5301)
- feat: Save Category Settings [`#5261`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5261) - feat: Save Category Settings [`#5261`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5261)
- feat: 🍰 Implement `UpdateGroup` Resolver [`#5224`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5224)
- feat: Topics Menu [`#5248`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5248) - feat: Topics Menu [`#5248`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5248)
- docs: 🍰 Document GraqhQL Playground [`#5253`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5253) - docs: 🍰 Document GraqhQL Playground [`#5253`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5253)
- feat: Categories Filter Menu [`#5198`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5198) - feat: Categories Filter Menu [`#5198`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5198)
- feat: 🍰 Implement `JoinGroup`, `GroupMember`, `SwitchGroupMemberRole` Resolvers [`#5199`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5199)
- fix: 🍰 Fix Test Description From `enter-nonce.vue` To `change-password` [`#5217`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5217) - fix: 🍰 Fix Test Description From `enter-nonce.vue` To `change-password` [`#5217`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5217)
- Bump cookie-universal-nuxt from 2.1.5 to 2.2.2 in /webapp [`#5218`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5218) - Bump cookie-universal-nuxt from 2.1.5 to 2.2.2 in /webapp [`#5218`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5218)
- Bump prettier from 2.2.1 to 2.7.1 in /webapp [`#5170`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5170) - Bump prettier from 2.2.1 to 2.7.1 in /webapp [`#5170`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5170)
@ -69,12 +141,10 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- feat: 🍰 Change Error Message With `Authorised` To `Authorized` All Over The Place To Have American English [`#5206`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5206) - feat: 🍰 Change Error Message With `Authorised` To `Authorized` All Over The Place To Have American English [`#5206`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5206)
- Bump cross-env from 7.0.2 to 7.0.3 in /webapp [`#5168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5168) - Bump cross-env from 7.0.2 to 7.0.3 in /webapp [`#5168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5168)
- chore: 🍰 Add `--logHeapUsage` To Jest Test Call [`#5182`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5182) - chore: 🍰 Add `--logHeapUsage` To Jest Test Call [`#5182`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5182)
- chore: 🍰 Add Groups To Seeding [`#5185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5185)
- feat: 🍰 Implement Group GQL Model And CRUD Resolvers First Step [`#5139`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5139)
- refactor: 🍰 Rename `UserGroup` To `UserRole` [`#5143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5143) - refactor: 🍰 Rename `UserGroup` To `UserRole` [`#5143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5143)
- improved code and tests as suggested by @tirokk, thanks for the great review! [`631f34a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/631f34a2e5224d68279337a92e7535794b670d70) - add new yunite icons [`bb0d632`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/bb0d6329e7e36ea03671318ea8dd128a6d5a5a7a)
- implement and test post visibilty when leaving or changing the role in a group [`76bfe48`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/76bfe484768cf9b20b2dced865d5d3e3eb999235) - cleanup refactor rebranding [`5f5c0fa`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5f5c0faa1f28cd4df7681eba335ae5998b2d9cca)
- comment out LanguagesFilter, EmotionsFilter, fix tests, fix lint [`52dcd77`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/52dcd772fa81e02a0d95e89a9fc8232e70a09d28) - change color and scss in branding [`52070b8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/52070b8c570970bf48df561134bf67cb4111b640)
#### [1.1.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.9...1.1.0) #### [1.1.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.9...1.1.0)

View File

@ -105,7 +105,7 @@ Sprint retrospective
## Philosophy ## Philosophy
We practise [collective code ownership](http://www.extremeprogramming.org/rules/collective.html) rather than strong code ownership, which means that: We practice [collective code ownership](http://www.extremeprogramming.org/rules/collective.html) rather than strong code ownership, which means that:
* developers can make contributions to other people's PRs (after checking in with them) * developers can make contributions to other people's PRs (after checking in with them)
* we avoid blocking because someone else isn't working, so we sometimes take over PRs from other developers * we avoid blocking because someone else isn't working, so we sometimes take over PRs from other developers
@ -115,7 +115,7 @@ We believe in open source contributions as a learning experience everyone is
We use pair programming sessions as a tool for knowledge sharing. We can learn a lot from each other and only by sharing what we know and overcoming challenges together can we grow as a team and truly own this project collectively. We use pair programming sessions as a tool for knowledge sharing. We can learn a lot from each other and only by sharing what we know and overcoming challenges together can we grow as a team and truly own this project collectively.
As a volunteeer you have no commitment except your own self development and your awesomeness by contributing to this free and open-source software project. Cheers to you! As a volunteer you have no commitment except your own self development and your awesomeness by contributing to this free and open-source software project. Cheers to you!
<!-- <!--
## Open-Source Bounties ## Open-Source Bounties
@ -149,3 +149,86 @@ Our Open-Source bounty program is a work-in-progress. Based on our future
experience we will make changes and improvements. So keep an eye on this experience we will make changes and improvements. So keep an eye on this
contribution guide. contribution guide.
--> -->
## Programming
### Localization
#### Quotation Marks
The following characters are different from the programming quotation mark:
`"` or `\"`
Please copy and paste the following quotes for the languages:
* de: „Dies ist ein Beispielsatz.“
* en: “This is a sample sentence.”
* See <https://grammar.collinsdictionary.com/easy-learning/when-do-you-use-quotation-marks-or-in-english>
## Docker More Closely
### Apple M1 Platform
***Attention:** For using Docker commands in Apple M1 environments!*
#### Environment Variable For Apple M1 Platform
If you encounter trouble building the docker containers on an Apple M1 chip you can try to explicitly define the target platform docker builds and pulls images for:
```bash
# set env variable for your shell
$ export DOCKER_DEFAULT_PLATFORM=linux/amd64
```
Or alternatively use a `YAML` docker compose overwrite file with `platform: linux/amd64`.
### Analyzing Docker Builds
To analyze a Docker build, there is a wonderful tool called [dive](https://github.com/wagoodman/dive). Please sponsor if you're using it!
The `dive build` command is exactly the right one to fulfill what we are looking for.
We can use it just like the `docker build` command and get an analysis afterwards.
So, in our main folder, we use it in the following way:
```bash
# in main folder
$ dive build --target <layer-name> -t "ocelotsocialnetwork/<app-name>:local-<layer-name>" --build-arg BBUILD_DATE="<build-date>" --build-arg BBUILD_VERSION="<build-version>" --build-arg BBUILD_COMMIT="<build-commit>" <app-folder-name-or-dot>/
```
The build arguments are optional.
For the specific applications, we use them as follows.
#### Backend
##### Production For Backend
```bash
# in main folder
$ dive build --target production -t "ocelotsocialnetwork/backend:local-production" backend/
```
##### Development For Backend
```bash
# in main folder
$ dive build --target development -t "ocelotsocialnetwork/backend:local-development" backend/
```
#### Webapp
##### Production For Webapp
```bash
# in main folder
$ dive build --target production -t "ocelotsocialnetwork/webapp:local-production" webapp/
```
##### Development For Webapp
```bash
# in main folder
$ dive build --target development -t "ocelotsocialnetwork/webapp:local-development" webapp/
```

View File

@ -1,86 +0,0 @@
# Docker More Closely
## Apple M1 Platform
***Attention:** For using Docker commands in Apple M1 environments!*
### Enviroment Variable For Apple M1 Platform
To set the Docker platform environment variable in your terminal tab, run:
```bash
# set env variable for your shell
$ export DOCKER_DEFAULT_PLATFORM=linux/amd64
```
### Docker Compose Override File For Apple M1 Platform
For Docker compose `up` or `build` commands, you can use our Apple M1 override file that specifies the M1 platform:
```bash
# in main folder
# for development
$ docker compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.apple-m1.override.yml up
# only once: init admin user and create indexes and contraints in Neo4j database
$ docker compose exec backend yarn prod:migrate init
# clean db
$ docker compose exec backend yarn db:reset
# seed db
$ docker compose exec backend yarn db:seed
# for production
$ docker compose -f docker-compose.yml -f docker-compose.apple-m1.override.yml up
# only once: init admin user and create indexes and contraints in Neo4j database
$ docker compose exec backend /bin/sh -c "yarn prod:migrate init"
```
## Analysing Docker Builds
To analyze a Docker build, there is a wonderful tool called [dive](https://github.com/wagoodman/dive). Please sponsor if you're using it!
The `dive build` command is exactly the right one to fulfill what we are looking for.
We can use it just like the `docker build` command and get an analysis afterwards.
So, in our main folder, we use it in the following way:
```bash
# in main folder
$ dive build --target <layer-name> -t "ocelotsocialnetwork/<app-name>:local-<layer-name>" --build-arg BBUILD_DATE="<build-date>" --build-arg BBUILD_VERSION="<build-version>" --build-arg BBUILD_COMMIT="<build-commit>" <app-folder-name-or-dot>/
```
The build arguments are optional.
For the specific applications, we use them as follows.
### Backend
#### Production For Backend
```bash
# in main folder
$ dive build --target production -t "ocelotsocialnetwork/backend:local-production" backend/
```
#### Development For Backend
```bash
# in main folder
$ dive build --target development -t "ocelotsocialnetwork/backend:local-development" backend/
```
### Webapp
#### Production For Webapp
```bash
# in main folder
$ dive build --target production -t "ocelotsocialnetwork/webapp:local-production" webapp/
```
#### Development For Webapp
```bash
# in main folder
$ dive build --target development -t "ocelotsocialnetwork/webapp:local-development" webapp/
```

View File

@ -20,12 +20,71 @@ At the same time, it should be possible in the future to link these networks wit
In other words, we are interested in a network of networks and in keeping the data as close as possible to the user and the operator they trusts. In other words, we are interested in a network of networks and in keeping the data as close as possible to the user and the operator they trusts.
## Introduction ## Screenshots
<img src="https://user-images.githubusercontent.com/17728384/218597429-554e4082-3906-4721-8f68-0c13146fc218.png" alt="Post feed" title="Post feed" />
Check out more screenshots [here](/wiki/en:Screenshots).
## Features
Ocelot.social networks feature:
* <strong>user accounts</strong>
* <strong>user roles</strong>
* <strong>posts</strong> and <strong>comments</strong>
* <strong>groups</strong>
* <strong>maps</strong>
* <strong>search</strong>
* <strong>filters</strong>
* and more …
Check out the [full feature list](/wiki/en:FAQ#what-are-the-features).
## User Guide and Frequently Asked Questions
In the [wiki](/wiki) you can find more information.
* [User Guide](/wiki/en:User-Guide)
* [Frequently Asked Questions](/wiki/en:FAQ)
## Demo
Try out our live demo network, see [here](#live-demo-and-developer-logins).
## Help us
If you're wondering how you could help, there are plenty of ways, e.g.:
* Spread the good word about ocelot.social to make it more popular:
* Add the link [ocelot.social](https://ocelot.social) to your website.
* Give ocelot.social a Like at https://alternativeto.net/software/ocelot-social/.
* Star our project on GitHub at https://github.com/Ocelot-Social-Community/Ocelot-Social/.
* Promote it on your social networks.
* Tell your friends about it by word-of-mouth.
* Write a press article on ocelot.social or contact the editorial office of your local newspage or radio station.
* Take a [good first issue](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) or issues that need help. Make sure to read [CONTRIBUTING.md](/CONTRIBUTING.md) first though.
* Testing and [reporting](/issues/new/choose) bugs.
* Translating: Please [contact us](#contact).
* Reviewing and testing pull requests.
## Donate
Your donation is very welcome and helps to enhance and improve the network. This software is mostly developped and maintained by the association [busFaktor() e.V.](https://www.busfaktor.org/en). Please support us with a [donation](https://www.busfaktor.org/en/donations) to busFaktor() e.V.. Thanks a lot! ❤️
## Contact
Are you interested in operating your own ocelot.social network or becoming a user? Please contact us here:
* [hello@ocelot.social](mailto:hello@ocelot.social)
* [Discord](https://discord.com/invite/DFSjPaX)
## For Developers and Contributors
### Introduction
Have a look into our short video: Have a look into our short video:
[ocelot.social - GitHub - Developer Welcome - Tutorial (english)](https://www.youtube.com/watch?v=gZSL6KvBIiY&list=PLFMD5liPP01kbuReHxYXxv_1fI5rIgS1f&index=1) [ocelot.social - GitHub - Developer Welcome - Tutorial (english)](https://www.youtube.com/watch?v=gZSL6KvBIiY&list=PLFMD5liPP01kbuReHxYXxv_1fI5rIgS1f&index=1)
## Directory Layout ### Directory Layout
There are three important directories: There are three important directories:
@ -41,9 +100,9 @@ There are two approaches:
1. [Local](#local-installation) installation, which means you have to take care of dependencies yourself. 1. [Local](#local-installation) installation, which means you have to take care of dependencies yourself.
2. **Or** Install everything through [Docker](#docker-installation) which takes care of dependencies for you. 2. **Or** Install everything through [Docker](#docker-installation) which takes care of dependencies for you.
## Installation ### Installation
### Clone the Repository #### Clone the Repository
Clone the repository, this will create a new folder called `Ocelot-Social`: Clone the repository, this will create a new folder called `Ocelot-Social`:
@ -65,7 +124,7 @@ Change into the new folder.
$ cd Ocelot-Social $ cd Ocelot-Social
``` ```
## Live Demo And Developer Logins ### Live Demo And Developer Logins
**Try out our deployed [development environment](https://stage.ocelot.social).** **Try out our deployed [development environment](https://stage.ocelot.social).**
@ -74,7 +133,7 @@ Visit our staging networks:
* central staging network: [stage.ocelot.social](https://stage.ocelot.social) * central staging network: [stage.ocelot.social](https://stage.ocelot.social)
<!-- - rebranded staging network: [rebrand.ocelot.social](https://stage.ocelot.social). --> <!-- - rebranded staging network: [rebrand.ocelot.social](https://stage.ocelot.social). -->
### Login #### Login
Logins for the live demos and developers (local developers after the following installations) in the browser: Logins for the live demos and developers (local developers after the following installations) in the browser:
@ -84,11 +143,11 @@ Logins for the live demos and developers (local developers after the following i
| `moderator@example.org` | 1234 | moderator | | `moderator@example.org` | 1234 | moderator |
| `admin@example.org` | 1234 | admin | | `admin@example.org` | 1234 | admin |
### Docker Installation #### Docker Installation
Docker is a software development container tool that combines software and its dependencies into one standardized unit that contains everything needed to run it. This helps us to avoid problems with dependencies and makes installation easier. Docker is a software development container tool that combines software and its dependencies into one standardized unit that contains everything needed to run it. This helps us to avoid problems with dependencies and makes installation easier.
#### General Installation of Docker ##### General Installation of Docker
There are [several ways to install Docker CE](https://docs.docker.com/install/) on your computer or server. There are [several ways to install Docker CE](https://docs.docker.com/install/) on your computer or server.
@ -105,7 +164,7 @@ $ docker-compose --version
docker-compose version 1.23.2 docker-compose version 1.23.2
``` ```
#### Start Ocelot-Social via Docker-Compose ##### Start Ocelot-Social via Docker-Compose
Prepare ENVs once beforehand: Prepare ENVs once beforehand:
@ -152,11 +211,11 @@ $ docker-compose exec backend yarn run db:seed
For a closer description see [backend README.md](./backend/README.md). For a closer description see [backend README.md](./backend/README.md).
For a full documentation see [SUMMARY](./SUMMARY.md). For a full documentation see [SUMMARY](./SUMMARY.md).
### Local Installation #### Local Installation
For a full documentation see [SUMMARY](./SUMMARY.md). For a full documentation see [SUMMARY](./SUMMARY.md).
## Contributing ### Contributing
Choose an issue (consider our label [good-first-issue](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)) and leave a comment there. We will then invite you to join our volunteers team. Choose an issue (consider our label [good-first-issue](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)) and leave a comment there. We will then invite you to join our volunteers team.
To have the necessary permission to push directly to this repository, please accept our invitation to join our volunteers team, you will receive via the email, Github will send you, once invited. If we did not invite you yet, please request an invitation via Discord. To have the necessary permission to push directly to this repository, please accept our invitation to join our volunteers team, you will receive via the email, Github will send you, once invited. If we did not invite you yet, please request an invitation via Discord.
@ -182,7 +241,7 @@ $ yarn test
Check out our [contribution guideline](./CONTRIBUTING.md), too! Check out our [contribution guideline](./CONTRIBUTING.md), too!
### Developer Chat #### Developer Chat
Join our friendly open-source community on [Discord](https://discord.gg/AJSX9DCSUA) :heart_eyes_cat: Join our friendly open-source community on [Discord](https://discord.gg/AJSX9DCSUA) :heart_eyes_cat:
Just introduce yourself at `#introduce-yourself` and mention a mentor or `@@Mentors` to get you onboard :neckbeard: Just introduce yourself at `#introduce-yourself` and mention a mentor or `@@Mentors` to get you onboard :neckbeard:
@ -190,13 +249,13 @@ Just introduce yourself at `#introduce-yourself` and mention a mentor or `@@Ment
We give write permissions to every developer who asks for it. Just text us on We give write permissions to every developer who asks for it. Just text us on
[Discord](https://discord.gg/AJSX9DCSUA). [Discord](https://discord.gg/AJSX9DCSUA).
## Deployment ### Deployment
Deployment methods can be found in the [Ocelot-Social-Deploy-Rebranding](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding) repository. Deployment methods can be found in the [Ocelot-Social-Deploy-Rebranding](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding) repository.
The only deployment method in this repository for development purposes as described above is `docker-compose`. The only deployment method in this repository for development purposes as described above is `docker-compose`.
## Technology Stack ### Technology Stack
* [VueJS](https://vuejs.org/) * [VueJS](https://vuejs.org/)
* [NuxtJS](https://nuxtjs.org/) * [NuxtJS](https://nuxtjs.org/)
@ -204,7 +263,7 @@ The only deployment method in this repository for development purposes as descri
* [NodeJS](https://nodejs.org/en/) * [NodeJS](https://nodejs.org/en/)
* [Neo4J](https://neo4j.com/) * [Neo4J](https://neo4j.com/)
### For Testing #### For Testing
* [Cypress](https://docs.cypress.io/) * [Cypress](https://docs.cypress.io/)
* [Storybook](https://storybook.js.org/) * [Storybook](https://storybook.js.org/)
@ -212,7 +271,7 @@ The only deployment method in this repository for development purposes as descri
* [Vue Test Utils](https://vue-test-utils.vuejs.org/) * [Vue Test Utils](https://vue-test-utils.vuejs.org/)
* [ESLint](https://eslint.org/) * [ESLint](https://eslint.org/)
## Attributions ### Attributions
Locale Icons made by [Freepik](http://www.freepik.com/) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/). Locale Icons made by [Freepik](http://www.freepik.com/) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
@ -220,6 +279,6 @@ Browser compatibility testing with [BrowserStack](https://www.browserstack.com/)
<img alt="BrowserStack Logo" src=".gitbook/assets/browserstack-logo.svg" width="256"> <img alt="BrowserStack Logo" src=".gitbook/assets/browserstack-logo.svg" width="256">
## License ### License
See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT). See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT).

View File

@ -1 +1 @@
v12.19.0 v19.4.0

View File

@ -1,7 +1,7 @@
################################################################################## ##################################################################################
# BASE (Is pushed to DockerHub for rebranding) ################################### # BASE (Is pushed to DockerHub for rebranding) ###################################
################################################################################## ##################################################################################
FROM node:12.19.0-alpine3.10 as base FROM node:19.4.0-alpine3.17 as base
# ENVs # ENVs
## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame
@ -35,7 +35,7 @@ LABEL maintainer="devops@ocelot.social"
# Install Additional Software # Install Additional Software
## install: git ## install: git
RUN apk --no-cache add git RUN apk --no-cache add git python3 make g++
# Settings # Settings
## Expose Container Port ## Expose Container Port

View File

@ -19,12 +19,19 @@ Wait a little until your backend is up and running at [http://localhost:4000/](h
## Installation without Docker ## Installation without Docker
For the local installation you need a recent version of For the local installation you need a recent version of
[node](https://nodejs.org/en/) (&gt;= `v10.12.0`). We are using [Node](https://nodejs.org/en/) (&gt;= `v16.19.0`). We are using
`12.19.0` and therefore we recommend to use the same version `v19.4.0` and therefore we recommend to use the same version
([see](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4082) ([see](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4082)
some known problems with more recent node versions). You can use the some known problems with more recent node versions). You can use the
[node version manager](https://github.com/nvm-sh/nvm) to switch [node version manager](https://github.com/nvm-sh/nvm) `nvm` to switch
between different local node versions. between different local Node versions:
```bash
# install Node
$ cd backend
$ nvm install v19.4.0
$ nvm use v19.4.0
```
Install node dependencies with [yarn](https://yarnpkg.com/en/): Install node dependencies with [yarn](https://yarnpkg.com/en/):
@ -32,6 +39,10 @@ Install node dependencies with [yarn](https://yarnpkg.com/en/):
# in main folder # in main folder
$ cd backend $ cd backend
$ yarn install $ yarn install
# or just
$ yarn
# or just later on to use version of ".nvmrc" file
$ nvm use && yarn
``` ```
Copy Environment Variables: Copy Environment Variables:
@ -68,9 +79,9 @@ More details about our GraphQL playground and how to use it with ocelot.social c
![GraphQL Playground](../.gitbook/assets/graphql-playground.png) ![GraphQL Playground](../.gitbook/assets/graphql-playground.png)
### Database Indices and Constraints ### Database Indexes and Constraints
Database indices and constraints need to be created when the database and the Database indexes and constraints need to be created when the database and the
backend is running: backend is running:
{% tabs %} {% tabs %}
@ -78,7 +89,13 @@ backend is running:
```bash ```bash
# in main folder while docker-compose is running # in main folder while docker-compose is running
$ docker-compose exec backend yarn run db:migrate init $ docker exec backend yarn run db:migrate init
# only once: init admin user and create indexes and constraints in Neo4j database
# for development
$ docker compose exec backend yarn prod:migrate init
# in production mode use command
$ docker compose exec backend /bin/sh -c "yarn prod:migrate init"
``` ```
{% endtab %} {% endtab %}
@ -105,18 +122,18 @@ In another terminal run:
```bash ```bash
# in main folder while docker-compose is running # in main folder while docker-compose is running
$ docker-compose exec backend yarn run db:seed $ docker exec backend yarn run db:seed
``` ```
To reset the database run: To reset the database run:
```bash ```bash
# in main folder while docker-compose is running # in main folder while docker-compose is running
$ docker-compose exec backend yarn run db:reset $ docker exec backend yarn run db:reset
# you could also wipe out your neo4j database and delete all volumes with: # you could also wipe out your neo4j database and delete all volumes with:
$ docker-compose down -v $ docker-compose down -v
# if container is not running, run this command to set up your database indeces and contstraints # if container is not running, run this command to set up your database indexes and constraints
$ docker-compose exec backend yarn run db:migrate init $ docker exec backend yarn run db:migrate init
``` ```
{% endtab %} {% endtab %}
@ -159,7 +176,7 @@ To run the migration:
```bash ```bash
# in main folder while docker-compose is running # in main folder while docker-compose is running
$ docker-compose exec backend yarn run db:migrate up $ docker exec backend yarn run db:migrate up
``` ```
{% endtab %} {% endtab %}
@ -195,7 +212,7 @@ Run the unit tests:
```bash ```bash
# in main folder while docker-compose is running # in main folder while docker-compose is running
$ docker-compose exec backend yarn run test $ docker exec backend yarn run test
``` ```
{% endtab %} {% endtab %}

14
backend/jest.config.js Normal file
View File

@ -0,0 +1,14 @@
module.exports = {
verbose: true,
collectCoverage: true,
collectCoverageFrom: [
'**/*.js',
'!**/node_modules/**',
'!**/test/**',
'!**/dist/**',
'!**/src/**/?(*.)+(spec|test).js?(x)'
],
coverageReporters: ['lcov', 'text'],
testMatch: ['**/src/**/?(*.)+(spec|test).js?(x)'],
setupFilesAfterEnv: ['<rootDir>/test/setup.js']
}

View File

@ -1,6 +1,6 @@
{ {
"name": "ocelot-social-backend", "name": "ocelot-social-backend",
"version": "2.2.0", "version": "2.4.0",
"description": "GraphQL Backend for ocelot.social", "description": "GraphQL Backend for ocelot.social",
"repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social",
"author": "ocelot.social Community", "author": "ocelot.social Community",
@ -15,29 +15,13 @@
"dev": "nodemon --exec babel-node src/ -e js,gql", "dev": "nodemon --exec babel-node src/ -e js,gql",
"dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql",
"lint": "eslint src --config .eslintrc.js", "lint": "eslint src --config .eslintrc.js",
"test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --forceExit --detectOpenHandles --runInBand --coverage --logHeapUsage", "test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --runInBand --coverage --forceExit --detectOpenHandles",
"db:clean": "babel-node src/db/clean.js", "db:clean": "babel-node src/db/clean.js",
"db:reset": "yarn run db:clean", "db:reset": "yarn run db:clean",
"db:seed": "babel-node src/db/seed.js", "db:seed": "babel-node src/db/seed.js",
"db:migrate": "yarn run __migrate --store ./src/db/migrate/store.js", "db:migrate": "yarn run __migrate --store ./src/db/migrate/store.js",
"db:migrate:create": "yarn run __migrate --template-file ./src/db/migrate/template.js --date-format 'yyyymmddHHmmss' create" "db:migrate:create": "yarn run __migrate --template-file ./src/db/migrate/template.js --date-format 'yyyymmddHHmmss' create"
}, },
"jest": {
"verbose": true,
"collectCoverageFrom": [
"**/*.js",
"!**/node_modules/**",
"!**/test/**",
"!**/dist/**",
"!**/src/**/?(*.)+(spec|test).js?(x)"
],
"coverageReporters": [
"lcov"
],
"testMatch": [
"**/src/**/?(*.)+(spec|test).js?(x)"
]
},
"dependencies": { "dependencies": {
"@babel/cli": "~7.8.4", "@babel/cli": "~7.8.4",
"@babel/core": "~7.9.0", "@babel/core": "~7.9.0",
@ -81,22 +65,22 @@
"linkifyjs": "~2.1.8", "linkifyjs": "~2.1.8",
"lodash": "~4.17.14", "lodash": "~4.17.14",
"merge-graphql-schemas": "^1.7.8", "merge-graphql-schemas": "^1.7.8",
"metascraper": "^5.11.8", "metascraper": "^5.33.5",
"metascraper-audio": "^5.14.26", "metascraper-audio": "^5.33.5",
"metascraper-author": "^5.14.22", "metascraper-author": "^5.33.5",
"metascraper-clearbit-logo": "^5.3.0", "metascraper-clearbit-logo": "^5.3.0",
"metascraper-date": "^5.11.8", "metascraper-date": "^5.33.5",
"metascraper-description": "^5.23.1", "metascraper-description": "^5.33.5",
"metascraper-image": "^5.11.8", "metascraper-image": "^5.33.5",
"metascraper-lang": "^5.23.1", "metascraper-lang": "^5.33.5",
"metascraper-lang-detector": "^4.10.2", "metascraper-lang-detector": "^4.10.2",
"metascraper-logo": "^5.14.26", "metascraper-logo": "^5.33.5",
"metascraper-publisher": "^5.23.0", "metascraper-publisher": "^5.33.5",
"metascraper-soundcloud": "^5.23.0", "metascraper-soundcloud": "^5.33.5",
"metascraper-title": "^5.11.8", "metascraper-title": "^5.33.5",
"metascraper-url": "^5.14.26", "metascraper-url": "^5.33.5",
"metascraper-video": "^5.11.8", "metascraper-video": "^5.33.5",
"metascraper-youtube": "^5.23.0", "metascraper-youtube": "^5.33.5",
"migrate": "^1.7.0", "migrate": "^1.7.0",
"mime-types": "^2.1.26", "mime-types": "^2.1.26",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
@ -132,13 +116,15 @@
"eslint-plugin-prettier": "~3.4.1", "eslint-plugin-prettier": "~3.4.1",
"eslint-plugin-promise": "~4.3.1", "eslint-plugin-promise": "~4.3.1",
"eslint-plugin-standard": "~4.0.1", "eslint-plugin-standard": "~4.0.1",
"jest": "~25.3.0", "jest": "29.4",
"nodemon": "~2.0.2", "nodemon": "~2.0.2",
"prettier": "~2.3.2", "prettier": "~2.3.2",
"rosie": "^2.0.1", "rosie": "^2.0.1",
"supertest": "~4.0.2" "supertest": "~4.0.2"
}, },
"resolutions": { "resolutions": {
"fs-capacitor": "6.0.0" "**/**/fs-capacitor": "^6.2.0",
"**/graphql-upload": "^11.0.0",
"nan": "2.17.0"
} }
} }

View File

@ -33,6 +33,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -1,3 +1,3 @@
// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js` // this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js`
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 100 // with removed HTML tags export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 50 // with removed HTML tags
export const DESCRIPTION_EXCERPT_HTML_LENGTH = 250 // with removed HTML tags export const DESCRIPTION_EXCERPT_HTML_LENGTH = 250 // with removed HTML tags

View File

@ -65,7 +65,6 @@ Factory.define('basicUser')
name: faker.name.findName, name: faker.name.findName,
password: '1234', password: '1234',
role: 'user', role: 'user',
about: faker.lorem.paragraph,
termsAndConditionsAgreedVersion: '0.0.1', termsAndConditionsAgreedVersion: '0.0.1',
termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z', termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z',
allowEmbedIframes: false, allowEmbedIframes: false,
@ -82,12 +81,28 @@ Factory.define('basicUser')
Factory.define('userWithoutEmailAddress') Factory.define('userWithoutEmailAddress')
.extend('basicUser') .extend('basicUser')
.option('about', faker.lorem.paragraph)
.after(async (buildObject, options) => {
return neode.create('User', buildObject)
})
Factory.define('userWithAboutNull')
.extend('basicUser')
.option('about', null)
.after(async (buildObject, options) => {
return neode.create('User', buildObject)
})
Factory.define('userWithAboutEmpty')
.extend('basicUser')
.option('about', '')
.after(async (buildObject, options) => { .after(async (buildObject, options) => {
return neode.create('User', buildObject) return neode.create('User', buildObject)
}) })
Factory.define('user') Factory.define('user')
.extend('basicUser') .extend('basicUser')
.option('about', faker.lorem.paragraph)
.option('email', faker.internet.exampleEmail) .option('email', faker.internet.exampleEmail)
.option('avatar', () => .option('avatar', () =>
Factory.build('image', { Factory.build('image', {

View File

@ -85,7 +85,7 @@ class Store {
await createDefaultAdminUser(session) await createDefaultAdminUser(session)
if (CONFIG.CATEGORIES_ACTIVE) await createCategories(session) if (CONFIG.CATEGORIES_ACTIVE) await createCategories(session)
const writeTxResultPromise = session.writeTransaction(async (txc) => { const writeTxResultPromise = session.writeTransaction(async (txc) => {
await txc.run('CALL apoc.schema.assert({},{},true)') // drop all indices and contraints await txc.run('CALL apoc.schema.assert({},{},true)') // drop all indices and constraints
return Promise.all( return Promise.all(
[ [
'CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"])', 'CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"])',

View File

@ -1,13 +1,3 @@
// TODO: can be replaced with: (which is no a fake)
// import gql from 'graphql-tag'
// See issue: https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/5152
//* This is a fake ES2015 template string, just to benefit of syntax
// highlighting of `gql` template strings in certain editors.
export function gql(strings) {
return strings.join('')
}
// sometime we have to wait to check a db state by having a look into the db in a certain moment // sometime we have to wait to check a db state by having a look into the db in a certain moment
// or we wait a bit to check if we missed to set an await somewhere // or we wait a bit to check if we missed to set an await somewhere
// see: https://www.sitepoint.com/delay-sleep-pause-wait/ // see: https://www.sitepoint.com/delay-sleep-pause-wait/

View File

@ -2,24 +2,26 @@
* iterate through all fields and replace it with the callback result * iterate through all fields and replace it with the callback result
* @property data Array * @property data Array
* @property fields Array * @property fields Array
* @property fieldName String
* @property callback Function * @property callback Function
*/ */
function walkRecursive(data, fields, callback, _key) { function walkRecursive(data, fields, fieldName, callback, _key) {
if (!Array.isArray(fields)) { if (!Array.isArray(fields)) {
throw new Error('please provide an fields array for the walkRecursive helper') throw new Error('please provide an fields array for the walkRecursive helper')
} }
if (data && typeof data === 'string' && fields.includes(_key)) { if (data && typeof data === 'string' && fields.includes(_key)) {
// well we found what we searched for, lets replace the value with our callback result // well we found what we searched for, lets replace the value with our callback result
data = callback(data, _key) const key = _key.split('!')
if (key.length === 1 || key[1] !== fieldName) data = callback(data, key[0])
} else if (data && Array.isArray(data)) { } else if (data && Array.isArray(data)) {
// go into the rabbit hole and dig through that array // go into the rabbit hole and dig through that array
data.forEach((res, index) => { data.forEach((res, index) => {
data[index] = walkRecursive(data[index], fields, callback, index) data[index] = walkRecursive(data[index], fields, fieldName, callback, index)
}) })
} else if (data && typeof data === 'object') { } else if (data && typeof data === 'object') {
// lets get some keys and stir them // lets get some keys and stir them
Object.keys(data).forEach((k) => { Object.keys(data).forEach((k) => {
data[k] = walkRecursive(data[k], fields, callback, k) data[k] = walkRecursive(data[k], fields, fieldName, callback, k)
}) })
} }
return data return data

View File

@ -36,6 +36,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -1,4 +1,4 @@
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { cleanDatabase } from '../../db/factories' import { cleanDatabase } from '../../db/factories'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
@ -50,6 +50,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -80,14 +80,6 @@ const testEmailData = (emailTemplate, templateBuilder, templateData, texts) => {
return emailTemplate return emailTemplate
} }
// beforeAll(async () => {
// await cleanDatabase()
// })
// afterAll(async () => {
// await cleanDatabase()
// })
describe('templateBuilder', () => { describe('templateBuilder', () => {
describe('signupTemplate', () => { describe('signupTemplate', () => {
describe('multi language', () => { describe('multi language', () => {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -28,6 +28,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
const createPostMutation = gql` const createPostMutation = gql`

View File

@ -10,11 +10,14 @@ const sendSignupMail = async (resolve, root, args, context, resolveInfo) => {
const { inviteCode } = args const { inviteCode } = args
const response = await resolve(root, args, context, resolveInfo) const response = await resolve(root, args, context, resolveInfo)
const { email, nonce } = response const { email, nonce } = response
if (nonce) {
// emails that already exist do not have a nonce
if (inviteCode) { if (inviteCode) {
await sendMail(signupTemplate({ email, variables: { nonce, inviteCode } })) await sendMail(signupTemplate({ email, variables: { nonce, inviteCode } }))
} else { } else {
await sendMail(signupTemplate({ email, variables: { nonce } })) await sendMail(signupTemplate({ email, variables: { nonce } }))
} }
}
delete response.nonce delete response.nonce
return response return response
} }
@ -30,7 +33,9 @@ const sendPasswordResetMail = async (resolve, root, args, context, resolveInfo)
const sendEmailVerificationMail = async (resolve, root, args, context, resolveInfo) => { const sendEmailVerificationMail = async (resolve, root, args, context, resolveInfo) => {
const response = await resolve(root, args, context, resolveInfo) const response = await resolve(root, args, context, resolveInfo)
const { email, nonce, name } = response const { email, nonce, name } = response
if (nonce) {
await sendMail(emailVerificationTemplate({ email, variables: { nonce, name } })) await sendMail(emailVerificationTemplate({ email, variables: { nonce, name } }))
}
delete response.nonce delete response.nonce
return response return response
} }

View File

@ -1,4 +1,4 @@
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { cleanDatabase } from '../../db/factories' import { cleanDatabase } from '../../db/factories'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
@ -56,6 +56,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,4 +1,4 @@
import { gql } from '../helpers/jest' import gql from 'graphql-tag'
import { cleanDatabase } from '../db/factories' import { cleanDatabase } from '../db/factories'
import { getNeode, getDriver } from '../db/neo4j' import { getNeode, getDriver } from '../db/neo4j'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -24,6 +24,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,7 +1,7 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../server' import createServer from '../server'
import Factory, { cleanDatabase } from '../db/factories' import Factory, { cleanDatabase } from '../db/factories'
import { gql } from '../helpers/jest' import gql from 'graphql-tag'
import { getDriver, getNeode } from '../db/neo4j' import { getDriver, getNeode } from '../db/neo4j'
import CONFIG from '../config' import CONFIG from '../config'
@ -28,6 +28,7 @@ describe('authorization', () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -33,6 +33,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {
@ -152,7 +153,7 @@ describe('slugifyMiddleware', () => {
}) })
describe('but if the client specifies a slug', () => { describe('but if the client specifies a slug', () => {
it('rejects CreateGroup', async (done) => { it('rejects CreateGroup', async () => {
try { try {
await expect( await expect(
mutate({ mutate({
@ -171,7 +172,6 @@ describe('slugifyMiddleware', () => {
}, },
], ],
}) })
done()
} catch (error) { } catch (error) {
throw new Error(` throw new Error(`
${error} ${error}
@ -258,7 +258,7 @@ describe('slugifyMiddleware', () => {
}) })
describe('setting slug explicitly', () => { describe('setting slug explicitly', () => {
it('rejects UpdateGroup', async (done) => { it('rejects UpdateGroup', async () => {
try { try {
await expect( await expect(
mutate({ mutate({
@ -275,7 +275,6 @@ describe('slugifyMiddleware', () => {
}, },
], ],
}) })
done()
} catch (error) { } catch (error) {
throw new Error(` throw new Error(`
${error} ${error}
@ -382,7 +381,7 @@ describe('slugifyMiddleware', () => {
}) })
describe('but if the client specifies a slug', () => { describe('but if the client specifies a slug', () => {
it('rejects CreatePost', async (done) => { it('rejects CreatePost', async () => {
try { try {
await expect( await expect(
mutate({ mutate({
@ -402,7 +401,6 @@ describe('slugifyMiddleware', () => {
}, },
], ],
}) })
done()
} catch (error) { } catch (error) {
throw new Error(` throw new Error(`
${error} ${error}

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -195,6 +195,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('softDeleteMiddleware', () => { describe('softDeleteMiddleware', () => {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../db/factories' import Factory, { cleanDatabase } from '../db/factories'
import { gql } from '../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../db/neo4j' import { getNeode, getDriver } from '../db/neo4j'
import createServer from '../server' import createServer from '../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -42,6 +42,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('middleware/userInteractions', () => { describe('middleware/userInteractions', () => {

View File

@ -1,4 +1,4 @@
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -75,6 +75,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,15 +1,22 @@
import walkRecursive from '../helpers/walkRecursive' import walkRecursive from '../helpers/walkRecursive'
import { cleanHtml } from '../middleware/helpers/cleanHtml.js' import { cleanHtml } from '../middleware/helpers/cleanHtml.js'
const fields = ['content', 'contentExcerpt', 'reasonDescription'] // exclamation mark separetes field names, that should not be sanitized
const fields = [
'content',
'contentExcerpt',
'reasonDescription',
'description!embed',
'descriptionExcerpt',
]
export default { export default {
Mutation: async (resolve, root, args, context, info) => { Mutation: async (resolve, root, args, context, info) => {
args = walkRecursive(args, fields, cleanHtml) args = walkRecursive(args, fields, info.fieldName, cleanHtml)
return resolve(root, args, context, info) return resolve(root, args, context, info)
}, },
Query: async (resolve, root, args, context, info) => { Query: async (resolve, root, args, context, info) => {
const result = await resolve(root, args, context, info) const result = await resolve(root, args, context, info)
return walkRecursive(result, fields, cleanHtml) return walkRecursive(result, fields, info.fieldName, cleanHtml)
}, },
} }

View File

@ -1,6 +1,7 @@
import { cleanDatabase } from '../db/factories' import { cleanDatabase } from '../db/factories'
import { getNeode } from '../db/neo4j' import { getNeode, getDriver } from '../db/neo4j'
const driver = getDriver()
const neode = getNeode() const neode = getNeode()
beforeAll(async () => { beforeAll(async () => {
@ -9,6 +10,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543
@ -37,11 +39,10 @@ describe('slug', () => {
) )
}) })
it('must be unique', async (done) => { it('must be unique', async () => {
await neode.create('User', { slug: 'Matt' }) await neode.create('User', { slug: 'Matt' })
try { try {
await expect(neode.create('User', { slug: 'Matt' })).rejects.toThrow('already exists') await expect(neode.create('User', { slug: 'Matt' })).rejects.toThrow('already exists')
done()
} catch (error) { } catch (error) {
throw new Error(` throw new Error(`
${error} ${error}

View File

@ -11,7 +11,7 @@ export default makeAugmentedSchema({
'Badge', 'Badge',
'Embed', 'Embed',
'EmailAddress', 'EmailAddress',
'Notfication', 'Notification',
'Statistics', 'Statistics',
'LoggedInUser', 'LoggedInUser',
'Location', 'Location',

View File

@ -0,0 +1,7 @@
import { GraphQLUpload } from 'graphql-upload'
export default {
// This maps the `Upload` scalar to the implementation provided
// by the `graphql-upload` package.
Upload: GraphQLUpload,
}

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server' import createServer from '../../server'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
@ -25,6 +25,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -37,6 +37,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('donations', () => { describe('donations', () => {

View File

@ -40,7 +40,9 @@ export default {
} }
// check email does not belong to anybody // check email does not belong to anybody
await existingEmailAddress({ args, context }) const existingEmail = await existingEmailAddress({ args, context })
if (existingEmail && existingEmail.alreadyExistingEmail && existingEmail.user)
return existingEmail.alreadyExistingEmail
const nonce = generateNonce() const nonce = generateNonce()
const { const {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getDriver, getNeode } from '../../db/neo4j' import { getDriver, getNeode } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -30,6 +30,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {
@ -134,11 +135,17 @@ describe('AddEmailAddress', () => {
}) })
describe('but if another user owns an `EmailAddress` already with that email', () => { describe('but if another user owns an `EmailAddress` already with that email', () => {
it('throws UserInputError because of unique constraints', async () => { it('does not throw UserInputError', async () => {
await Factory.build('user', {}, { email: 'new-email@example.org' }) await Factory.build('user', {}, { email: 'new-email@example.org' })
await expect(mutate({ mutation, variables })).resolves.toMatchObject({ await expect(mutate({ mutation, variables })).resolves.toMatchObject({
data: { AddEmailAddress: null }, data: {
errors: [{ message: 'A user account with this email already exists.' }], AddEmailAddress: {
createdAt: expect.any(String),
verifiedAt: null,
email: 'new-email@example.org',
},
},
errors: undefined,
}) })
}) })
}) })

View File

@ -3,7 +3,7 @@ import fs from 'fs'
import path from 'path' import path from 'path'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server' import createServer from '../../server'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
jest.mock('node-fetch') jest.mock('node-fetch')
const { Response } = jest.requireActual('node-fetch') const { Response } = jest.requireActual('node-fetch')
@ -96,7 +96,7 @@ describe('Query', () => {
description: null, description: null,
html: null, html: null,
image: null, image: null,
lang: null, lang: 'false',
publisher: null, publisher: null,
sources: ['resource'], sources: ['resource'],
title: null, title: null,

View File

@ -2,7 +2,7 @@ import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { getDriver, getNeode } from '../../db/neo4j' import { getDriver, getNeode } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
const driver = getDriver() const driver = getDriver()
const neode = getNeode() const neode = getNeode()
@ -71,6 +71,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -252,6 +252,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('in mode', () => { describe('in mode', () => {

View File

@ -1,5 +1,3 @@
import { UserInputError } from 'apollo-server'
export default async function alreadyExistingMail({ args, context }) { export default async function alreadyExistingMail({ args, context }) {
const session = context.driver.session() const session = context.driver.session()
try { try {
@ -20,9 +18,11 @@ export default async function alreadyExistingMail({ args, context }) {
}) })
}) })
const [emailBelongsToUser] = await existingEmailAddressTxPromise const [emailBelongsToUser] = await existingEmailAddressTxPromise
const { alreadyExistingEmail, user } = emailBelongsToUser || {} /*
const { alreadyExistingEmail, user } =
if (user) throw new UserInputError('A user account with this email already exists.') if (user) throw new UserInputError('A user account with this email already exists.')
return alreadyExistingEmail */
return emailBelongsToUser || {}
} finally { } finally {
session.close() session.close()
} }

View File

@ -0,0 +1,40 @@
import { mergeWith, isArray } from 'lodash'
const getMyGroupIds = async (context) => {
const { user } = context
if (!(user && user.id)) return []
const session = context.driver.session()
const readTxResultPromise = await session.readTransaction(async (transaction) => {
const cypher = `
MATCH (group:Group)<-[membership:MEMBER_OF]-(:User { id: $userId })
WHERE membership.role IN ['usual', 'admin', 'owner']
RETURN collect(group.id) AS myGroupIds`
const getMyGroupIdsResponse = await transaction.run(cypher, { userId: user.id })
return getMyGroupIdsResponse.records.map((record) => record.get('myGroupIds'))
})
try {
const [myGroupIds] = readTxResultPromise
return myGroupIds
} finally {
session.close()
}
}
export const filterPostsOfMyGroups = async (params, context) => {
if (!(params.filter && params.filter.postsInMyGroups)) return params
delete params.filter.postsInMyGroups
const myGroupIds = await getMyGroupIds(context)
params.filter = mergeWith(
params.filter,
{
group: { id_in: myGroupIds },
},
(objValue, srcValue) => {
if (isArray(objValue)) {
return objValue.concat(srcValue)
}
},
)
return params
}

View File

@ -113,10 +113,11 @@ const sanitizeRelationshipType = (relationshipType) => {
const localFileUpload = ({ createReadStream, uniqueFilename }) => { const localFileUpload = ({ createReadStream, uniqueFilename }) => {
const destination = `/uploads/${uniqueFilename}` const destination = `/uploads/${uniqueFilename}`
return new Promise((resolve, reject) => return new Promise((resolve, reject) =>
createReadStream() createReadStream().pipe(
.pipe(createWriteStream(`public${destination}`)) createWriteStream(`public${destination}`)
.on('finish', () => resolve(destination)) .on('finish', () => resolve(destination))
.on('error', reject), .on('error', (error) => reject(error)),
),
) )
} }

View File

@ -15,6 +15,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {
@ -78,7 +79,7 @@ describe('deleteImage', () => {
await expect(someString).toEqual('Hello') await expect(someString).toEqual('Hello')
}) })
it('rolls back the transaction in case of errors', async (done) => { it('rolls back the transaction in case of errors', async () => {
await expect(neode.all('Image')).resolves.toHaveLength(1) await expect(neode.all('Image')).resolves.toHaveLength(1)
const session = driver.session() const session = driver.session()
try { try {
@ -93,7 +94,6 @@ describe('deleteImage', () => {
// nothing has been deleted // nothing has been deleted
await expect(neode.all('Image')).resolves.toHaveLength(1) await expect(neode.all('Image')).resolves.toHaveLength(1)
// all good // all good
done()
} finally { } finally {
session.close() session.close()
} }
@ -239,7 +239,7 @@ describe('mergeImage', () => {
}) })
}) })
it('rolls back the transaction in case of errors', async (done) => { it('rolls back the transaction in case of errors', async () => {
const session = driver.session() const session = driver.session()
try { try {
await session.writeTransaction(async (transaction) => { await session.writeTransaction(async (transaction) => {
@ -254,7 +254,6 @@ describe('mergeImage', () => {
// nothing has been created // nothing has been created
await expect(neode.all('Image')).resolves.toHaveLength(0) await expect(neode.all('Image')).resolves.toHaveLength(0)
// all good // all good
done()
} finally { } finally {
session.close() session.close()
} }

View File

@ -1,6 +1,6 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { getDriver } from '../../db/neo4j' import { getDriver } from '../../db/neo4j'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import CONSTANTS_REGISTRATION from './../../constants/registration' import CONSTANTS_REGISTRATION from './../../constants/registration'
@ -52,6 +52,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('inviteCodes', () => { describe('inviteCodes', () => {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -26,6 +26,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -70,6 +70,7 @@ describe('moderate resources', () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getDriver } from '../../db/neo4j' import { getDriver } from '../../db/neo4j'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../.././server' import createServer from '../.././server'
@ -34,6 +34,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import CONSTANTS_REGISTRATION from './../../constants/registration' import CONSTANTS_REGISTRATION from './../../constants/registration'
import createPasswordReset from './helpers/createPasswordReset' import createPasswordReset from './helpers/createPasswordReset'
@ -38,6 +38,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(() => { beforeEach(() => {

View File

@ -6,6 +6,7 @@ import { mergeImage, deleteImage } from './images/images'
import Resolver from './helpers/Resolver' import Resolver from './helpers/Resolver'
import { filterForMutedUsers } from './helpers/filterForMutedUsers' import { filterForMutedUsers } from './helpers/filterForMutedUsers'
import { filterInvisiblePosts } from './helpers/filterInvisiblePosts' import { filterInvisiblePosts } from './helpers/filterInvisiblePosts'
import { filterPostsOfMyGroups } from './helpers/filterPostsOfMyGroups'
import CONFIG from '../../config' import CONFIG from '../../config'
const maintainPinnedPosts = (params) => { const maintainPinnedPosts = (params) => {
@ -21,12 +22,14 @@ const maintainPinnedPosts = (params) => {
export default { export default {
Query: { Query: {
Post: async (object, params, context, resolveInfo) => { Post: async (object, params, context, resolveInfo) => {
params = await filterPostsOfMyGroups(params, context)
params = await filterInvisiblePosts(params, context) params = await filterInvisiblePosts(params, context)
params = await filterForMutedUsers(params, context) params = await filterForMutedUsers(params, context)
params = await maintainPinnedPosts(params) params = await maintainPinnedPosts(params)
return neo4jgraphql(object, params, context, resolveInfo) return neo4jgraphql(object, params, context, resolveInfo)
}, },
profilePagePosts: async (object, params, context, resolveInfo) => { profilePagePosts: async (object, params, context, resolveInfo) => {
params = await filterPostsOfMyGroups(params, context)
params = await filterInvisiblePosts(params, context) params = await filterInvisiblePosts(params, context)
params = await filterForMutedUsers(params, context) params = await filterForMutedUsers(params, context)
return neo4jgraphql(object, params, context, resolveInfo) return neo4jgraphql(object, params, context, resolveInfo)

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -56,6 +56,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -61,6 +61,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('Posts in Groups', () => { describe('Posts in Groups', () => {
@ -1677,5 +1678,59 @@ describe('Posts in Groups', () => {
}) })
}) })
}) })
describe('filter posts in my groups', () => {
describe('without any posts in groups', () => {
beforeAll(async () => {
authenticatedUser = await anyUser.toJson()
})
it('finds no posts', async () => {
const result = await query({
query: filterPosts(),
variables: { filter: { postsInMyGroups: true } },
})
expect(result.data.Post).toHaveLength(0)
expect(result).toMatchObject({
data: {
Post: [],
},
errors: undefined,
})
})
})
describe('with posts in groups', () => {
beforeAll(async () => {
// member of hidden-group and closed-group
authenticatedUser = await allGroupsUser.toJson()
})
it('finds two posts', async () => {
const result = await query({
query: filterPosts(),
variables: { filter: { postsInMyGroups: true } },
})
expect(result.data.Post).toHaveLength(2)
expect(result).toMatchObject({
data: {
Post: expect.arrayContaining([
{
id: 'post-to-closed-group',
title: 'A post to a closed group',
content: 'I am posting into a closed group as a member of the group',
},
{
id: 'post-to-hidden-group',
title: 'A post to a hidden group',
content: 'I am posting into a hidden group as a member of the group',
},
]),
},
errors: undefined,
})
})
})
})
}) })
}) })

View File

@ -13,7 +13,12 @@ export default {
args.nonce = generateNonce() args.nonce = generateNonce()
args.email = normalizeEmail(args.email) args.email = normalizeEmail(args.email)
let emailAddress = await existingEmailAddress({ args, context }) let emailAddress = await existingEmailAddress({ args, context })
if (emailAddress) return emailAddress /*
if (emailAddress.user) {
// what to do?
}
*/
if (emailAddress.alreadyExistingEmail) return emailAddress.alreadyExistingEmail
try { try {
emailAddress = await neode.create('EmailAddress', args) emailAddress = await neode.create('EmailAddress', args)
return emailAddress.toJson() return emailAddress.toJson()

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getDriver, getNeode } from '../../db/neo4j' import { getDriver, getNeode } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -29,6 +29,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {
@ -118,9 +119,9 @@ describe('Signup', () => {
await emailAddress.relateTo(user, 'belongsTo') await emailAddress.relateTo(user, 'belongsTo')
}) })
it('throws UserInputError error because of unique constraint violation', async () => { it('does not throw UserInputError error', async () => {
await expect(mutate({ mutation, variables })).resolves.toMatchObject({ await expect(mutate({ mutation, variables })).resolves.toMatchObject({
errors: [{ message: 'A user account with this email already exists.' }], data: { Signup: { email: 'someuser@example.org' } },
}) })
}) })
}) })

View File

@ -1,7 +1,7 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../.././server' import createServer from '../.././server'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getDriver, getNeode } from '../../db/neo4j' import { getDriver, getNeode } from '../../db/neo4j'
const instance = getNeode() const instance = getNeode()
@ -117,6 +117,7 @@ describe('file a report on a resource', () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -33,6 +33,7 @@ describe('rewards', () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -26,6 +26,8 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
neode.close()
}) })
const searchQuery = gql` const searchQuery = gql`

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -51,6 +51,7 @@ describe('shout and unshout posts', () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(async () => { beforeEach(async () => {

View File

@ -1,7 +1,7 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server' import createServer from '../../server'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getDriver } from '../../db/neo4j' import { getDriver } from '../../db/neo4j'
const driver = getDriver() const driver = getDriver()
@ -12,6 +12,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('SocialMedia', () => { describe('SocialMedia', () => {

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -39,6 +39,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -60,6 +60,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('resolvers/userData', () => { describe('resolvers/userData', () => {

View File

@ -1,15 +1,17 @@
import jwt from 'jsonwebtoken' import jwt from 'jsonwebtoken'
import CONFIG from './../../config' import CONFIG from './../../config'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { loginMutation } from '../../graphql/userManagement' import { loginMutation } from '../../graphql/userManagement'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer, { context } from '../../server' import createServer, { context } from '../../server'
import encode from '../../jwt/encode' import encode from '../../jwt/encode'
import { getNeode } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import { categories } from '../../constants/categories' import { categories } from '../../constants/categories'
const neode = getNeode() const neode = getNeode()
const driver = getDriver()
let query, mutate, variables, req, user let query, mutate, variables, req, user
const disable = async (id) => { const disable = async (id) => {
@ -47,6 +49,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(() => { beforeEach(() => {
@ -137,7 +140,12 @@ describe('currentUser', () => {
describe('authenticated', () => { describe('authenticated', () => {
describe('and corresponding user in the database', () => { describe('and corresponding user in the database', () => {
let avatar
beforeEach(async () => { beforeEach(async () => {
avatar = await Factory.build('image', {
url: 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg',
})
await Factory.build( await Factory.build(
'user', 'user',
{ {
@ -149,9 +157,7 @@ describe('currentUser', () => {
}, },
{ {
email: 'test@example.org', email: 'test@example.org',
avatar: Factory.build('image', { avatar,
url: 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg',
}),
}, },
) )
const userBearerToken = encode({ id: 'u3' }) const userBearerToken = encode({ id: 'u3' })
@ -163,9 +169,11 @@ describe('currentUser', () => {
data: { data: {
currentUser: { currentUser: {
id: 'u3', id: 'u3',
avatar: Factory.build('image', { avatar: {
url: 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg', url: expect.stringContaining(
}), 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg',
),
},
email: 'test@example.org', email: 'test@example.org',
name: 'Matilde Hermiston', name: 'Matilde Hermiston',
slug: 'matilde-hermiston', slug: 'matilde-hermiston',
@ -243,7 +251,7 @@ describe('login', () => {
describe('ask for a `token`', () => { describe('ask for a `token`', () => {
describe('with a valid email/password combination', () => { describe('with a valid email/password combination', () => {
it('responds with a JWT bearer token', async (done) => { it('responds with a JWT bearer token', async () => {
const { const {
data: { login: token }, data: { login: token },
} = await mutate({ mutation: loginMutation, variables }) } = await mutate({ mutation: loginMutation, variables })
@ -252,7 +260,6 @@ describe('login', () => {
id: 'acb2d923-f3af-479e-9f00-61b12e864666', id: 'acb2d923-f3af-479e-9f00-61b12e864666',
}) })
expect(err).toBeNull() expect(err).toBeNull()
done()
}) })
}) })

View File

@ -1,5 +1,5 @@
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -81,6 +81,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543

View File

@ -1,4 +1,4 @@
import { gql } from '../../../helpers/jest' import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '../../../db/factories' import Factory, { cleanDatabase } from '../../../db/factories'
import { getNeode, getDriver } from '../../../db/neo4j' import { getNeode, getDriver } from '../../../db/neo4j'
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
@ -90,6 +90,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(() => { beforeEach(() => {

View File

@ -1,7 +1,7 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../../../server' import createServer from '../../../server'
import { cleanDatabase } from '../../../db/factories' import { cleanDatabase } from '../../../db/factories'
import { gql } from '../../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../../db/neo4j' import { getNeode, getDriver } from '../../../db/neo4j'
const driver = getDriver() const driver = getDriver()
@ -18,6 +18,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
beforeEach(() => { beforeEach(() => {

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../db/factories' import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest' import gql from 'graphql-tag'
import { getNeode, getDriver } from '../../db/neo4j' import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server' import createServer from '../../server'
@ -28,6 +28,7 @@ beforeAll(async () => {
afterAll(async () => { afterAll(async () => {
await cleanDatabase() await cleanDatabase()
driver.close()
}) })
describe('count post teaser views', () => { describe('count post teaser views', () => {

View File

@ -82,6 +82,7 @@ input _PostFilter {
emotions_single: _PostEMOTEDFilter emotions_single: _PostEMOTEDFilter
emotions_every: _PostEMOTEDFilter emotions_every: _PostEMOTEDFilter
group: _GroupFilter group: _GroupFilter
postsInMyGroups: Boolean
} }
enum _PostOrdering { enum _PostOrdering {

View File

@ -12,6 +12,7 @@ import { RedisPubSub } from 'graphql-redis-subscriptions'
import { PubSub } from 'graphql-subscriptions' import { PubSub } from 'graphql-subscriptions'
import Redis from 'ioredis' import Redis from 'ioredis'
import bodyParser from 'body-parser' import bodyParser from 'body-parser'
import { graphqlUploadExpress } from 'graphql-upload'
export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED' export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED'
const { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } = CONFIG const { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } = CONFIG
@ -67,6 +68,7 @@ const createServer = (options) => {
}, },
}, },
debug: !!CONFIG.DEBUG, debug: !!CONFIG.DEBUG,
uploads: false,
tracing: !!CONFIG.DEBUG, tracing: !!CONFIG.DEBUG,
formatError: (error) => { formatError: (error) => {
if (error.message === 'ERROR_VALIDATION') { if (error.message === 'ERROR_VALIDATION') {
@ -85,6 +87,7 @@ const createServer = (options) => {
app.use(express.static('public')) app.use(express.static('public'))
app.use(bodyParser.json({ limit: '10mb' })) app.use(bodyParser.json({ limit: '10mb' }))
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true })) app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }))
app.use(graphqlUploadExpress())
server.applyMiddleware({ app, path: '/' }) server.applyMiddleware({ app, path: '/' })
const httpServer = http.createServer(app) const httpServer = http.createServer(app)
server.installSubscriptionHandlers(httpServer) server.installSubscriptionHandlers(httpServer)

8
backend/test/setup.js Normal file
View File

@ -0,0 +1,8 @@
// Polyfill missing encoders in jsdom
// https://stackoverflow.com/questions/68468203/why-am-i-getting-textencoder-is-not-defined-in-jest
import { TextEncoder, TextDecoder } from 'util'
global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder
// Metascraper takes longer nowadays, double time
jest.setTimeout(10000)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
{ {
"projectId": "qa7fe2", "projectId": "qa7fe2",
"defaultCommandTimeout": 10000,
"ignoreTestFiles": "*.js", "ignoreTestFiles": "*.js",
"chromeWebSecurity": false, "chromeWebSecurity": false,
"baseUrl": "http://localhost:3000", "baseUrl": "http://localhost:3000",

View File

@ -1,5 +1,4 @@
import { Given } from "cypress-cucumber-preprocessor/steps"; import { Given } from "cypress-cucumber-preprocessor/steps";
import { gql } from '../../../backend/src/helpers/jest'
Given('somebody reported the following posts:', table => { Given('somebody reported the following posts:', table => {
table.hashes().forEach(({ submitterEmail, resourceId, reasonCategory, reasonDescription }) => { table.hashes().forEach(({ submitterEmail, resourceId, reasonCategory, reasonDescription }) => {
@ -10,7 +9,7 @@ Given('somebody reported the following posts:', table => {
cy.factory() cy.factory()
.build('user', {}, submitter) .build('user', {}, submitter)
.authenticateAs(submitter) .authenticateAs(submitter)
.mutate(gql`mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { .mutate(`mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
fileReport(resourceId: $resourceId, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription) { fileReport(resourceId: $resourceId, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription) {
reportId reportId
} }

View File

@ -1,6 +1,12 @@
import { Then } from "cypress-cucumber-preprocessor/steps"; import { Then } from "cypress-cucumber-preprocessor/steps";
Then('I can see my new name {string} when I click on my profile picture in the top right', name => { Then('I can see my new name {string} when I click on my profile picture in the top right', name => {
cy.get(".avatar-menu").then(($menu) => {
if (!$menu.is(':visible')){
cy.scrollTo("top");
cy.wait(500);
}
})
cy.get('.avatar-menu').click() // open cy.get('.avatar-menu').click() // open
cy.get('.avatar-menu-popover').contains(name) cy.get('.avatar-menu-popover').contains(name)
cy.get('.avatar-menu').click() // close again cy.get('.avatar-menu').click() // close again

View File

@ -13,29 +13,29 @@ Feature: User profile - list social media accounts
When I navigate to page "/settings/my-social-media" When I navigate to page "/settings/my-social-media"
Then I am on page "/settings/my-social-media" Then I am on page "/settings/my-social-media"
When I add a social media link When I add a social media link
Then I see a toaster with "Added social media" Then I see a toaster with status "success"
And the new social media link shows up on the page And the new social media link shows up on the page
Scenario: Other users viewing my Social Media Scenario: Other users viewing my Social Media
Given I have added a social media link Given I have added the social media link "https://freeradical.zone/peter-pan"
When I navigate to page "/profile/peter-pan" When I navigate to page "/profile/peter-pan"
Then they should be able to see my social media links Then they should be able to see my social media links
Scenario: Deleting Social Media Scenario: Deleting Social Media
When I navigate to page "/settings/my-social-media" When I navigate to page "/settings/my-social-media"
Then I am on page "/settings/my-social-media" Then I am on page "/settings/my-social-media"
Given I have added a social media link Given I have added the social media link "https://freeradical.zone/peter-pan"
When I delete a social media link When I delete the social media link "https://freeradical.zone/peter-pan"
Then I see a toaster with "Deleted social media" Then I see a toaster with status "success"
Scenario: Editing Social Media Scenario: Editing Social Media
When I navigate to page "/settings/my-social-media" When I navigate to page "/settings/my-social-media"
Then I am on page "/settings/my-social-media" Then I am on page "/settings/my-social-media"
Given I have added a social media link Given I have added the social media link "https://freeradical.zone/peter-pan"
When I start editing a social media link When I start editing a social media link
Then I can cancel editing Then I can cancel editing
When I start editing a social media link When I start editing a social media link
And I edit and save the link And I edit and save the link
Then I see a toaster with "Added social media" Then I see a toaster with status "success"
And the new url is displayed And the new url is displayed
But the old url is not displayed But the old url is not displayed

View File

@ -1,12 +1,10 @@
import { When } from "cypress-cucumber-preprocessor/steps"; import { When } from "cypress-cucumber-preprocessor/steps";
When('I add a social media link', () => { When('I add a social media link', () => {
cy.get('button') cy.get('[data-test="add-save-button"]')
.contains('Add link')
.click() .click()
.get('#editSocialMedia') .get('#editSocialMedia')
.type('https://freeradical.zone/peter-pan') .type('https://freeradical.zone/peter-pan')
.get('button') .get('[data-test="add-save-button"]')
.contains('Save')
.click() .click()
}) })

View File

@ -1,6 +0,0 @@
import { When } from "cypress-cucumber-preprocessor/steps";
When('I delete a social media link', () => {
cy.get(".base-button[title='Delete']")
.click()
})

View File

@ -0,0 +1,12 @@
import { When } from "cypress-cucumber-preprocessor/steps";
When('I delete the social media link {string}', (link) => {
cy.get('[data-test="delete-button"]')
.click()
cy.get('[data-test="confirm-modal"]')
.should("be.visible")
cy.get('[data-test="confirm-button"]')
.click()
cy.get('.ds-list-item-content > a')
.contains(link).should('not.exist')
})

View File

@ -4,7 +4,6 @@ When('I edit and save the link', () => {
cy.get('input#editSocialMedia') cy.get('input#editSocialMedia')
.clear() .clear()
.type('https://freeradical.zone/tinkerbell') .type('https://freeradical.zone/tinkerbell')
.get('button') .get('[data-test="add-save-button"]')
.contains('Save')
.click() .click()
}) })

View File

@ -1,13 +0,0 @@
import { Given } from "cypress-cucumber-preprocessor/steps";
Given('I have added a social media link', () => {
cy.visit('/settings/my-social-media')
.get('button')
.contains('Add link')
.click()
.get('#editSocialMedia')
.type('https://freeradical.zone/peter-pan')
.get('button')
.contains('Save')
.click()
})

View File

@ -0,0 +1,13 @@
import { Given } from "cypress-cucumber-preprocessor/steps";
Given('I have added the social media link {string}', (link) => {
cy.visit('/settings/my-social-media')
.get('[data-test="add-save-button"]')
.click()
.get('#editSocialMedia')
.type(link)
.get('[data-test="add-save-button"]')
.click()
cy.get('.ds-list-item-content > a')
.contains(link)
})

View File

@ -1,6 +1,6 @@
import { When } from "cypress-cucumber-preprocessor/steps"; import { When } from "cypress-cucumber-preprocessor/steps";
When('I start editing a social media link', () => { When('I start editing a social media link', () => {
cy.get(".base-button[title='Edit']") cy.get('[data-test="edit-button"]')
.click() .click()
}) })

View File

@ -1,8 +1,8 @@
import { Then } from "cypress-cucumber-preprocessor/steps"; import { Then } from "cypress-cucumber-preprocessor/steps";
Then('they should be able to see my social media links', () => { Then('they should be able to see my social media links', () => {
cy.get('.base-card') cy.get('[data-test="social-media-list-headline"]')
.contains('Where else can I find Peter Pan?') .contains('Peter Pan')
.get('a[href="https://freeradical.zone/peter-pan"]') .get('a[href="https://freeradical.zone/peter-pan"]')
.should('have.length', 1) .should('have.length', 1)
}) })

View File

@ -1,6 +1,12 @@
import { When } from "cypress-cucumber-preprocessor/steps"; import { When } from "cypress-cucumber-preprocessor/steps";
When("I log out", () => { When("I log out", () => {
cy.get(".avatar-menu").then(($menu) => {
if (!$menu.is(':visible')){
cy.scrollTo("top");
cy.wait(500);
}
})
cy.get(".avatar-menu") cy.get(".avatar-menu")
.click(); .click();
cy.get(".avatar-menu-popover") cy.get(".avatar-menu-popover")

View File

@ -0,0 +1,9 @@
import { Then } from "cypress-cucumber-preprocessor/steps";
Then("I see a toaster with status {string}", (status) => {
switch (status) {
case "success":
cy.get(".iziToast.iziToast-color-green").should("be.visible");
break;
}
})

View File

@ -15,11 +15,10 @@
/* globals Cypress cy */ /* globals Cypress cy */
import "cypress-file-upload"; import "cypress-file-upload";
import { GraphQLClient, request } from 'graphql-request' import { GraphQLClient, request } from 'graphql-request'
import { gql } from '../../backend/src/helpers/jest'
import config from '../../backend/src/config' import config from '../../backend/src/config'
const authenticatedHeaders = (variables) => { const authenticatedHeaders = (variables) => {
const mutation = gql` const mutation = `
mutation($email: String!, $password: String!) { mutation($email: String!, $password: String!) {
login(email: $email, password: $password) login(email: $email, password: $password)
} }

1
deployment/.env.dist Normal file
View File

@ -0,0 +1 @@
CONFIGURATION=example

25
deployment/Minikube.md Normal file
View File

@ -0,0 +1,25 @@
# Minikube
There are many Kubernetes providers, but if you're just getting started, Minikube is a tool that you can use to get your feet wet.
After you [installed Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/)
open your minikube dashboard:
```text
$ minikube dashboard
```
This will give you an overview. Some of the steps below need some timing to make resources available to other dependent deployments. Keeping an eye on the dashboard is a great way to check that.
Follow the installation instruction for [Kubernetes with Helm](./kubernetes/README.md).
If all the pods and services have settled and everything looks green in your
minikube dashboard, expose the services you want on your host system.
For example:
```text
$ minikube service webapp --namespace=ocelotsocialnetwork
# optionally
$ minikube service backend --namespace=ocelotsocialnetwork
```

View File

@ -0,0 +1,23 @@
# Deployment
Before you start the deployment you have to do preparations.
## Deployment Preparations
Since all deployment methods described here depend on [Docker](https://docker.com) and [DockerHub](https://hub.docker.com), you need to create your own organisation on DockerHub and put its name in the [package.json](/package.json) file as your `dockerOrganisation`.
Read more details in the [main README](/README.md) under [Usage](/README.md#usage).
## Deployment Methods
You have the following options for a deployment:
- [Kubernetes with Helm](./kubernetes/README.md)
## After Deployment
After the first deployment of the new network on your server, the database is initialized with the default administrator:
- E-mail: admin@example.org
- Password: 1234
***ATTENTION:*** When you are logged in for the first time, please change your (the admin's) e-mail to an existing one and change your password to a secure one !!!

136
deployment/README.md Normal file
View File

@ -0,0 +1,136 @@
# Ocelot.Social Deploy And Rebranding
[![Build Status Publish](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/actions/workflows/publish.yml/badge.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/actions)
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/blob/LICENSE.md)
[![Discord Channel](https://img.shields.io/discord/489522408076738561.svg)](https://discord.gg/AJSX9DCSUA)
[![Open Source Helpers](https://www.codetriage.com/ocelot-social-community/ocelot-social-deploy-rebranding/badges/users.svg)](https://www.codetriage.com/ocelot-social-community/ocelot-social-deploy-rebranding)
This repository is an in use template to rebrand, configure, and deploy [ocelot.social](https://github.com/Ocelot-Social-Community/Ocelot-Social) networks.
The forked original repository is [Ocelot-Social-Deploy-Rebranding](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding).
<!-- markdownlint-disable MD033 -->
<p align="center">
<a href="https://ocelot.social" target="_blank"><img src="branding/static/img/custom/logo-squared.svg" alt="Ocelot-Social" width="40%" height="40%"></a>
</p>
<!-- markdownlint-enable MD033 -->
## Live demo
__Try out our deployed [development environment](https://stage.ocelot.social).__
Visit our staging networks:
- central staging network: [stage.ocelot.social](https://stage.ocelot.social)
<!-- - rebranded staging network: [rebrand.ocelot.social](https://stage.ocelot.social). -->
Logins:
| email | password | role |
| :--- | :--- | :--- |
| `user@example.org` | 1234 | user |
| `moderator@example.org` | 1234 | moderator |
| `admin@example.org` | 1234 | admin |
## Usage
Fork this repository to configure and rebrand it for your own [ocelot.social](https://github.com/Ocelot-Social-Community/Ocelot-Social) network.
### Package.Json And DockerHub Organisation
Write your own data into the main configuration file:
- [package.json](/package.json)
Since all deployment methods described here depend on [Docker](https://docker.com) and [DockerHub](https://hub.docker.com), you need to create your own organisation on DockerHub and put its name in the [package.json](/package.json) file as your `dockerOrganisation`.
### Configure And Branding
The next step is:
- [Configure And Branding](/branding/README.md)
### Optional: Locally Testing Configuration And Branding
Just in case you have Docker installed and run the following, you can check your branding locally:
```bash
# in main folder
$ docker-compose up
# fill the database with an initial admin
$ docker-compose exec backend yarn run prod:migrate init
```
The database is then initialised with the default administrator:
- E-mail: admin@example.org
- Password: 1234
For login or registration have a look in your browser at `http://localhost:3000/`.
For the maintenance page have a look in your browser at `http://localhost:5000/`.
### Push Changes To GitHub
Before merging these changes into the "master" branch on your GitHub fork repository, you need to configure the GitHub repository secrets. This is necessary to [publish](/.github/workflows/publish.yml) the Docker images by pushing them via GitHub actions to repositories belonging to your DockerHub organisation.
First, go to your DockerHub profile under `Account Settings` and click on the `Security` tab. There you create an access token called `<your-organisation>-access-token` and copy the token to a safe place.
Secondly, in your GitHub repository, click on the 'Settings' tab and go to the 'Secrets' tab. There you create two secrets by clicking on `New repository secret`:
1. Named `DOCKERHUB_TOKEN` with the newly created DockerHub token (only the code, not the token name).
2. Named `DOCKERHUB_USERNAME` with your DockerHub username.
### Optional: Locally Testing Your DockerHub Images
Just in case you like to check your pushed Docker images in your organisation's DockerHub repositories locally:
- rename the file `docker-compose.ocelotsocial-branded.yml` with your network name
- in the file, rename the ocelot.social DockerHub organisation `ocelotsocialnetwork` to your organisations name
Remove any local Docker images if necessary and do the following:
```bash
# in main folder
$ docker-compose -f docker-compose.<your-organisation>-branded.yml up
# fill the database with an initial admin
$ docker-compose exec backend yarn run prod:migrate init
```
See the login details and browser addresses above.
### Deployment
Afterwards you can [deploy](/deployment/README.md) it on your server:
- [Kubernetes with Helm](/deployment/kubernetes/README.md)
## Developer Chat
Join our friendly open-source community on [Discord](https://discord.gg/AJSX9DCSUA) :heart_eyes_cat:
Just introduce yourself at `#introduce-yourself` and mention `@@Mentor` to get you onboard :neckbeard:
Check out the [contribution guideline](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/CONTRIBUTING.md), too!
We give write permissions to every developer who asks for it. Just text us on
[Discord](https://discord.gg/AJSX9DCSUA).
## Technology Stack
- [Docker](https://www.docker.com)
- [Kubernetes](https://kubernetes.io)
- [Helm](https://helm.sh)
<!--
## Attributions
Locale Icons made by [Freepik](http://www.freepik.com/) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
Browser compatibility testing with [BrowserStack](https://www.browserstack.com/).
<img alt="BrowserStack Logo" src=".gitbook/assets/browserstack-logo.svg" width="256">
-->
## License
See the [LICENSE](/LICENSE.md) file for license rights and limitations (MIT).
We need `DOCKER_BUILDKIT=0` for this to work.

View File

@ -0,0 +1,86 @@
# Todo For Next Update
When you overtake this deploy and rebrand repo to your network you have to recognize the following changes and doings:
## Version >= 2.4.0 with 'ocelotDockerVersionTag' 2.4.0-XXX
### Main Code PR feat(webapp): map #5843
- Create your own [Mapbox](https://mapbox.com/) account at [https://mapbox.com/](https://mapbox.com/) for your organization to get your own Mapbox token.
- You have to add the `MAPBOX_TOKEN` from the `deployment/kubernetes/values.template.yaml` to your `deployment/kubernetes/values.yaml` and set it to your own Mapbox token.
## Version >= 2.2.0 with 'ocelotDockerVersionTag' 2.2.0-267
### Main Code PR feat: 🍰 Footer And Header Links Configurable To Have External Link Target #5590
- You have to add property `target` to all array elements with value `url` to your preferred value in `branding/constants/headerMenu.js` originally in main code file `webapp/constants/headerMenu.js`.
- You have to move value of all `externalLink` to new property `externalLink.url` and set new property `externalLink.target` to your preferred value in `branding/constants/links.js` originally in main code file `webapp/constants/links.js`.
### Main Code PR feat: 🍰 Make Donation Progress Bar Color Configurable #5593
- You have to set `PROGRESS_BAR_COLOR_TYPE` in `branding/constants/donation.js` originally in main code file `webapp/constants/donation.js` to your preferred value.
### Main Code PR feat: 🍰 Header Logo Routing Update #5579
- You have to move value of `LOGO_HEADER_CLICK.externalLink` to new property `LOGO_HEADER_CLICK.externalLink.url` and set new property `LOGO_HEADER_CLICK.externalLink.target` to your preferred value in `branding/constants/logos.js` originally in main code file `webapp/constants/logos.js`.
## Version >= 2.0.0 with 'ocelotDockerVersionTag' 2.0.0-250
### Main Code PR feat: 🍰 Implement LOGO_HEADER_CLICK As Configuration #5525
- You have to set `LOGO_HEADER_CLICK` in `branding/constants/logos.js` originally in main code file `webapp/constants/logos.js` to your preferred value.
### Main Code Issue 🌟 [EPIC] Release v2.0.0 Beta Test → Final #5547
- You have to set `SHOW_GROUP_BUTTON_IN_HEADER` in `branding/constants/groups.js` originally in main code file `webapp/constants/groups.js` to your preferred value.
## Version >= 1.1.0 with 'ocelotDockerVersionTag' 1.1.0-205
### Deployment/Rebranding PR chore: 🍰 Release v1.1.0 - Implement Categories Again #63
- You have to add the `CATEGORIES_ACTIVE` from the `deployment/kubernetes/values.template.yaml` to your `deployment/kubernetes/values.yaml` and set it to your preferred value.
- Make sure the correct categories are in your Neo4j database on the server.
## Version >= 1.0.9 with 'ocelotDockerVersionTag' 1.0.9-199
### Deployment/Rebranding PR chore: 🍰 Implement PRODUCTION_DB_CLEAN_ALLOW for Staging Production Environments #56
- Copy `PRODUCTION_DB_CLEAN_ALLOW` from `deployment/kubernetes/values.template.yaml` to `values.yaml` and set it to `false` for production environments and only for several stage test servers to `true`.
### Deployment/Rebranding PR chore: [WIP] 🍰 Refine docs, first step #46
Upgrade the cert-manager, but install CRDs of the version 1.0.0-alpha to actually be able to upgrade ocelot. Then uninstall the legacy CRDs and install the correct ones.
```bash
# upgrade cert-manager to 1.9.1
> helm upgrade --set installCRDs=true --version 1.9.1 --namespace cert-manager cert-manager jetstack/cert-manager
# apply legacy CRDs
> kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.0.0-alpha.1/cert-manager.crds.yaml
# upgrade ocelot
> helm upgrade ocelot ./
# delete legacy CRDs
> kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.0.0-alpha.1/cert-manager.crds.yaml
# apply CRDs for cert-manager 1.9.1
> kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml
```
Background: We had to upgrade cert-manager due to an external dependency - therefore we had to update cert-manager apiVersion `cert-manager.io/v1alpha2` to `cert-manager.io/v1`.
The error occurring when not doing this is the following:
```bash
Error: UPGRADE FAILED: unable to build kubernetes objects from current release manifest: [resource mapping not found for name: "letsencrypt-production" namespace: "" from "": no matches for kind "ClusterIssuer" in version "cert-manager.io/v1alpha2"
ensure CRDs are installed first, resource mapping not found for name: "letsencrypt-staging" namespace: "" from "": no matches for kind "ClusterIssuer" in version "cert-manager.io/v1alpha2"
ensure CRDs are installed first]
```
## Version >= 1.0.8 with 'ocelotDockerVersionTag' 1.0.8-182
### PR feat: 🍰 Configure Cookie Expire Time #43
- You have to add the `COOKIE_EXPIRE_TIME` from the `deployment/kubernetes/values.template.yaml` to your `deployment/kubernetes/values.yaml` and set it to your preferred value.
- Correct `locale` cookie exploration time in data privacy.
## Version 1.0.7 with 'ocelotDockerVersionTag' 1.0.7-171
- No information.

3
deployment/configurations/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/*
!/example
!.gitignore

View File

@ -0,0 +1,5 @@
# Configure And Branding
In this folder you will find all configuration files and logo images to customise the configuration and branding of the [ocelot.social](https://github.com/Ocelot-Social-Community/Ocelot-Social) network code to your own needs.
Please change these and they will be used automatically as part of the [deployment](/deployment/README.md) process.

View File

@ -0,0 +1,5 @@
/*
*
* Here, all SCSS variables and classes can be adapted to your custom design.
*
*/

View File

@ -0,0 +1 @@
export const PROGRESS_BAR_COLOR_TYPE = 'gradient' // 'uni' is the other option

View File

@ -0,0 +1,8 @@
// this file is duplicated in `backend/src/config/` and `webapp/constants/` and replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/constants/
export default {
SUPPORT_EMAIL: 'hello@ocelot.social',
MODERATION_EMAIL: 'hello@ocelot.social',
// ATTENTION: the following links have to be defined even for internal pages with full URLs as example like 'https://staging.ocelot.social/support', because they are used in e-mails!
ORGANIZATION_LINK: 'https://ocelot.social',
SUPPORT_LINK: 'https://ocelot.social',
}

Some files were not shown because too many files have changed in this diff Show More