mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-12 23:35:52 +00:00
Merge branch 'master' into cypress-migrate-to-v10
This commit is contained in:
commit
4afe3e05a5
71
.github/workflows/lint_pr.yml
vendored
Normal file
71
.github/workflows/lint_pr.yml
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
name: "ocelot.social lint pull request CI"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- edited
|
||||||
|
- synchronize
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
name: Validate PR title
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: amannn/action-semantic-pull-request@v5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
# Configure which types are allowed (newline delimited).
|
||||||
|
# Default: https://github.com/commitizen/conventional-commit-types
|
||||||
|
#types: |
|
||||||
|
# fix
|
||||||
|
# feat
|
||||||
|
# Configure which scopes are allowed (newline delimited).
|
||||||
|
scopes: |
|
||||||
|
backend
|
||||||
|
webapp
|
||||||
|
database
|
||||||
|
release
|
||||||
|
other
|
||||||
|
# Configure that a scope must always be provided.
|
||||||
|
requireScope: true
|
||||||
|
# Configure which scopes (newline delimited) are disallowed in PR
|
||||||
|
# titles. For instance by setting # the value below, `chore(release):
|
||||||
|
# ...` and `ci(e2e,release): ...` will be rejected.
|
||||||
|
#disallowScopes: |
|
||||||
|
# release
|
||||||
|
# Configure additional validation for the subject based on a regex.
|
||||||
|
# This example ensures the subject doesn't start with an uppercase character.
|
||||||
|
subjectPattern: ^(?![A-Z]).+$
|
||||||
|
# If `subjectPattern` is configured, you can use this property to override
|
||||||
|
# the default error message that is shown when the pattern doesn't match.
|
||||||
|
# The variables `subject` and `title` can be used within the message.
|
||||||
|
subjectPatternError: |
|
||||||
|
The subject "{subject}" found in the pull request title "{title}"
|
||||||
|
didn't match the configured pattern. Please ensure that the subject
|
||||||
|
doesn't start with an uppercase character.
|
||||||
|
# If you use GitHub Enterprise, you can set this to the URL of your server
|
||||||
|
#githubBaseUrl: https://github.myorg.com/api/v3
|
||||||
|
# If the PR contains one of these labels (newline delimited), the
|
||||||
|
# validation is skipped.
|
||||||
|
# If you want to rerun the validation when labels change, you might want
|
||||||
|
# to use the `labeled` and `unlabeled` event triggers in your workflow.
|
||||||
|
#ignoreLabels: |
|
||||||
|
# bot
|
||||||
|
# ignore-semantic-pull-request
|
||||||
|
# If you're using a format for the PR title that differs from the traditional Conventional
|
||||||
|
# Commits spec, you can use these options to customize the parsing of the type, scope and
|
||||||
|
# subject. The `headerPattern` should contain a regex where the capturing groups in parentheses
|
||||||
|
# correspond to the parts listed in `headerPatternCorrespondence`.
|
||||||
|
# See: https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser#headerpattern
|
||||||
|
headerPattern: '^(\w*)(?:\(([\w$.\-*/ ]*)\))?: (.*)$'
|
||||||
|
headerPatternCorrespondence: type, scope, subject
|
||||||
|
# For work-in-progress PRs you can typically use draft pull requests
|
||||||
|
# from GitHub. However, private repositories on the free plan don't have
|
||||||
|
# this option and therefore this action allows you to opt-in to using the
|
||||||
|
# special "[WIP]" prefix to indicate this state. This will avoid the
|
||||||
|
# validation of the PR title and the pull request checks remain pending.
|
||||||
|
# Note that a second check will be reported if this is enabled.
|
||||||
|
wip: true
|
||||||
32
.github/workflows/publish.yml
vendored
32
.github/workflows/publish.yml
vendored
@ -21,7 +21,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 ??? #####################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@ -42,7 +42,7 @@ jobs:
|
|||||||
# CHECKOUT CODE ##########################################################
|
# CHECKOUT CODE ##########################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SET ENVS ###############################################################
|
# SET ENVS ###############################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@ -62,7 +62,7 @@ jobs:
|
|||||||
- 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
|
||||||
@ -79,7 +79,7 @@ jobs:
|
|||||||
# CHECKOUT CODE ##########################################################
|
# CHECKOUT CODE ##########################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SET ENVS ###############################################################
|
# SET ENVS ###############################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@ -102,7 +102,7 @@ jobs:
|
|||||||
- 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
|
||||||
@ -119,7 +119,7 @@ jobs:
|
|||||||
# CHECKOUT CODE ##########################################################
|
# CHECKOUT CODE ##########################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SET ENVS ###############################################################
|
# SET ENVS ###############################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@ -142,7 +142,7 @@ jobs:
|
|||||||
- 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
|
||||||
@ -159,7 +159,7 @@ jobs:
|
|||||||
# CHECKOUT CODE ##########################################################
|
# CHECKOUT CODE ##########################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SET ENVS ###############################################################
|
# SET ENVS ###############################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@ -182,7 +182,7 @@ jobs:
|
|||||||
- 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
|
||||||
@ -202,33 +202,33 @@ 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-community
|
name: docker-neo4j-community
|
||||||
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-production
|
name: docker-backend-production
|
||||||
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-production
|
name: docker-webapp-production
|
||||||
path: /tmp
|
path: /tmp
|
||||||
- name: Load Docker Image
|
- 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
|
||||||
@ -262,7 +262,7 @@ jobs:
|
|||||||
# CHECKOUT CODE ##########################################################
|
# CHECKOUT CODE ##########################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SET ENVS ###############################################################
|
# SET ENVS ###############################################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@ -335,7 +335,7 @@ jobs:
|
|||||||
# CHECKOUT CODE ##########################################################
|
# 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
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|||||||
44
.github/workflows/test.yml
vendored
44
.github/workflows/test.yml
vendored
@ -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
|
||||||
@ -173,19 +173,19 @@ 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
|
||||||
@ -230,12 +230,12 @@ 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 (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
|
||||||
@ -290,26 +290,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 +332,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/
|
||||||
|
|||||||
98
CHANGELOG.md
98
CHANGELOG.md
@ -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)
|
||||||
|
|
||||||
|
|||||||
107
CONTRIBUTING.md
107
CONTRIBUTING.md
@ -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,106 @@ 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
|
||||||
|
|
||||||
|
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"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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/
|
||||||
|
```
|
||||||
|
|||||||
@ -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/
|
|
||||||
```
|
|
||||||
@ -1 +1 @@
|
|||||||
v12.19.0
|
v19.4.0
|
||||||
@ -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
|
||||||
|
|||||||
@ -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/) (>= `v10.12.0`). We are using
|
[Node](https://nodejs.org/en/) (>= `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:
|
||||||
|
|||||||
14
backend/jest.config.js
Normal file
14
backend/jest.config.js
Normal 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']
|
||||||
|
}
|
||||||
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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"])',
|
||||||
|
|||||||
@ -9,9 +9,9 @@ import {
|
|||||||
createGroupMutation,
|
createGroupMutation,
|
||||||
joinGroupMutation,
|
joinGroupMutation,
|
||||||
changeGroupMemberRoleMutation,
|
changeGroupMemberRoleMutation,
|
||||||
} from './graphql/groups'
|
} from '../graphql/groups'
|
||||||
import { createPostMutation } from './graphql/posts'
|
import { createPostMutation } from '../graphql/posts'
|
||||||
import { createCommentMutation } from './graphql/comments'
|
import { createCommentMutation } from '../graphql/comments'
|
||||||
import { categories } from '../constants/categories'
|
import { categories } from '../constants/categories'
|
||||||
|
|
||||||
if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
|
if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -50,6 +50,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -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', () => {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
|
|||||||
@ -10,10 +10,13 @@ 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 (inviteCode) {
|
if (nonce) {
|
||||||
await sendMail(signupTemplate({ email, variables: { nonce, inviteCode } }))
|
// emails that already exist do not have a nonce
|
||||||
} else {
|
if (inviteCode) {
|
||||||
await sendMail(signupTemplate({ email, variables: { nonce } }))
|
await sendMail(signupTemplate({ email, variables: { nonce, inviteCode } }))
|
||||||
|
} else {
|
||||||
|
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
|
||||||
await sendMail(emailVerificationTemplate({ email, variables: { nonce, name } }))
|
if (nonce) {
|
||||||
|
await sendMail(emailVerificationTemplate({ email, variables: { nonce, name } }))
|
||||||
|
}
|
||||||
delete response.nonce
|
delete response.nonce
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -24,6 +24,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -122,37 +122,41 @@ const isAllowedToChangeGroupMemberRole = rule({
|
|||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }) => {
|
||||||
if (!(user && user.id)) return false
|
if (!(user && user.id)) return false
|
||||||
const adminId = user.id
|
const currentUserId = user.id
|
||||||
const { groupId, userId, roleInGroup } = args
|
const { groupId, userId, roleInGroup } = args
|
||||||
if (adminId === userId) return false
|
if (currentUserId === userId) return false
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
const readTxPromise = session.readTransaction(async (transaction) => {
|
const readTxPromise = session.readTransaction(async (transaction) => {
|
||||||
const transactionResponse = await transaction.run(
|
const transactionResponse = await transaction.run(
|
||||||
`
|
`
|
||||||
MATCH (admin:User {id: $adminId})-[adminMembership:MEMBER_OF]->(group:Group {id: $groupId})
|
MATCH (currentUser:User {id: $currentUserId})-[currentUserMembership:MEMBER_OF]->(group:Group {id: $groupId})
|
||||||
OPTIONAL MATCH (group)<-[userMembership:MEMBER_OF]-(member:User {id: $userId})
|
OPTIONAL MATCH (group)<-[userMembership:MEMBER_OF]-(member:User {id: $userId})
|
||||||
RETURN group {.*}, admin {.*, myRoleInGroup: adminMembership.role}, member {.*, myRoleInGroup: userMembership.role}
|
RETURN group {.*}, currentUser {.*, myRoleInGroup: currentUserMembership.role}, member {.*, myRoleInGroup: userMembership.role}
|
||||||
`,
|
`,
|
||||||
{ groupId, adminId, userId },
|
{ groupId, currentUserId, userId },
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
admin: transactionResponse.records.map((record) => record.get('admin'))[0],
|
currentUser: transactionResponse.records.map((record) => record.get('currentUser'))[0],
|
||||||
group: transactionResponse.records.map((record) => record.get('group'))[0],
|
group: transactionResponse.records.map((record) => record.get('group'))[0],
|
||||||
member: transactionResponse.records.map((record) => record.get('member'))[0],
|
member: transactionResponse.records.map((record) => record.get('member'))[0],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const { admin, group, member } = await readTxPromise
|
const { currentUser, group, member } = await readTxPromise
|
||||||
|
const groupExists = !!group
|
||||||
|
const currentUserExists = !!currentUser
|
||||||
|
const userIsMember = !!member
|
||||||
|
const sameUserRoleInGroup = member && member.myRoleInGroup === roleInGroup
|
||||||
|
const userIsOwner = member && ['owner'].includes(member.myRoleInGroup)
|
||||||
|
const currentUserIsAdmin = currentUser && ['admin'].includes(currentUser.myRoleInGroup)
|
||||||
|
const adminCanSetRole = ['pending', 'usual', 'admin'].includes(roleInGroup)
|
||||||
|
const currentUserIsOwner = currentUser && ['owner'].includes(currentUser.myRoleInGroup)
|
||||||
|
const ownerCanSetRole = ['pending', 'usual', 'admin', 'owner'].includes(roleInGroup)
|
||||||
return (
|
return (
|
||||||
!!group &&
|
groupExists &&
|
||||||
!!admin &&
|
currentUserExists &&
|
||||||
(!member ||
|
(!userIsMember || (userIsMember && (sameUserRoleInGroup || !userIsOwner))) &&
|
||||||
(!!member &&
|
((currentUserIsAdmin && adminCanSetRole) || (currentUserIsOwner && ownerCanSetRole))
|
||||||
(member.myRoleInGroup === roleInGroup || !['owner'].includes(member.myRoleInGroup)))) &&
|
|
||||||
((['admin'].includes(admin.myRoleInGroup) &&
|
|
||||||
['pending', 'usual', 'admin'].includes(roleInGroup)) ||
|
|
||||||
(['owner'].includes(admin.myRoleInGroup) &&
|
|
||||||
['pending', 'usual', 'admin', 'owner'].includes(roleInGroup)))
|
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -2,9 +2,9 @@ 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'
|
||||||
import Factory, { cleanDatabase } from '../db/factories'
|
import Factory, { cleanDatabase } from '../db/factories'
|
||||||
import { createGroupMutation, updateGroupMutation } from '../db/graphql/groups'
|
import { createGroupMutation, updateGroupMutation } from '../graphql/groups'
|
||||||
import { createPostMutation } from '../db/graphql/posts'
|
import { createPostMutation } from '../graphql/posts'
|
||||||
import { signupVerificationMutation } from '../db/graphql/authentications'
|
import { signupVerificationMutation } from '../graphql/authentications'
|
||||||
|
|
||||||
let authenticatedUser
|
let authenticatedUser
|
||||||
let variables
|
let variables
|
||||||
@ -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}
|
||||||
|
|||||||
@ -195,6 +195,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('softDeleteMiddleware', () => {
|
describe('softDeleteMiddleware', () => {
|
||||||
|
|||||||
@ -42,6 +42,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('middleware/userInteractions', () => {
|
describe('middleware/userInteractions', () => {
|
||||||
|
|||||||
@ -75,6 +75,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export default makeAugmentedSchema({
|
|||||||
'Badge',
|
'Badge',
|
||||||
'Embed',
|
'Embed',
|
||||||
'EmailAddress',
|
'EmailAddress',
|
||||||
'Notfication',
|
'Notification',
|
||||||
'Statistics',
|
'Statistics',
|
||||||
'LoggedInUser',
|
'LoggedInUser',
|
||||||
'Location',
|
'Location',
|
||||||
|
|||||||
7
backend/src/schema/resolvers/Upload.js
Normal file
7
backend/src/schema/resolvers/Upload.js
Normal 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,
|
||||||
|
}
|
||||||
@ -25,6 +25,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -37,6 +37,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('donations', () => {
|
describe('donations', () => {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -71,6 +71,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -97,7 +97,7 @@ export default {
|
|||||||
if (isMember) {
|
if (isMember) {
|
||||||
cypher = `MATCH (user:User)-[membership:MEMBER_OF]->(group:Group)
|
cypher = `MATCH (user:User)-[membership:MEMBER_OF]->(group:Group)
|
||||||
WHERE user.id = $userId
|
WHERE user.id = $userId
|
||||||
AND membership.role IN ['usual', 'admin', 'owner']
|
AND membership.role IN ['usual', 'admin', 'owner', 'pending']
|
||||||
RETURN toString(count(group)) AS count`
|
RETURN toString(count(group)) AS count`
|
||||||
} else {
|
} else {
|
||||||
cypher = `MATCH (group:Group)
|
cypher = `MATCH (group:Group)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
changeGroupMemberRoleMutation,
|
changeGroupMemberRoleMutation,
|
||||||
groupMembersQuery,
|
groupMembersQuery,
|
||||||
groupQuery,
|
groupQuery,
|
||||||
} from '../../db/graphql/groups'
|
} from '../../graphql/groups'
|
||||||
import { getNeode, getDriver } from '../../db/neo4j'
|
import { getNeode, getDriver } from '../../db/neo4j'
|
||||||
import createServer from '../../server'
|
import createServer from '../../server'
|
||||||
import CONFIG from '../../config'
|
import CONFIG from '../../config'
|
||||||
@ -252,6 +252,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('in mode', () => {
|
describe('in mode', () => {
|
||||||
|
|||||||
@ -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 || {}
|
/*
|
||||||
if (user) throw new UserInputError('A user account with this email already exists.')
|
const { alreadyExistingEmail, user } =
|
||||||
return alreadyExistingEmail
|
if (user) throw new UserInputError('A user account with this email already exists.')
|
||||||
|
*/
|
||||||
|
return emailBelongsToUser || {}
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,6 +52,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('inviteCodes', () => {
|
describe('inviteCodes', () => {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -70,6 +70,7 @@ describe('moderate resources', () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -29,6 +29,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -38,6 +38,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@ -56,6 +56,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -6,19 +6,19 @@ import {
|
|||||||
createGroupMutation,
|
createGroupMutation,
|
||||||
changeGroupMemberRoleMutation,
|
changeGroupMemberRoleMutation,
|
||||||
leaveGroupMutation,
|
leaveGroupMutation,
|
||||||
} from '../../db/graphql/groups'
|
} from '../../graphql/groups'
|
||||||
import {
|
import {
|
||||||
createPostMutation,
|
createPostMutation,
|
||||||
postQuery,
|
postQuery,
|
||||||
filterPosts,
|
filterPosts,
|
||||||
profilePagePosts,
|
profilePagePosts,
|
||||||
searchPosts,
|
searchPosts,
|
||||||
} from '../../db/graphql/posts'
|
} from '../../graphql/posts'
|
||||||
import { createCommentMutation } from '../../db/graphql/comments'
|
import { createCommentMutation } from '../../graphql/comments'
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
import { DESCRIPTION_WITHOUT_HTML_LENGTH_MIN } from '../../constants/groups'
|
import { DESCRIPTION_WITHOUT_HTML_LENGTH_MIN } from '../../constants/groups'
|
||||||
import CONFIG from '../../config'
|
import CONFIG from '../../config'
|
||||||
import { signupVerificationMutation } from '../../db/graphql/authentications'
|
import { signupVerificationMutation } from '../../graphql/authentications'
|
||||||
|
|
||||||
CONFIG.CATEGORIES_ACTIVE = false
|
CONFIG.CATEGORIES_ACTIVE = false
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Posts in Groups', () => {
|
describe('Posts in Groups', () => {
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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' } },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -33,6 +33,7 @@ describe('rewards', () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -26,6 +26,8 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
|
neode.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
const searchQuery = gql`
|
const searchQuery = gql`
|
||||||
|
|||||||
@ -51,6 +51,7 @@ describe('shout and unshout posts', () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('SocialMedia', () => {
|
describe('SocialMedia', () => {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -60,6 +60,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('resolvers/userData', () => {
|
describe('resolvers/userData', () => {
|
||||||
|
|||||||
@ -2,14 +2,16 @@ 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 '../../helpers/jest'
|
||||||
import { loginMutation } from '../../db/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()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -90,6 +90,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@ -18,6 +18,7 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDatabase()
|
await cleanDatabase()
|
||||||
|
driver.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@ -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', () => {
|
||||||
|
|||||||
@ -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
8
backend/test/setup.js
Normal 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)
|
||||||
4169
backend/yarn.lock
4169
backend/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -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
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { Then } from "@badeball/cypress-cucumber-preprocessor";
|
import { Then } from "@badeball/cypress-cucumber-preprocessor";
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
import { When } from "@badeball/cypress-cucumber-preprocessor";
|
import { When } from "@badeball/cypress-cucumber-preprocessor";
|
||||||
|
|
||||||
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()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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')
|
||||||
|
})
|
||||||
@ -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()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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)
|
||||||
|
})
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { When } from "@badeball/cypress-cucumber-preprocessor";
|
import { When } from "@badeball/cypress-cucumber-preprocessor";
|
||||||
|
|
||||||
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()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Then } from "@badeball/cypress-cucumber-preprocessor";
|
import { Then } from "@badeball/cypress-cucumber-preprocessor";
|
||||||
|
|
||||||
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)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { When } from "@badeball/cypress-cucumber-preprocessor";
|
import { When } from "@badeball/cypress-cucumber-preprocessor";
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -20,7 +20,6 @@ services:
|
|||||||
- GRAPHQL_URI=http://localhost:4000
|
- GRAPHQL_URI=http://localhost:4000
|
||||||
- CLIENT_URI=http://localhost:3000
|
- CLIENT_URI=http://localhost:3000
|
||||||
- JWT_SECRET=b/&&7b78BF&fv/Vd
|
- JWT_SECRET=b/&&7b78BF&fv/Vd
|
||||||
- MAPBOX_TOKEN=pk.eyJ1IjoiYnVzZmFrdG9yIiwiYSI6ImNraDNiM3JxcDBhaWQydG1uczhpZWtpOW4ifQ.7TNRTO-o9aK1Y6MyW_Nd4g
|
|
||||||
- PRIVATE_KEY_PASSPHRASE=a7dsf78sadg87ad87sfagsadg78
|
- PRIVATE_KEY_PASSPHRASE=a7dsf78sadg87ad87sfagsadg78
|
||||||
- NEO4J_apoc_import_file_enabled=true
|
- NEO4J_apoc_import_file_enabled=true
|
||||||
- "SSH_USERNAME=${SSH_USERNAME}"
|
- "SSH_USERNAME=${SSH_USERNAME}"
|
||||||
|
|||||||
@ -98,22 +98,22 @@ On a server with Kubernetes cluster:
|
|||||||
$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "yarn prod:migrate init"
|
$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "yarn prod:migrate init"
|
||||||
```
|
```
|
||||||
|
|
||||||
***Cypher commands to show indexes and contraints***
|
***Cypher commands to show indexes and constraints***
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# in browser command line or cypher shell
|
# in browser command line or cypher shell
|
||||||
|
|
||||||
# show all indexes and contraints
|
# show all indexes and constraints
|
||||||
$ :schema
|
$ :schema
|
||||||
|
|
||||||
# show all indexes
|
# show all indexes
|
||||||
$ CALL db.indexes();
|
$ CALL db.indexes();
|
||||||
|
|
||||||
# show all contraints
|
# show all constraints
|
||||||
$ CALL db.constraints();
|
$ CALL db.constraints();
|
||||||
```
|
```
|
||||||
|
|
||||||
***Cypher commands to create and drop indexes and contraints***
|
***Cypher commands to create and drop indexes and constraints***
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# in browser command line or cypher shell
|
# in browser command line or cypher shell
|
||||||
@ -126,6 +126,6 @@ $ CALL db.index.fulltext.createNodeIndex("tag_fulltext_search",["Tag"],["id"]);
|
|||||||
# drop an index
|
# drop an index
|
||||||
$ DROP CONSTRAINT ON ( image:Image ) ASSERT image.url IS UNIQUE
|
$ DROP CONSTRAINT ON ( image:Image ) ASSERT image.url IS UNIQUE
|
||||||
|
|
||||||
# drop all indexes and contraints
|
# drop all indexes and constraints
|
||||||
$ CALL apoc.schema.assert({},{},true) YIELD label, key RETURN * ;
|
$ CALL apoc.schema.assert({},{},true) YIELD label, key RETURN * ;
|
||||||
```
|
```
|
||||||
|
|||||||
19
package.json
19
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ocelot-social",
|
"name": "ocelot-social",
|
||||||
"version": "2.2.0",
|
"version": "2.4.0",
|
||||||
"description": "Free and open source software program code available to run social networks.",
|
"description": "Free and open source software program code available to run social networks.",
|
||||||
"author": "ocelot.social Community",
|
"author": "ocelot.social Community",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -15,8 +15,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"db:seed": "cd backend && yarn run db:seed",
|
"db:seed": "cd backend && yarn run db:seed",
|
||||||
"db:reset": "cd backend && yarn run db:reset",
|
"db:reset": "cd backend && yarn run db:reset",
|
||||||
"cypress:run": "cypress run --browser electron --config-file ./cypress/cypress.config.js",
|
"cypress:run": "cypress run --browser electron --config-file ./cypress/cypress.json",
|
||||||
"cypress:open": "cypress open --browser electron --config-file ./cypress/cypress.config.js",
|
"cypress:open": "cypress open --browser electron --config-file ./cypress/cypress.json",
|
||||||
"cucumber:setup": "cd backend && yarn run dev",
|
"cucumber:setup": "cd backend && yarn run dev",
|
||||||
"cucumber": "wait-on tcp:4000 && cucumber-js --require-module @babel/register --exit",
|
"cucumber": "wait-on tcp:4000 && cucumber-js --require-module @babel/register --exit",
|
||||||
"release": "yarn version --no-git-tag-version --no-commit-hooks --no-commit && auto-changelog --latest-version $(node -p -e \"require('./package.json').version\") && cd backend && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp/maintenance/source && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../../../package.json').version\")"
|
"release": "yarn version --no-git-tag-version --no-commit-hooks --no-commit && auto-changelog --latest-version $(node -p -e \"require('./package.json').version\") && cd backend && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp/maintenance/source && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../../../package.json').version\")"
|
||||||
@ -25,15 +25,15 @@
|
|||||||
"@babel/core": "^7.9.0",
|
"@babel/core": "^7.9.0",
|
||||||
"@babel/preset-env": "^7.12.7",
|
"@babel/preset-env": "^7.12.7",
|
||||||
"@babel/register": "^7.12.10",
|
"@babel/register": "^7.12.10",
|
||||||
"@badeball/cypress-cucumber-preprocessor": "^13.0.3",
|
|
||||||
"@cypress/browserify-preprocessor": "^3.0.2",
|
|
||||||
"@faker-js/faker": "5.1.0",
|
"@faker-js/faker": "5.1.0",
|
||||||
"auto-changelog": "^2.3.0",
|
"auto-changelog": "^2.3.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"codecov": "^3.8.2",
|
"codecov": "^3.8.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cypress": "^10.11.0",
|
"cucumber": "^6.0.5",
|
||||||
"cypress-file-upload": "^5.0.8",
|
"cypress": "^7.0.1",
|
||||||
|
"cypress-cucumber-preprocessor": "^2.2.1",
|
||||||
|
"cypress-file-upload": "^3.5.3",
|
||||||
"date-fns": "^2.25.0",
|
"date-fns": "^2.25.0",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"expect": "^25.3.0",
|
"expect": "^25.3.0",
|
||||||
@ -48,7 +48,8 @@
|
|||||||
"slug": "^6.0.0"
|
"slug": "^6.0.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"set-value": "^2.0.1"
|
"set-value": "^2.0.1",
|
||||||
|
"nan": "2.17.0"
|
||||||
},
|
},
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
SENTRY_DSN_WEBAPP=
|
SENTRY_DSN_WEBAPP=
|
||||||
COMMIT=
|
COMMIT=
|
||||||
PUBLIC_REGISTRATION=false
|
|
||||||
INVITE_REGISTRATION=true
|
|
||||||
WEBSOCKETS_URI=ws://localhost:3000/api/graphql
|
WEBSOCKETS_URI=ws://localhost:3000/api/graphql
|
||||||
GRAPHQL_URI=http://localhost:4000/
|
GRAPHQL_URI=http://localhost:4000/
|
||||||
|
MAPBOX_TOKEN="pk.eyJ1IjoiYnVzZmFrdG9yIiwiYSI6ImNraDNiM3JxcDBhaWQydG1uczhpZWtpOW4ifQ.7TNRTO-o9aK1Y6MyW_Nd4g"
|
||||||
|
PUBLIC_REGISTRATION=false
|
||||||
|
INVITE_REGISTRATION=true
|
||||||
CATEGORIES_ACTIVE=false
|
CATEGORIES_ACTIVE=false
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
v12.19.0
|
v19.4.0
|
||||||
@ -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
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
##################################################################################
|
##################################################################################
|
||||||
# BASE ###########################################################################
|
# BASE ###########################################################################
|
||||||
##################################################################################
|
##################################################################################
|
||||||
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
|
||||||
|
|||||||
@ -4,18 +4,32 @@
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
For preparation we need Node and recommend to use [node version manager](https://github.com/nvm-sh/nvm) `nvm` to switch
|
||||||
|
between different local Node versions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# install Node
|
||||||
|
$ cd webapp
|
||||||
|
$ nvm install v16.19.0
|
||||||
|
$ nvm use v16.19.0
|
||||||
|
```
|
||||||
|
|
||||||
|
Install node dependencies with [yarn](https://yarnpkg.com/en/):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# install all dependencies
|
# install all dependencies
|
||||||
$ cd webapp/
|
$ cd webapp
|
||||||
$ yarn install
|
$ yarn install
|
||||||
# or just
|
# or just
|
||||||
$ yarn
|
$ yarn
|
||||||
|
# or just later on to use version of ".nvmrc" file
|
||||||
|
$ nvm use && yarn
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy:
|
Copy:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
# in webapp/
|
# in webapp
|
||||||
cp .env.template .env
|
cp .env.template .env
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
5
webapp/assets/_new/icons/svgs/angle-up.svg
Normal file
5
webapp/assets/_new/icons/svgs/angle-up.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<!-- Generated by IcoMoon.io -->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
|
<title>angle-up</title>
|
||||||
|
<path d="M16 6.594l0.719 0.688 12.5 12.5-1.438 1.438-11.781-11.781-11.781 11.781-1.438-1.438 12.5-12.5z"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 275 B |
1
webapp/assets/_new/icons/svgs/globe-detailed.svg
Normal file
1
webapp/assets/_new/icons/svgs/globe-detailed.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 121 KiB |
@ -3,28 +3,28 @@
|
|||||||
* @presenter Color
|
* @presenter Color
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$color-primary: rgb(23, 181, 63);
|
$color-primary: rgb(23, 181, 63);
|
||||||
$color-primary-light: rgb(96, 214, 98);
|
$color-primary-light: rgb(96, 214, 98);
|
||||||
$color-primary-dark: rgb(25, 122, 49);
|
$color-primary-dark: rgb(25, 122, 49);
|
||||||
$color-primary-active: rgb(25, 194, 67);
|
$color-primary-active: rgb(25, 194, 67);
|
||||||
$color-primary-inverse: rgb(241, 253, 244);
|
$color-primary-inverse: rgb(241, 253, 244);
|
||||||
$color-secondary: rgb(0, 142, 230);
|
$color-secondary: rgb(0, 142, 230);
|
||||||
$color-secondary-active: rgb(10, 161, 255);
|
$color-secondary-active: rgb(10, 161, 255);
|
||||||
$color-secondary-inverse: rgb(240, 249, 255);
|
$color-secondary-inverse: rgb(240, 249, 255);
|
||||||
$color-success: rgb(23, 181, 63);
|
$color-success: rgb(23, 181, 63);
|
||||||
$color-success-active: rgb(26, 203, 71);
|
$color-success-active: rgb(26, 203, 71);
|
||||||
$color-success-inverse: rgb(241, 253, 244);
|
$color-success-inverse: rgb(241, 253, 244);
|
||||||
$color-danger: rgb(219, 57, 36);
|
$color-danger: rgb(219, 57, 36);
|
||||||
$color-danger-light: rgb(242, 97, 65);
|
$color-danger-light: rgb(242, 97, 65);
|
||||||
$color-danger-dark: rgb(158, 43, 28);
|
$color-danger-dark: rgb(158, 43, 28);
|
||||||
$color-danger-active: rgb(224, 81, 62);
|
$color-danger-active: rgb(224, 81, 62);
|
||||||
$color-danger-inverse: rgb(253, 243, 242);
|
$color-danger-inverse: rgb(253, 243, 242);
|
||||||
$color-warning: rgb(230, 121, 25);
|
$color-warning: rgb(230, 121, 25);
|
||||||
$color-warning-active: rgb(233, 137, 53);
|
$color-warning-active: rgb(233, 137, 53);
|
||||||
$color-warning-inverse: rgb(253, 247, 241);
|
$color-warning-inverse: rgb(253, 247, 241);
|
||||||
$color-yellow: rgb(245, 196, 0);
|
$color-yellow: rgb(245, 196, 0);
|
||||||
$color-yellow-active: rgb(255, 206, 10);
|
$color-yellow-active: rgb(255, 206, 10);
|
||||||
$color-yellow-inverse: rgb(255, 252, 240);
|
$color-yellow-inverse: rgb(255, 252, 240);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @tokens Color Neutral
|
* @tokens Color Neutral
|
||||||
|
|||||||
@ -31,7 +31,10 @@
|
|||||||
slot-scope="item"
|
slot-scope="item"
|
||||||
:route="item.route"
|
:route="item.route"
|
||||||
:parents="item.parents"
|
:parents="item.parents"
|
||||||
@click.native="closeMenu(false)"
|
@click.native="
|
||||||
|
closeMenu(false)
|
||||||
|
$emit('toggle-Mobile-Menu-view')
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<base-icon :name="item.route.icon" />
|
<base-icon :name="item.route.icon" />
|
||||||
{{ item.route.name }}
|
{{ item.route.name }}
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
import CategoryQuery from '~/graphql/CategoryQuery'
|
import CategoryQuery from '~/graphql/CategoryQuery'
|
||||||
import { CATEGORIES_MAX } from '~/constants/categories.js'
|
import { CATEGORIES_MAX } from '~/constants/categories.js'
|
||||||
import xor from 'lodash/xor'
|
import xor from 'lodash/xor'
|
||||||
|
import SortCategories from '~/mixins/sortCategoriesMixin.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: {
|
inject: {
|
||||||
@ -30,6 +31,7 @@ export default {
|
|||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mixins: [SortCategories],
|
||||||
props: {
|
props: {
|
||||||
existingCategoryIds: { type: Array, default: () => [] },
|
existingCategoryIds: { type: Array, default: () => [] },
|
||||||
model: { type: String, required: true },
|
model: { type: String, required: true },
|
||||||
@ -72,7 +74,7 @@ export default {
|
|||||||
return CategoryQuery()
|
return CategoryQuery()
|
||||||
},
|
},
|
||||||
result({ data: { Category } }) {
|
result({ data: { Category } }) {
|
||||||
this.categories = Category
|
this.categories = this.sortCategories(Category)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-tag class="category-tag">
|
<ds-tag class="category-tag" :class="filterActive ? 'filterActive' : ''">
|
||||||
<base-icon :name="icon" />
|
<base-icon :name="icon" />
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</ds-tag>
|
</ds-tag>
|
||||||
@ -11,6 +11,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
icon: { type: String, required: true },
|
icon: { type: String, required: true },
|
||||||
name: { type: String, default: '' },
|
name: { type: String, default: '' },
|
||||||
|
filterActive: { type: Boolean, default: false, required: false },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -28,4 +29,7 @@ export default {
|
|||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.filterActive {
|
||||||
|
background-color: $color-success-active;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
:filled="!filteredCategoryIds.length"
|
:filled="!filteredCategoryIds.length"
|
||||||
:label="$t('filter-menu.all')"
|
:label="$t('filter-menu.all')"
|
||||||
icon="check"
|
icon="check"
|
||||||
@click="resetCategories"
|
@click="setResetCategories"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li class="item item-save-topics">
|
<li class="item item-save-topics">
|
||||||
@ -39,15 +39,14 @@ import CategoryQuery from '~/graphql/CategoryQuery.js'
|
|||||||
import SaveCategories from '~/graphql/SaveCategories.js'
|
import SaveCategories from '~/graphql/SaveCategories.js'
|
||||||
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
|
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
|
||||||
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
|
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
|
||||||
|
import SortCategories from '~/mixins/sortCategoriesMixin.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FilterMenuSection,
|
FilterMenuSection,
|
||||||
LabeledButton,
|
LabeledButton,
|
||||||
},
|
},
|
||||||
props: {
|
mixins: [SortCategories],
|
||||||
showMobileMenu: { type: Boolean, default: false },
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
categories: [],
|
categories: [],
|
||||||
@ -63,6 +62,10 @@ export default {
|
|||||||
resetCategories: 'posts/RESET_CATEGORIES',
|
resetCategories: 'posts/RESET_CATEGORIES',
|
||||||
toggleCategory: 'posts/TOGGLE_CATEGORY',
|
toggleCategory: 'posts/TOGGLE_CATEGORY',
|
||||||
}),
|
}),
|
||||||
|
setResetCategories() {
|
||||||
|
this.resetCategories()
|
||||||
|
this.$emit('showFilterMenu')
|
||||||
|
},
|
||||||
saveCategories() {
|
saveCategories() {
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
@ -70,6 +73,7 @@ export default {
|
|||||||
variables: { activeCategories: this.filteredCategoryIds },
|
variables: { activeCategories: this.filteredCategoryIds },
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
this.$emit('showFilterMenu')
|
||||||
this.$toast.success(this.$t('filter-menu.save.success'))
|
this.$toast.success(this.$t('filter-menu.save.success'))
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -84,7 +88,7 @@ export default {
|
|||||||
},
|
},
|
||||||
update({ Category }) {
|
update({ Category }) {
|
||||||
if (!Category) return []
|
if (!Category) return []
|
||||||
this.categories = Category
|
this.categories = this.sortCategories(Category)
|
||||||
},
|
},
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -11,15 +11,7 @@
|
|||||||
<base-icon class="dropdown-arrow" name="angle-down" />
|
<base-icon class="dropdown-arrow" name="angle-down" />
|
||||||
</base-button>
|
</base-button>
|
||||||
<template slot="popover">
|
<template slot="popover">
|
||||||
<div class="filter-menu-options">
|
<filter-menu-component />
|
||||||
<h2 class="title">{{ $t('filter-menu.filter-by') }}</h2>
|
|
||||||
<following-filter />
|
|
||||||
<categories-filter v-if="categoriesActive" :showMobileMenu="showMobileMenu" />
|
|
||||||
</div>
|
|
||||||
<div class="filter-menu-options">
|
|
||||||
<h2 class="title">{{ $t('filter-menu.order-by') }}</h2>
|
|
||||||
<order-by-filter />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</dropdown>
|
</dropdown>
|
||||||
</template>
|
</template>
|
||||||
@ -27,26 +19,16 @@
|
|||||||
<script>
|
<script>
|
||||||
import Dropdown from '~/components/Dropdown'
|
import Dropdown from '~/components/Dropdown'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import FollowingFilter from './FollowingFilter'
|
import FilterMenuComponent from './FilterMenuComponent'
|
||||||
import OrderByFilter from './OrderByFilter'
|
|
||||||
import CategoriesFilter from './CategoriesFilter'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
FollowingFilter,
|
FilterMenuComponent,
|
||||||
OrderByFilter,
|
|
||||||
CategoriesFilter,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
categoriesActive: this.$env.CATEGORIES_ACTIVE,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
placement: { type: String },
|
placement: { type: String },
|
||||||
offset: { type: [String, Number] },
|
offset: { type: [String, Number] },
|
||||||
showMobileMenu: { type: Boolean, default: false },
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
@ -55,14 +37,3 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.filter-menu-options {
|
|
||||||
max-width: $size-max-width-filter-menu;
|
|
||||||
padding: $space-small $space-x-small;
|
|
||||||
|
|
||||||
> .title {
|
|
||||||
font-size: $font-size-large;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user