diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 82b50aba3..000000000 --- a/.codecov.yml +++ /dev/null @@ -1,157 +0,0 @@ -codecov: - #token: uuid # Your private repository token - #url: "http" # for Codecov Enterprise customers - #slug: "owner/repo" # for Codecov Enterprise customers - #branch: master # override the default branch - #bot: username # set user whom will be the consumer of oauth requests - #ci: # Custom CI domains if Codecov does not identify them automatically - # - ci.domain.com - # - !provider # ignore these providers when checking if CI passed - # # ex. You may test on Travis, Circle, and AppVeyor, but only need - # # to check if Travis passes. Therefore add: !circle and !appveyor - notify: - #after_n_builds: null # number of expected builds to recieve before sending notifications - # # after: check ci status unless disabled via require_ci_to_pass - require_ci_to_pass: yes # yes: will delay sending notifications until all ci is finished - # no: will send notifications without checking ci status and wait till "after_n_builds" are uploaded - #countdown: null # number of seconds to wait before first ci build check - #delay: null # number of seconds to wait between ci build checks - -coverage: - precision: 2 # 2 = xx.xx%, 0 = xx% - round: nearest # down|up|nearest - default down - # range: 50...60 # default 70...90. red...green - - #notify: - # irc: - # default: - # server: "chat.freenode.net"|encrypted - # branches: null # all branches by default - # threshold: 1% - # message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message - # flags: null - # paths: null - # - # slack: - # default: - # url: "http"|encrypted - # threshold: 1% - # branches: null # all branches by default - # message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message - # attachments: "sunburst, diff" - # only_pulls: false - # flags: null - # paths: null - # - # email: - # default: - # to: - # - example@domain.com - # - &author - # threshold: 1% - # only_pulls: false - # layout: header, diff, trends - # flags: null - # paths: null - # - # hipchat: - # default: - # url: "http"|encrypted - # room: name|id - # threshold: 1% - # token: encrypted - # branches: null # all branches by default - # notify: false # if the hipchat message is silent or loud (default false) - # message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message - # flags: null - # paths: null - # - # gitter: - # url: "http"|encrypted - # threshold: 1% - # branches: null # all branches by default - # message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message - # - # webhooks: - # _name_: - # url: "http"|encrypted - # threshold: 1% - # branches: null # all branches by default - - status: - project: - default: false # disable the default status that measures entire project - backend: # declare a new status context "backend" - against: parent - target: auto - threshold: null - #threshold: 1% - base: auto - if_no_uploads: error - if_not_found: success - if_ci_failed: error - only_pulls: false - #branches: - # - master - #flags: - # - integration - paths: - - backend/ # only include coverage in "backend/" folder - webapp: # declare a new status context "frontend" - against: parent - target: auto - threshold: null - #threshold: 1% - base: auto - if_no_uploads: error - if_not_found: success - if_ci_failed: error - only_pulls: false - #branches: - # - master - #flags: - # - integration - paths: - - webapp/ # only include coverage in "webapp/" folder - - patch: - default: false - # against: parent - # target: 80% - # branches: null - # if_no_uploads: success - # if_not_found: success - # if_ci_failed: error - # only_pulls: false - # flags: - # - integration - # paths: - # - folder - - #changes: - # default: - # against: parent - # branches: null - # if_no_uploads: error - # if_not_found: success - # if_ci_failed: error - # only_pulls: false - # flags: - # - integration - # paths: - # - folder - - #flags: - # integration: - # branches: - # - master - # ignore: - # - app/ui - - #ignore: # files and folders for processing - # - tests/* - - #fixes: - # - "old_path::new_path" - -comment: off diff --git a/.github/file-filters.yml b/.github/file-filters.yml new file mode 100644 index 000000000..d7f9cb6c0 --- /dev/null +++ b/.github/file-filters.yml @@ -0,0 +1,9 @@ +backend: &backend + - 'backend/**/*' + - 'neo4j/**/*' + +docker: &docker + - 'docker-compose.*' + +webapp: &webapp + - 'webapp/**/*' diff --git a/.github/workflows/publish-branded.yml b/.github/workflows/publish-branded.yml deleted file mode 100644 index 869eb6302..000000000 --- a/.github/workflows/publish-branded.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: publish-branded -on: - repository_dispatch: - types: [trigger-build-success] -jobs: - build_branded: - name: Docker Build Branded - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.event.client_payload.ref }} - - name: Setup env - run: echo "OCELOT_VERSION=${{ github.event.client_payload.BUILD_VERSION }}" >> $GITHUB_ENV - - name: Build branded images - run: | - deployment/scripts/branded-images.build.sh - docker save "ocelotsocialnetwork/backend-branded" > /tmp/backend-branded.tar - docker save "ocelotsocialnetwork/webapp-branded" > /tmp/webapp-branded.tar - docker save "ocelotsocialnetwork/maintenance-branded" > /tmp/maintenance-branded.tar - - - name: Upload Artifact (Backend) - uses: actions/upload-artifact@v2 - with: - name: docker-backend-branded - path: /tmp/backend-branded.tar - - - name: Upload Artifact (Webapp) - uses: actions/upload-artifact@v2 - with: - name: docker-webapp-branded - path: /tmp/webapp-branded.tar - - - name: Upload Artifact (Maintenance) - uses: actions/upload-artifact@v2 - with: - name: docker-maintenance-branded - path: /tmp/maintenance-branded.tar - - upload_to_dockerhub: - name: Upload to Dockerhub - runs-on: ubuntu-latest - needs: [build_branded] - env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.event.client_payload.ref }} - - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v2 - with: - name: docker-backend-branded - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend-branded.tar - - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v2 - with: - name: docker-webapp-branded - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp-branded.tar - - - name: Download Docker Image (Maintenance) - uses: actions/download-artifact@v2 - with: - name: docker-maintenance-branded - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/maintenance-branded.tar - - - name: Upload to dockerhub - run: deployment/scripts/branded-images.upload.sh \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 18ff7a379..e386b7efa 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -292,18 +292,26 @@ jobs: echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV - run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - - name: Repository Dispatch - uses: peter-evans/repository-dispatch@v2 - with: - token: ${{ github.token }} - event-type: trigger-build-success - repository: ${{ github.repository }} - client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' + #- name: Repository Dispatch + # uses: peter-evans/repository-dispatch@v2 + # with: + # token: ${{ github.token }} + # event-type: trigger-ocelot-build-success + # repository: ${{ github.repository }} + # client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' - name: Repository Dispatch stage.ocelot.social uses: peter-evans/repository-dispatch@v2 with: token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository - event-type: trigger-build-success + event-type: trigger-ocelot-build-success repository: 'Ocelot-Social-Community/stage.ocelot.social' - client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' \ No newline at end of file + client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' + + - name: Repository Dispatch stage.yunite.me + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository + event-type: trigger-ocelot-build-success + repository: 'Yunite-Net/stage.yunite.me' + client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' \ No newline at end of file diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml new file mode 100644 index 000000000..84d87c770 --- /dev/null +++ b/.github/workflows/test-backend.yml @@ -0,0 +1,120 @@ +name: ocelot.social backend test CI + + +on: [push] + +jobs: + files-changed: + name: Detect File Changes - Backend + runs-on: ubuntu-latest + outputs: + backend: ${{ steps.changes.outputs.backend }} + docker: ${{ steps.changes.outputs.docker }} + steps: + - uses: actions/checkout@v3.3.0 + + - name: Check for frontend file changes + uses: dorny/paths-filter@v2.11.1 + id: changes + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + list-files: shell + + build_test_neo4j: + name: Docker Build Test - Neo4J + if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Neo4J | Build 'community' image + run: | + docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/ + docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: docker-neo4j-image + path: /tmp/neo4j.tar + + build_test_backend: + name: Docker Build Test - Backend + if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: backend | Build 'test' image + run: | + docker build --target test -t "ocelotsocialnetwork/backend:test" backend/ + docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: docker-backend-test + path: /tmp/backend.tar + + lint_backend: + name: Lint Backend + if: needs.files-changed.outputs.backend == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: backend | Lint + run: cd backend && yarn && yarn run lint + + unit_test_backend: + name: Unit tests - Backend + if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' + needs: [files-changed, build_test_neo4j, build_test_backend] + runs-on: ubuntu-latest + permissions: + checks: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Download Docker Image (Neo4J) + uses: actions/download-artifact@v3 + with: + name: docker-neo4j-image + path: /tmp + + - name: Load Docker Image + run: docker load < /tmp/neo4j.tar + + - name: Download Docker Image (Backend) + uses: actions/download-artifact@v3 + with: + name: docker-backend-test + path: /tmp + + - name: Load Docker Image + run: docker load < /tmp/backend.tar + + - name: backend | copy env files webapp + run: cp webapp/.env.template webapp/.env + - name: backend | copy env files backend + run: cp backend/.env.template backend/.env + + - name: backend | docker-compose + run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend + + - name: backend | Initialize Database + run: docker-compose exec -T backend yarn db:migrate init + + - name: backend | Migrate Database Up + run: docker-compose exec -T backend yarn db:migrate up + + - name: backend | Unit test incl. coverage check + run: docker-compose exec -T backend yarn test diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml new file mode 100644 index 000000000..d76ab129f --- /dev/null +++ b/.github/workflows/test-e2e.yml @@ -0,0 +1,41 @@ +name: ocelot.social end-to-end test CI +on: push + +jobs: + fullstack_tests: + name: Fullstack tests + runs-on: ubuntu-latest + env: + jobs: 8 + strategy: + matrix: + # run copies of the current job in parallel + job: [1, 2, 3, 4, 5, 6, 7, 8] + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: webapp | copy env file + run: cp webapp/.env.template webapp/.env + + - name: backend | copy env file + run: cp backend/.env.template backend/.env + + - name: boot up test system | docker-compose + run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend + + - name: cypress | Fullstack tests + id: e2e-tests + run: | + yarn install + yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) + + ########################################################################## + # UPLOAD SCREENSHOTS - IF TESTS FAIL ##################################### + ########################################################################## + - name: Full stack tests | if any test failed, upload screenshots + if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} + uses: actions/upload-artifact@v3 + with: + name: cypress-screenshots + path: cypress/screenshots/ diff --git a/.github/workflows/test-webapp.yml b/.github/workflows/test-webapp.yml new file mode 100644 index 000000000..9ca3023cc --- /dev/null +++ b/.github/workflows/test-webapp.yml @@ -0,0 +1,101 @@ +name: ocelot.social webapp test CI + + +on: [push] + +jobs: + files-changed: + name: Detect File Changes - Webapp + runs-on: ubuntu-latest + outputs: + docker: ${{ steps.changes.outputs.docker }} + webapp: ${{ steps.changes.outputs.webapp }} + steps: + - uses: actions/checkout@v3.3.0 + + - name: Check for frontend file changes + uses: dorny/paths-filter@v2.11.1 + id: changes + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + list-files: shell + + prepare: + name: Prepare + if: needs.files-changed.outputs.webapp + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Check translation files + run: | + scripts/translations/sort.sh + scripts/translations/missing-keys.sh + + build_test_webapp: + name: Docker Build Test - Webapp + if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp + needs: [files-changed, prepare] + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: webapp | Build 'test' image + run: | + docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/ + docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: docker-webapp-test + path: /tmp/webapp.tar + + lint_webapp: + name: Lint Webapp + if: needs.files-changed.outputs.webapp + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: webapp | Lint + run: cd webapp && yarn && yarn run lint + + unit_test_webapp: + name: Unit Tests - Webapp + if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp + needs: [files-changed, build_test_webapp] + runs-on: ubuntu-latest + permissions: + checks: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Download Docker Image (Webapp) + uses: actions/download-artifact@v3 + with: + name: docker-webapp-test + path: /tmp + + - name: Load Docker Image + run: docker load < /tmp/webapp.tar + + - name: backend | copy env files webapp + run: cp webapp/.env.template webapp/.env + + - name: backend | copy env files backend + run: cp backend/.env.template backend/.env + + - name: backend | docker-compose + run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp + + - name: webapp | Unit tests incl. coverage check + run: docker-compose exec -T webapp yarn test + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 1740c09fe..000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,344 +0,0 @@ -name: ocelot.social test CI - - -on: [push] - -jobs: - ############################################################################## - # JOB: PREPARE ##################################################### - ############################################################################## - prepare: - name: Prepare - runs-on: ubuntu-latest - # needs: [nothing] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # TODO: DO STUFF ??? ##################################################### - ########################################################################## - - name: Check translation files - run: | - scripts/translations/sort.sh - scripts/translations/missing-keys.sh - - ############################################################################## - # JOB: DOCKER BUILD TEST NEO4J ############################################### - ############################################################################## - build_test_neo4j: - name: Docker Build Test - Neo4J - runs-on: ubuntu-latest - needs: [prepare] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # NEO4J ################################################################## - ########################################################################## - - name: Neo4J | Build `community` image - run: | - docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/ - docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-neo4j-image - path: /tmp/neo4j.tar - - ############################################################################## - # JOB: DOCKER BUILD TEST BACKEND ############################################# - ############################################################################## - build_test_backend: - name: Docker Build Test - Backend - runs-on: ubuntu-latest - needs: [prepare] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # BUILD BACKEND DOCKER IMAGE (build) ##################################### - ########################################################################## - - name: backend | Build `test` image - run: | - docker build --target test -t "ocelotsocialnetwork/backend:test" backend/ - docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-backend-test - path: /tmp/backend.tar - - ############################################################################## - # JOB: DOCKER BUILD TEST WEBAPP ############################################## - ############################################################################## - build_test_webapp: - name: Docker Build Test - WebApp - runs-on: ubuntu-latest - needs: [prepare] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # BUILD WEBAPP DOCKER IMAGE (build) ###################################### - ########################################################################## - - name: webapp | Build `test` image - run: | - docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/ - docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-webapp-test - path: /tmp/webapp.tar - - ############################################################################## - # JOB: LINT BACKEND ########################################################## - ############################################################################## - lint_backend: - name: Lint backend - runs-on: ubuntu-latest - needs: [build_test_backend] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGE ################################################## - ########################################################################## - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v3 - with: - name: docker-backend-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend.tar - ########################################################################## - # LINT BACKEND ########################################################### - ########################################################################## - - name: backend | Lint - run: docker run --rm ocelotsocialnetwork/backend:test yarn run lint - - ############################################################################## - # JOB: LINT WEBAPP ########################################################### - ############################################################################## - lint_webapp: - name: Lint webapp - runs-on: ubuntu-latest - needs: [build_test_webapp] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGE ################################################## - ########################################################################## - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v3 - with: - name: docker-webapp-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp.tar - ########################################################################## - # LINT WEBAPP ############################################################ - ########################################################################## - - name: webapp | Lint - run: docker run --rm ocelotsocialnetwork/webapp:test yarn run lint - - ############################################################################## - # JOB: UNIT TEST BACKEND ##################################################### - ############################################################################## - unit_test_backend: - name: Unit tests - backend - runs-on: ubuntu-latest - needs: [build_test_neo4j,build_test_backend] - permissions: - checks: write - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGES ################################################# - ########################################################################## - - name: Download Docker Image (Neo4J) - uses: actions/download-artifact@v3 - with: - name: docker-neo4j-image - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/neo4j.tar - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v3 - with: - name: docker-backend-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend.tar - ########################################################################## - # UNIT TESTS BACKEND ##################################################### - ########################################################################## - - name: backend | copy env files webapp - run: cp webapp/.env.template webapp/.env - - name: backend | copy env files backend - run: cp backend/.env.template backend/.env - - name: backend | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend - - name: backend | Initialize Database - run: docker-compose exec -T backend yarn db:migrate init - - name: backend | Migrate Database Up - run: docker-compose exec -T backend yarn db:migrate up - - name: backend | Unit test - run: docker-compose exec -T backend yarn test - ########################################################################## - # COVERAGE CHECK BACKEND ################################################# - ########################################################################## - - name: backend | Coverage check - uses: webcraftmedia/coverage-check-action@master - with: - report_name: Coverage Backend - type: lcov - result_path: ./coverage/lcov.info - min_coverage: 57 - token: ${{ github.token }} - - ############################################################################## - # JOB: UNIT TEST WEBAPP ###################################################### - ############################################################################## - unit_test_webapp: - name: Unit tests - webapp - runs-on: ubuntu-latest - needs: [build_test_webapp] - permissions: - checks: write - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGES ################################################# - ########################################################################## - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v3 - with: - name: docker-webapp-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp.tar - ########################################################################## - # UNIT TESTS WEBAPP ###################################################### - ########################################################################## - - name: backend | copy env files webapp - run: cp webapp/.env.template webapp/.env - - name: backend | copy env files backend - run: cp backend/.env.template backend/.env - - name: backend | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp - - name: webapp | Unit tests - run: docker-compose exec -T webapp yarn test - ########################################################################## - # COVERAGE REPORT FRONTEND ################################################ - ########################################################################## - #- name: frontend | Coverage report - # uses: romeovs/lcov-reporter-action@v0.2.21 - # with: - # github-token: ${{ secrets.GITHUB_TOKEN }} - # lcov-file: ./coverage/lcov.info - ########################################################################## - # COVERAGE CHECK WEBAPP ################################################## - ########################################################################## - - name: webapp | Coverage check - uses: webcraftmedia/coverage-check-action@master - with: - report_name: Coverage Webapp - type: lcov - result_path: ./coverage/lcov.info - min_coverage: 83 - token: ${{ github.token }} - - ############################################################################## - # JOB: FULLSTACK TESTS ####################################################### - ############################################################################## - fullstack_tests: - name: Fullstack tests - runs-on: ubuntu-latest - needs: [build_test_webapp, build_test_backend, build_test_neo4j] - env: - jobs: 8 - strategy: - matrix: - # run copies of the current job in parallel - job: [1, 2, 3, 4, 5, 6, 7, 8] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGES ################################################# - ########################################################################## - - name: Download Docker Image (Neo4J) - uses: actions/download-artifact@v3 - with: - name: docker-neo4j-image - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/neo4j.tar - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v3 - with: - name: docker-backend-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend.tar - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v3 - with: - name: docker-webapp-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp.tar - ########################################################################## - # FULLSTACK TESTS CYPRESS ################################################ - ########################################################################## - - name: webapp | copy env files webapp - run: cp webapp/.env.template webapp/.env - - name: backend | copy env files backend - run: cp backend/.env.template backend/.env - - name: backend | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend - - name: cypress | Fullstack tests - id: e2e-tests - run: | - yarn install - yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) - ########################################################################## - # UPLOAD SCREENSHOTS - IF TESTS FAIL ##################################### - ########################################################################## - - name: Full stack tests | if any test failed, upload screenshots - if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} - uses: actions/upload-artifact@v3 - with: - name: cypress-screenshots - path: cypress/screenshots/ diff --git a/.gitmodules b/.gitmodules index 24249a28e..b2aae2ea3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "styleguide"] path = styleguide url = https://github.com/Human-Connection/Nitro-Styleguide.git +[submodule "deployment/configurations/stage.ocelot.social"] + path = deployment/configurations/stage.ocelot.social + url = git@github.com:Ocelot-Social-Community/stage.ocelot.social.git diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3cd77a905..000000000 --- a/.travis.yml +++ /dev/null @@ -1,84 +0,0 @@ -dist: xenial -language: node_js -node_js: lts/* -cache: - yarn: false - npm: false - -addons: - apt: - packages: - - libgconf-2-4 - snaps: - - docker - firefox: "latest-esr" - -install: - - yarn global add wait-on - # Install Codecov - - yarn install --frozen-lockfile - - cp backend/.env.template backend/.env - -before_script: - - docker-compose -f docker-compose.yml build --parallel - - docker-compose -f docker-compose.yml -f docker-compose.build-and-test.yml build # just tagging, just be quite fast - - docker-compose -f docker-compose.yml -f docker-compose.build-and-test.yml up -d - - wait-on http://localhost:7474 - - docker-compose -f docker-compose.yml -f docker-compose.build-and-test.yml exec backend yarn run db:migrate init - -script: - - export CYPRESS_RETRIES=1 - - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) - - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH" - # Miscellaneous - - ./scripts/translations/sort.sh - - ./scripts/translations/missing-keys.sh - # Backend - - docker-compose exec backend yarn run lint - - docker-compose exec backend yarn run test --ci --verbose=false --coverage - - docker-compose exec backend yarn run db:seed - - docker-compose exec backend yarn run db:reset - # Frontend - - docker-compose exec webapp yarn run lint - - docker-compose exec webapp yarn run test --ci --verbose=false --coverage - # Fullstack - - docker-compose down - - docker-compose -f docker-compose.yml up -d - - wait-on http://localhost:7474 - # disable for last deploy, because of flakiness! - # - yarn run cypress:run --record - # - yarn run cucumber - # Coverage - # disable this uneffective thing for last deploy, because of easyness! - # - yarn run codecov - -after_success: - - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh - - chmod +x send.sh - - ./send.sh success $WEBHOOK_URL - - if [ $TRAVIS_BRANCH == "master" ] && [ $TRAVIS_EVENT_TYPE == "push" ]; then - wget https://raw.githubusercontent.com/Human-Connection/Discord-Bot/develop/tester.sh && - chmod +x tester.sh && - ./tester.sh staging $WEBHOOK_URL; - fi - -after_failure: - - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh - - chmod +x send.sh - - ./send.sh failure $WEBHOOK_URL - -before_deploy: - - go get -u github.com/tcnksm/ghr - # stop deployment to kubernetes until we have set it up - # - ./scripts/setup_kubernetes.sh - -deploy: - - provider: script - script: bash scripts/docker_push.sh - on: - branch: master - # stop deployment to kubernetes until we have set it up - # - provider: script - # script: bash scripts/deploy.sh - # on: - # branch: master diff --git a/CHANGELOG.md b/CHANGELOG.md index ac1cf7e02..7030227c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,177 @@ 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). +#### [2.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.1...2.6.0) + +- fix(other): docker-compose for rebranding deployment [`#6265`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6265) +- feat(webapp): default categories of group for posts in group [`#6259`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6259) +- refactor(webapp): make action radius select in group form a reusable component [`#6244`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6244) +- fix(webapp): show avatar for group members [`#6258`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6258) +- fix(webapp): fix search for 3 chars [`#6256`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6256) +- fix(backend): group posts cannot be pinned [`#6242`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6242) +- Bump metascraper-soundcloud from 5.33.5 to 5.34.2 in /backend [`#6213`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6213) +- refactor(other): refactor test workflows [`#6151`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6151) +- fix(other): deployment fix typo, update stage.ocelot.social reference [`#6230`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6230) +- fix(other): bump metascraper-url from 5.33.5 to 5.34.2 in /backend [`#6217`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6217) +- fix(other): workflow typo [`#6235`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6235) +- feat(other): publish stage.yunite.me hook [`#6234`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6234) +- fix(other): reduce kubernetes memory limits [`#6229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6229) +- fix(other): deployment for branded image with custom names [`#6228`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6228) +- Bump node from 19.8.1-alpine3.17 to 19.9.0-alpine3.17 in /backend [`#6219`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6219) +- Bump node from 19.8.1-alpine3.17 to 19.9.0-alpine3.17 in /webapp [`#6220`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6220) +- feat(other): deployment pod resources [`#6132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6132) +- Bump @babel/core from 7.12.17 to 7.21.4 in /webapp [`#6215`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6215) +- Bump jsonwebtoken from 8.5.1 to 9.0.0 in /webapp [`#6079`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6079) +- Bump jest from 29.4.2 to 29.5.0 in /webapp [`#6094`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6094) +- Bump babel-jest from 29.4.2 to 29.5.0 in /webapp [`#6095`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6095) +- Bump neode from 0.4.8 to 0.4.9 in /backend [`#6075`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6075) +- Bump node from 19.4.0-alpine3.17 to 19.8.1-alpine3.17 in /webapp [`#6155`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6155) +- Bump node from 19.4.0-alpine3.17 to 19.8.1-alpine3.17 in /backend [`#6156`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6156) +- Bump @babel/core from 7.9.0 to 7.21.4 [`#6200`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6200) +- Bump @babel/preset-env from 7.12.7 to 7.21.4 [`#6204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6204) +- Bump expect from 25.3.0 to 29.5.0 [`#6098`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6098) +- separate test workflows [`3533a36`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3533a36cdc811c0e1dae218fbc2184f7c4bc3951) +- get it working [`8df7d5d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8df7d5d265b0c5ba16f167a213631d765d2f985e) +- feat(webapp): group categories on posts [`3244f3f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3244f3f86d1e8c09e0fd49f43c49f0a3aa8b85ab) + +#### [2.5.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.0...2.5.1) + +> 23 March 2023 + +- chore(other): release v2.5.1 – fix filter menu width [`#6180`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6180) +- feat(webapp): add tooltips to all menu icons [`#6185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6185) +- fix(webapp): popup filter max-width [`#6177`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6177) +- Add tooltip to header notifications menu [`28505a5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/28505a5b181008ebcde6fa58b7a4a8459a492018) +- Add tooltip to header avatar menu [`4c0469f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4c0469f61a3c2fae23e50c6a5a2a91b63fac149a) +- Release v2.5.1 - fix filter menu width [`08def14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/08def14cafef7816d8e43f1896430400bda9635d) + +#### [2.5.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.4.0...2.5.0) + +> 21 March 2023 + +- chore(other): release v2.5.0 [`#6172`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6172) +- fix(other): publish transmit github run number properly [`#6171`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6171) +- feat(other): deployment include GitHub run number on branded images [`#6170`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6170) +- fix(backend): new migration to create search indexes [`#6167`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6167) +- fix(other): prevent exposing secrets in the github actions by not setting debug mode on cluster deploy [`#6168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6168) +- feat(other): echo current configuration when running scripts [`#6169`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6169) +- refactor(other): build & deployment of branded images on stage.ocelot.social [`#6163`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6163) +- fix(webapp): close popover notification menu [`#6166`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6166) +- fix(webapp): small buttons in notifications menu [`#6162`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6162) +- fix(webapp): revert pr `on newsfeed add bigger y-gap between posts #6121` [`#6164`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6164) +- fix(webapp): join leave button for pending members [`#6152`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6152) +- feat(backend): notifications for groups [`#6150`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6150) +- feat(webapp): add hint text to create and edit a post of a group aside of the save and abort buttons [`#6114`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6114) +- fix(other): use access token to trigger build on external repo [`#6145`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6145) +- feat(webapp): set different icon and text on join leave button, when member is pending [`#6124`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6124) +- refactor(other): deployment upgrade to specific version, trigger build on stage [`#6143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6143) +- feat(webapp): show 2 GroupItem per row in GroupList [`#6135`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6135) +- fix(backend): do not delete migrations on db reset [`#6136`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6136) +- feat(other): deployment reseed [`#6129`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6129) +- feat(other): deployment secrets [`#6120`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6120) +- feat(webapp): refactor notification page [`#6116`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6116) +- fix(webapp): fix ribbons position [`#6130`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6130) +- fix(webapp): fix donation bar blink [`#6107`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6107) +- feat(webapp): change order of groups to new first [`#6122`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6122) +- fix(webapp): error in user profil on the 'show x more' button [`#6093`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6093) +- feat(webapp): filter button style change [`#6109`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6109) +- refactor(other): deactivate video recording & only upload screenshots, if tests fail for e2e tests [`#6125`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6125) +- fix(webapp): change icon color of active topics (categories) of post teaser [`#6112`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6112) +- docs(other): correct **/README.md [`#6059`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6059) +- fix(webapp): fix `viewport``width=device-width` by removing it [`#6110`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6110) +- feat(webapp): on newsfeed add bigger y-gap between posts [`#6121`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6121) +- Bump peter-evans/repository-dispatch from 1 to 2 [`#6117`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6117) +- fix(webapp): fix gap news feed [`#6065`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6065) +- feat(webapp): change shout icon `bullhorn` to `heart-o` [`#6115`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6115) +- refactor(webapp): change invite code button and menu to copy invite link [`#6108`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6108) +- feat(webapp): change group filter button text [`#6105`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6105) +- feat(webapp): 🍰 allows mark all notifications as read [`#3922`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3922) +- fix(other): deploy branded - upload to dockerhub [`#6099`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6099) +- feat(webapp): remove user from group [`#6072`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6072) +- chore(other): remove apple m1 docker overrides [`#6056`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6056) +- refactor(other): ocelot publish workflows [`#6083`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6083) +- fix(other): lint pr only on pullrequest [`#6088`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6088) +- fix(other): dependabot do not rebase [`#6096`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6096) +- feat(backend): filter posts in my groups [`#6091`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6091) +- refactor(backend): withdraw mock of gql and replace with graphql-tag function [`#6022`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6022) +- docs(other): update readme.md [`#6090`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6090) +- feat(webapp): adjust and create branding possibilities [`#6063`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6063) +- fix(other): exclude dependabot from pr title linting [`#6085`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6085) +- feat(webapp): change ``Benutzer`` to ``Nutzer`` [`#6027`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6027) +- docs(webapp): change the used nvm version [`#6023`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6023) +- feat(other): backup script [`#6051`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6051) +- fix(backend): user or group has null as description [`#5996`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5996) +- feat(other): script to set a cluster in maintenance mode [`#6042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6042) +- feat(other): fix dependabot [`#6035`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6035) +- fix(other): fix maintenance page & maintenance build [`#6032`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6032) +- refactor(webapp): upgrade jest and vue test util [`#5968`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5968) +- refactor(other): deployment [`#5975`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5975) +- fix(webapp): remove additional markers from map [`#6021`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6021) +- feat(webapp): add align center to the user profile slug [`#6012`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6012) +- chore(other): update github actions for node 16 [`#5971`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5971) +- refactor(backend): update jest [`#5964`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5964) +- Revert "V2.3.0" [`#95`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/95) +- V2.3.0 [`#94`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/94) +- v2.3.0-281 [`#93`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/93) +- rebranding for yunite [`#26`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/26) +- feat(webapp): copy fonts from assets [`#25`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/25) +- feat(webapp): copy fonts from assets [`#92`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/92) +- chore: 🍰 Release v2.2.0-267 – Fixes And Groups Page Etc. [`#19`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/19) +- fix: 🍰 Change Hasttag Menu Search Color To `#17b53f` [`#21`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/21) +- chore: 🍰 Release v2.2.0-267 [`#90`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/90) +- Docu Updates [`#86`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/86) +- chore: 🍰 Release v2.1.0-253 – Merge Groups Into master – Epic Groups [`#12`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/12) +- chore: 🍰 Release v2.1.0-253 [`#87`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/87) +- chore: [WIP] 🍰 Release v2.0.0-250 – Groups – Configurable Header Menu Is Translatable Etc. [`#16`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/16) +- chore: 🍰 Release v2.0.0 – Groups Etc. – Extend Rebranding And Deployment [`#83`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/83) +- fix: 🍰 Fix Implementation Of Overwriting Locales [`#80`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/80) +- feat: 🍰 Merge Locales [`#77`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/77) +- chore: 🍰 Groups Release v1.1.1-231 - Show New Features [`#14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/14) +- chore: 🍰 Release v1.1.1 – First Design Rebranding [`#10`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/10) +- chore: [WIP] 🍰 Refine Rebanding And Deployment [`#8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8) +- chore: 🍰 Fix Folder Name From `branding/assets/styles/import` To `branding/assets/styles/imports` [`#71`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/71) +- chore: 🍰 Release v1.1.1-228 – Refactor Rebranding [`#68`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/68) +- chore: 🍰 Release v1.1.0-205 [`#6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6) +- chore: 🍰 Release v1.1.0-225 [`#66`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/66) +- chore: [WIP] 🍰 Refine Deployment Setup And Documentation [`#46`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/46) +- chore: [WIP] 🍰 Release v1.1.0 - Implement Categories Again [`#63`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/63) +- Update issue templates [`#3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3) +- chore: 🍰 Release v1.0.9-199 [`#59`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/59) +- chore: 🍰 Implement `PRODUCTION_DB_CLEAN_ALLOW` for Staging Production Environments [`#56`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/56) +- chore: 🍰 Add Docker Compose Override For Apple M1 And Docu [`#57`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/57) +- Chore: 🍰 Fix `apiVersion: cert-manager.io/v1alpha2` To `*/v1` [`#53`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/53) +- chore: 🍰 Adjust `maintenance` Container Name In Deployment With Helm [`#50`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/50) +- chore: 🍰 Release New Build Version `v1.0.8-184` [`#51`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/51) +- chore: 🍰 Rename Neo4j Docker Image In General To `neo4j-community:*` [`#49`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/49) +- feat: 🍰 Release v1.0.8 – Configure Cookie Expire Time – second run [`#44`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/44) +- feat: 🍰 Configure Cookie Expire Time [`#43`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/43) +- docs: 🍰 Add Docs For Backups, Rollbacks, And Release v1.0.7-171 [`#40`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/40) +- chore: 🍰 Realease v1.0.6-170 [`#37`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/37) +- chore: 🍰 Refactor FAQ Link To Use Internal Page Which Was Implemented Before [`#36`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/36) +- chore: 🍰 Add Branding Templates For Terms And Conditions Etc. [`#32`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/32) +- feat: 🍰 Add Rebranded E-Mails For Sending Notifications [`#29`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/29) +- bug: 🍰 Fix Minor Errors And Clarify Docs [`#28`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/28) +- chore: 🍰 Implement New Internal Pages – Main Release v1.0.5 [`#25`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/25) +- feat: [WIP] 🍰 Add Landing Page Etc. [`#22`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/22) +- docs: 🍰 [WIP] Add Configure And Rebranding Readme.md [`#20`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/20) +- chore: [WIP] 🍰 New Deployment With 'base' And 'code' Docker Images [`#15`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/15) +- feat: [WIP] 🍰 Flexible Footer Links [`#17`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/17) +- 💥 Release v1.0.3 [`#12`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/12) +- 🛠 [Refactor] Add README And LICENSE [`#11`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/11) +- chore: 🍰 Implement Use Of package.json 'Version' Etc. For Build And Refine Helm Chart [`#8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8) +- chore: 🍰 Replace Ocelot Logos 619x593 With 600x570 [`#6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6) +- brand_as_default [`#4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4) +- limit_replicasets [`#3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3) +- Deployment [`#2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2) +- moved example into stage.ocelot.social [`61b5112`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/61b5112b8b547a7491d644c7c4dbfead39b61d79) +- feat(backand): upgrade jest to 29.4 [`4390d72`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4390d72477fb941f69bc9bdc24ac7713ef06e827) +- pages tests nearly working [`4850e45`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4850e456fe5b7c158f23acc7f153576472604300) + #### [2.4.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.3.0...2.4.0) +> 10 February 2023 + +- chore(release): v2.4.0 [`#5961`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5961) - 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) diff --git a/backend/.dockerignore b/backend/.dockerignore index 25a941824..d694f0d21 100644 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -13,7 +13,7 @@ docker-compose*.yml node_modules/ scripts/ -dist/ +build/ maintenance-worker/ neo4j/ diff --git a/backend/.env.template b/backend/.env.template index dd46846a9..c1742ef93 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -1,3 +1,5 @@ +DEBUG=true + NEO4J_URI=bolt://localhost:7687 NEO4J_USERNAME=neo4j NEO4J_PASSWORD=letmein diff --git a/backend/.gitignore b/backend/.gitignore index 81a29c8e6..833f7e34e 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -3,7 +3,7 @@ node_modules/ .vscode .idea yarn-error.log -dist/* +build/* coverage.lcov .nyc_output/ public/uploads/* diff --git a/backend/.nvmrc b/backend/.nvmrc index cb77acbfe..58b8c2a00 100644 --- a/backend/.nvmrc +++ b/backend/.nvmrc @@ -1 +1 @@ -v19.4.0 \ No newline at end of file +v20.2.0 \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile index c04cd9bc9..fc15aca63 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # BASE (Is pushed to DockerHub for rebranding) ################################### ################################################################################## -FROM node:19.4.0-alpine3.17 as base +FROM node:20.2.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame @@ -90,7 +90,7 @@ CMD /bin/sh -c "yarn run dev" FROM base as production # Copy "binary"-files from build image -COPY --from=build ${DOCKER_WORKDIR}/dist ./dist +COPY --from=build ${DOCKER_WORKDIR}/build ./build COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules # Copy static files # TODO - externalize the uploads so we can copy the whole folder diff --git a/backend/jest.config.js b/backend/jest.config.js index aabb59083..38c59916d 100644 --- a/backend/jest.config.js +++ b/backend/jest.config.js @@ -5,10 +5,14 @@ module.exports = { '**/*.js', '!**/node_modules/**', '!**/test/**', - '!**/dist/**', + '!**/build/**', '!**/src/**/?(*.)+(spec|test).js?(x)' ], - coverageReporters: ['lcov', 'text'], + coverageThreshold: { + global: { + lines: 57, + }, + }, testMatch: ['**/src/**/?(*.)+(spec|test).js?(x)'], setupFilesAfterEnv: ['/test/setup.js'] } diff --git a/backend/package.json b/backend/package.json index 3f7098206..9e0e3b72e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social-backend", - "version": "2.4.0", + "version": "2.6.0", "description": "GraphQL Backend for ocelot.social", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "author": "ocelot.social Community", @@ -9,10 +9,10 @@ "main": "src/index.js", "scripts": { "__migrate": "migrate --compiler 'js:@babel/register' --migrations-dir ./src/db/migrations", - "prod:migrate": "migrate --migrations-dir ./dist/db/migrations --store ./dist/db/migrate/store.js", - "start": "node dist/", - "build": "babel src/ -d dist/ --copy-files", - "dev": "nodemon --exec babel-node src/ -e js,gql", + "prod:migrate": "migrate --migrations-dir ./build/db/migrations --store ./build/db/migrate/store.js", + "start": "node build/", + "build": "tsc && mkdir -p build/middleware/helpers/email/templates/ && cp -r src/middleware/helpers/email/templates/*.html build/middleware/helpers/email/templates/ && mkdir -p build/middleware/helpers/email/templates/en/ && cp -r src/middleware/helpers/email/templates/en/*.html build/middleware/helpers/email/templates/en/ && mkdir -p build/middleware/helpers/email/templates/de/ && cp -r src/middleware/helpers/email/templates/de/*.html build/middleware/helpers/email/templates/de/ && mkdir -p build/schema/types/ && cp -r src/schema/types/*.gql build/schema/types/ && mkdir -p build/schema/types/enum/ && cp -r src/schema/types/enum/*.gql build/schema/types/enum/ && mkdir -p build/schema/types/scalar/ && cp -r src/schema/types/scalar/*.gql build/schema/types/scalar/ && mkdir -p build/schema/types/type/ && cp -r src/schema/types/type/*.gql build/schema/types/type/", + "dev": "nodemon --exec ts-node src/ -e js,ts,gql", "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", "lint": "eslint src --config .eslintrc.js", "test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --runInBand --coverage --forceExit --detectOpenHandles", @@ -29,7 +29,6 @@ "@babel/plugin-proposal-throw-expressions": "^7.8.3", "@babel/preset-env": "~7.9.5", "@babel/register": "^7.9.0", - "@hapi/joi": "^17.1.1", "@sentry/node": "^5.15.4", "apollo-cache-inmemory": "~1.6.5", "apollo-client": "~2.6.8", @@ -46,19 +45,16 @@ "cheerio": "~1.0.0-rc.3", "cors": "~2.8.5", "cross-env": "~7.0.3", - "date-fns": "2.22.1", "debug": "~4.1.1", "dotenv": "~8.2.0", "express": "^4.17.1", "graphql": "^14.6.0", - "graphql-custom-directives": "~0.2.14", - "graphql-iso-date": "~3.6.1", "graphql-middleware": "~4.0.2", "graphql-middleware-sentry": "^3.2.1", "graphql-redis-subscriptions": "^2.2.1", "graphql-shield": "~7.2.2", "graphql-tag": "~2.10.3", - "helmet": "~3.22.0", + "helmet": "~7.0.0", "ioredis": "^4.16.1", "jsonwebtoken": "~8.5.1", "languagedetect": "^2.0.0", @@ -66,9 +62,8 @@ "lodash": "~4.17.14", "merge-graphql-schemas": "^1.7.8", "metascraper": "^5.33.5", - "metascraper-audio": "^5.33.5", + "metascraper-audio": "^5.34.4", "metascraper-author": "^5.33.5", - "metascraper-clearbit-logo": "^5.3.0", "metascraper-date": "^5.33.5", "metascraper-description": "^5.33.5", "metascraper-image": "^5.33.5", @@ -76,9 +71,9 @@ "metascraper-lang-detector": "^4.10.2", "metascraper-logo": "^5.33.5", "metascraper-publisher": "^5.33.5", - "metascraper-soundcloud": "^5.33.5", + "metascraper-soundcloud": "^5.34.4", "metascraper-title": "^5.33.5", - "metascraper-url": "^5.33.5", + "metascraper-url": "^5.34.2", "metascraper-video": "^5.33.5", "metascraper-youtube": "^5.33.5", "migrate": "^1.7.0", @@ -87,23 +82,21 @@ "mustache": "^4.2.0", "neo4j-driver": "^4.0.2", "neo4j-graphql-js": "^2.11.5", - "neode": "^0.4.8", + "neode": "^0.4.9", "node-fetch": "~2.6.1", "nodemailer": "^6.4.4", "nodemailer-html-to-text": "^3.2.0", - "npm-run-all": "~4.1.5", "request": "~2.88.2", "sanitize-html": "~1.22.0", "slug": "~6.0.0", "subscriptions-transport-ws": "^0.9.19", "trunc-html": "~1.1.2", "uuid": "~8.3.2", - "validator": "^13.0.0", - "wait-on": "~4.0.1", + "validator": "^13.9.0", "xregexp": "^4.3.0" }, "devDependencies": { - "@faker-js/faker": "5.1.0", + "@faker-js/faker": "7.6.0", "apollo-server-testing": "~2.11.0", "chai": "~4.2.0", "cucumber": "~6.0.5", @@ -120,7 +113,8 @@ "nodemon": "~2.0.2", "prettier": "~2.3.2", "rosie": "^2.0.1", - "supertest": "~4.0.2" + "ts-node": "^10.9.1", + "typescript": "^5.0.4" }, "resolutions": { "**/**/fs-capacitor": "^6.2.0", diff --git a/backend/src/db/factories.js b/backend/src/db/factories.js index 44af5bbea..3f38b5b9c 100644 --- a/backend/src/db/factories.js +++ b/backend/src/db/factories.js @@ -2,7 +2,7 @@ import { v4 as uuid } from 'uuid' import slugify from 'slug' import { hashSync } from 'bcryptjs' import { Factory } from 'rosie' -import faker from '@faker-js/faker' +import { faker } from '@faker-js/faker' import { getDriver, getNeode } from './neo4j' import CONFIG from '../config/index.js' import generateInviteCode from '../schema/resolvers/helpers/generateInviteCode.js' @@ -63,7 +63,7 @@ Factory.define('basicUser') .option('password', '1234') .attrs({ id: uuid, - name: faker.name.findName, + name: faker.name.fullName, password: '1234', role: 'user', termsAndConditionsAgreedVersion: '0.0.1', diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.js index ac762647b..0c0b63943 100644 --- a/backend/src/db/migrate/store.js +++ b/backend/src/db/migrate/store.js @@ -86,13 +86,6 @@ class Store { if (CONFIG.CATEGORIES_ACTIVE) await createCategories(session) const writeTxResultPromise = session.writeTransaction(async (txc) => { await txc.run('CALL apoc.schema.assert({},{},true)') // drop all indices and constraints - return Promise.all( - [ - 'CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"])', - 'CALL db.index.fulltext.createNodeIndex("post_fulltext_search",["Post"],["title", "content"])', - 'CALL db.index.fulltext.createNodeIndex("tag_fulltext_search",["Tag"],["id"])', - ].map((statement) => txc.run(statement)), - ) }) try { await writeTxResultPromise diff --git a/backend/src/db/migrations/20230320130345-fulltext-search-indexes.js b/backend/src/db/migrations/20230320130345-fulltext-search-indexes.js new file mode 100644 index 000000000..11029bea6 --- /dev/null +++ b/backend/src/db/migrations/20230320130345-fulltext-search-indexes.js @@ -0,0 +1,68 @@ +import { getDriver } from '../../db/neo4j' + +export const description = '' + +export async function up(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + + try { + // Drop indexes if they exist because due to legacy code they might be set already + const indexesResponse = await transaction.run(`CALL db.indexes()`) + const indexes = indexesResponse.records.map((record) => record.get('indexName')) + if (indexes.indexOf('user_fulltext_search') > -1) { + await transaction.run(`CALL db.index.fulltext.drop("user_fulltext_search")`) + } + if (indexes.indexOf('post_fulltext_search') > -1) { + await transaction.run(`CALL db.index.fulltext.drop("post_fulltext_search")`) + } + if (indexes.indexOf('tag_fulltext_search') > -1) { + await transaction.run(`CALL db.index.fulltext.drop("tag_fulltext_search")`) + } + // Create indexes + await transaction.run( + `CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"])`, + ) + await transaction.run( + `CALL db.index.fulltext.createNodeIndex("post_fulltext_search",["Post"],["title", "content"])`, + ) + await transaction.run( + `CALL db.index.fulltext.createNodeIndex("tag_fulltext_search",["Tag"],["id"])`, + ) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} + +export async function down(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + + try { + await transaction.run(`CALL db.index.fulltext.drop("user_fulltext_search")`) + await transaction.run(`CALL db.index.fulltext.drop("post_fulltext_search")`) + await transaction.run(`CALL db.index.fulltext.drop("tag_fulltext_search")`) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} diff --git a/backend/src/db/migrations/20230329150329-article-label-for-posts.js b/backend/src/db/migrations/20230329150329-article-label-for-posts.js new file mode 100644 index 000000000..3cf435203 --- /dev/null +++ b/backend/src/db/migrations/20230329150329-article-label-for-posts.js @@ -0,0 +1,53 @@ +import { getDriver } from '../../db/neo4j' + +export const description = 'Add to all existing posts the Article label' + +export async function up(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + + try { + await transaction.run(` + MATCH (post:Post) + SET post:Article + RETURN post + `) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} + +export async function down(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + + try { + await transaction.run(` + MATCH (post:Post) + REMOVE post:Article + RETURN post + `) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 8339e48a8..a8f8b9c68 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -2,7 +2,7 @@ import sample from 'lodash/sample' import { createTestClient } from 'apollo-server-testing' import CONFIG from '../config' import createServer from '../server' -import faker from '@faker-js/faker' +import { faker } from '@faker-js/faker' import Factory from '../db/factories' import { getNeode, getDriver } from '../db/neo4j' import { @@ -173,6 +173,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, { email: 'moderator@example.org', + avatar: null, }, ), Factory.build( @@ -209,6 +210,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }, { email: 'dewey@example.org', + avatar: null, }, ), Factory.build( diff --git a/backend/src/graphql/GraphQL-Playground.md b/backend/src/graphql/GraphQL-Playground.md index af248f112..33e371eb5 100644 --- a/backend/src/graphql/GraphQL-Playground.md +++ b/backend/src/graphql/GraphQL-Playground.md @@ -1,5 +1,7 @@ # GraphQL Playground +***Attention:** For using the GraphQL Playground set `DEBUG=true` in your backend `.env`, see `.env.template`!* + To use GraphQL Playground, we need to know some basics: ## How To Login? diff --git a/backend/src/graphql/posts.js b/backend/src/graphql/posts.js index 2669d6f24..d1dc3ee45 100644 --- a/backend/src/graphql/posts.js +++ b/backend/src/graphql/posts.js @@ -11,6 +11,8 @@ export const createPostMutation = () => { $content: String! $categoryIds: [ID] $groupId: ID + $postType: PostType + $eventInput: _EventInput ) { CreatePost( id: $id @@ -19,11 +21,31 @@ export const createPostMutation = () => { content: $content categoryIds: $categoryIds groupId: $groupId + postType: $postType + eventInput: $eventInput ) { id slug title content + disabled + deleted + postType + author { + name + } + categories { + id + } + eventStart + eventEnd + eventLocationName + eventVenue + eventIsOnline + eventLocation { + lng + lat + } } } ` @@ -50,6 +72,7 @@ export const filterPosts = () => { id title content + eventStart } } ` diff --git a/backend/src/index.js b/backend/src/index.ts similarity index 100% rename from backend/src/index.js rename to backend/src/index.ts diff --git a/backend/src/middleware/notifications/notificationsMiddleware.js b/backend/src/middleware/notifications/notificationsMiddleware.js index a871605f7..1c97e9591 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.js @@ -51,6 +51,50 @@ const publishNotifications = async (context, promises) => { }) } +const handleJoinGroup = async (resolve, root, args, context, resolveInfo) => { + const { groupId, userId } = args + const user = await resolve(root, args, context, resolveInfo) + if (user) { + await publishNotifications(context, [ + notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context), + ]) + } + return user +} + +const handleLeaveGroup = async (resolve, root, args, context, resolveInfo) => { + const { groupId, userId } = args + const user = await resolve(root, args, context, resolveInfo) + if (user) { + await publishNotifications(context, [ + notifyOwnersOfGroup(groupId, userId, 'user_left_group', context), + ]) + } + return user +} + +const handleChangeGroupMemberRole = async (resolve, root, args, context, resolveInfo) => { + const { groupId, userId } = args + const user = await resolve(root, args, context, resolveInfo) + if (user) { + await publishNotifications(context, [ + notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context), + ]) + } + return user +} + +const handleRemoveUserFromGroup = async (resolve, root, args, context, resolveInfo) => { + const { groupId, userId } = args + const user = await resolve(root, args, context, resolveInfo) + if (user) { + await publishNotifications(context, [ + notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context), + ]) + } + return user +} + const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => { const idsOfUsers = extractMentionedUsers(args.content) const post = await resolve(root, args, context, resolveInfo) @@ -94,6 +138,72 @@ const postAuthorOfComment = async (commentId, { context }) => { } } +const notifyOwnersOfGroup = async (groupId, userId, reason, context) => { + const cypher = ` + MATCH (group:Group { id: $groupId })<-[membership:MEMBER_OF]-(owner:User) + WHERE membership.role = 'owner' + WITH owner, group + MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(owner) + WITH group, owner, notification + SET notification.read = FALSE + SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) + SET notification.updatedAt = toString(datetime()) + SET notification.relatedUserId = $userId + RETURN notification {.*, from: group, to: properties(owner)} + ` + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const notificationTransactionResponse = await transaction.run(cypher, { + groupId, + reason, + userId, + }) + return notificationTransactionResponse.records.map((record) => record.get('notification')) + }) + try { + const notifications = await writeTxResultPromise + return notifications + } catch (error) { + throw new Error(error) + } finally { + session.close() + } +} + +const notifyMemberOfGroup = async (groupId, userId, reason, context) => { + const { user: owner } = context + const cypher = ` + MATCH (user:User { id: $userId }) + MATCH (group:Group { id: $groupId }) + WITH user, group + MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(user) + WITH group, user, notification + SET notification.read = FALSE + SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) + SET notification.updatedAt = toString(datetime()) + SET notification.relatedUserId = $ownerId + RETURN notification {.*, from: group, to: properties(user)} + ` + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const notificationTransactionResponse = await transaction.run(cypher, { + groupId, + reason, + userId, + ownerId: owner.id, + }) + return notificationTransactionResponse.records.map((record) => record.get('notification')) + }) + try { + const notifications = await writeTxResultPromise + return notifications + } catch (error) { + throw new Error(error) + } finally { + session.close() + } +} + const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => { if (!(idsOfUsers && idsOfUsers.length)) return [] await validateNotifyUsers(label, reason) @@ -188,5 +298,9 @@ export default { UpdatePost: handleContentDataOfPost, CreateComment: handleContentDataOfComment, UpdateComment: handleContentDataOfComment, + JoinGroup: handleJoinGroup, + LeaveGroup: handleLeaveGroup, + ChangeGroupMemberRole: handleChangeGroupMemberRole, + RemoveUserFromGroup: handleRemoveUserFromGroup, }, } diff --git a/backend/src/middleware/notifications/notificationsMiddleware.spec.js b/backend/src/middleware/notifications/notificationsMiddleware.spec.js index a8a5d396b..a9046b09f 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.spec.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.spec.js @@ -3,6 +3,13 @@ import { cleanDatabase } from '../../db/factories' import { createTestClient } from 'apollo-server-testing' import { getNeode, getDriver } from '../../db/neo4j' import createServer, { pubsub } from '../../server' +import { + createGroupMutation, + joinGroupMutation, + leaveGroupMutation, + changeGroupMemberRoleMutation, + removeUserFromGroupMutation, +} from '../../graphql/groups' let server, query, mutate, notifiedUser, authenticatedUser let publishSpy @@ -92,6 +99,9 @@ describe('notifications', () => { read reason createdAt + relatedUser { + id + } from { __typename ... on Post { @@ -102,6 +112,9 @@ describe('notifications', () => { id content } + ... on Group { + id + } } } } @@ -185,6 +198,7 @@ describe('notifications', () => { id: 'c47', content: commentContent, }, + relatedUser: null, }, ], }, @@ -357,6 +371,7 @@ describe('notifications', () => { id: 'p47', content: expectedUpdatedContent, }, + relatedUser: null, }, ], }, @@ -513,6 +528,7 @@ describe('notifications', () => { id: 'c47', content: commentContent, }, + relatedUser: null, }, ], }, @@ -547,6 +563,7 @@ describe('notifications', () => { id: 'c47', content: commentContent, }, + relatedUser: null, }, ], }, @@ -616,4 +633,232 @@ describe('notifications', () => { }) }) }) + + describe('group notifications', () => { + let groupOwner + + beforeEach(async () => { + groupOwner = await neode.create( + 'User', + { + id: 'group-owner', + name: 'Group Owner', + slug: 'group-owner', + }, + { + email: 'owner@example.org', + password: '1234', + }, + ) + authenticatedUser = await groupOwner.toJson() + await mutate({ + mutation: createGroupMutation(), + variables: { + id: 'closed-group', + name: 'The Closed Group', + about: 'Will test the closed group!', + description: 'Some description' + Array(50).join('_'), + groupType: 'public', + actionRadius: 'regional', + categoryIds, + }, + }) + }) + + describe('user joins group', () => { + beforeEach(async () => { + authenticatedUser = await notifiedUser.toJson() + await mutate({ + mutation: joinGroupMutation(), + variables: { + groupId: 'closed-group', + userId: authenticatedUser.id, + }, + }) + authenticatedUser = await groupOwner.toJson() + }) + + it('has the notification in database', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + read: false, + reason: 'user_joined_group', + createdAt: expect.any(String), + from: { + __typename: 'Group', + id: 'closed-group', + }, + relatedUser: { + id: 'you', + }, + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('user leaves group', () => { + beforeEach(async () => { + authenticatedUser = await notifiedUser.toJson() + await mutate({ + mutation: joinGroupMutation(), + variables: { + groupId: 'closed-group', + userId: authenticatedUser.id, + }, + }) + await mutate({ + mutation: leaveGroupMutation(), + variables: { + groupId: 'closed-group', + userId: authenticatedUser.id, + }, + }) + authenticatedUser = await groupOwner.toJson() + }) + + it('has two the notification in database', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + read: false, + reason: 'user_left_group', + createdAt: expect.any(String), + from: { + __typename: 'Group', + id: 'closed-group', + }, + relatedUser: { + id: 'you', + }, + }, + { + read: false, + reason: 'user_joined_group', + createdAt: expect.any(String), + from: { + __typename: 'Group', + id: 'closed-group', + }, + relatedUser: { + id: 'you', + }, + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('user role in group changes', () => { + beforeEach(async () => { + authenticatedUser = await notifiedUser.toJson() + await mutate({ + mutation: joinGroupMutation(), + variables: { + groupId: 'closed-group', + userId: authenticatedUser.id, + }, + }) + authenticatedUser = await groupOwner.toJson() + await mutate({ + mutation: changeGroupMemberRoleMutation(), + variables: { + groupId: 'closed-group', + userId: 'you', + roleInGroup: 'admin', + }, + }) + authenticatedUser = await notifiedUser.toJson() + }) + + it('has notification in database', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + read: false, + reason: 'changed_group_member_role', + createdAt: expect.any(String), + from: { + __typename: 'Group', + id: 'closed-group', + }, + relatedUser: { + id: 'group-owner', + }, + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('user is removed from group', () => { + beforeEach(async () => { + authenticatedUser = await notifiedUser.toJson() + await mutate({ + mutation: joinGroupMutation(), + variables: { + groupId: 'closed-group', + userId: authenticatedUser.id, + }, + }) + authenticatedUser = await groupOwner.toJson() + await mutate({ + mutation: removeUserFromGroupMutation(), + variables: { + groupId: 'closed-group', + userId: 'you', + }, + }) + authenticatedUser = await notifiedUser.toJson() + }) + + it('has notification in database', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + read: false, + reason: 'removed_user_from_group', + createdAt: expect.any(String), + from: { + __typename: 'Group', + id: 'closed-group', + }, + relatedUser: { + id: 'group-owner', + }, + }, + ], + }, + errors: undefined, + }) + }) + }) + }) }) diff --git a/backend/src/schema/resolvers/embeds.spec.js b/backend/src/schema/resolvers/embeds.spec.js index 0f0d41357..b22927d1b 100644 --- a/backend/src/schema/resolvers/embeds.spec.js +++ b/backend/src/schema/resolvers/embeds.spec.js @@ -126,7 +126,7 @@ describe('Query', () => { author: null, date: expect.any(String), description: - 'Human Connection, Weilheim an der Teck. Gefällt 24.407 Mal. An upcoming non-profit social network focused on local and global positive change. Twitter accounts : @hc_world (EN), @hc_deutschland (GE),...', + 'Human Connection, Weilheim an der Teck. Gefällt 24.407 Mal. An upcoming non-profit social network focused on local and global positive change. Twitter accounts : @hc_world (EN), @hc_deutschland (GE),…', html: null, image: 'https://scontent.ftxl3-1.fna.fbcdn.net/v/t1.0-1/c5.0.200.200a/p200x200/12108307_997373093648222_70057205881020137_n.jpg?_nc_cat=110&_nc_oc=AQnPPYQlR0dU556gOfl4xkXr7IPZdRIAUfQeXl3fpUv4DAsFN8T4PfgOjPwuq85GPKGZ5S5E5mWQ8IVV1UiRBAIZ&_nc_ht=scontent.ftxl3-1.fna&oh=90309adddaab38839782f16e7d4b7bcf&oe=5DEEDFE5', @@ -196,7 +196,7 @@ Have all the information for the brand in separate config files. Set these defau publisher: 'YouTube', date: expect.any(String), description: - 'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...', + 'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al…', url: 'https://www.youtube.com/watch?v=qkdXAtO40Fo', image: 'https://i.ytimg.com/vi/qkdXAtO40Fo/maxresdefault.jpg', audio: null, diff --git a/backend/src/schema/resolvers/embeds/scraper.js b/backend/src/schema/resolvers/embeds/scraper.js index df37611f3..bcaa6e462 100644 --- a/backend/src/schema/resolvers/embeds/scraper.js +++ b/backend/src/schema/resolvers/embeds/scraper.js @@ -17,7 +17,6 @@ const metascraper = Metascraper([ require('metascraper-lang')(), require('metascraper-lang-detector')(), require('metascraper-logo')(), - // require('metascraper-clearbit-logo')(), require('metascraper-publisher')(), require('metascraper-title')(), require('metascraper-url')(), diff --git a/backend/src/schema/resolvers/filter-posts.spec.js b/backend/src/schema/resolvers/filter-posts.spec.js new file mode 100644 index 000000000..0b96e001f --- /dev/null +++ b/backend/src/schema/resolvers/filter-posts.spec.js @@ -0,0 +1,230 @@ +import { createTestClient } from 'apollo-server-testing' +import Factory, { cleanDatabase } from '../../db/factories' +import { getNeode, getDriver } from '../../db/neo4j' +import createServer from '../../server' +import CONFIG from '../../config' +import { filterPosts, createPostMutation } from '../../graphql/posts' + +CONFIG.CATEGORIES_ACTIVE = false + +const driver = getDriver() +const neode = getNeode() + +let query +let mutate +let authenticatedUser +let user + +beforeAll(async () => { + await cleanDatabase() + + const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + } + }, + }) + query = createTestClient(server).query + mutate = createTestClient(server).mutate +}) + +afterAll(async () => { + await cleanDatabase() + driver.close() +}) + +describe('Filter Posts', () => { + const now = new Date() + + beforeAll(async () => { + user = await Factory.build('user', { + id: 'user', + name: 'User', + about: 'I am a user.', + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'a1', + title: 'I am an article', + content: 'I am an article written by user.', + }, + }) + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'a2', + title: 'I am anonther article', + content: 'I am another article written by user.', + }, + }) + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'e1', + title: 'Illegaler Kindergeburtstag', + content: 'Elli wird fünf. Wir feiern ihren Geburtstag.', + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventVenue: 'Garten der Familie Maier', + }, + }, + }) + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'e2', + title: 'Räuber-Treffen', + content: 'Planung der nächsten Räuberereien', + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(), + eventVenue: 'Wirtshaus im Spessart', + }, + }, + }) + }) + + describe('no filters set', () => { + it('finds all posts', async () => { + const { + data: { Post: result }, + } = await query({ query: filterPosts() }) + expect(result).toHaveLength(4) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'a1' }), + expect.objectContaining({ id: 'a2' }), + expect.objectContaining({ id: 'e1' }), + expect.objectContaining({ id: 'e2' }), + ]), + ) + }) + }) + + describe('post type filter set to ["Article"]', () => { + it('finds the articles', async () => { + const { + data: { Post: result }, + } = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Article'] } } }) + expect(result).toHaveLength(2) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'a1' }), + expect.objectContaining({ id: 'a2' }), + ]), + ) + }) + }) + + describe('post type filter set to ["Event"]', () => { + it('finds the articles', async () => { + const { + data: { Post: result }, + } = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Event'] } } }) + expect(result).toHaveLength(2) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'e1' }), + expect.objectContaining({ id: 'e2' }), + ]), + ) + }) + }) + + describe('post type filter set to ["Article", "Event"]', () => { + it('finds all posts', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { filter: { postType_in: ['Article', 'Event'] } }, + }) + expect(result).toHaveLength(4) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'a1' }), + expect.objectContaining({ id: 'a2' }), + expect.objectContaining({ id: 'e1' }), + expect.objectContaining({ id: 'e2' }), + ]), + ) + }) + }) + + describe('order events by event start descending', () => { + it('finds the events orderd accordingly', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_desc'] }, + }) + expect(result).toHaveLength(2) + expect(result).toEqual([ + expect.objectContaining({ + id: 'e1', + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }), + expect.objectContaining({ + id: 'e2', + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(), + }), + ]) + }) + }) + + describe('order events by event start ascending', () => { + it('finds the events orderd accordingly', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_asc'] }, + }) + expect(result).toHaveLength(2) + expect(result).toEqual([ + expect.objectContaining({ + id: 'e2', + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(), + }), + expect.objectContaining({ + id: 'e1', + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }), + ]) + }) + }) + + describe('filter events by event start date', () => { + it('finds only events after given date', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { + filter: { + postType_in: ['Event'], + eventStart_gte: new Date( + now.getFullYear(), + now.getMonth(), + now.getDate() + 2, + ).toISOString(), + }, + }, + }) + expect(result).toHaveLength(1) + expect(result).toEqual([ + expect.objectContaining({ + id: 'e1', + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }), + ]) + }) + }) +}) diff --git a/backend/src/schema/resolvers/helpers/events.js b/backend/src/schema/resolvers/helpers/events.js new file mode 100644 index 000000000..84e64299d --- /dev/null +++ b/backend/src/schema/resolvers/helpers/events.js @@ -0,0 +1,47 @@ +import { UserInputError } from 'apollo-server' + +export const validateEventParams = (params) => { + if (params.postType && params.postType === 'Event') { + const { eventInput } = params + validateEventDate(eventInput.eventStart) + params.eventStart = eventInput.eventStart + if (eventInput.eventEnd) { + validateEventEnd(eventInput.eventStart, eventInput.eventEnd) + params.eventEnd = eventInput.eventEnd + } + if (eventInput.eventLocationName && !eventInput.eventVenue) { + throw new UserInputError('Event venue must be present if event location is given!') + } + params.eventVenue = eventInput.eventVenue + params.eventLocationName = eventInput.eventLocationName + params.eventIsOnline = !!eventInput.eventIsOnline + } + delete params.eventInput + let locationName + if (params.eventLocationName) { + locationName = params.eventLocationName + } else { + params.eventLocationName = null + locationName = null + } + return locationName +} + +const validateEventDate = (dateString) => { + const date = new Date(dateString) + if (date.toString() === 'Invalid Date') + throw new UserInputError('Event start date must be a valid date!') + const now = new Date() + if (date.getTime() < now.getTime()) { + throw new UserInputError('Event start date must be in the future!') + } +} + +const validateEventEnd = (start, end) => { + const endDate = new Date(end) + if (endDate.toString() === 'Invalid Date') + throw new UserInputError('Event end date must be a valid date!') + const startDate = new Date(start) + if (endDate < startDate) + throw new UserInputError('Event end date must be a after event start date!') +} diff --git a/backend/src/schema/resolvers/notifications.js b/backend/src/schema/resolvers/notifications.js index a2b850336..c3b882146 100644 --- a/backend/src/schema/resolvers/notifications.js +++ b/backend/src/schema/resolvers/notifications.js @@ -47,12 +47,22 @@ export default { ` MATCH (resource {deleted: false, disabled: false})-[notification:NOTIFIED]->(user:User {id:$id}) ${whereClause} - WITH user, notification, resource, + OPTIONAL MATCH (relatedUser:User { id: notification.relatedUserId }) + OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(relatedUser) + WITH user, notification, resource, membership, relatedUser, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts - WITH resource, user, notification, authors, posts, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource - RETURN notification {.*, from: finalResource, to: properties(user)} + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts + WITH resource, user, notification, authors, posts, relatedUser, membership, + resource {.*, + __typename: labels(resource)[0], + author: authors[0], + post: posts[0], + myRole: membership.role } AS finalResource + RETURN notification {.*, + from: finalResource, + to: properties(user), + relatedUser: properties(relatedUser) + } ${orderByClause} ${offset} ${limit} `, @@ -80,9 +90,10 @@ export default { SET notification.read = TRUE WITH user, notification, resource, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts - WITH resource, user, notification, authors, posts, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts + OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user) + WITH resource, user, notification, authors, posts, membership, + resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role } AS finalResource RETURN notification {.*, from: finalResource, to: properties(user)} `, { resourceId: args.id, id: currentUser.id }, @@ -109,9 +120,10 @@ export default { SET notification.read = TRUE WITH user, notification, resource, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts - WITH resource, user, notification, authors, posts, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts + OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user) + WITH resource, user, notification, authors, posts, membership, + resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role} AS finalResource RETURN notification {.*, from: finalResource, to: properties(user)} `, { id: currentUser.id }, diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.js index 47134aea6..9deaea457 100644 --- a/backend/src/schema/resolvers/notifications.spec.js +++ b/backend/src/schema/resolvers/notifications.spec.js @@ -397,18 +397,20 @@ describe('given some notifications', () => { it('returns all as read', async () => { const response = await mutate({ mutation: markAllAsReadMutation(), variables }) - expect(response.data.markAllAsRead).toEqual([ - { - createdAt: '2019-08-30T19:33:48.651Z', - from: { __typename: 'Comment', content: 'You have been mentioned in a comment' }, - read: true, - }, - { - createdAt: '2019-08-31T17:33:48.651Z', - from: { __typename: 'Post', content: 'You have been mentioned in a post' }, - read: true, - }, - ]) + expect(response.data.markAllAsRead).toEqual( + expect.arrayContaining([ + { + createdAt: '2019-08-30T19:33:48.651Z', + from: { __typename: 'Comment', content: 'You have been mentioned in a comment' }, + read: true, + }, + { + createdAt: '2019-08-31T17:33:48.651Z', + from: { __typename: 'Post', content: 'You have been mentioned in a post' }, + read: true, + }, + ]), + ) expect(response.errors).toBeUndefined() }) }) diff --git a/backend/src/schema/resolvers/posts.js b/backend/src/schema/resolvers/posts.js index d806f3803..c7d2eebdb 100644 --- a/backend/src/schema/resolvers/posts.js +++ b/backend/src/schema/resolvers/posts.js @@ -7,6 +7,8 @@ import Resolver from './helpers/Resolver' import { filterForMutedUsers } from './helpers/filterForMutedUsers' import { filterInvisiblePosts } from './helpers/filterInvisiblePosts' import { filterPostsOfMyGroups } from './helpers/filterPostsOfMyGroups' +import { validateEventParams } from './helpers/events' +import { createOrUpdateLocations } from './users/location' import CONFIG from '../../config' const maintainPinnedPosts = (params) => { @@ -81,6 +83,9 @@ export default { CreatePost: async (_parent, params, context, _resolveInfo) => { const { categoryIds, groupId } = params const { image: imageInput } = params + + const locationName = validateEventParams(params) + delete params.categoryIds delete params.image delete params.groupId @@ -125,12 +130,13 @@ export default { SET post.updatedAt = toString(datetime()) SET post.clickedCount = 0 SET post.viewedTeaserCount = 0 + SET post:${params.postType} WITH post MATCH (author:User {id: $userId}) MERGE (post)<-[:WROTE]-(author) ${categoriesCypher} ${groupCypher} - RETURN post {.*} + RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post") } `, { userId: context.user.id, categoryIds, groupId, params }, ) @@ -142,6 +148,9 @@ export default { }) try { const post = await writeTxResultPromise + if (locationName) { + await createOrUpdateLocations('Post', post.id, locationName, session) + } return post } catch (e) { if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed') @@ -154,6 +163,9 @@ export default { UpdatePost: async (_parent, params, context, _resolveInfo) => { const { categoryIds } = params const { image: imageInput } = params + + const locationName = validateEventParams(params) + delete params.categoryIds delete params.image const session = context.driver.session() @@ -183,7 +195,16 @@ export default { ` } - updatePostCypher += `RETURN post {.*}` + if (params.postType) { + updatePostCypher += ` + REMOVE post:Article + REMOVE post:Event + SET post:${params.postType} + WITH post + ` + } + + updatePostCypher += `RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post")}` const updatePostVariables = { categoryIds, params } try { const writeTxResultPromise = session.writeTransaction(async (transaction) => { @@ -196,6 +217,9 @@ export default { return post }) const post = await writeTxResultPromise + if (locationName) { + await createOrUpdateLocations('Post', post.id, locationName, session) + } return post } finally { session.close() @@ -310,6 +334,7 @@ export default { ` MATCH (user:User {id: $userId}) WHERE user.role = 'admin' MATCH (post:Post {id: $params.id}) + WHERE NOT((post)-[:IN]->(:Group)) MERGE (user)-[pinned:PINNED {createdAt: toString(datetime())}]->(post) SET post.pinned = true RETURN post, pinned.createdAt as pinnedAt @@ -322,10 +347,12 @@ export default { })) }) const [transactionResult] = await writeTxResultPromise - const { pinnedPost, pinnedAt } = transactionResult - pinnedPostWithNestedAttributes = { - ...pinnedPost, - pinnedAt, + if (transactionResult) { + const { pinnedPost, pinnedAt } = transactionResult + pinnedPostWithNestedAttributes = { + ...pinnedPost, + pinnedAt, + } } } finally { session.close() @@ -382,7 +409,19 @@ export default { }, Post: { ...Resolver('Post', { - undefinedToNull: ['activityId', 'objectId', 'language', 'pinnedAt', 'pinned'], + undefinedToNull: [ + 'activityId', + 'objectId', + 'language', + 'pinnedAt', + 'pinned', + 'eventVenue', + 'eventLocation', + 'eventLocationName', + 'eventStart', + 'eventEnd', + 'eventIsOnline', + ], hasMany: { tags: '-[:TAGGED]->(related:Tag)', categories: '-[:CATEGORIZED]->(related:Category)', @@ -395,6 +434,7 @@ export default { pinnedBy: '<-[:PINNED]-(related:User)', image: '-[:HERO_IMAGE]->(related:Image)', group: '-[:IN]->(related:Group)', + eventLocation: '-[:IS_IN]->(related:Location)', }, count: { commentsCount: diff --git a/backend/src/schema/resolvers/posts.spec.js b/backend/src/schema/resolvers/posts.spec.js index 9335c1313..87d09e262 100644 --- a/backend/src/schema/resolvers/posts.spec.js +++ b/backend/src/schema/resolvers/posts.spec.js @@ -3,6 +3,10 @@ import Factory, { cleanDatabase } from '../../db/factories' import gql from 'graphql-tag' import { getNeode, getDriver } from '../../db/neo4j' import createServer from '../../server' +import { createPostMutation } from '../../graphql/posts' +import CONFIG from '../../config' + +CONFIG.CATEGORIES_ACTIVE = true const driver = getDriver() const neode = getNeode() @@ -15,29 +19,6 @@ let user const categoryIds = ['cat9', 'cat4', 'cat15'] let variables -const createPostMutation = gql` - mutation ($id: ID, $title: String!, $content: String!, $language: String, $categoryIds: [ID]) { - CreatePost( - id: $id - title: $title - content: $content - language: $language - categoryIds: $categoryIds - ) { - id - title - content - slug - disabled - deleted - language - author { - name - } - } - } -` - beforeAll(async () => { await cleanDatabase() @@ -281,7 +262,7 @@ describe('CreatePost', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { - const { errors } = await mutate({ mutation: createPostMutation, variables }) + const { errors } = await mutate({ mutation: createPostMutation(), variables }) expect(errors[0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -296,7 +277,7 @@ describe('CreatePost', () => { data: { CreatePost: { title: 'I am a title', content: 'Some content' } }, errors: undefined, } - await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject( + await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject( expected, ) }) @@ -313,25 +294,327 @@ describe('CreatePost', () => { }, errors: undefined, } - await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject( + await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject( expected, ) }) it('`disabled` and `deleted` default to `false`', async () => { const expected = { data: { CreatePost: { disabled: false, deleted: false } } } - await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject( + await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject( expected, ) }) + + it('has label "Article" as default', async () => { + await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject({ + data: { CreatePost: { postType: ['Article'] } }, + }) + }) + + describe('with invalid post type', () => { + it('throws an error', async () => { + await expect( + mutate({ + mutation: createPostMutation(), + variables: { ...variables, postType: 'not-valid' }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: + 'Variable "$postType" got invalid value "not-valid"; Expected type PostType.', + }, + ], + }) + }) + }) + + describe('with post type "Event"', () => { + describe('without event start date', () => { + it('throws an error', async () => { + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: "Cannot read properties of undefined (reading 'eventStart')", + }, + ], + }) + }) + }) + + describe('with invalid event start date', () => { + it('throws an error', async () => { + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: 'no date', + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event start date must be a valid date!', + }, + ], + }) + }) + }) + + describe('with event start date in the past', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() - 1).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event start date must be in the future!', + }, + ], + }) + }) + }) + + describe('with valid start date and invalid end date', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventEnd: 'not-valid', + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event end date must be a valid date!', + }, + ], + }) + }) + }) + + describe('with valid start date and end date before start date', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event end date must be a after event start date!', + }, + ], + }) + }) + }) + + describe('with valid start date and valid end date', () => { + it('creates the event', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + data: { + CreatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(), + eventIsOnline: false, + }, + }, + errors: undefined, + }) + }) + }) + + describe('with valid start date and event is online', () => { + it('creates the event', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventIsOnline: true, + }, + }, + }), + ).resolves.toMatchObject({ + data: { + CreatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventIsOnline: true, + }, + }, + errors: undefined, + }) + }) + }) + + describe('event location name is given but event venue is missing', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Berlin', + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event venue must be present if event location is given!', + }, + ], + }) + }) + }) + + describe('valid event input without location', () => { + it('has label "Event" set', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + data: { + CreatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventIsOnline: false, + }, + }, + errors: undefined, + }) + }) + }) + + describe('valid event input with location name', () => { + it('has label "Event" set', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Leipzig', + eventVenue: 'Connewitzer Kreuz', + }, + }, + }), + ).resolves.toMatchObject({ + data: { + CreatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Leipzig', + eventVenue: 'Connewitzer Kreuz', + eventLocation: { + lng: 12.374733, + lat: 51.340632, + }, + }, + }, + errors: undefined, + }) + }) + }) + }) }) }) describe('UpdatePost', () => { let author, newlyCreatedPost const updatePostMutation = gql` - mutation ($id: ID!, $title: String!, $content: String!, $image: ImageInput) { - UpdatePost(id: $id, title: $title, content: $content, image: $image) { + mutation ( + $id: ID! + $title: String! + $content: String! + $image: ImageInput + $categoryIds: [ID] + $postType: PostType + $eventInput: _EventInput + ) { + UpdatePost( + id: $id + title: $title + content: $content + image: $image + categoryIds: $categoryIds + postType: $postType + eventInput: $eventInput + ) { id title content @@ -341,26 +624,34 @@ describe('UpdatePost', () => { } createdAt updatedAt + categories { + id + } + postType + eventStart + eventLocationName + eventVenue + eventLocation { + lng + lat + } } } ` beforeEach(async () => { author = await Factory.build('user', { slug: 'the-author' }) - newlyCreatedPost = await Factory.build( - 'post', - { - id: 'p9876', + authenticatedUser = await author.toJson() + const { data } = await mutate({ + mutation: createPostMutation(), + variables: { title: 'Old title', content: 'Old content', - }, - { - author, categoryIds, }, - ) - + }) + newlyCreatedPost = data.CreatePost variables = { - id: 'p9876', + id: newlyCreatedPost.id, title: 'New title', content: 'New content', } @@ -394,7 +685,7 @@ describe('UpdatePost', () => { it('updates a post', async () => { const expected = { - data: { UpdatePost: { id: 'p9876', content: 'New content' } }, + data: { UpdatePost: { id: newlyCreatedPost.id, content: 'New content' } }, errors: undefined, } await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject( @@ -405,7 +696,11 @@ describe('UpdatePost', () => { it('updates a post, but maintains non-updated attributes', async () => { const expected = { data: { - UpdatePost: { id: 'p9876', content: 'New content', createdAt: expect.any(String) }, + UpdatePost: { + id: newlyCreatedPost.id, + content: 'New content', + createdAt: expect.any(String), + }, }, errors: undefined, } @@ -415,23 +710,20 @@ describe('UpdatePost', () => { }) it('updates the updatedAt attribute', async () => { - newlyCreatedPost = await newlyCreatedPost.toJson() const { data: { UpdatePost }, } = await mutate({ mutation: updatePostMutation, variables }) - expect(newlyCreatedPost.updatedAt).toBeTruthy() - expect(Date.parse(newlyCreatedPost.updatedAt)).toEqual(expect.any(Number)) expect(UpdatePost.updatedAt).toBeTruthy() expect(Date.parse(UpdatePost.updatedAt)).toEqual(expect.any(Number)) expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePost.updatedAt) }) - /* describe('no new category ids provided for update', () => { + describe('no new category ids provided for update', () => { it('resolves and keeps current categories', async () => { const expected = { data: { UpdatePost: { - id: 'p9876', + id: newlyCreatedPost.id, categories: expect.arrayContaining([{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]), }, }, @@ -441,9 +733,9 @@ describe('UpdatePost', () => { expected, ) }) - }) */ + }) - /* describe('given category ids', () => { + describe('given category ids', () => { beforeEach(() => { variables = { ...variables, categoryIds: ['cat27'] } }) @@ -452,7 +744,7 @@ describe('UpdatePost', () => { const expected = { data: { UpdatePost: { - id: 'p9876', + id: newlyCreatedPost.id, categories: expect.arrayContaining([{ id: 'cat27' }]), }, }, @@ -462,9 +754,160 @@ describe('UpdatePost', () => { expected, ) }) - }) */ + }) - describe('params.image', () => { + describe('change post type to event', () => { + describe('with missing event start date', () => { + it('throws an error', async () => { + await expect( + mutate({ + mutation: updatePostMutation, + variables: { ...variables, postType: 'Event' }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: "Cannot read properties of undefined (reading 'eventStart')", + }, + ], + }) + }) + }) + + describe('with invalid event start date', () => { + it('throws an error', async () => { + await expect( + mutate({ + mutation: updatePostMutation, + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: 'no-date', + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event start date must be a valid date!', + }, + ], + }) + }) + }) + + describe('with event start date in the past', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: updatePostMutation, + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() - 1).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event start date must be in the future!', + }, + ], + }) + }) + }) + + describe('event location name is given but event venue is missing', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: updatePostMutation, + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Berlin', + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event venue must be present if event location is given!', + }, + ], + }) + }) + }) + + describe('valid event input without location name', () => { + it('has label "Event" set', async () => { + const now = new Date() + await expect( + mutate({ + mutation: updatePostMutation, + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + data: { + UpdatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }, + }, + errors: undefined, + }) + }) + }) + + describe('valid event input with location name', () => { + it('has label "Event" set', async () => { + const now = new Date() + await expect( + mutate({ + mutation: updatePostMutation, + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Leipzig', + eventVenue: 'Connewitzer Kreuz', + }, + }, + }), + ).resolves.toMatchObject({ + data: { + UpdatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Leipzig', + eventVenue: 'Connewitzer Kreuz', + eventLocation: { + lng: 12.374733, + lat: 51.340632, + }, + }, + }, + errors: undefined, + }) + }) + }) + }) + + describe.skip('params.image', () => { describe('is object', () => { beforeEach(() => { variables = { ...variables, image: { sensitive: true } } diff --git a/backend/src/schema/resolvers/postsInGroups.spec.js b/backend/src/schema/resolvers/postsInGroups.spec.js index 86a278207..ba9041090 100644 --- a/backend/src/schema/resolvers/postsInGroups.spec.js +++ b/backend/src/schema/resolvers/postsInGroups.spec.js @@ -818,11 +818,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -846,11 +848,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -874,11 +878,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -902,11 +908,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -930,21 +938,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1319,16 +1331,19 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, ]), }, @@ -1361,21 +1376,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1410,16 +1429,19 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1452,11 +1474,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -1489,21 +1513,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1534,21 +1562,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1579,21 +1611,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1628,21 +1664,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1675,21 +1715,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1739,11 +1783,13 @@ describe('Posts in Groups', () => { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js index 3fdf22da3..a67abe90d 100644 --- a/backend/src/schema/resolvers/searches.js +++ b/backend/src/schema/resolvers/searches.js @@ -223,8 +223,7 @@ export default { }, searchResults: async (_parent, args, context, _resolveInfo) => { const { query, limit } = args - let userId = null - if (context.user) userId = context.user.id + const userId = context.user?.id || null const searchType = query.replace(/^([!@#&]?).*$/, '$1') const searchString = query.replace(/^([!@#&])/, '') diff --git a/backend/src/schema/resolvers/searches/queryString.js b/backend/src/schema/resolvers/searches/queryString.js index 5ef84cdce..8f415c5e6 100644 --- a/backend/src/schema/resolvers/searches/queryString.js +++ b/backend/src/schema/resolvers/searches/queryString.js @@ -33,7 +33,7 @@ const matchSomeWordsExactly = (str, boost = 2) => { const matchBeginningOfWords = (str) => { return str .split(' ') - .filter((s) => s.length > 3) + .filter((s) => s.length >= 2) .map((s) => s + '*') .join(' ') } diff --git a/backend/src/schema/resolvers/searches/queryString.spec.js b/backend/src/schema/resolvers/searches/queryString.spec.js index 23a746be1..fe3c91d3c 100644 --- a/backend/src/schema/resolvers/searches/queryString.spec.js +++ b/backend/src/schema/resolvers/searches/queryString.spec.js @@ -37,7 +37,7 @@ describe('queryString', () => { describe('globbing for longer words', () => { it('globs words with more than three characters', () => { - expect(queryString('a couple of words')).toContain('couple* words*') + expect(queryString('a couple of words')).toContain('couple* of* words*') }) }) }) diff --git a/backend/src/schema/resolvers/users/location.js b/backend/src/schema/resolvers/users/location.js index 9d8a11f89..54d73560b 100644 --- a/backend/src/schema/resolvers/users/location.js +++ b/backend/src/schema/resolvers/users/location.js @@ -22,7 +22,7 @@ const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl', 'ru'] const createLocation = async (session, mapboxData) => { const data = { - id: mapboxData.id, + id: mapboxData.id + (mapboxData.address ? `-${mapboxData.address}` : ''), nameEN: mapboxData.text_en, nameDE: mapboxData.text_de, nameFR: mapboxData.text_fr, @@ -33,6 +33,7 @@ const createLocation = async (session, mapboxData) => { namePL: mapboxData.text_pl, nameRU: mapboxData.text_ru, type: mapboxData.id.split('.')[0].toLowerCase(), + address: mapboxData.address, lng: mapboxData.center && mapboxData.center.length ? mapboxData.center[0] : null, lat: mapboxData.center && mapboxData.center.length ? mapboxData.center[1] : null, } @@ -54,6 +55,10 @@ const createLocation = async (session, mapboxData) => { if (data.lat && data.lng) { mutation += ', l.lat = $lat, l.lng = $lng' } + if (data.address) { + mutation += ', l.address = $address' + } + mutation += ' RETURN l.id' await session.writeTransaction((transaction) => { @@ -72,7 +77,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s locationName, )}.json?access_token=${ CONFIG.MAPBOX_TOKEN - }&types=region,place,country&language=${locales.join(',')}`, + }&types=region,place,country,address&language=${locales.join(',')}`, ) debug(res) @@ -103,6 +108,10 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s let parent = data + if (parent.address) { + parent.id += `-${parent.address}` + } + if (data.context) { await asyncForEach(data.context, async (ctx) => { await createLocation(session, ctx) diff --git a/backend/src/schema/types/enum/PostType.gql b/backend/src/schema/types/enum/PostType.gql new file mode 100644 index 000000000..eef80d6ba --- /dev/null +++ b/backend/src/schema/types/enum/PostType.gql @@ -0,0 +1,4 @@ +enum PostType { + Article + Event +} diff --git a/backend/src/schema/types/enum/ReasonNotification.gql b/backend/src/schema/types/enum/ReasonNotification.gql deleted file mode 100644 index e870e01dc..000000000 --- a/backend/src/schema/types/enum/ReasonNotification.gql +++ /dev/null @@ -1,5 +0,0 @@ -enum ReasonNotification { - mentioned_in_post - mentioned_in_comment - commented_on_post -} diff --git a/backend/src/schema/types/schema.gql b/backend/src/schema/types/schema.gql index b15179443..9e2d00bca 100644 --- a/backend/src/schema/types/schema.gql +++ b/backend/src/schema/types/schema.gql @@ -1,17 +1,3 @@ -type Mutation { - # Get a JWT Token for the given Email and password - login(email: String!, password: String!): String! - changePassword(oldPassword: String!, newPassword: String!): String! - requestPasswordReset(email: String!): Boolean! - resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean! - # Shout the given Type and ID - shout(id: ID!, type: ShoutTypeEnum): Boolean! - # Unshout the given Type and ID - unshout(id: ID!, type: ShoutTypeEnum): Boolean! - followUser(id: ID!): User - unfollowUser(id: ID!): User -} - enum ShoutTypeEnum { Post } @@ -27,4 +13,4 @@ type Reward { type SharedInboxEndpoint { id: ID! uri: String -} +} \ No newline at end of file diff --git a/backend/src/schema/types/type/NOTIFIED.gql b/backend/src/schema/types/type/NOTIFIED.gql index 864cdea4d..62a1f3696 100644 --- a/backend/src/schema/types/type/NOTIFIED.gql +++ b/backend/src/schema/types/type/NOTIFIED.gql @@ -6,9 +6,10 @@ type NOTIFIED { updatedAt: String! read: Boolean reason: NotificationReason + relatedUser: User } -union NotificationSource = Post | Comment +union NotificationSource = Post | Comment | Group enum NotificationOrdering { createdAt_asc @@ -21,6 +22,10 @@ enum NotificationReason { mentioned_in_post mentioned_in_comment commented_on_post + user_joined_group + user_left_group + changed_group_member_role + removed_user_from_group } type Query { diff --git a/backend/src/schema/types/type/Post.gql b/backend/src/schema/types/type/Post.gql index 6fc7a3215..af1e14188 100644 --- a/backend/src/schema/types/type/Post.gql +++ b/backend/src/schema/types/type/Post.gql @@ -83,6 +83,8 @@ input _PostFilter { emotions_every: _PostEMOTEDFilter group: _GroupFilter postsInMyGroups: Boolean + postType_in: [PostType] + eventStart_gte: String } enum _PostOrdering { @@ -104,6 +106,8 @@ enum _PostOrdering { language_desc pinned_asc pinned_desc + eventStart_asc + eventStart_desc } @@ -171,12 +175,30 @@ type Post { @cypher(statement: "MATCH (this)<-[emoted:EMOTED]-(:User) RETURN COUNT(DISTINCT emoted)") group: Group @relation(name: "IN", direction: "OUT") + + postType: [PostType] + @cypher(statement: "RETURN filter(l IN labels(this) WHERE NOT l = 'Post')") + + eventLocationName: String + eventLocation: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l") + eventVenue: String + eventStart: String + eventEnd: String + eventIsOnline: Boolean } input _PostInput { id: ID! } +input _EventInput { + eventStart: String! + eventEnd: String + eventVenue: String + eventLocationName: String + eventIsOnline: Boolean +} + type Mutation { CreatePost( id: ID @@ -189,6 +211,8 @@ type Mutation { categoryIds: [ID] contentExcerpt: String groupId: ID + postType: PostType = Article + eventInput: _EventInput ): Post UpdatePost( id: ID! @@ -200,6 +224,8 @@ type Mutation { visibility: Visibility language: String categoryIds: [ID] + postType: PostType + eventInput: _EventInput ): Post DeletePost(id: ID!): Post AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED @@ -207,6 +233,11 @@ type Mutation { pinPost(id: ID!): Post unpinPost(id: ID!): Post markTeaserAsViewed(id: ID!): Post + + # Shout the given Type and ID + shout(id: ID!, type: ShoutTypeEnum): Boolean! + # Unshout the given Type and ID + unshout(id: ID!, type: ShoutTypeEnum): Boolean! } type Query { diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index fe1ff43f0..f406e4e45 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -214,10 +214,21 @@ type Mutation { muteUser(id: ID!): User unmuteUser(id: ID!): User + blockUser(id: ID!): User unblockUser(id: ID!): User + followUser(id: ID!): User + unfollowUser(id: ID!): User + switchUserRole(role: UserRole!, id: ID!): User saveCategorySettings(activeCategories: [String]): Boolean + + requestPasswordReset(email: String!): Boolean! + resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean! + changePassword(oldPassword: String!, newPassword: String!): String! + + # Get a JWT Token for the given Email and password + login(email: String!, password: String!): String! } diff --git a/backend/src/server.js b/backend/src/server.js index bcbd84617..d0b205035 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -82,7 +82,13 @@ const createServer = (options) => { const app = express() app.set('driver', driver) - app.use(helmet()) + // TODO: this exception is required for the graphql playground, since the playground loads external resources + // See: https://github.com/graphql/graphql-playground/issues/1283 + app.use( + helmet( + (CONFIG.DEBUG && { contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }) || {}, + ), + ) app.use('/.well-known/', webfinger()) app.use(express.static('public')) app.use(bodyParser.json({ limit: '10mb' })) diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 000000000..3271196ed --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,111 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./build", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["./src/**/*"], + "exclude": ["./src/**/*.spec.ts", "./src/**/*.spec.js"] +} diff --git a/backend/yarn.lock b/backend/yarn.lock index c2fb0d28c..b55842174 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -1088,10 +1088,17 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@faker-js/faker@5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-5.1.0.tgz#cee1d77ada0d0dbbe77201d18b1ebabf432d9c0f" - integrity sha512-0VonSKh7fBCqvY+V2FLN2ZW4pR4ZtWJalWmwSaiaB7yK7y4qp8vDfuaq9QdLjf/cdZGx3M7Wc4Q+x4fZHxI21Q== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@faker-js/faker@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-7.6.0.tgz#9ea331766084288634a9247fcd8b84f16ff4ba07" + integrity sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw== "@gar/promisify@^1.1.3": version "1.1.3" @@ -1131,33 +1138,16 @@ resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== -"@hapi/address@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@hapi/address/-/address-4.0.1.tgz#267301ddf7bc453718377a6fb3832a2f04a721dd" - integrity sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw== - dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/bourne@1.x.x": version "1.3.2" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== -"@hapi/formula@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-2.0.0.tgz#edade0619ed58c8e4f164f233cda70211e787128" - integrity sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A== - "@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": version "8.5.1" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== -"@hapi/hoek@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.0.tgz#ba83436edfac1d1ffd0e94797d43419c20ad49b8" - integrity sha512-XxD4A5YMIH70ddjG7BJBUz7RWVQAwIP/36Eoyh0DsaWp92OAeXkrbtSEaYkynBPTsN9Uv2mZq9QWZYILl2Svrw== - "@hapi/joi@^15.1.1": version "15.1.1" resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" @@ -1168,22 +1158,6 @@ "@hapi/hoek" "8.x.x" "@hapi/topo" "3.x.x" -"@hapi/joi@^17.1.0", "@hapi/joi@^17.1.1": - version "17.1.1" - resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-17.1.1.tgz#9cc8d7e2c2213d1e46708c6260184b447c661350" - integrity sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg== - dependencies: - "@hapi/address" "^4.0.1" - "@hapi/formula" "^2.0.0" - "@hapi/hoek" "^9.0.0" - "@hapi/pinpoint" "^2.0.0" - "@hapi/topo" "^5.0.0" - -"@hapi/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" - integrity sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw== - "@hapi/topo@3.x.x": version "3.1.6" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" @@ -1191,13 +1165,6 @@ dependencies: "@hapi/hoek" "^8.3.0" -"@hapi/topo@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" - integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== - dependencies: - "@hapi/hoek" "^9.0.0" - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1460,6 +1427,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" @@ -1470,6 +1442,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" @@ -1485,6 +1465,13 @@ dependencies: json-buffer "~3.0.1" +"@keyvhq/core@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@keyvhq/core/-/core-2.0.0.tgz#518311a59dbc4d6b6fd56852c15f483edb9fc7c9" + integrity sha512-fi3+F7GNImn1j4r6UFhsHRwN8a05uhUlrbNWZgnkX0h1NzcBEPNNqqMOE4KSASJwH2e9Eh/jm+bEfto58csNgg== + dependencies: + json-buffer "~3.0.1" + "@keyvhq/memoize@~1.6.14": version "1.6.14" resolved "https://registry.yarnpkg.com/@keyvhq/memoize/-/memoize-1.6.14.tgz#6a347b81e9be7040c678f8fc4b9046186484b6fc" @@ -1493,6 +1480,14 @@ "@keyvhq/core" "^1.6.14" mimic-fn "~3.0.0" +"@keyvhq/memoize@~2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@keyvhq/memoize/-/memoize-2.0.0.tgz#58b1118c2972b631aede81040eab6daefce8f5e8" + integrity sha512-0vibPmDh7nCWsbdS4A1IJX1G89PyT+nJEDGj1tUYsLPQ5BLnpLwneCudmXIvxD6cUUvMYqmhxKyjpvHd8DpPkA== + dependencies: + "@keyvhq/core" "^2.0.0" + mimic-fn "~3.0.0" + "@metascraper/helpers@^4.10.2": version "4.10.2" resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-4.10.2.tgz#864e49c71468548441f3a1ab68fdb2913855821b" @@ -1516,15 +1511,15 @@ url-regex "~4.1.1" video-extensions "~1.1.0" -"@metascraper/helpers@^5.33.5": - version "5.33.5" - resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.33.5.tgz#f980b41b3b7d7e67e11f849664727ef9d4802740" - integrity sha512-gcULKpM00CNxlf7iWRTi4hQQIXWQUjeFal0V5U60C4P4YyfLXfjuQVBk6mmKSYENSRh7oBQhAR+YVnMalVWBcw== +"@metascraper/helpers@^5.33.5", "@metascraper/helpers@^5.34.2", "@metascraper/helpers@^5.34.4": + version "5.34.4" + resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.34.4.tgz#59faf01466938b26aa8df147f97c7f9f4d739d28" + integrity sha512-OZdXkfxJXH5dW+aoptLJzxN56Xj+ABzbqZ9NDuKn908zW4tvLBPD6go3qdd3GXXQZH7TxvWpETn9i1AxzoyKmQ== dependencies: audio-extensions "0.0.0" - chrono-node "~2.5.0" + chrono-node "~2.6.2" condense-whitespace "~2.0.0" - entities "~4.4.0" + entities "~4.5.0" file-extension "~4.0.5" has-values "~2.0.1" image-extensions "~1.1.0" @@ -1532,7 +1527,7 @@ is-uri "~1.2.4" iso-639-3 "~2.2.0" isostring "0.0.1" - jsdom "~21.1.0" + jsdom "~22.0.0" lodash "~4.17.21" memoize-one "~6.0.0" microsoft-capitalize "~1.0.5" @@ -1540,7 +1535,7 @@ normalize-url "~6.1.0" re2 "~1.18.0" smartquotes "~2.3.2" - tldts "~5.7.103" + tldts "~6.0.1" url-regex-safe "~3.0.0" video-extensions "~1.2.0" @@ -1718,11 +1713,6 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272" integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g== -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - "@sindresorhus/is@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.1.tgz#d26729db850fa327b7cacc5522252194404226f5" @@ -1742,13 +1732,6 @@ dependencies: "@sinonjs/commons" "^2.0.0" -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - "@szmarczak/http-timer@^4.0.5": version "4.0.6" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" @@ -1761,6 +1744,26 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@types/accepts@*", "@types/accepts@^1.3.5": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" @@ -2143,20 +2146,12 @@ accepts@^1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-globals@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" - integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== - dependencies: - acorn "^8.1.0" - acorn-walk "^8.0.2" - acorn-jsx@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== -acorn-walk@^8.0.2: +acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== @@ -2166,7 +2161,7 @@ acorn@^7.1.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.1.0, acorn@^8.8.1: +acorn@^8.4.1: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== @@ -2641,6 +2636,11 @@ arg@1.0.0: resolved "https://registry.yarnpkg.com/arg/-/arg-1.0.0.tgz#444d885a4e25b121640b55155ef7cd03975d6050" integrity sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw== +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -3022,11 +3022,6 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -bowser@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9" - integrity sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA== - boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -3189,19 +3184,6 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - cacheable-request@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" @@ -3243,11 +3225,6 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelize@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" - integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= - caniuse-lite@^1.0.30001219: version "1.0.30001230" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" @@ -3424,10 +3401,10 @@ chrono-node@~1.3.11: dependencies: moment "2.21.0" -chrono-node@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/chrono-node/-/chrono-node-2.5.0.tgz#c4d5f4f4db9d72604a5beb79fdc5fd57be4b212f" - integrity sha512-GasdFCw4tsb8UKlwyJW1S+3bdN06vsyGR2cEDMlhEGI7ic4SQRnLyl/hbItwSum6pPkkUTrzFcaR3C2tZnnO5Q== +chrono-node@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/chrono-node/-/chrono-node-2.6.3.tgz#fa257cffb2dfc33fa5a01b26bd86f93741ca6dc5" + integrity sha512-VkWaaZnNulqzNH9i4XCdyI05OX6MFEnCMNKdZOR4w//wS5/E2qkwAss/O5sj6SfTZK84fX4SSOG4pzqjqIseiA== dependencies: dayjs "^1.10.0" @@ -3623,7 +3600,7 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.0, component-emitter@^1.2.1: +component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -3672,11 +3649,6 @@ content-disposition@0.5.3: dependencies: safe-buffer "5.1.2" -content-security-policy-builder@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz#0a2364d769a3d7014eec79ff7699804deb8cfcbb" - integrity sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ== - content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -3714,11 +3686,6 @@ cookie@^0.3.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= -cookiejar@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== - copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" @@ -3772,6 +3739,11 @@ create-error-class@^3.0.0: dependencies: capture-stack-trace "^1.0.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-env@~7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" @@ -3858,22 +3830,12 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= -cssom@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" - integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== +cssstyle@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-3.0.0.tgz#17ca9c87d26eac764bb8cfd00583cff21ce0277a" + integrity sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg== dependencies: - cssom "~0.3.6" + rrweb-cssom "^0.6.0" cucumber-expressions@^8.1.0: version "8.2.1" @@ -3936,24 +3898,14 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -dasherize@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dasherize/-/dasherize-2.0.0.tgz#6d809c9cd0cf7bb8952d80fc84fa13d47ddb1308" - integrity sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg= - -data-urls@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" - integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== +data-urls@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4" + integrity sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g== dependencies: abab "^2.0.6" whatwg-mimetype "^3.0.0" - whatwg-url "^11.0.0" - -date-fns@2.22.1: - version "2.22.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.22.1.tgz#1e5af959831ebb1d82992bf67b765052d8f0efc4" - integrity sha512-yUFPQjrxEmIsMqlHhAhmxkuH769baF21Kk+nZwZGyrMoyLA+LugaQtC0+Tqf9CBUUULWwUJt6Q5ySI3LJDDCGg== + whatwg-url "^12.0.0" dateformat@^3.0.3: version "3.0.3" @@ -3979,7 +3931,7 @@ debug@4, debug@^4.0.1, debug@~4.1.1: dependencies: ms "^2.1.1" -debug@^3.1.0, debug@^3.2.6: +debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -3993,7 +3945,7 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.3: dependencies: ms "2.1.2" -decimal.js@^10.4.2: +decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== @@ -4003,13 +3955,6 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -4049,11 +3994,6 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== -defer-to-connect@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" - integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== - defer-to-connect@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" @@ -4103,11 +4043,6 @@ denque@^1.1.0: resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - depd@^1.1.2, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -4157,11 +4092,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-prefetch-control@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz#73988161841f3dcc81f47686d539a2c702c88624" - integrity sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q== - doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -4317,11 +4247,6 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.1" -dont-sniff-mimetype@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz#c7d0427f8bcb095762751252af59d148b0a623b2" - integrity sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug== - dot-prop@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" @@ -4431,11 +4356,16 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== -entities@^4.2.0, entities@^4.3.0, entities@^4.4.0, entities@~4.4.0: +entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== +entities@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" @@ -4460,7 +4390,7 @@ error-stack-parser@^2.0.1: dependencies: stackframe "^1.0.4" -es-abstract@^1.12.0, es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.7.0: +es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== @@ -4574,18 +4504,6 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - eslint-config-prettier@~6.15.0: version "6.15.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" @@ -4755,7 +4673,7 @@ espree@^6.1.2: acorn-jsx "^5.1.0" eslint-visitor-keys "^1.1.0" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -4779,11 +4697,6 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4881,11 +4794,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect-ct@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/expect-ct/-/expect-ct-0.2.0.tgz#3a54741b6ed34cc7a93305c605f63cd268a54a62" - integrity sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g== - expect@^29.4.2: version "29.4.2" resolved "https://registry.yarnpkg.com/expect/-/expect-29.4.2.tgz#2ae34eb88de797c64a1541ad0f1e2ea8a7a7b492" @@ -4948,7 +4856,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.2: +extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -5046,11 +4954,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -feature-policy@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069" - integrity sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ== - figures@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" @@ -5160,15 +5063,6 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== -form-data@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.0.tgz#094ec359dc4b55e7d62e0db4acd76e89fe874d37" - integrity sha512-WXieX3G/8side6VIqx44ablyULoGruSde5PNTxoUyo5CeyAMX6nVWUd0rgist/EuX655cjhUhTo1Fo3tRYqbcA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - form-data@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" @@ -5196,11 +5090,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -formidable@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659" - integrity sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg== - forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -5213,11 +5102,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -frameguard@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/frameguard/-/frameguard-3.1.0.tgz#bd1442cca1d67dc346a6751559b6d04502103a22" - integrity sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g== - franc@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/franc/-/franc-4.0.0.tgz#365951bc787b92ffbb1c63c1c492d6b76cbd3a56" @@ -5277,7 +5161,7 @@ fsevents@~2.1.1: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== -function-bind@^1.0.2, function-bind@^1.1.1: +function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== @@ -5345,7 +5229,7 @@ get-stream@^3.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= -get-stream@^4.0.0, get-stream@^4.1.0: +get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== @@ -5484,7 +5368,7 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -got@~11.8.0, got@~11.8.5: +got@~11.8.0, got@~11.8.5, got@~11.8.6: version "11.8.6" resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== @@ -5501,23 +5385,6 @@ got@~11.8.0, got@~11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -got@~9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - graceful-fs@^4.1.11, graceful-fs@^4.1.2: version "4.2.2" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" @@ -5542,16 +5409,6 @@ graphql-auth-directives@^2.1.0: graphql-tools "^4.0.4" jsonwebtoken "^8.3.0" -graphql-custom-directives@~0.2.14: - version "0.2.14" - resolved "https://registry.yarnpkg.com/graphql-custom-directives/-/graphql-custom-directives-0.2.14.tgz#88611b8cb074477020ad85af47bfe168c4c23992" - integrity sha512-c3+r+st7dbBNGOLumkWrnv4nwAHJr1sZnkYc72AIMtzjuQ4+Slk1ZsFVYt1kwXJpfxXgf6g2g0jYc9+Lmz4ENg== - dependencies: - libphonenumber-js "^1.6.4" - lodash "^4.17.5" - moment "^2.22.2" - numeral "^2.0.6" - graphql-extensions@^0.12.6: version "0.12.6" resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.12.6.tgz#c66be43035662a8cfb0b8efe9df96595338bd13c" @@ -5561,11 +5418,6 @@ graphql-extensions@^0.12.6: apollo-server-env "^2.4.5" apollo-server-types "^0.6.1" -graphql-iso-date@~3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/graphql-iso-date/-/graphql-iso-date-3.6.1.tgz#bd2d0dc886e0f954cbbbc496bbf1d480b57ffa96" - integrity sha512-AwFGIuYMJQXOEAgRlJlFL4H1ncFM8n8XmoVDTNypNOZyQ8LFDG2ppMFlsS862BSTCDcSUfHp8PD3/uJhv7t59Q== - graphql-middleware-sentry@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/graphql-middleware-sentry/-/graphql-middleware-sentry-3.2.1.tgz#b5653d78903d655cf4212a602cfa6e26689cda07" @@ -5744,46 +5596,10 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -helmet-crossdomain@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e" - integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA== - -helmet-csp@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.10.0.tgz#685dde1747bc16c5e28ad9d91e229a69f0a85e84" - integrity sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w== - dependencies: - bowser "2.9.0" - camelize "1.0.0" - content-security-policy-builder "2.1.0" - dasherize "2.0.0" - -helmet@~3.22.0: - version "3.22.0" - resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.22.0.tgz#3a6f11d931799145f0aff15dbc563cff9e13131f" - integrity sha512-Xrqicn2nm1ZIUxP3YGuTBmbDL04neKsIT583Sjh0FkiwKDXYCMUqGqC88w3NUvVXtA75JyR2Jn6jw6ZEMOD+ZA== - dependencies: - depd "2.0.0" - dns-prefetch-control "0.2.0" - dont-sniff-mimetype "1.1.0" - expect-ct "0.2.0" - feature-policy "0.3.0" - frameguard "3.1.0" - helmet-crossdomain "0.4.0" - helmet-csp "2.10.0" - hide-powered-by "1.1.0" - hpkp "2.0.0" - hsts "2.2.0" - ienoopen "1.1.0" - nocache "2.1.0" - referrer-policy "1.2.0" - x-xss-protection "1.3.0" - -hide-powered-by@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.1.0.tgz#be3ea9cab4bdb16f8744be873755ca663383fa7a" - integrity sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg== +helmet@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-7.0.0.tgz#ac3011ba82fa2467f58075afa58a49427ba6212d" + integrity sha512-MsIgYmdBh460ZZ8cJC81q4XJknjG567wzEmv46WOBblDb6TUd3z8/GhgmsM9pn8g2B80tAJ4m5/d3Bi1KrSUBQ== homedir-polyfill@^1.0.1: version "1.0.3" @@ -5797,18 +5613,6 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== -hpkp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hpkp/-/hpkp-2.0.0.tgz#10e142264e76215a5d30c44ec43de64dee6d1672" - integrity sha1-EOFCJk52IVpdMMROxD3mTe5tFnI= - -hsts@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/hsts/-/hsts-2.2.0.tgz#09119d42f7a8587035d027dda4522366fe75d964" - integrity sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ== - dependencies: - depd "2.0.0" - html-encoding-sniffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" @@ -5991,11 +5795,6 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ienoopen@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.1.0.tgz#411e5d530c982287dbdc3bb31e7a9c9e32630974" - integrity sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ== - ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -7008,27 +6807,24 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdom@~21.1.0: - version "21.1.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.0.tgz#d56ba4a84ed478260d83bd53dc181775f2d8e6ef" - integrity sha512-m0lzlP7qOtthD918nenK3hdItSd2I+V3W9IrBcB36sqDwG+KnUs66IF5GY7laGWUnlM9vTsD0W1QwSEBYWWcJg== +jsdom@~22.0.0: + version "22.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-22.0.0.tgz#3295c6992c70089c4b8f5cf060489fddf7ee9816" + integrity sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw== dependencies: abab "^2.0.6" - acorn "^8.8.1" - acorn-globals "^7.0.0" - cssom "^0.5.0" - cssstyle "^2.3.0" - data-urls "^3.0.2" - decimal.js "^10.4.2" + cssstyle "^3.0.0" + data-urls "^4.0.0" + decimal.js "^10.4.3" domexception "^4.0.0" - escodegen "^2.0.0" form-data "^4.0.0" html-encoding-sniffer "^3.0.0" http-proxy-agent "^5.0.0" https-proxy-agent "^5.0.1" is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.2" - parse5 "^7.1.1" + nwsapi "^2.2.4" + parse5 "^7.1.2" + rrweb-cssom "^0.6.0" saxes "^6.0.0" symbol-tree "^3.2.4" tough-cookie "^4.1.2" @@ -7036,8 +6832,8 @@ jsdom@~21.1.0: webidl-conversions "^7.0.0" whatwg-encoding "^2.0.0" whatwg-mimetype "^3.0.0" - whatwg-url "^11.0.0" - ws "^8.11.0" + whatwg-url "^12.0.1" + ws "^8.13.0" xml-name-validator "^4.0.0" jsesc@^2.5.1: @@ -7050,21 +6846,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - json-buffer@3.0.1, json-buffer@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -7138,13 +6924,6 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - keyv@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254" @@ -7220,14 +6999,6 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libphonenumber-js@^1.6.4: - version "1.7.22" - resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.7.22.tgz#e206e3c227ec47ff306f7405ac52c331911e1b35" - integrity sha512-KCK4874gp640B+d1zjNi2ZiZ3ubEUPH/0B9AwcuhHDVAL6NdthxC8obbdhGlo7FcEpjFVwEMDoHRfi+lI8NM/g== - dependencies: - minimist "^1.2.0" - xml2js "^0.4.17" - lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -7252,16 +7023,6 @@ load-json-file@^2.0.0: pify "^2.0.0" strip-bom "^3.0.0" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -7365,7 +7126,7 @@ lodash@4.17.15: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.15.0, lodash@^4.17.14, lodash@^4.17.5, lodash@~4.17.11, lodash@~4.17.14: +lodash@^4.15.0, lodash@^4.17.14, lodash@~4.17.11, lodash@~4.17.14: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -7404,7 +7165,7 @@ lower-case@^2.0.1: dependencies: tslib "^1.10.0" -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: +lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== @@ -7468,6 +7229,11 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + make-fetch-happen@^10.0.3: version "10.2.1" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164" @@ -7519,11 +7285,6 @@ memoize-one@~6.0.0: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -7548,14 +7309,14 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== -metascraper-audio@^5.33.5: - version "5.33.5" - resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.33.5.tgz#5400fab5154636f166aff10e205a429c9e75d9a2" - integrity sha512-zO2PyRIVH10RTZlphYXVOAn8U17ZaH/JkY95h1BJ9eMBWfnziuWCtN0tIUUysQ+Ci8vcci65tasYqdG7jfcHKQ== +metascraper-audio@^5.34.4: + version "5.34.4" + resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.34.4.tgz#84437c3962a9186cda69510229f6b68e6a25563a" + integrity sha512-Z/BzT0KLq8H6Zc0wm4PqKlSeI7O54ZsD2QhV9GgkJNz5jGj0Rs4P3OOvoa+FEtDyRKGfIzYuldAuhQMVmo1WMA== dependencies: - "@keyvhq/memoize" "~1.6.14" - "@metascraper/helpers" "^5.33.5" - got "~11.8.5" + "@keyvhq/memoize" "~2.0.0" + "@metascraper/helpers" "^5.34.4" + got "~11.8.6" p-reflect "~2.1.0" metascraper-author@^5.33.5: @@ -7565,13 +7326,6 @@ metascraper-author@^5.33.5: dependencies: "@metascraper/helpers" "^5.33.5" -metascraper-clearbit-logo@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/metascraper-clearbit-logo/-/metascraper-clearbit-logo-5.3.0.tgz#e4596dbaf35503635d585a705f4119c7eddc6773" - integrity sha512-Vg9m8cj2yEIUDrRjvCORvf8vgq2HLsWLVqNnIactNUPJ+Lcly5Xcxh5TcmHYp5Qx5DtNUCoKlakomYHn8mOjqg== - dependencies: - got "~9.6.0" - metascraper-date@^5.33.5: version "5.33.5" resolved "https://registry.yarnpkg.com/metascraper-date/-/metascraper-date-5.33.5.tgz#fccd8f7b685e0f3bb152c86aa93ed03a96c3c834" @@ -7624,12 +7378,12 @@ metascraper-publisher@^5.33.5: dependencies: "@metascraper/helpers" "^5.33.5" -metascraper-soundcloud@^5.33.5: - version "5.33.5" - resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.33.5.tgz#9cd39e7ff432e715f8ecdca5256e7ea67f485557" - integrity sha512-hkDhRfTKEUugIN9Gxh/l9HuWlkNAOKEBXov/9fYKbIMgaj7e2UU7bkNYjaDOXzMikCRWEIrrGP3UzwwIcs6Gjg== +metascraper-soundcloud@^5.34.4: + version "5.34.4" + resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.34.4.tgz#f5e154e20ddad8902630b6f128f0928e7475ef83" + integrity sha512-EO17QYd7HOEGFHgKjC68x5fp8j+V+iYeGO0IgWY53olOfIrxBMG6gG1IIqcOjhbZFVHNX1uBz4BVmNtTvHvcjw== dependencies: - "@metascraper/helpers" "^5.33.5" + "@metascraper/helpers" "^5.34.4" metascraper-title@^5.33.5: version "5.33.5" @@ -7638,12 +7392,12 @@ metascraper-title@^5.33.5: dependencies: "@metascraper/helpers" "^5.33.5" -metascraper-url@^5.33.5: - version "5.33.5" - resolved "https://registry.yarnpkg.com/metascraper-url/-/metascraper-url-5.33.5.tgz#eb0ba736f47aef7c9a511ca04e509d11ee51c95d" - integrity sha512-bXKfsfxCfy6uhhnb9lMlIu1Uwqkn9eXa4QVcHdq/+1UWTOE8b2u4NTH4YgJMjcPmdth7s3cKXBxG1yBnsAoN0w== +metascraper-url@^5.34.2: + version "5.34.2" + resolved "https://registry.yarnpkg.com/metascraper-url/-/metascraper-url-5.34.2.tgz#1136dbf1177d08835d6b8677a64d9f10f0517fb0" + integrity sha512-ijPe3G64kyxFRWPA7YmH01dt5JImqBgWV07WIpgPj8wuD4ThwteGqV1CtjNYJN8yo/tCQeFNJPoubwiv9RsrJw== dependencies: - "@metascraper/helpers" "^5.33.5" + "@metascraper/helpers" "^5.34.2" metascraper-video@^5.33.5: version "5.33.5" @@ -7676,7 +7430,7 @@ metascraper@^5.33.5: lodash "~4.17.21" whoops "~4.1.2" -methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: +methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -7751,7 +7505,7 @@ mime-types@^2.1.26, mime-types@~2.1.22, mime-types@~2.1.24: dependencies: mime-db "1.43.0" -mime@1.6.0, mime@^1.4.1: +mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -7776,7 +7530,7 @@ mimic-fn@~3.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== -mimic-response@^1.0.0, mimic-response@^1.0.1: +mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== @@ -7925,11 +7679,6 @@ moment@2.21.0: resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" integrity sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ== -moment@^2.22.2: - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -8034,17 +7783,7 @@ neo4j-driver-core@^4.4.7: resolved "https://registry.yarnpkg.com/neo4j-driver-core/-/neo4j-driver-core-4.4.7.tgz#d2475e107b3fea2b9d1c36b0c273da5c5a291c37" integrity sha512-NhvVuQYgG7eO/vXxRaoJfkWUNkjvIpmCIS9UWU9Bbhb4V+wCOyX/MVOXqD0Yizhs4eyIkD7x90OXb79q+vi+oA== -neo4j-driver@^4.0.1, neo4j-driver@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-4.0.2.tgz#78de3b91e91572bcbd9d2e02554322fe1ab399ea" - integrity sha512-xQN4BZZsweaNNac7FDYAV6f/JybghwY3lk4fwblS8V5KQ+DBMPe4Pthh672mp+wEYZGyzPalq5CfpcBrWaZ4Gw== - dependencies: - "@babel/runtime" "^7.5.5" - rxjs "^6.5.2" - text-encoding-utf-8 "^1.0.2" - uri-js "^4.2.2" - -neo4j-driver@^4.2.2: +neo4j-driver@^4.0.1, neo4j-driver@^4.0.2, neo4j-driver@^4.2.2: version "4.4.7" resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-4.4.7.tgz#51b3fb48241e66eb3be94e90032cc494c44e59f3" integrity sha512-N7GddPhp12gVJe4eB84u5ik5SmrtRv8nH3rK47Qy7IUKnJkVEos/F1QjOJN6zt1jLnDXwDcGzCKK8XklYpzogw== @@ -8067,10 +7806,10 @@ neo4j-graphql-js@^2.11.5: lodash "^4.17.15" neo4j-driver "^4.0.1" -neode@^0.4.8: - version "0.4.8" - resolved "https://registry.yarnpkg.com/neode/-/neode-0.4.8.tgz#0889b4fc7f1bf0b470b01fa5b8870373b5d47ad6" - integrity sha512-pb91NfCOg4Fj5o+98H+S2XYC+ByQfbdhwcc1UVuzuUQ0Ezzj+jWz8NmKWU8ZfCH6l4plk71yDAPd2eTwpt+Xvg== +neode@^0.4.9: + version "0.4.9" + resolved "https://registry.yarnpkg.com/neode/-/neode-0.4.9.tgz#11c46c50d0348751dc6db828f3ca59252e7c247f" + integrity sha512-3RufLD2cmTXrPpvsgkEAqS3maRjXJ89vjbyYmyqJMJl5uv6gcUa32N6hRwHcqfjWRWUaFKaoGLEJLaOQobs4eA== dependencies: "@hapi/joi" "^15.1.1" dotenv "^4.0.0" @@ -8102,11 +7841,6 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" -nocache@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" - integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== - node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -8244,11 +7978,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" - integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== - normalize-url@^6.0.1, normalize-url@~6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" @@ -8272,21 +8001,6 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-run-all@~4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" - integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== - dependencies: - ansi-styles "^3.2.1" - chalk "^2.4.1" - cross-spawn "^6.0.5" - memorystream "^0.3.1" - minimatch "^3.0.4" - pidtree "^0.3.0" - read-pkg "^3.0.0" - shell-quote "^1.6.1" - string.prototype.padend "^3.0.0" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -8340,15 +8054,10 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -numeral@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/numeral/-/numeral-2.0.6.tgz#4ad080936d443c2561aed9f2197efffe25f4e506" - integrity sha1-StCAk21EPCVhrtnyGX7//iX05QY= - -nwsapi@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" - integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== +nwsapi@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.4.tgz#fd59d5e904e8e1f03c25a7d5a15cfa16c714a1e5" + integrity sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g== oauth-sign@~0.9.0: version "0.9.0" @@ -8467,7 +8176,7 @@ optimism@^0.10.0: dependencies: "@wry/context" "^0.4.0" -optionator@^0.8.1, optionator@^0.8.3: +optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -8497,11 +8206,6 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - p-cancelable@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" @@ -8621,14 +8325,6 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -8669,7 +8365,7 @@ parse5@^3.0.1: dependencies: "@types/node" "*" -parse5@^7.0.0, parse5@^7.1.1: +parse5@^7.0.0, parse5@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== @@ -8746,13 +8442,6 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -8778,11 +8467,6 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidtree@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" - integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg== - pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -8855,11 +8539,6 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -8977,7 +8656,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== @@ -8987,11 +8666,6 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -qs@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.8.0.tgz#87b763f0d37ca54200334cd57bb2ef8f68a1d081" - integrity sha512-tPSkj8y92PfZVbinY1n84i1Qdx75lZjMQYx9WZhnkofyxzw2r7Ho39G3/aEvSUdebxpnnM4LZJCtvE/Aq3+s9w== - qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -9100,16 +8774,7 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.5: +readable-stream@^2.0.2, readable-stream@^2.0.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -9178,11 +8843,6 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -referrer-policy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.2.0.tgz#b99cfb8b57090dc454895ef897a4cc35ef67a98e" - integrity sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA== - regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -9316,23 +8976,7 @@ repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== - dependencies: - lodash "^4.17.15" - -request-promise-native@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" - integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== - dependencies: - request-promise-core "1.1.3" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.88.0, request@~2.88.2: +request@~2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -9416,13 +9060,6 @@ resolve@^1.20.0, resolve@^1.3.2: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - responselike@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" @@ -9479,6 +9116,11 @@ rosie@^2.0.1: resolved "https://registry.yarnpkg.com/rosie/-/rosie-2.0.1.tgz#c250c4787ce450b72aa9eff26509f68589814fa2" integrity sha1-wlDEeHzkULcqqe/yZQn2hYmBT6I= +rrweb-cssom@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" + integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw== + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -9496,7 +9138,7 @@ run-parallel@^1.1.9: resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== -rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.5.4: +rxjs@^6.4.0: version "6.5.4" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== @@ -9715,11 +9357,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.6.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.1.tgz#3161d969886fb14f9140c65245a5dd19b6f0b06b" - integrity sha512-2kUqeAGnMAu6YrTPX4E3LfxacH9gKljzVjlkUeSqY0soGwK4KLl7TURXCem712tkhBCeeaFP9QK4dKn88s3Icg== - signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -9865,7 +9502,7 @@ source-map@^0.5.0, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -9994,11 +9631,6 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== - streamsearch@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" @@ -10052,15 +9684,6 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.padend@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" - integrity sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.4.3" - function-bind "^1.0.2" - string.prototype.trimend@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" @@ -10181,30 +9804,6 @@ subscriptions-transport-ws@^0.9.11, subscriptions-transport-ws@^0.9.16, subscrip symbol-observable "^1.0.4" ws "^5.2.0 || ^6.0.0 || ^7.0.0" -superagent@^3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" - integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== - dependencies: - component-emitter "^1.2.0" - cookiejar "^2.1.0" - debug "^3.1.0" - extend "^3.0.0" - form-data "^2.3.1" - formidable "^1.2.0" - methods "^1.1.1" - mime "^1.4.1" - qs "^6.5.1" - readable-stream "^2.3.5" - -supertest@~4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-4.0.2.tgz#c2234dbdd6dc79b6f15b99c8d6577b90e4ce3f36" - integrity sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ== - dependencies: - methods "^1.1.2" - superagent "^3.8.3" - supports-color@^4.0.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" @@ -10311,11 +9910,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-encoding-utf-8@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -10378,17 +9972,17 @@ tlds@^1.228.0: resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.236.0.tgz#a118eebe33261c577e3a3025144faeabb7dd813c" integrity sha512-oP2PZ3KeGlgpHgsEfrtva3/K9kzsJUNliQSbCfrJ7JMCWFoCdtG+9YMq/g2AnADQ1v5tVlbtvKJZ4KLpy/P6MA== -tldts-core@^5.7.104: - version "5.7.104" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-5.7.104.tgz#4313a9663e4085332750a5fb04bfa0b0d91b826d" - integrity sha512-8vhSgc2nzPNT0J7XyCqcOtQ6+ySBn+gsPmj5h95YytIZ7L2Xl40paUmj0T6Uko42HegHGQxXieunHIQuABWSmQ== +tldts-core@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.0.3.tgz#b59d87507c51cd2488c322b92020b973b608b59a" + integrity sha512-PLiEM2aCkfGifyr8npbd93eWIW4isFRB44vTiup5DRie6e2Qy3+9quwHb252v12JyoM+RmF1cxtDgwD2PVBOjA== -tldts@~5.7.103: - version "5.7.104" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-5.7.104.tgz#c964cf8a194936b086fa4c72994e92d4cd4d2562" - integrity sha512-PlziEIVPH/ogbqOhS35K6MOeD09rd9U5g2NHO5n9NZeMC1PGpXgsjQpoJ1KiRnjhZsWDkzN8EoX3xQZuz5ZyFQ== +tldts@~6.0.1: + version "6.0.3" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.0.3.tgz#6a4a8bb550f396d6d72818606150e0e0263ae826" + integrity sha512-rcdUIwrcGuMWe5+fg5FFBrmWTYdbfpHwkk1AjBKoSDbpsdAsYqJYKoZOVOHn8MQCYatADKGAx/SU+jpSKxSYNw== dependencies: - tldts-core "^5.7.104" + tldts-core "^6.0.3" tmp@^0.0.33: version "0.0.33" @@ -10414,11 +10008,6 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -10461,14 +10050,6 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@^2.3.3, tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - tough-cookie@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" @@ -10479,13 +10060,21 @@ tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" -tr46@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" - integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: + psl "^1.1.28" punycode "^2.1.1" +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== + dependencies: + punycode "^2.3.0" + trigram-utils@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/trigram-utils/-/trigram-utils-1.0.2.tgz#47574b7fade636e0fc06515788cbbd61786d2292" @@ -10526,6 +10115,25 @@ ts-invariant@^0.4.0: dependencies: tslib "^1.9.3" +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tslib@1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" @@ -10595,6 +10203,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typescript@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + undefsafe@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" @@ -10749,13 +10362,6 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" @@ -10845,6 +10451,11 @@ uuid@^8.0.0, uuid@~8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-compile-cache@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" @@ -10874,10 +10485,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.0.0.tgz#0fb6c6bb5218ea23d368a8347e6d0f5a70e3bcab" - integrity sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA== +validator@^13.9.0: + version "13.9.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" + integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA== vary@^1, vary@~1.1.2: version "1.1.2" @@ -10910,18 +10521,6 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" -wait-on@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-4.0.1.tgz#c49ca18b1ea60580404feed9df76ab3af2425a56" - integrity sha512-x83fmTH2X0KL7vXoGt9aV5x4SMCvO8A/NbwWpaYYh4NJ16d3KSgbHwBy9dVdHj0B30cEhOFRvDob4fnpUmZxvA== - dependencies: - "@hapi/joi" "^17.1.0" - lodash "^4.17.15" - minimist "^1.2.0" - request "^2.88.0" - request-promise-native "^1.0.8" - rxjs "^6.5.4" - walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -10946,12 +10545,12 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== -whatwg-url@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" - integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== +whatwg-url@^12.0.0, whatwg-url@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-12.0.1.tgz#fd7bcc71192e7c3a2a97b9a8d6b094853ed8773c" + integrity sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ== dependencies: - tr46 "^3.0.0" + tr46 "^4.1.1" webidl-conversions "^7.0.0" which@^1.2.9: @@ -11062,15 +10661,10 @@ ws@^6.0.0: dependencies: async-limiter "~1.0.0" -ws@^8.11.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" - integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== - -x-xss-protection@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c" - integrity sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg== +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== xdg-basedir@^3.0.0: version "3.0.0" @@ -11082,7 +10676,7 @@ xml-name-validator@^4.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== -xml2js@0.4.19, xml2js@^0.4.17: +xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== @@ -11163,6 +10757,11 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" diff --git a/deployment/README.deployment.md b/deployment/README.deployment.md index 5335c11ad..f085b48d0 100644 --- a/deployment/README.deployment.md +++ b/deployment/README.deployment.md @@ -17,7 +17,62 @@ You have the following options for a deployment: After the first deployment of the new network on your server, the database is initialized with the default administrator: -- E-mail: admin@example.org -- Password: 1234 +- E-mail: `admin@example.org` +- Password: `1234` ***ATTENTION:*** When you are logged in for the first time, please change your (the admin's) e-mail to an existing one and change your password to a secure one !!! + +## Use the Scripts + +To use all the scripts you have to set the variable `CONFIGURATION` in your terminal by entering: + +```bash +# in deployment folder + +# set configuration name to folder name in 'configurations' folder (network name) +$ export CONFIGURATION=`` +# to check this +$ echo $CONFIGURATION +``` + +### Secrets Encrypt/Decrypt + +To encrypt and decrypt the secrets of your network in your terminal set a correct password in a (new) file `configurations//SECRET`. +If done please enter: + +```bash +# in deployment folder + +# encrypt secrets +$ scripts/secrets.encrypt.sh + +# decrypt secrets +$ scripts/secrets.decrypt.sh +``` + +### Maintenance Mode On/Off + +Activate or deactivate maintenance mode in your terminal: + +```bash +# in deployment folder + +# activate maintenance mode +$ scripts/cluster.maintenance.sh on + +# deactivate maintenance mode +$ scripts/cluster.maintenance.sh off +``` + +### Backup Script + +To save a locale backup of the database and uploaded images: + +```bash +# in deployment folder + +# save backup +$ scripts/cluster.backup.sh +``` + +The backup will be saved into your network folders `backup` folder in a new folder with the date and time. diff --git a/deployment/TODO-next-update.md b/deployment/TODO-next-update.md index 769fe4d67..8630275b7 100644 --- a/deployment/TODO-next-update.md +++ b/deployment/TODO-next-update.md @@ -2,7 +2,9 @@ When you overtake this deploy and rebrand repo to your network you have to recognize the following changes and doings: -## Version >= 2.4.0 with 'ocelotDockerVersionTag' 2.4.0-XXX +## Version >= 2.4.0 with 'ocelotDockerVersionTag' 2.4.0-298 + +- You have to set `SHOW_CONTENT_FILTER_HEADER_MENU` and `SHOW_CONTENT_FILTER_MASONRY_GRID` in `branding/constants/filter.js` originally in main code file `webapp/constants/filter.js` to your preferred value. ### Main Code PR – feat(webapp): map #5843 diff --git a/deployment/configurations/example/branding/README.md b/deployment/configurations/example/branding/README.md deleted file mode 100644 index dd2a3b1fc..000000000 --- a/deployment/configurations/example/branding/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Configure And Branding - -In this folder you will find all configuration files and logo images to customise the configuration and branding of the [ocelot.social](https://github.com/Ocelot-Social-Community/Ocelot-Social) network code to your own needs. - -Please change these and they will be used automatically as part of the [deployment](/deployment/README.md) process. diff --git a/deployment/configurations/example/branding/assets/fonts/.gitkeep b/deployment/configurations/example/branding/assets/fonts/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/deployment/configurations/example/branding/assets/styles/imports/_branding.scss b/deployment/configurations/example/branding/assets/styles/imports/_branding.scss deleted file mode 100644 index 75058595d..000000000 --- a/deployment/configurations/example/branding/assets/styles/imports/_branding.scss +++ /dev/null @@ -1,5 +0,0 @@ -/* - * - * Here, all SCSS variables and classes can be adapted to your custom design. - * -*/ \ No newline at end of file diff --git a/deployment/configurations/example/branding/constants/donation.js b/deployment/configurations/example/branding/constants/donation.js deleted file mode 100644 index 3e36ae9a8..000000000 --- a/deployment/configurations/example/branding/constants/donation.js +++ /dev/null @@ -1 +0,0 @@ -export const PROGRESS_BAR_COLOR_TYPE = 'gradient' // 'uni' is the other option diff --git a/deployment/configurations/example/branding/constants/emails.js b/deployment/configurations/example/branding/constants/emails.js deleted file mode 100644 index f5bd9a4a6..000000000 --- a/deployment/configurations/example/branding/constants/emails.js +++ /dev/null @@ -1,8 +0,0 @@ -// this file is duplicated in `backend/src/config/` and `webapp/constants/` and replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/constants/ -export default { - SUPPORT_EMAIL: 'hello@ocelot.social', - MODERATION_EMAIL: 'hello@ocelot.social', - // ATTENTION: the following links have to be defined even for internal pages with full URLs as example like 'https://staging.ocelot.social/support', because they are used in e-mails! - ORGANIZATION_LINK: 'https://ocelot.social', - SUPPORT_LINK: 'https://ocelot.social', -} diff --git a/deployment/configurations/example/branding/constants/groups.js b/deployment/configurations/example/branding/constants/groups.js deleted file mode 100644 index 1c49d3ff3..000000000 --- a/deployment/configurations/example/branding/constants/groups.js +++ /dev/null @@ -1,5 +0,0 @@ -// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js` -export const NAME_LENGTH_MIN = 3 -export const NAME_LENGTH_MAX = 50 -export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 100 // with removed HTML tags -export const SHOW_GROUP_BUTTON_IN_HEADER = true diff --git a/deployment/configurations/example/branding/constants/headerMenu.js b/deployment/configurations/example/branding/constants/headerMenu.js deleted file mode 100644 index aa87a598c..000000000 --- a/deployment/configurations/example/branding/constants/headerMenu.js +++ /dev/null @@ -1,13 +0,0 @@ -export default { - MENU: [ - // { - // nameIdent: 'nameIdent', - // path: '/', - // }, - // { - // nameIdent: 'nameIdent', - // url: 'https://ocelot.social', - // target: '_blank', - // }, - ], -} diff --git a/deployment/configurations/example/branding/constants/links.js b/deployment/configurations/example/branding/constants/links.js deleted file mode 100644 index 7efac159f..000000000 --- a/deployment/configurations/example/branding/constants/links.js +++ /dev/null @@ -1,152 +0,0 @@ -// this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/constants/ - -import { defaultPageParamsPages } from '~/components/utils/InternalPages.js' - -const ORGANIZATION = defaultPageParamsPages.ORGANIZATION.overwrite({ - // if defined it's dominating - externalLink: { - url: 'https://ocelot.social', - target: '_blank', - }, - - internalPage: { - // footerIdent: 'site.made', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.made', // localized string identifier, if undefined default is used - // headlineIdent: 'site.made', // localized string identifier, on null it's hidden, if undefined default is used - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const DONATE = defaultPageParamsPages.DONATE.overwrite({ - // if defined it's dominating - externalLink: { - // we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly - url: 'https://ocelot-social.herokuapp.com/donations', - target: '_blank', - }, - - internalPage: { - // footerIdent: 'site.donate', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.donate', // localized string identifier, if undefined default is used - // headlineIdent: 'site.donate', // localized string identifier, on null it's hidden, if undefined default is used - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const IMPRINT = defaultPageParamsPages.IMPRINT.overwrite({ - // if defined it's dominating - externalLink: { - // we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly - url: 'https://ocelot-social.herokuapp.com/imprint', - target: '_blank', - }, - - internalPage: { - // footerIdent: 'site.imprint', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.imprint', // localized string identifier, if undefined default is used - // headlineIdent: 'site.imprint', // localized string identifier, on null it's hidden, if undefined default is used - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const TERMS_AND_CONDITIONS = defaultPageParamsPages.TERMS_AND_CONDITIONS.overwrite({ - // externalLink: null, // if defined it's dominating - - internalPage: { - // footerIdent: 'site.termsAndConditions', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.termsAndConditions', // localized string identifier, if undefined default is used - // headlineIdent: 'site.termsAndConditions', // localized string identifier, on null it's hidden, if undefined default is used - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const CODE_OF_CONDUCT = defaultPageParamsPages.CODE_OF_CONDUCT.overwrite({ - // externalLink: null, // if defined it's dominating - - internalPage: { - // footerIdent: 'site.code-of-conduct', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.code-of-conduct', // localized string identifier, if undefined default is used - // headlineIdent: 'site.code-of-conduct', // localized string identifier, on null it's hidden, if undefined default is used - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const DATA_PRIVACY = defaultPageParamsPages.DATA_PRIVACY.overwrite({ - // externalLink: null, // if defined it's dominating - - internalPage: { - // footerIdent: 'site.data-privacy', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.data-privacy', // localized string identifier, if undefined default is used - // headlineIdent: 'site.data-privacy', // localized string identifier, on null it's hidden, if undefined default is used - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const FAQ = defaultPageParamsPages.FAQ.overwrite({ - // externalLink: null, // if defined it's dominating - - internalPage: { - // footerIdent: 'site.faq', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.faq', // localized string identifier, if undefined default is used - // headlineIdent: 'site.faq', // on null default is used, on empty string it's hidden - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) -const SUPPORT = defaultPageParamsPages.SUPPORT.overwrite({ - // if defined it's dominating - externalLink: { - url: 'https://ocelot.social', - target: '_blank', - }, - - internalPage: { - // footerIdent: 'site.support', // localized string identifier, if undefined default is used - // headTitleIdent: 'site.support', // localized string identifier, if undefined default is used - // headlineIdent: 'site.support', // on null default is used, on empty string it's hidden - hasContainer: true, - hasBaseCard: true, - hasLoginInHeader: true, - // in case internal page content is here 'branding/locales/html/' - }, -}) - -export default { - LANDING_PAGE: '/login', // examples: '/login', '/registration', '/organization', or external 'https://ocelot.social' - - // you can find and store templates for 👇🏼 at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ - - ORGANIZATION, - DONATE, - IMPRINT, - TERMS_AND_CONDITIONS, - CODE_OF_CONDUCT, - DATA_PRIVACY, - FAQ, - SUPPORT, - - FOOTER_LINK_LIST: [ - ORGANIZATION, - TERMS_AND_CONDITIONS, - CODE_OF_CONDUCT, - DATA_PRIVACY, - FAQ, - DONATE, - IMPRINT, - SUPPORT, - ], -} diff --git a/deployment/configurations/example/branding/constants/logos.js b/deployment/configurations/example/branding/constants/logos.js deleted file mode 100644 index 714e78a2c..000000000 --- a/deployment/configurations/example/branding/constants/logos.js +++ /dev/null @@ -1,24 +0,0 @@ -// this file is duplicated in `backend/src/config/logos.js` and `webapp/constants/logos.js` and replaced on rebranding -// this are the paths in the webapp -export default { - LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg', - LOGO_HEADER_WIDTH: '130px', - LOGO_HEADER_CLICK: { - // externalLink: { - // url: 'https://ocelot.social', - // target: '_blank', - // }, - externalLink: null, - internalPath: { - to: { - name: 'index', - }, - scrollTo: '.main-navigation', - }, - }, - LOGO_SIGNUP_PATH: '/img/custom/logo-squared.svg', - LOGO_WELCOME_PATH: '/img/custom/logo-squared.svg', - LOGO_LOGOUT_PATH: '/img/custom/logo-squared.svg', - LOGO_PASSWORD_RESET_PATH: '/img/custom/logo-squared.svg', - LOGO_MAINTENACE_RESET_PATH: '/img/custom/logo-squared.svg', -} diff --git a/deployment/configurations/example/branding/constants/metadata.js b/deployment/configurations/example/branding/constants/metadata.js deleted file mode 100644 index 3d09066d5..000000000 --- a/deployment/configurations/example/branding/constants/metadata.js +++ /dev/null @@ -1,9 +0,0 @@ -// this file is duplicated in `backend/src/config/metadata.js` and `webapp/constants/metadata.js` and replaced on rebranding -export default { - APPLICATION_NAME: 'ocelot.social', - APPLICATION_SHORT_NAME: 'ocelot.social', - APPLICATION_DESCRIPTION: 'Ocelot Social Community', - COOKIE_NAME: 'ocelot-social-token', - ORGANIZATION_NAME: 'busFaktor e.V.', - ORGANIZATION_JURISDICTION: 'Deutschland', -} diff --git a/deployment/configurations/example/branding/email/.gitkeep b/deployment/configurations/example/branding/email/.gitkeep deleted file mode 100644 index afe8c26c9..000000000 --- a/deployment/configurations/example/branding/email/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -we can put multilanguage e-mails and a layout.html in here \ No newline at end of file diff --git a/deployment/configurations/example/branding/email/templates/de/.gitkeep b/deployment/configurations/example/branding/email/templates/de/.gitkeep deleted file mode 100644 index 5b414a0c8..000000000 --- a/deployment/configurations/example/branding/email/templates/de/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -we can put translated e-mails in here \ No newline at end of file diff --git a/deployment/configurations/example/branding/email/templates/en/.gitkeep b/deployment/configurations/example/branding/email/templates/en/.gitkeep deleted file mode 100644 index 5b414a0c8..000000000 --- a/deployment/configurations/example/branding/email/templates/en/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -we can put translated e-mails in here \ No newline at end of file diff --git a/deployment/configurations/example/branding/locales/de.json b/deployment/configurations/example/branding/locales/de.json deleted file mode 100644 index 2c63c0851..000000000 --- a/deployment/configurations/example/branding/locales/de.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/deployment/configurations/example/branding/locales/en.json b/deployment/configurations/example/branding/locales/en.json deleted file mode 100644 index 2c63c0851..000000000 --- a/deployment/configurations/example/branding/locales/en.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/deployment/configurations/example/branding/locales/html/de/code-of-conduct.html b/deployment/configurations/example/branding/locales/html/de/code-of-conduct.html deleted file mode 100644 index c4538e37d..000000000 --- a/deployment/configurations/example/branding/locales/html/de/code-of-conduct.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Präambel -

-

- Ich bin der Inhalt vom Verhaltenskodex. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/data-privacy.html b/deployment/configurations/example/branding/locales/html/de/data-privacy.html deleted file mode 100644 index 104d18300..000000000 --- a/deployment/configurations/example/branding/locales/html/de/data-privacy.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Information über die Erhebung personenbezogener Daten -

-

- Das hier wäre der Inhalt der Datenschutzbestimmungen. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/donate.html b/deployment/configurations/example/branding/locales/html/de/donate.html deleted file mode 100644 index 71f1027ef..000000000 --- a/deployment/configurations/example/branding/locales/html/de/donate.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Wohin kann ich spenden? -

-

- Hier steht was zu den Spenden. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/faq.html b/deployment/configurations/example/branding/locales/html/de/faq.html deleted file mode 100644 index 15a9d976d..000000000 --- a/deployment/configurations/example/branding/locales/html/de/faq.html +++ /dev/null @@ -1,67 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Wie bediene ich dieses Netzwerk? -

-

- Hier findest Du die - Bedienungsanleitung.
-

-

- Betreiberspezifische FAQs -

-

- Hier steht was zu den betreiberspezifischen FAQs. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/imprint.html b/deployment/configurations/example/branding/locales/html/de/imprint.html deleted file mode 100644 index ad3c93562..000000000 --- a/deployment/configurations/example/branding/locales/html/de/imprint.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Betreiber -

-

- Ich bin das Impressum. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/organization.html b/deployment/configurations/example/branding/locales/html/de/organization.html deleted file mode 100644 index 089d72fa4..000000000 --- a/deployment/configurations/example/branding/locales/html/de/organization.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Das Entwicklernetzwerk -

-

- Hier wird das Netzwerk beschrieben. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/support.html b/deployment/configurations/example/branding/locales/html/de/support.html deleted file mode 100644 index f4dcb537e..000000000 --- a/deployment/configurations/example/branding/locales/html/de/support.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Ansprechpartner -

-

- Ich bin der Inhalt vom Support. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/de/terms-and-conditions.html b/deployment/configurations/example/branding/locales/html/de/terms-and-conditions.html deleted file mode 100644 index 74057ada1..000000000 --- a/deployment/configurations/example/branding/locales/html/de/terms-and-conditions.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - -
-

- Für das soziale Netzwerk Ocelot.Social Staging -

-

- Nutzung und Lizenz -

-

- Ich bin der Inhalt der Seite "Nutzungsbedingungen". -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/code-of-conduct.html b/deployment/configurations/example/branding/locales/html/en/code-of-conduct.html deleted file mode 100644 index 714cad330..000000000 --- a/deployment/configurations/example/branding/locales/html/en/code-of-conduct.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- Präambel -

-

- I am the content of the code of conduct. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/data-privacy.html b/deployment/configurations/example/branding/locales/html/en/data-privacy.html deleted file mode 100644 index c4b718fe0..000000000 --- a/deployment/configurations/example/branding/locales/html/en/data-privacy.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- Information about the collection of personal data -

-

- This would be our data privacy section. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/donate.html b/deployment/configurations/example/branding/locales/html/en/donate.html deleted file mode 100644 index d25e9f419..000000000 --- a/deployment/configurations/example/branding/locales/html/en/donate.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- Where can I donate? -

-

- Here's what it says about donations. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/faq.html b/deployment/configurations/example/branding/locales/html/en/faq.html deleted file mode 100644 index a5998db78..000000000 --- a/deployment/configurations/example/branding/locales/html/en/faq.html +++ /dev/null @@ -1,67 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- How do I operate this network? -

-

- Here you can find the - user manual.
-

-

- Operator-Specific FAQs -

-

- Here are the operator-specific FAQs. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/imprint.html b/deployment/configurations/example/branding/locales/html/en/imprint.html deleted file mode 100644 index 6a7489a06..000000000 --- a/deployment/configurations/example/branding/locales/html/en/imprint.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- Operator -

-

- I am the imprint. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/organization.html b/deployment/configurations/example/branding/locales/html/en/organization.html deleted file mode 100644 index e5a6d0f93..000000000 --- a/deployment/configurations/example/branding/locales/html/en/organization.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- The Developers Network -

-

- Here the network is described. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/support.html b/deployment/configurations/example/branding/locales/html/en/support.html deleted file mode 100644 index 118328b06..000000000 --- a/deployment/configurations/example/branding/locales/html/en/support.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- Contact -

-

- I am the content of the support. -

-
- - diff --git a/deployment/configurations/example/branding/locales/html/en/terms-and-conditions.html b/deployment/configurations/example/branding/locales/html/en/terms-and-conditions.html deleted file mode 100644 index 44e3fe3cd..000000000 --- a/deployment/configurations/example/branding/locales/html/en/terms-and-conditions.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -
-

- For the social network Ocelot.Social Staging -

-

- Use and License -

-

- I am the content of the page "Terms And Conditions". -

-
- - diff --git a/deployment/configurations/example/branding/static/favicon.ico b/deployment/configurations/example/branding/static/favicon.ico deleted file mode 100644 index 430cef437..000000000 Binary files a/deployment/configurations/example/branding/static/favicon.ico and /dev/null differ diff --git a/deployment/configurations/example/branding/static/icon.png b/deployment/configurations/example/branding/static/icon.png deleted file mode 100644 index 1c81fa5fc..000000000 Binary files a/deployment/configurations/example/branding/static/icon.png and /dev/null differ diff --git a/deployment/configurations/example/branding/static/img/custom/logo-horizontal.svg b/deployment/configurations/example/branding/static/img/custom/logo-horizontal.svg deleted file mode 100644 index d821c8329..000000000 --- a/deployment/configurations/example/branding/static/img/custom/logo-horizontal.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/deployment/configurations/example/branding/static/img/custom/logo-squared.svg b/deployment/configurations/example/branding/static/img/custom/logo-squared.svg deleted file mode 100644 index 15f420c79..000000000 --- a/deployment/configurations/example/branding/static/img/custom/logo-squared.svg +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/deployment/configurations/example/branding/templates/locales/html/general/de/faq.html b/deployment/configurations/example/branding/templates/locales/html/general/de/faq.html deleted file mode 100644 index b06c7e039..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/general/de/faq.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - -
-

- Für das soziale Netzwerk {{ organization }} -

-

- Wie bediene ich dieses Netzwerk? -

-

- Hier findest Du die - Bedienungsanleitung.
-

-
- - diff --git a/deployment/configurations/example/branding/templates/locales/html/general/en/faq.html b/deployment/configurations/example/branding/templates/locales/html/general/en/faq.html deleted file mode 100644 index 4a01a4540..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/general/en/faq.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - -
-

- For the social network of {{ organization }} -

-

- How do I operate this network? -

-

- Here you can find the - user manual.
-

-
- - diff --git a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/code-of-conduct.html b/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/code-of-conduct.html deleted file mode 100644 index f0fd19a4f..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/code-of-conduct.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - -
-

- Für das soziale Netzwerk {{ organization }} -

-

- Präambel -

-

- {{ networkName}} ist ein gemeinnütziges soziales Wissens- und Aktionsnetzwerk der nächsten Generation. - Von Menschen – für Menschen. - Free-Software, Open-Source, fair und transparent. - Für positiven lokalen und globalen Wandel in allen Lebensbereichen. - Wir gestalten den öffentlichen Austausch von Wissen, Ideen und Projekten völlig neu. - Die Funktionen von {{ networkName }} bringen die Menschen zusammen – offline und online – so dass wir die Welt zu einem besseren Ort machen können.
-

-

- Zweck -

-

- Mit diesen Verhaltensregeln regeln wir die wesentlichen Grundsätze für das Verhalten in unserem Sozialen Netzwerk. - Dabei ist die Menschenrechtscharta der Vereinten Nationen unsere Orientierung und bildet das Herz unseres Werteverständnisses. - Die Verhaltensregeln dienen als Leitsätze für den persönlichen Auftritt und den Umgang untereinander. - Wer als Nutzer im {{ networkName }} Netzwerk aktiv ist, Beiträge verfasst, kommentiert oder mit anderen Nutzern, auch außerhalb des Netzwerkes, Kontakt aufnimmt, erkennt diese Verhaltensregeln als verbindlich an.
-

-

- Erwartetes Verhalten -

-

- Die folgenden Verhaltensweisen werden von allen Community-Mitgliedern erwartet und gefordert:
-

-
    -
  • - Sei rücksichtsvoll und respektvoll, bei dem, was Du schreibst und tust. -
  • -
  • - Versuche auf andere zuzugehen, bevor ein Konflikt entsteht. -
  • -
  • - Vermeide erniedrigende, diskriminierende oder belästigende Verhaltensweisen und Ausdrücke. -
  • -
  • - Achte Dein Umfeld und Deine Mitmenschen. Warne die Verantwortlichen der Community, falls Du eine gefährliche Situation, jemanden in Not oder Verstöße gegen diesen Verhaltenskodex bemerkst, auch wenn diese unbedeutend erscheinen. -
  • -
-

- Nichtakzeptables Verhalten -

-

- Die folgenden Verhaltensweisen sind in unserer Community inakzeptabel:
-

-
    -
  • - Diskriminierende Beiträge, Kommentare, Äußerungen oder Beleidigungen, insbesondere solche, die sich auf Geschlecht, sexuelle Orientierung, Rasse, Religion, politische oder weltanschauliche Ausrichtung oder Behinderung beziehen -
  • -
  • - Das Senden oder Verlinken eindeutig pornografischen Materials -
  • -
  • - Verherrlichung oder Verharmlosung grausamer oder unmenschlicher Gewalttätigkeiten -
  • -
  • - Das Veröffentlichen von personenbezogenen Daten anderer ohne deren Einverständnis oder das Androhen dessen („Doxing“) -
  • -
  • - Absichtliche Einschüchterung, Stalking oder Verfolgung -
  • -
  • - Bewerben von Produkten und Dienstleistungen mit kommerzieller Absicht -
  • -
  • - Strafbares Verhalten bzw. Verstoß gegen deutsches Recht -
  • -
  • - Befürworten oder Ermutigen zu diesen Verhaltensweisen -
  • -
-

- Konsequenzen inakzeptablen Verhaltens -

-

- Wenn ein Gemeinschaftsmitglied inakzeptables Verhalten an den Tag legt, können die verantwortlichen Betreiber, Moderatoren und Administratoren des Netzwerks angemessene Maßnahmen ergreifen, u.a.:
-

-
    -
  • - Auffordern zum sofortigen Abstellen des inakzeptablen Verhaltens -
  • -
  • - Sperren oder Löschen von Kommentaren -
  • -
  • - Vorübergehender Ausschluss aus dem jeweiligen Beitrag -
  • -
  • - Sperren bzw. Löschen von Inhalten -
  • -
  • - Vorübergehender Entzug von Schreibrechten -
  • -
  • - Vorübergehender Ausschluss aus dem Netzwerk -
  • -
  • - Endgültiger Ausschluss aus dem Netzwerk -
  • -
  • - Verstöße gegen deutsches Recht können zur Anzeige gebracht werden. -
  • -
-

- Wenn Du einem inakzeptablen Verhalten ausgesetzt bist, es miterlebst oder andere Bedenken hast, melde bitte so schnell wie möglich den oder die entsprechenden Inhalte an die Moderatoren. - Bitte klicke beim Beitrag, Kommentar oder Benutzer auf die drei Punkte und melde ihn über das aufgeklappte Menü.
-

-
- - diff --git a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/data-privacy.html b/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/data-privacy.html deleted file mode 100644 index 9109840fd..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/data-privacy.html +++ /dev/null @@ -1,1010 +0,0 @@ - - - - -
-

- Für das soziale Netzwerk {{ organization }} -

-

- Information über die Erhebung personenbezogener Daten -

-

- Wir freuen uns, dass Du unsere Website besuchst und bedanken uns für Dein Interesse. - Im Folgenden informieren wir Dich über den Umgang mit Deinen personenbezogenen Daten bei Nutzung unserer Website, unsere Netzwerkes oder der Uhr des Wandels. - Diese Website nutzt aus Sicherheitsgründen und zum Schutz der Übertragung personenbezogene Daten und anderer vertraulicher Inhalte (z.B. Bestellungen oder Anfragen an den Verantwortlichen) eine SSL-bzw. TLS-Verschlüsselung. - Du kannst eine verschlüsselte Verbindung an der Zeichenfolge „https://“ und dem Schloss-Symbol in Deiner Browserzeile erkennen.
-

-

- Kontaktdaten des Verantwortlichen -

-

- Verantwortlich für die Datenverarbeitung auf dieser Website im Sinne der Datenschutz-Grundverordnung (DSGVO) ist
-

-

- {{ organization }}
- Musterstraße 11
- 53487 Musterort
- Deutschland
-

-

- Tel.: +49 151 / 43 80 42 22
- E-Mail: info@example.org
-

-

- Datenschutzbeauftragter -

-

- Unser Datenschutzbeauftragter ist erreichbar unter folgender E-Mail-Adresse: datenschutz@@example.org
-

-

- Diese Website nutzt aus Sicherheitsgründen und zum Schutz der Übertragung personenbezogene Daten und anderer vertraulicher Inhalte (z.B. Bestellungen oder Anfragen an den Verantwortlichen) eine SSL-bzw. TLS-Verschlüsselung. Du kannst eine verschlüsselte Verbindung an der Zeichenfolge „https://“ und dem Schloss-Symbol in Deiner Browserzeile erkennen.
-

-

- Datenerfassung beim Besuch unserer Website -

-

- Bei der bloß informatorischen Nutzung unserer Website, also wenn Du Dich nicht registrierst oder uns anderweitig Informationen übermittelst, erheben wir nur solche Daten, die Dein Browser an unseren Server übermittelt (sog. „Server-Logfiles“). Wenn Du unsere Website aufrufst, erheben wir die folgenden Daten, die für uns technisch erforderlich sind, um Dir die Website anzuzeigen:
-

-
    -
  • - unsere besuchte Website -
  • -
  • - Datum und Uhrzeit zum Zeitpunkt des Zugriffes -
  • -
  • - Menge der gesendeten Daten in Byte -
  • -
  • - Quelle/Verweis, von welchem Du auf die Seite gelangst -
  • -
  • - verwendeter Browser -
  • -
  • - verwendetes Betriebssystem -
  • -
  • - verwendete IP-Adresse (ggf.: in anonymisierter Form) -
  • -
-

- Die Verarbeitung erfolgt gemäß Art. 6 Abs. 1 lit. f DSGVO auf Basis unseres berechtigten Interesses an der Verbesserung der Stabilität und Funktionalität unserer Website. Empfänger dieser Daten sind nur wir und unser Provider Netcup, mit welchem wir einen Auftragsverarbeitungsvertrag haben, um Deine Rechte schützen zu können. - Eine Weitergabe oder anderweitige Verwendung der Daten findet nicht statt. - Wir behalten uns allerdings vor, die Server-Logfiles nachträglich zu überprüfen, sollten konkrete Anhaltspunkte auf eine rechtswidrige Nutzung hinweisen.
-

-

- Dauer der Speicherung personenbezogener Daten -

-

- Die Dauer der Speicherung von personenbezogenen Daten bemisst sich anhand der jeweiligen gesetzlichen Aufbewahrungsfrist (z.B. handels- und steuerrechtliche Aufbewahrungsfristen). Nach Ablauf der Frist werden die entsprechenden Daten routinemäßig gelöscht, sofern sie nicht mehr zur Vertragserfüllung oder Vertragsanbahnung erforderlich sind und/oder unsererseits kein berechtigtes Interesse an der Weiterspeicherung fortbesteht.
-

-

- Cookies -

-

- Um den Besuch unserer Website attraktiv zu gestalten und die Nutzung bestimmter Funktionen zu ermöglichen, verwenden wir auf verschiedenen Seiten sogenannte Cookies. Hierbei handelt es sich um kleine Textdateien, die auf Deinem Endgerät abgelegt werden. Einige der von uns verwendeten Cookies werden nach dem Ende der Browser-Sitzung, also nach Schließen Deines Browsers, wieder gelöscht (sog. Sitzungs-Cookies). Andere Cookies verbleiben auf Deinem Endgerät und ermöglichen uns oder unseren Partnerunternehmen (Cookies von Drittanbietern), Deinen Browser beim nächsten Besuch wiederzuerkennen (persistente Cookies). Werden Cookies gesetzt, erheben und verarbeiten diese im individuellen Umfang bestimmte Nutzerinformationen wie Browser- und Standortdaten sowie IP-Adresswerte. Persistente Cookies werden automatisiert nach einer vorgegebenen Dauer gelöscht, die sich je nach Cookie unterscheiden kann.
-

-

- Sofern durch einzelne von uns implementierte Cookies auch personenbezogene Daten verarbeitet werden, erfolgt die Verarbeitung gemäß Art. 6 Abs. 1 lit. f DSGVO zur Wahrung unserer berechtigten Interessen an der bestmöglichen Funktionalität der Website sowie einer kundenfreundlichen und effektiven Ausgestaltung des Seitenbesuchs.
-

-

- Wir arbeiten unter Umständen mit Werbepartnern zusammen, die uns helfen, unser Internetangebot interessanter zu gestalten. Zu diesem Zweck werden für diesen Fall bei Deinem Besuch unserer Website auch Cookies von Partnerunternehmen in Deinem Browser gespeichert (Cookies von Drittanbietern). Wenn wir mit vorbenannten Werbepartnern zusammenarbeiten, wirst Du über den Einsatz derartiger Cookies und den Umfang der jeweils erhobenen Informationen innerhalb der nachstehenden Absätze individuell und gesondert informiert.
-

-

- Bitte beachte, dass Du Deinen Browser so einstellen kannst, dass Du über das Setzen von Cookies informiert wirst und einzeln über deren Annahme entscheiden oder die Annahme von Cookies für bestimmte Fälle oder generell ausschließen kannst. Jeder Browser unterscheidet sich in der Art, wie er die Cookie-Einstellungen verwaltet. Diese ist in dem Hilfemenü jedes Browsers beschrieben, welches Dir erläutert, wie Du Deine Cookie-Einstellungen ändern kannst. Diese findest Du für die jeweiligen Browser unter den folgenden Links:
-

- -

- Bitte beachte auch, dass bei Nichtannahme von Cookies die Funktionalität unserer Website eingeschränkt sein kann.
-

-

- Spendenformular -

-

- Wenn Du unsere Fundraisingbox (Spendenformular) auf unserer Webseite nutzt, dann benötigen wir von Dir folgende personenbezogene Daten: - Deinen Vor- und Nachnamen, Deine E-Mail-Adresse und Deine Bankverbindung mit Kontoinhaber, IBAN und BIC. Solltest Du uns durch eine einfache Überweisung spenden, bekommen wir alle diese Daten auch, bis auf die E-Mail-Adresse. - Wenn Du uns diese in der Überweisung mitteilst, wäre das gut. - Gleichzeitig speichern wir folgende, von Dir eingegebene Daten (Name, E-Mail, Anschrift und Betrag) zur Ausstellung einer Spendenbescheinigung.
-

-

- Deine E-Mail-Adresse und die Höhe deiner Spende wird ebenfalls von uns gespeichert, um später die Möglichkeit zu schaffen, Deine Unterstützung durch eine Spende über eine sogenannte Badge-Anzeige in unserem Netzwerk öffentlich zu honorieren. - Solltest Du uns nicht nur finanziell unterstützen, sondern auch Nutzer unseres Netzwerkes sein, wirst Du nach dem Go-Live unseres Netzwerkes selber entscheiden können, ob diese Badges angezeigt werden sollen, oder nicht. - Dieser Punkt wird, sobald vollständig implementiert, näher in den Datenschutzbedingungen unseres Netzwerkes beschrieben sein.
-

-

- Als gemeinnützige Organisation haben wir ein berechtigtes Interesse gem. Art. 6 Abs. 1 lit. f) DSGVO, unseren Spendern eine einfache und sichere Zahlungsmöglichkeit zu bieten, welches die Rechtsgrundlage für diese Verarbeitung ist. - Der Zweck ist die finanzielle Unterstützung unserer gemeinnützigen Organisation.
-

-

- Die Speicherdauer Deiner Daten beträgt aus steuerrechtlichen Gründen 10 Jahre. - Wir löschen diese Daten spätestens 12 Monate danach.
-

-

- Für unser Spendenformular auf der Webseite nutzen wir den Finanzdienstleister Fundraisingbox, mit welchem wir einen entsprechenden Auftragsdatenverarbeitungsvertrag abgeschlossen haben, um Deine Rechte, wie unten angegegeben, im Zusammenhang mit Deiner Spende auch durchsetzen zu können. - FundraisingBox und wir sind Empfänger dieser Daten.
-

-

- Alle weiteren Finanzdienstleister bzw. Banken, die Du angeben kannst, arbeiten nicht im Auftrag von uns bzw. nach unseren Vorgaben, sondern eigenverantwortlich. - Diese sind, je nachdem, auf welchem Weg Du spendest, die GLS Bank, Paypal, VISA, Klarna, Stripe und Deine Bank, von der Du spendest. - FundraisingBox selber liefert dabei keine personenbezogenen Daten in ein Drittland. - Bei von Dir angegebenen bzw. genutzten Finanzdienstleistern kann dies unter Umständen der Fall sein. - Von den oben angegebenen sind hier die Datenschutzinformationen noch einmal gesondert aufgeführt:
-

- -

- Das Spendenformular ist auf unserer Webseite über einen sogenannten iFrame eingebunden und die Inhalte werden verschlüsselt zu FundraisingBox übertragen. - Dies bedeutet, dass niemand außer Dir und FundraisingBox bei dieser Übertragung Daten zu sehen bekommt. - Zu Fundraisingbox werden entsprechend Daten übertragen, die Dein Webbrowser liefert, also Deine IP-Adresse und, je nachdem, welchen Browser Du nutzt und wie er eingestellt ist, in der Regel Dein Betriebssystem, die Browserversion und einige andere Daten. - Zum Datenschutz von Fundraisingbox kannst Du hier die Details lesen: https://www.fundraisingbox.com/datensicherheit/.
-

-

- Support -

-

- Zweck -

-

- Wir stellen Dir zum Zweck der Problemlösung einen Support zur Verfügung, wenn Du Probleme mit unserem Netzwerk, unserer Webseite oder der Clock-of-Change hast oder generell etwas von und mit uns geklärt haben willst. - Ebenso kannst Du den Support über das Senden einer E-Mail erreichen. - Optional kannst Du, wenn Du Dich bei uns registriert hast, Deine vergangenen Support-Tickets betrachten.
-

-

- Personenbezogene Daten: - Um Dir kommunizieren zu können, benötigen wir von Dir Deine E-Mail-Adresse und einen Namen oder ein Pseudonym, damit wir Dich ansprechen können. - Optional kannst Du uns eine Telefonnummer angeben, unter welcher wir Dich erreichen können, wenn Du das möchtest. - Weitere personenbezogene Daten können im Text Deiner Support-Anfrage enthalten sein.
-

-

- Ebenfalls werden bei Deiner Anfrage, wenn sie über unsere Support-Website stattfindet, Deine IP-Adresse und weitere Daten übertragen, die Dein Browser uns liefert. - Diese Daten werden von uns nicht gespeichert (kein Logging).
-

-

- Speicherdauer -

-

- Wir speichern Deine Supportanfragen für Dich, bis Du deinen Account löscht oder uns Bescheid gibst, dass Du sie gelöscht haben möchtest. - Wir löschen allerdings jede Supportanfrage spätestens nach 12 Monaten, nachdem sie geschlossen wurde.
-

-

- Rechtsgrundlage -

-

- Als gemeinnützige Organisation haben wir ein berechtigtes Interesse gem. Art. 6 Abs. 1 lit. f) DSGVO, unseren Spendern eine einfache und sichere Support-Möglichkeit für die von uns zur Verfügung gestellten Dienste und damit zusammenhängenden Fragen zu bieten. - Nutzer sind unter Umständen mit Herausforderungen oder Fragestellungen konfrontiert, die sie nicht alleine lösen können. - Mit dem Support bieten wir dafür eine notwendige Kommunikationsschnittstelle, die auch für den Nutzer transparent einsehbar ist.
-

-

- Empfänger -

-

- Deine personenbezogenen Daten können nur wir sehen und prinzipiell auch unser Provider, mit welchem wir einen Auftragsdatenverarbeitungsvertrag haben, der unsere Durchgriffsmöglichkeiten und Verantwortlichkeiten regelt.
-

-

- Drittlandtransfer -

-

- Unsere Support-Daten werden nicht in einem Drittland gespeichert oder verarbeitet.
-

-

- Nutzung deiner Daten zur Direktwerbung -

-

- Anmeldung zu unserem E-Mail-Newsletter -

-

- Wenn Du Dich zu unserem E-Mail Newsletter anmeldest, übersenden wir Dir regelmäßig Informationen zu unseren Angeboten. - Pflichtangabe für die Übersendung des Newsletters ist allein Deine E-Mail-Adresse. - Die Angabe weiterer evtl. Daten ist freiwillig und wird verwendet, um Dich persönlich ansprechen zu können. - Für den Versand des Newsletters verwenden wir das sog. Double Opt-in Verfahren. - Dies bedeutet, dass wir Dir erst dann einen E-Mail-Newsletter übermitteln werden, wenn Du uns ausdrücklich bestätigt hast, dass Du dem Versand des Newsletters einwilligst. - Wir schicken Dir dann eine Bestätigungsmail, mit der Du gebeten wirst, durch Anklicken eines entsprechenden Links zu bestätigen, dass Du künftig unseren Newsletter erhalten willst.
-

-

- Mit der Aktivierung des Bestätigungslinks erteilst Du uns Deine Einwilligung für die Nutzung Deiner personenbezogenen Daten gemäß Art. 6 Abs. 1 lit. a DSGVO. - Bei der Anmeldung zum Newsletter speichern wir Deine vom Internet Service-Provider (ISP) eingetragene IP-Adresse sowie das Datum und die Uhrzeit der Anmeldung, um einen möglichen Missbrauch Deiner E-Mailadresse zu einem späteren Zeitpunkt nachvollziehen zu können. - Die von uns bei der Anmeldung zum Newsletter erhobenen Daten werden ausschließlich für Zwecke der werblichen Ansprache im Wege des Newsletters benutzt. - Du kannst den Newsletter jederzeit über den dafür vorgesehenen Link im Newsletter selbst oder durch entsprechende Nachricht an den Support (siehe Formular) abbestellen. - Nach erfolgter Abmeldung wird Deine E-Mailadresse unverzüglich in unserem Newsletter-Verteiler gelöscht, soweit Du nicht ausdrücklich zu einer weiteren Nutzung Deiner Daten eingewilligt hast oder wir uns eine darüberhinausgehende Datenverwendung vorbehalten, die gesetzlich erlaubt ist und über die wir Dich in dieser Erklärung informieren.
-

-

- Verwendung von Videos -

-

- Verwendung von Youtube-Videos -

-

- Diese Website nutzt die Youtube-Einbettungsfunktion zur Anzeige und Wiedergabe von Videos des Anbieters „Youtube“, der zu der Google LLC., 1600 Amphitheatre Parkway, Mountain View, CA 94043, USA („Google“) gehört.
-

-

- Hierbei wird der erweiterte Datenschutzmodus verwendet, der nach Anbieterangaben eine Speicherung von Nutzerinformationen erst bei Wiedergabe des/der Videos in Gang setzt. - Wird die Wiedergabe eingebetteter Youtube-Videos gestartet, setzt der Anbieter „Youtube“ Cookies ein, um Informationen über das Nutzerverhalten zu sammeln. - Hinweisen von „Youtube“ zufolge dienen diese unter anderem dazu, Videostatistiken zu erfassen, die Nutzerfreundlichkeit zu verbessern und missbräuchliche Handlungsweisen zu unterbinden. - Wenn Du bei Google eingeloggt bist, werden Deine Daten direkt Deinem Konto zugeordnet, wenn Du ein Video anklickst. - Wenn Du die Zuordnung zu Deinen Profil bei YouTube nicht wünscht, muss Du Dich vor Aktivierung des Buttons ausloggen. - Google speichert Deine Daten (selbst für nicht eingeloggte Nutzer) als Nutzungsprofile und wertet diese aus. - Eine solche Auswertung erfolgt insbesondere gemäß Art. 6 Abs. 1 lit.f DSGVO auf Basis der berechtigten Interessen von Google an der Einblendung personalisierter Werbung, Marktforschung und/oder bedarfsgerechten Gestaltung seiner Website. - Dir steht ein Widerspruchsrecht gegen die Bildung dieser Nutzerprofile zu, wobei Du Dich zur Ausübung dessen an YouTube richten musst.
-

-

- Unabhängig von einer Wiedergabe der eingebetteten Videos wird bei jedem Aufruf dieser Website eine Verbindung zum Google-Netzwerk „DoubleClick“ aufgenommen, was ohne unseren Einfluss weitere Datenverarbeitungsvorgänge auslösen kann.
-

-

- Google LLC mit Sitz in den USA ist für das us-europäische Datenschutzübereinkommen „Privacy Shield“ zertifiziert, welches die Einhaltung des in der EU geltenden Datenschutzniveaus gewährleistet.
-

-

- Weitere Informationen zum Datenschutz bei „YouTube“ findest Du in der Datenschutzerklärung des Anbieters unter: https://www.google.de/intl/de/policies/privacy.
-

-

- Netzwerk -

-

- Wir betreiben ein gemeinnütziges soziales Wissens- und Aktionsnetzwerks, um den Herausforderungen unserer Zeit gemeinsam zu begegnen, die Würde des Menschen zu wahren und eine lebenswerte Zukunft für alle Menschen und zukünftigen Generationen zu schaffen.
-

-

- Im Folgenden sind die Einzelnen Datenverarbeitungen aufgeführt, die im Rahmen des Betriebs unseres Netzwerkes notwendig sind.
-

-

- Anmeldedaten -

-

- Zweck -

-

- Die Anmeldedaten werden für die Anmeldung am Netzwerk benötigt.
-

-

- Personenbezogene Daten -

-

- Im Sinne der Datenminimierung registrierst Du Dich für unser Netzwerk einzig mit Deiner E-Mail-Adresse. - Weitere personenbezogene Daten sind für die Registrierung nicht nötig. - Über diese E-Mail-Adresse stellen wir Deine Identität fest.
-

-

- In der Kommunikation mit uns spielt die von Dir verwendete E-Mail-Adresse also eine zentrale Rolle. - Daher werden wir alle von Dir ausgeübten Rechte und ggf. Wünsche, die Du an uns richtest, immer über Deine E-Mail-Adresse verifizieren. - Niemals werden wir auf Basis eines Anrufes oder einer sonstigen Information an Deinem Account etwas ändern, ihn z.B. löschen oder stillegen, ohne diese Verifizierung – außer, wir sind durch ein Gesetz dazu gezwungen. - Gesichert ist Dein Account in unserem Netzwerk über ein Passwort, was von Dir selbst vergeben werden muss und jederzeit geändert werden kann.
-

-

- Speicherdauer -

-

- Wir speichern Deine Anmeldedaten, bis Du deinen Account löschst oder uns via E-Mail Bescheid gibst, dass Du sie gelöscht haben möchtest.
-

-

- Rechtsgrundlage -

-

- Die Einwilligung durch Registrierung am Netzwerk gem. Art. 6 Abs. 1 lit. a) DSGVO. - Die Einwilligung kann jederzeit durch Löschen des Accounts samt aller Daten Widerrufen werden. - Beim Löschen ist da Löschen der Beiträge und Kommentare vorgegeben, aber optional. - Sollen Beiträge und Kommentare nicht gelöscht werden, werden diese anonymisiert. - Dadurch sind sie nicht mehr zuordenbar, weswegen auch anschließend kein Recht auf Löschung mehr geltend gemacht werden kann.
-

-

- Die E-Mail-Adresse kann jederzeit selber geändert werden. - Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt.
-

-

- Empfänger -

-

- Deine personenbezogenen Daten können nur wir und unser Provider einsehen, mit welchem wir einen Auftragsdatenverarbeitungsvertrag haben, der unsere Durchgriffsmöglichkeiten und Verantwortlichkeiten regelt.
-

-

- Weitergabe an Dritte -

-

- Die Anmeldedaten werden nicht an Dritte weitergegeben, außer ein Gesetz zwingt uns dazu.
-

-

- Drittlandtransfer -

-

- Die Daten werden nicht in einem Drittland gespeichert.
-

-

- Profildaten -

-

- Zweck -

-

- Die Profildaten ermöglichen es Nutzern, freiwillig weitere Informationen über sich weltweit und frei abrufbar zu veröffentlichen.
-

-

- Personenbezogene Daten -

-

- Angaben, wie Dein Pseudonym, ein Avatar-Bildchen oder weitere Angaben, die ggf. auch personenbezogene Daten sein können, vergibst Du selbst.
-

-

- Speicherdauer -

-

- Wir speichern Deine Profildaten, bis Du sie löscht. Da die Daten öffentlich sind, können sie von Dritten kopiert worden sein und sind daher ggf. nicht zurückholbar.
-

-

- Rechtsgrundlage -

-

- Die Einwilligung gem. Art. 6 Abs. 1 lit. a), diese Profildaten öffentlich zu machen. - Die Veröffentlichung geschieht mit der Eingabe. - Die Einwilligung kann jederzeit durch Löschen der Daten widerrufen werden. - Die Profildaten können jederzeit selber geändert werden.
-

-

- Empfänger -

-

- Deine Profildaten sind öffentlich und können weltweit von jedem, der zugreift, gesehen werden.
-

-

- Dritte -

-

- Deine Profildaten sind öffentlich und können weltweit von jedem, der zugreift, gesehen werden.
-

-

- Drittlandtransfer -

-

- Die Daten werden von uns nicht in einem Drittland gespeichert oder an ein solches übertragen.
-

-

- Session-Daten -

-

- Zweck -

-

- Speicherung der Anmeldung im Browser, damit nicht jeder Seitenaufruf eine neue Anmeldung erfordert.
-

-

- Personenbezogene Daten -

-

- Ein Session-Cookie, der in Deinem Webbrowser gespeichert wird.
-

-

- Speicherdauer -

-

- Wir speichern Diesen Cookie einen Tag lang.
-

-

- Cookies -

-

- Dieser Cookie wird gespeichert:
-

- - - - - - - - - - - - - - - - - -
- Name - - Zweck - - Speicherdauer - - Typ -
- ocelot-social-token - - Merken der Anmeldung am Netzwerk. - Mit diesem Cookie bleibst Du bis zu einem Tag in unserem Netzwerk angemeldet. - - 730 Tage, ca. 2 Jahre - - HTTP-Cookie -
-

- Rechtsgrundlage -

-

- Das berechtigtes Interesse gem. Art. 6 Abs. 1 lit. f), unseren Nutzern das Login auf unser Netzwerk technisch zu ermöglichen.
-

-

- Empfänger -

-

- Deine personenbezogenen Daten können nur wir und unser Provider, mit welchem wir einen Auftragsdatenverarbeitungsvertrag haben, der unsere Durchgriffsmöglichkeiten und Verantwortlichkeiten regelt.
-

-

- Drittlandtransfer -

-

- Die Daten werden nicht in einem Drittland gespeichert.
-

-

- Browser-Zugriffsdaten -

-

- Zweck -

-

- Technische Funktionsfähigkeit der Webanwendung inkl. korrekter Darstellung in der jeweiligen Landessprache.
-

-

- Personenbezogene Daten -

-

- Übertragen werden u.a., je nach verwendetem Browser und dessen Einstellungen: - Datum und Uhrzeit des Zugriffes, Menge der gesendeten Daten in Byte, ggf. Quelle/Verweis, von welcher Seite Du auf unsere jeweilige gelangst, verwendeter Browser, verwendetes Betriebssystem, Sprachinformation, Größe des Browserfensters, verwendete IP-Adresse.
-

-

- Speicherdauer -

-

- Diese Daten werden von uns nicht gespeichert, sondern nur zur Beantwortung der konkreten Anfrage verwendet.
-

-

- Rechtsgrundlage -

-

- Das berechtigtes Interesse gem. Art. 6 Abs. 1 lit. f), unseren Nutzern die Nutzung unseres netzwerkes technisch zu ermöglichen.
-

-

- Empfänger -

-

- Deine personenbezogenen Daten können nur wir und unser Provider, mit welchem wir einen Auftragsdatenverarbeitungsvertrag haben, der unsere Durchgriffsmöglichkeiten und Verantwortlichkeiten regelt.
-

-

- Drittlandtransfer -

-

- Die Daten werden nicht in einem Drittland gespeichert.
-

-

- Inhalte -

-

- Zweck -

-

- Veröffentlichung von Inhalten in unserem weltweit offenen sozialen Wissens- und Aktionsnetzwerk.
-

-

- Personenbezogene Daten -

-

- Alle Beiträge und Kommentare
-

-

- Speicherdauer -

-

- Wir speichern Deine Beiträge und Kommentare, bis Du sie löscht. - Da die Daten öffentlich sind, können sie von Dritten kopiert worden sein und sind daher ggf. nicht zurückholbar.
-

-

- Rechtsgrundlage -

-

- Die Einwilligung zur Veröffentlichung gem. Art. 6 Abs. 1 lit. a). Die Veröffentlichung geschieht mit der Eingabe. - Die Einwilligung kann jederzeit durch Löschen der Beiträge und Kommentare widerrufen werden. - Die Beiträge und Kommentare können jederzeit selber geändert werden. - Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt.
-

-

- Empfänger -

-

- Deine Beiträge und Kommentare sind öffentlich und können weltweit von jedem, der zugreift, gesehen werden.
-

-

- Dritte -

-

- Deine Beiträge und Kommentare sind öffentlich und können weltweit von jedem, der zugreift, gesehen werden.
-

-

- Drittlandtransfer -

-

- Die Daten werden von uns nicht in einem Drittland gespeichert oder an ein solches übertragen.
-

-

- Einbettung von Inhalten von Drittanbietern -

-

- Der Nutzer kann einwilligen, dass Inhalte von Drittanbietern, wie Facebook, Twitter oder Vimeo nicht als Link dargestellt werden, sondern optional in der Webseite angezeigt bzw. abgespielt werden. - Wir empfehlen, darauf zu verzichten. - Die Grundeinstellung in unserem Netzwerk ist, dass Inhalte von Drittanbietern nicht eingebunden werden.
-

-

- Zweck -

-

- Darstellung der Inhalte von Drittanbietern, wie Facebook, Twitter im Kontext des jeweiligen Artikels oder Beitrags im Browser des Nutzers.
-

-

- Personenbezogene Daten, Speicherdauer, Empfänger und Drittlandtransfer -

-

- Man kann prinzipiell davon ausgehen, dass Dienste von Drittanbietern durch das Sammeln von Daten über Dich bzw. den damit möglichen Gewinnen finanziert werden. - Daher raten wir davon ab, das Einbinden von Drittanbieterinhalten einzuschalten.
-

-

- Die von den Drittanbietern gesammelten personenbezogenen Daten und deren Verwendung können wir letztendlich nicht kontrollieren. - Sie sind auch keine Auftragsverarbeiter von uns oder funktionaler Bestandteil unseres Netzwerkes, sondern eigenständig Verantwortliche. - Ein Nutzer kann sich entscheiden, von anderen Nutzern eingestellte Links bzw. deren Inhalte Inhalte eingebettet anzuzeigen. - Die dabei preisgegebenen personenbezogenen daten entsprechen im Großen und Ganzen denen eines Aufrufes des jeweiligen Links. - Dies sind, abhängig vom jeweiligen Browser des Nutzers und seiner Einstellung zum Beispiel:
-

-
    -
  • - unsere besuchte Website -
  • -
  • - Datum und Uhrzeit zum Zeitpunkt des Zugriffes -
  • -
  • - Menge der gesendeten Daten in Byte -
  • -
  • - Quelle/Verweis, von welchem Du auf die Seite gelangst -
  • -
  • - verwendeter Browser -
  • -
  • - verwendetes Betriebssystem -
  • -
  • - verwendete IP-Adresse (ggf.: in anonymisierter Form) -
  • -
-

- Ebenso können Cookies von Drittanbietern gesetzt und gespeichert werden, wenn Du dies in Deinem Browser zugelassen hast.
-

-

- Drittanbieter ändern ihre Geschäftsbedingungen in der Regel häufiger. - Daher sind hier die jeweiligen Nutzungsbedingungen und Datenschutzbestimmungen mit genauen und stets aktuellen Details verlinkt:
-

- -

- Rechtsgrundlage -

-

- Einwilligung des Nutzers gem. Art. 6 Abs. 1 lit. a) durch Freischalten der Einbettung in den Benutzereinstellungen. - Die Einwilligung kann jederzeit in den Benutzereinstellungen widerrufen werden. - Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt.
-

-

- Youtube-Videos -

-

- Zweck -

-

- Freiwillige Einbettung von Youtube-Videos auf unserer Webseite um Videos in der Webseite und nicht in einem neuen Browserfenster darzustellen.
-

-

- Marketing-Cookies werden von Google genutzt, um Nutzer zu tracken. Der Hintergrund ist die Anzeige von personalisierter Werbung, wofür entsprechende Daten gesammelt werden. - Wir empfehlen das Netzwerk in den Benutzereinstellungen so zu konfigurieren, dass eingebettete Objekte nicht verwendet werden. - Die Inhalte werden dann nicht dargestellt und keine Cookies gespeichert und personenbezogene Daten übertragen.
-

-

- Hier die aktuellsten mitgeltenden Google-Datenschutzbestimmungen.
-

-

- Personenbezogene Daten -

-

- Oben angegebene Daten zum Browserzugriff und die hier folgenden Cookie-Daten mit Details:
-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Name - - Zweck - - Speicherdauer - - Typ -
- GPS - - Registriert eine eindeutige ID auf mobilen Geräten, um Tracking basierend auf dem geografischen GPS-Standort zu ermöglichen. - - 30 Minuten - - HTTP-Cookie -
- PREF - - Registriert eine eindeutige ID, die von Google verwendet wird, um Statistiken dazu, wie der Besucher YouTube-Videos auf verschiedenen Websites nutzt, zu behalten. - - 8 Monate - - HTTP-Cookie -
- VISITOR_INFO1_LIVE - - Versucht, die Benutzerbandbreite auf Seiten mit integrierten YouTube-Videos zu schätzen. - - 6 Monate - - HTTP-Cookie -
- YSC - - Registriert eine eindeutige ID, die das Gerät eines wiederkehrenden Benutzers identifiziert. Die ID wird für gezielte Werbung genutzt. - - Sitzungsende - - HTTP-Cookie -
- yt-player-bandwith - - Wird verwendet, um die optimale Videoqualität basierend auf den Geräte- und Netzwerkeinstellungen des Besuchers zu bestimmen. - - Dauerhaft - - Local Storage -
- yt-player-headers-readable - - Sammelt Daten zur Besucherinteraktion mit dem Video-Inhalt der Webseite – Diese Daten werden verwendet, um den Video-Inhalt der Webseite für den Besucher relevanter zu machen. - - Dauerhaft - - Local Storage -
- yt-remote-connected-devices - - Speichert die Benutzereinstellungen beim Abruf eines auf anderen Webseiten integrierten Youtube-Videos. - - Dauerhaft - - Local Storage -
- yt-remote-device-id - - Speichert die Benutzereinstellungen beim Abruf eines auf anderen Webseiten integrierten Youtube-Videos. - - Dauerhaft - - Local Storage -
- yt-remote-fast-check-period - - Speichert die Benutzereinstellungen beim Abruf eines auf anderen Webseiten integrierten Youtube-Videos. - - Sitzungsende - - Session Storage -
- yt-remote-session-app - - Speichert die Benutzereinstellungen beim Abruf eines auf anderen Webseiten integrierten Youtube-Videos. - - Sitzungsende - - Session Storage -
- yt-remote-session-name - - Speichert die Benutzereinstellungen beim Abruf eines auf anderen Webseiten integrierten Youtube-Videos. - - Sitzungsende - - Session Storage -
-

- Speicherdauer -

-

- Datails siehe oben.
-

-

- Rechtsgrundlage -

-

- Die Einwilligung gem. Art. 6 Abs. 1 lit. a) durch Freischalten der Einbettung in den Benutzereinstellungen. - Die Einwilligung kann jederzeit in den Benutzereinstellungen widerrufen werden. - Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt.
-

-

- Empfänger -

-

- Der Drittanbieter „Youtube“, der zu der Google LLC., 1600 Amphitheatre Parkway, Mountain View, CA 94043, USA („Google“) gehört.
-

-

- Drittlandtransfer -

-

- Die Daten werden nicht in einem Drittland gespeichert.
-

-

- Rechte des Betroffenen -

-

- Das geltende Datenschutzrecht gewährt Dir gegenüber dem Verantwortlichen hinsichtlich der Verarbeitung Deiner personenbezogenen Daten umfassende Betroffenenrechte (Auskunfts- und Interventionsrechte), über die wir Dich nachstehend informieren:
-

-

- Auskunftsrecht gemäß Art. 15 DSGVO: -

-

- Du hast insbesondere ein Recht auf Auskunft über Deine von uns verarbeiteten personenbezogenen Daten, die Verarbeitungszwecke, die Kategorien der verarbeiteten personenbezogenen Daten, die Empfänger oder Kategorien von Empfängern, gegenüber denen Deine Daten offengelegt wurden oder werden, die geplante Speicherdauer bzw. die Kriterien für die Festlegung der Speicherdauer, das Bestehen eines Rechts auf Berichtigung, Löschung, Einschränkung der Verarbeitung, Widerspruch gegen die Verarbeitung, Beschwerde bei einer Aufsichtsbehörde, die Herkunft Deiner Daten, wenn diese nicht durch uns bei Dir erhoben wurden, das Bestehen einer automatisierten Entscheidungsfindung einschließlich Profiling und ggf. aussagekräftige Informationen über die involvierte Logik und die Dich betreffende Tragweite und die angestrebten Auswirkungen einer solchen Verarbeitung, sowie Dein Recht auf Unterrichtung, welche Garantien gemäß Art. 46 DSGVO bei Weiterleitung Deiner Daten in Drittländer bestehen;
-

-

- Recht auf Berichtigung gemäß Art. 16 DSGVO: -

-

- Du hast ein Recht auf unverzügliche Berichtigung Dich betreffender unrichtiger Daten und/oder Vervollständigung Deiner bei uns gespeicherten unvollständigen Daten;
-

-

- Recht auf Löschung gemäß Art. 17 DSGVO: -

-

- Du hast das Recht, die Löschung Deiner personenbezogenen Daten bei Vorliegen der Voraussetzungen des Art. 17 Abs. 1 DSGVO zu verlangen. - Dieses Recht besteht jedoch insbesondere dann nicht, wenn die Verarbeitung zur Ausübung des Rechts auf freie Meinungsäußerung und Information, zur Erfüllung einer rechtlichen Verpflichtung, aus Gründen des öffentlichen Interesses oder zur Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen erforderlich ist.
-

-

- Recht auf Einschränkung der Verarbeitung gemäß Art. 18 DSGVO: -

-

- Du hast das Recht, die Einschränkung der Verarbeitung Deiner personenbezogenen Daten zu verlangen, solange die von Dir bestrittene Richtigkeit Deiner Daten überprüft wird, wenn Du eine Löschung Deiner Daten wegen unzulässiger Datenverarbeitung ablehnst und stattdessen die Einschränkung der Verarbeitung Deiner Daten verlangst, wenn Du Deine Daten zur Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen benötigst, nachdem wir diese Daten nach Zweckerreichung nicht mehr benötigen oder wenn Du Widerspruch aus Gründen Deiner besonderen Situation eingelegt habst, solange noch nicht feststeht, ob unsere berechtigten Gründe überwiegen.
-

-

- Recht auf Unterrichtung gemäß Art. 19 DSGVO: -

-

- Hast Du das Recht auf Berichtigung, Löschung oder Einschränkung der Verarbeitung gegenüber dem Verantwortlichen geltend gemacht, ist dieser verpflichtet, allen Empfängern, denen die Dich betreffenden personenbezogenen Daten offengelegt wurden, diese Berichtigung oder Löschung der Daten oder Einschränkung der Verarbeitung mitzuteilen, es sei denn, dies erweist sich als unmöglich oder ist mit einem unverhältnismäßigen Aufwand verbunden. - Dir steht das Recht zu, über diese Empfänger unterrichtet zu werden.
-

-

- Recht auf Datenübertragbarkeit gemäß Art. 20 DSGVO: -

-

- Du hast das Recht, Deine personenbezogenen Daten, die Du uns bereitgestellt habst, in einem strukturierten, gängigen und maschinenlesebaren Format zu erhalten oder die Übermittlung an einen anderen Verantwortlichen zu verlangen, soweit dies technisch machbar is.
-

-

- Recht auf Widerruf erteilter Einwilligungen gemäß Art. 7 Abs. 3 DSGVO: -

-

- Du hast das Recht, eine einmal erteilte Einwilligung in die Verarbeitung von Daten jederzeit mit Wirkung für die Zukunft zu widerrufen. - Im Falle des Widerrufs werden wir die betroffenen Daten unverzüglich löschen, sofern eine weitere Verarbeitung nicht auf eine Rechtsgrundlage zur einwilligungslosen Verarbeitung gestützt werden kann. - Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt.
-

-

- Recht auf Beschwerde gemäß Art. 77 DSGVO: -

-

- Wenn Du der Ansicht bist, dass die Verarbeitung der Dich betreffenden personenbezogenen Daten gegen die DSGVO verstößt, hast Du – unbeschadet eines anderweitigen verwaltungsrechtlichen oder gerichtlichen Rechtsbehelfs – das Recht auf Beschwerde bei einer Aufsichtsbehörde, insbesondere in dem Mitgliedstaat Deines Aufenthaltsortes, Deines Arbeitsplatzes oder des Ortes des mutmaßlichen Verstoßes.
-

-

- WIDERSPRUCHSRECHT -

-

- WENN WIR IM RAHMEN EINER INTERESSENABWÄGUNG IHRE PERSONENBEZOGENEN DATEN AUFGRUND UNSERES ÜBERWIEGENDEN BERECHTIGTEN INTERESSES VERARBEITEN, HAST DU DAS JEDERZEITIGE RECHT, AUS GRÜNDEN, DIE SICH AUS DEINER BESONDEREN SITUATION ERGEBEN, GEGEN DIESE VERARBEITUNG WIDERSPRUCH MIT WIRKUNG FÜR DIE ZUKUNFT EINZULEGEN.
- MACHST DU VON DEINEM WIDERSPRUCHSRECHT GEBRAUCH, BEENDEN WIR DIE VERARBEITUNG DER BETROFFENEN DATEN. - EINE WEITERVERARBEITUNG BLEIBT ABER VORBEHALTEN, WENN WIR ZWINGENDE SCHUTZWÜRDIGE GRÜNDE FÜR DIE VERARBEITUNG NACHWEISEN KÖNNEN, DIE DEINE INTERESSEN, GRUNDRECHTE UND GRUNDFREIHEITEN ÜBERWIEGEN, ODER WENN DIE VERARBEITUNG DER GELTENDMACHUNG, AUSÜBUNG ODER VERTEIDIGUNG VON RECHTSANSPRÜCHEN DIENT.
-

-

- WERDEN DEINE PERSONENBEZOGENEN DATEN VON UNS VERARBEITET, UM DIREKTWERBUNG ZU BETREIBEN, HAST DU DAS RECHT, JEDERZEIT WIDERSPRUCH GEGEN DIE VERARBEITUNG SIE BETREFFENDER PERSONENBEZOGENER DATEN ZUM ZWECKE DERARTIGER WERBUNG EINZULEGEN. - DU KANNST DEN WIDERSPRUCH WIE OBEN BESCHRIEBEN AUSÜBEN.
-

-

- MACHST DU VON DEINEM WIDERSPRUCHSRECHT GEBRAUCH, BEENDEN WIR DIE VERARBEITUNG DER BETROFFENEN DATEN ZU DIREKTWERBEZWECKEN.
-

-
- - diff --git a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/terms-and-conditions.html b/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/terms-and-conditions.html deleted file mode 100644 index fe02cdab5..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/de/terms-and-conditions.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - -
-

- Für das soziale Netzwerk {{ organization }} -

-

- Nutzungsbedingungen -

-

- Die folgenden Nutzungsbedingungen sind Basis für die Nutzung unseres {{ networkName }} Netzwerkes. - Beim Registrieren musst Du diese anerkennen und wir werden Dich auch später über ggf. stattfindende Änderungen informieren. - Unser Netzwerk wird in der {{ organizationLocation }} betrieben und unterliegt daher {{ organizationLocation2 }} Recht. - Gerichtsstand ist {{ legacyLocation }}. - Zu Details schau in unser Impressum: https://{{ networkURL }}/imprint/.
-

-

- Nutzung und Lizenz -

-

- Sind Inhalte, die Du bei uns einstellst, durch Rechte am geistigen Eigentum geschützt, erteilst Du uns eine nicht-exklusive, übertragbare, unterlizenzierbare und weltweite Lizenz für die Nutzung dieser Inhalte für die Bereitstellung in unserem Netzwerk. - Diese Lizenz endet, sobald Du Deine Inhalte oder Deinen ganzen Account löscht. - Bedenke, dass andere Deine Inhalte weiter teilen können und wir diese nicht löschen können.
-

-

- Datenschutz -

-

- Unser Netzwerk ist ein soziales Wissens- und Aktionsnetzwerk. - Daher ist es uns besonders wichtig, dass möglichst viele Inhalte öffentlich zugänglich sind. - Im Laufe der Entwicklung unseres Netzwerkes wird es mehr und mehr die Möglichkeit geben, über die Sichtbarkeit der selbst angegebenen bzw. persönlichen Daten zu entscheiden. - Über diese neuen Funktionen werden wir Euch informieren. - Ansonsten gilt, dass Du immer darüber nachdenken solltest, welche persönlichen Daten Du über Dich (oder andere) preisgibst. - Dies gilt insbesondere für Inhalte von Beiträgen und Kommentaren, da diese einen weitgehend öffentlichen Charakter haben. - Später wird es Möglichkeiten geben, die Sichtbarkeit Deines Profils einzuschränken. - Teil der Nutzungsbedingungen ist unsere Datenschutzerklärung, die Dich über die einzelnen Datenverarbeitungen in unserem Netzwerk informiert: https://{{ networkURL }}/data-privacy. - Unsere Datenschutzerklärung ist an die Gesetzeslage und die Charakteristika unseres Netzwerks angepasst und gilt immer in der aktuellsten Version.
-

-

- Verhaltenscodex -

-

- Unser Verhaltenskodex dient als Leitfaden für das persönliche Auftreten und den Umgang miteinander. - Wer als Nutzer im {{ networkName }} Netzwerk aktiv ist, Beiträge verfasst, kommentiert oder mit anderen Nutzern, auch außerhalb des Netzwerkes, Kontakt aufnimmt, erkennt diese Verhaltensregeln als verbindlich an. https://{{ networkURL }}/code-of-conduct
-

-

- Moderation -

-

- Bis unsere finanziellen Möglichkeiten uns erlauben, das Community-Moderationssystem zu implementieren, moderieren wir mit einem vereinfachten System und eigenen bzw. ggf. ehrenamtlichen Mitarbeitern. - Wir schulen diese Moderatoren und aus diesem Grund treffen auch nur diese entsprechende Entscheidungen. - Diese Moderatoren führen Ihre Tätigkeit anonym aus. - Du kannst uns Beiträge, Kommentare und auch Nutzer melden (wenn diese zum Beispiel in ihrem Profil Angaben machen oder Bilder haben, die diese Nutzungsbedingungen verletzen). - Wenn Du uns etwas meldest, kannst Du einen Meldegrund angeben und noch eine kurze Erläuterung mitgeben. - Wir schauen uns dann das Gemeldete an und sanktionieren ggf., z.B. indem wir Beiträge, Kommentare oder Nutzer sperren. - Du und auch der Betroffene erhalten derzeitig von uns leider noch keine Rückmeldung, das ist aber in Planung. - Unabhängig davon behalten wir uns prinzipiell Sanktionen vor aus Gründen, die unter Umständen nicht oder noch nicht in unserem Verhaltenscodex oder diesen Nutzungsbedingungen aufgeführt sind.
-

-

- Fehler und Rückmeldungen -

-

- Wir sind sehr bemüht, unser Netzwerk und unsere Daten sicher und abrufbar zu erhalten. - Jede neue Version der Software durchläuft sowohl automatisierte als auch manuelle Tests. - Es können jedoch unvorhergesehene Fehler auftreten. - Deshalb sind wir dankbar für jeden gemeldeten Fehler. - Du kannst gerne jeden von Dir entdeckten Fehler dem Support/der Hilfe-Assistenz mitteilen: https://{{ networkURL }}/support.
-

-

- Keine kommerzielle Nutzung -

-

- Die Nutzung des {{ networkName }} Netzwerkes ist nicht für kommerzielle Zwecke gestattet. - Darunter fällt unter anderem das Bewerben von Produkten mit kommerzieller Absicht, das Einstellen von Affiliate-Links (Geschäftspartner-Links), direkter Aufruf zu Spenden oder finanzieller Unterstützung für Zwecke, die steuerlich nicht als gemeinnützig anerkannt sind.
-

-

- Keine politische Nutzung -

-

- Nutzerkonten von politischen Parteien oder offizielle Nutzerkonten eines politischen Vertreters sind unzulässig.
-

-

- Hilfe und Fragen -

-

- Für Hilfe und Fragen haben wir Dir eine umfassende Sammlung an häufig gestellten Fragen und Antworten (FAQ) zusammengestellt; Du findest diese auf https://{{ networkURL }}/faq.
-

-
- - diff --git a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/en/code-of-conduct.html b/deployment/configurations/example/branding/templates/locales/html/hc-y2020/en/code-of-conduct.html deleted file mode 100644 index 682b8d491..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/en/code-of-conduct.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - -
-

- For the social network of {{ organization }} -

-

- Präambel -

-

- {{ networkName }} is a non-profit social knowledge and action network of the next generation. - By people - for people. Free software, open source, fair and transparent. - For positive local and global change in all areas of life. - We completely redesign the public exchange of knowledge, ideas and projects. - The functions of {{ networkName }} bring people together - offline and online - so that we can make the world a better place.
-

-

- Purpose -

-

- With these code of conduct we regulate the essential principles for behavior in our social network. - The United Nations Charter of Human Rights is our orientation and forms the heart of our understanding of values. - The code of conduct serves as guiding principles for our personal appearance and interaction with one another. - Anyone who is active as a user in the {{ networkName }} Network, writes articles, comments or contacts other users, including those outside the network,acknowledges these rules of conduct as binding.
-

-

- Expected Behaviour -

-

- The following behaviors are expected and requested of all community members:
-

-
    -
  • - Exercise consideration and respect in your speech and actions. -
  • -
  • - Attempt collaboration before conflict. -
  • -
  • - Refrain from demeaning, discriminatory, or harassing behavior and speech. -
  • -
  • - Be mindful of your surroundings and of your fellow participants. - Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. -
  • -
-

- Unacceptable Behavior -

-

- The following behaviors are unacceptable within our community:
-

-
    -
  • - Discriminatory posts, comments, utterances or insults, particularly those relating to gender, sexual orientation, race, religion, political or philosophical orientation or disability. -
  • -
  • - Posting or linking of clearly pornographic material. -
  • -
  • - Glorification or trivialization of cruel or inhuman acts of violence. -
  • -
  • - The disclosure of others' personal information without their consent or threat there of ("doxing"). -
  • -
  • - Intentional intimidation, stalking or persecution. -
  • -
  • - Advertising products and services with commercial intent. -
  • -
  • - Criminal behavior or violation of German law. -
  • -
  • - Endorse or encourage such conduct. -
  • -
-

- Consequences of Unacceptable Behavior -

-

- If a community member exhibits unacceptable behaviour, the responsible operators, moderators and administrators of the network may take appropriate measures, including but not limited to:
-

-
    -
  • - Request for immediate cessation of unacceptable conduct -
  • -
  • - Locking or deleting comments -
  • -
  • - Temporary exclusion from the respective post or contribution -
  • -
  • - Blocking or deleting of content -
  • -
  • - Temporary withdrawal of write permissions -
  • -
  • - Temporary exclusion from the network -
  • -
  • - Final exclusion from the network -
  • -
  • - Violations of German law can be reported. -
  • -
-

- If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible and link or refer to the corresponding content. - Please click on the three dots on the post, comment or user and report it using the drop-down menu.
-

-
- - diff --git a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/en/terms-and-conditions.html b/deployment/configurations/example/branding/templates/locales/html/hc-y2020/en/terms-and-conditions.html deleted file mode 100644 index 4687b8c45..000000000 --- a/deployment/configurations/example/branding/templates/locales/html/hc-y2020/en/terms-and-conditions.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - -
-

- For the social network of {{ organization }} -

-

- Terms of Service -

-

- The following terms of use form the basis for the use of our network. - When you register, you must accept them and we will inform you later about any changes that may take place. - The {{ networkName }} Network is operated in Germany and is therefore subject to German law. - Place of jurisdiction is {{ organizationLocation }}. - For details see our imprint: https://{{ networkURL }}/imprint/
-

-

- Use and License -

-

- If any content you post to us is protected by intellectual property rights, you grant us a non-exclusive, transferable, sublicensable, worldwide license to use such content for posting to our network. - This license expires when you delete your content or your entire account. - Remember that others may share your content and we cannot delete it.
-

-

- Privacy Statement -

-

- Our network is a social knowledge and action network. - It is therefore particularly important to us that as much content as possible is publicly accessible. - In the course of the development of our network there will be more and more the possibility to decide about the visibility of the personal data. - We will inform you about these new features. - Otherwise, you should always think about which personal data you disclose about yourself (or others). - This applies in particular to the content of posts and comments, as these have a largely public character. - Later there will be possibilities to limit the visibility of your profile. - Part of the terms of service is our privacy statement, which informs you about the individual data processing operations in our network: https://{{ networkURL }}/data-privacy. - Our privacy statement is adapted to the legal situation and characteristics of our network and is always valid in the most current version.
-

-

- Code of Conduct -

-

- Our code of conduct serves as a handbook for personal appearance and interaction with each other. - Whoever is active as a user in the {{ networkName }} network, writes articles, comments or makes contact with other users, even outside the network, acknowledges these rules of conduct as binding. https://{{ networkURL }}/code-of-conduct
-

-

- Moderation -

-

- Until our financial possibilities allow us to implement the community moderation system, we moderate with a simplified system and with our own or possibly volunteer staff. - We train these moderators and for this reason only they make the appropriate decisions. - These moderators carry out their work anonymously. - You can report posts, comments and users to us (for example, if they provide information in their profile or have images that violate these Terms of Use). - If you report something to us, you can give us a reason and a short explanation. - We will then take a look at what you have reported and sanction you if necessary, e.g. by blocking contributions, comments or users. - Unfortunately, you and the person concerned will not receive any feedback from us at this time, but this is in the planning stage. - Irrespective of this, we reserve the right to impose sanctions in principle for reasons that may not or not yet be listed in our Code of Conduct or these terms of service.
-

-

- Errors and Feedback -

-

- We make every effort to keep our network and data secure and available. - Each new release of the software goes through both automated and manual testing. - However, unforeseen errors may occur. Therefore, we are grateful for any reported bugs. - You are welcome to report any bugs you discover by emailing Support at https://{{ networkURL }}/support
-

-

- No Commercial Use -

-

- The use of the {{ networkName }} Network is not permitted for commercial purposes. - This includes, but is not limited to, advertising products with commercial intent, posting affiliate links, directly soliciting donations, or providing financial support for purposes that are not recognized as charitable for tax purposes.
-

-

- No Political Use -

-

- User accounts of political parties or official user accounts of a political representative are not permitted.
-

-

- Help and Questions -

-

- For help and questions we have compiled a comprehensive collection of frequently asked questions and answers (FAQ) for you. You can find them here: https://{{ networkURL }}/faq
-

-
- - diff --git a/deployment/configurations/example/kubernetes/dns.values.template.yaml b/deployment/configurations/example/kubernetes/dns.values.template.yaml deleted file mode 100644 index 09539e37e..000000000 --- a/deployment/configurations/example/kubernetes/dns.values.template.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# please duplicate template file and rename to "dns.values.yaml" and fill in your value - -provider: digitalocean -digitalocean: - # create the API token at https://cloud.digitalocean.com/account/api/tokens - # needs read + write - apiToken: "TODO" -domainFilters: - # domains you want external-dns to be able to edit - - TODO.TODO -rbac: - create: true \ No newline at end of file diff --git a/deployment/configurations/example/kubernetes/values.template.yaml b/deployment/configurations/example/kubernetes/values.template.yaml deleted file mode 100644 index 86c02310c..000000000 --- a/deployment/configurations/example/kubernetes/values.template.yaml +++ /dev/null @@ -1,120 +0,0 @@ -# please duplicate template file and rename to "values.yaml" and fill in your value - -# change all the below if needed -MAPBOX_TOKEN: "pk.eyJ1IjoiYnVzZmFrdG9yIiwiYSI6ImNraDNiM3JxcDBhaWQydG1uczhpZWtpOW4ifQ.7TNRTO-o9aK1Y6MyW_Nd4g" -PRODUCTION_DB_CLEAN_ALLOW: false # only true for production environments on staging servers -PUBLIC_REGISTRATION: false -INVITE_REGISTRATION: false -COOKIE_EXPIRE_TIME: 730 # days (730 days, two years is the default in main code) -CATEGORIES_ACTIVE: false - -BACKEND: - # change all the below if needed - # DOCKER_IMAGE_REPO - change that to your branded docker image - # label is appended based on .Chart.appVersion - DOCKER_IMAGE_REPO: "ocelotsocialnetwork/backend-branded" - CLIENT_URI: "https://staging.ocelot.social" - # create a new one for your network - JWT_SECRET: "b/&&7b78BF&fv/Vd" - PRIVATE_KEY_PASSPHRASE: "a7dsf78sadg87ad87sfagsadg78" - # ocelot.social mail dummy - EMAIL_DEFAULT_SENDER: "devops@ocelot.social" - SMTP_HOST: "mail.ocelot.social" - SMTP_USERNAME: "devops@ocelot.social" - SMTP_PASSWORD: "devops@ocelot.social" - SMTP_PORT: "587" - SMTP_IGNORE_TLS: 'false' - SMTP_SECURE: 'false' # true for 465, false for other ports - # or - # SMTP_PORT: "465" - # SMTP_IGNORE_TLS: 'true' - # SMTP_SECURE: 'true' # true for 465, false for other ports - - # most likely you don't need to change this - MIN_READY_SECONDS: "15" - PROGRESS_DEADLINE_SECONDS: "60" - REVISIONS_HISTORY_LIMIT: "25" - CONTAINER_RESTART_POLICY: "Always" - CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30" - DOCKER_IMAGE_PULL_POLICY: "Always" - STORAGE_UPLOADS: "25Gi" - -WEBAPP: - # change all the below if needed - # DOCKER_IMAGE_REPO - change that to your branded docker image - # label is appended based on .Chart.appVersion - DOCKER_IMAGE_REPO: "ocelotsocialnetwork/webapp-branded" - WEBSOCKETS_URI: "wss://staging.ocelot.social/api/graphql" - - # Most likely you don't need to change this - REPLICAS: "2" - MIN_READY_SECONDS: "15" - PROGRESS_DEADLINE_SECONDS: "60" - REVISIONS_HISTORY_LIMIT: "25" - CONTAINER_RESTART_POLICY: "Always" - CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30" - DOCKER_IMAGE_PULL_POLICY: "Always" - -NEO4J: - # most likely you don't need to change this - REVISIONS_HISTORY_LIMIT: "25" - DOCKER_IMAGE_REPO: "ocelotsocialnetwork/neo4j-community-branded" - DOCKER_IMAGE_PULL_POLICY: "Always" - CONTAINER_RESTART_POLICY: "Always" - CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30" - STORAGE: "5Gi" - # RESOURCE_REQUESTS_MEMORY configures the memory available for requests. - RESOURCE_REQUESTS_MEMORY: "2G" - # RESOURCE_LIMITS_MEMORY configures the memory limits available. - RESOURCE_LIMITS_MEMORY: "4G" - # required for Neo4j Enterprice version - #ACCEPT_LICENSE_AGREEMENT: "yes" - ACCEPT_LICENSE_AGREEMENT: "no" - AUTH: "none" - #DBMS_CONNECTOR_BOLT_THREAD_POOL_MAX_SIZE: "10000" # hc value - DBMS_CONNECTOR_BOLT_THREAD_POOL_MAX_SIZE: "400" # default value - #DBMS_MEMORY_HEAP_INITIAL_SIZE: "500MB" # HC value - DBMS_MEMORY_HEAP_INITIAL_SIZE: "" # default - #DBMS_MEMORY_HEAP_MAX_SIZE: "500MB" # HC value - DBMS_MEMORY_HEAP_MAX_SIZE: "" # default - #DBMS_MEMORY_PAGECACHE_SIZE: "490M" # HC value - DBMS_MEMORY_PAGECACHE_SIZE: "" # default - #APOC_IMPORT_FILE_ENABLED: "true" # HC value - APOC_IMPORT_FILE_ENABLED: "false" # default - DBMS_SECURITY_PROCEDURES_UNRESTRICTED: "algo.*,apoc.*" - -MAINTENANCE: - # change all the below if needed - # DOCKER_IMAGE_REPO - change that to your branded docker image - # label is appended based on .Chart.appVersion - DOCKER_IMAGE_REPO: "ocelotsocialnetwork/maintenance-branded" - - # Most likely you don't need to change this - REVISIONS_HISTORY_LIMIT: "25" - CONTAINER_RESTART_POLICY: "Always" - CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30" - DOCKER_IMAGE_PULL_POLICY: "Always" - -LETSENCRYPT: - # change all the below if needed - # ISSUER is used by cert-manager to set up certificates with the given provider. - # change it to "letsencrypt-production" once you are ready to have valid cetrificates. - # Be aware that the is an issuing limit with letsencrypt, so a dry run with staging might be wise - ISSUER: "letsencrypt-staging" - EMAIL: "devops@ocelot.social" - DOMAINS: - - "staging.ocelot.social" - - "www.staging.ocelot.social" - -NGINX: - # most likely you don't need to change this - PROXY_BODY_SIZE: "10m" - -STORAGE: - # change all the below if needed - PROVISIONER: "dobs.csi.digitalocean.com" - - # most likely you don't need to change this - RECLAIM_POLICY: "Retain" - VOLUME_BINDING_MODE: "Immediate" - ALLOW_VOLUME_EXPANSION: true \ No newline at end of file diff --git a/deployment/configurations/stage.ocelot.social b/deployment/configurations/stage.ocelot.social new file mode 160000 index 000000000..be3ac7ad2 --- /dev/null +++ b/deployment/configurations/stage.ocelot.social @@ -0,0 +1 @@ +Subproject commit be3ac7ad29f37d6a00fb3203db302cd91cebb9fa diff --git a/deployment/docker-compose.yml b/deployment/docker-compose.yml index a0dda4dc0..973dc6ac5 100644 --- a/deployment/docker-compose.yml +++ b/deployment/docker-compose.yml @@ -65,10 +65,10 @@ services: backend: image: ocelotsocialnetwork/backend-branded:local-${CONFIGURATION} - container_name: backend + container_name: backend-branded build: dockerfile: src/docker/backend.Dockerfile - target: branded-branded + target: branded context: . args: - CONFIGURATION=$CONFIGURATION @@ -143,7 +143,7 @@ services: neo4j: image: ocelotsocialnetwork/neo4j-community:latest - container_name: neo4j + container_name: neo4j-branded networks: - test-network volumes: diff --git a/deployment/scripts/branded-images.build.sh b/deployment/scripts/branded-images.build.sh index 099ba460a..fa9da67d1 100755 --- a/deployment/scripts/branded-images.build.sh +++ b/deployment/scripts/branded-images.build.sh @@ -9,20 +9,38 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + +# check DOCKERHUB_BRAND_VARRIANT +if [ -z ${DOCKERHUB_BRAND_VARRIANT} ]; then + echo "You must provide a `DOCKERHUB_BRAND_VARRIANT` via environment variable" + exit 1 +fi +echo "Using DOCKERHUB_BRAND_VARRIANT=${DOCKERHUB_BRAND_VARRIANT}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} DOCKERHUB_ORGANISATION=${DOCKERHUB_ORGANISATION:-"ocelotsocialnetwork"} OCELOT_VERSION=${OCELOT_VERSION:-$(node -p -e "require('${SCRIPT_DIR}/../../package.json').version")} +OCELOT_GITHUB_RUN_NUMBER=${OCELOT_GITHUB_RUN_NUMBER:-master} +OCELOT_VERSION_BUILD=${OCELOT_VERSION_BUILD:-${OCELOT_VERSION}-${OCELOT_GITHUB_RUN_NUMBER}} BRANDED_VERSION=${BRANDED_VERSION:-${GITHUB_RUN_NUMBER:-"local"}} BUILD_DATE=${BUILD_DATE:-$(date -u +'%Y-%m-%dT%H:%M:%SZ')} -BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION} +BUILD_VERSION_BASE=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION} +BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION_BUILD} BUILD_COMMIT=${GITHUB_SHA:-"0000000"} # backend docker build --target branded \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:latest" \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION}" \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:latest" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \ -f "${SCRIPT_DIR}/../src/docker/backend.Dockerfile" \ --build-arg "CONFIGURATION=${CONFIGURATION}" \ --build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \ @@ -31,9 +49,11 @@ docker build --target branded \ # webapp docker build --target branded \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:latest" \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION}" \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:latest" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \ -f "${SCRIPT_DIR}/../src/docker/webapp.Dockerfile" \ --build-arg "CONFIGURATION=${CONFIGURATION}" \ --build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \ @@ -42,9 +62,11 @@ docker build --target branded \ # mainteance docker build --target branded \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:latest" \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION}" \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:latest" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \ -f "${SCRIPT_DIR}/../src/docker/maintenance.Dockerfile" \ --build-arg "CONFIGURATION=${CONFIGURATION}" \ --build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \ diff --git a/deployment/scripts/branded-images.upload.sh b/deployment/scripts/branded-images.upload.sh index 3891fe474..83e27496b 100755 --- a/deployment/scripts/branded-images.upload.sh +++ b/deployment/scripts/branded-images.upload.sh @@ -10,26 +10,42 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check DOCKERHUB_BRAND_VARRIANT +if [ -z ${DOCKERHUB_BRAND_VARRIANT} ]; then + echo "You must provide a `DOCKERHUB_BRAND_VARRIANT` via environment variable" + exit 1 +fi +echo "Using DOCKERHUB_BRAND_VARRIANT=${DOCKERHUB_BRAND_VARRIANT}" + # configuration DOCKERHUB_ORGANISATION=${DOCKERHUB_ORGANISATION:-"ocelotsocialnetwork"} OCELOT_VERSION=${OCELOT_VERSION:-$(node -p -e "require('${SCRIPT_DIR}/../../package.json').version")} +OCELOT_GITHUB_RUN_NUMBER=${OCELOT_GITHUB_RUN_NUMBER:-master} +OCELOT_VERSION_BUILD=${OCELOT_VERSION_BUILD:-${OCELOT_VERSION}-${OCELOT_GITHUB_RUN_NUMBER}} BRANDED_VERSION=${BRANDED_VERSION:-${GITHUB_RUN_NUMBER:-"local"}} -BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION} +BUILD_VERSION_BASE=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION} +BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION_BUILD} # login to dockerhub echo "${DOCKERHUB_TOKEN}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin # push backend images -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:latest -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION} -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:latest +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION} # push webapp images -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:latest -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION} -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:latest +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION} # push maintenance images -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:latest -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION} -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION} \ No newline at end of file +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:latest +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD} +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE} +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION} \ No newline at end of file diff --git a/deployment/scripts/cluster.backup.sh b/deployment/scripts/cluster.backup.sh index b83bab198..7d9cbd44d 100755 --- a/deployment/scripts/cluster.backup.sh +++ b/deployment/scripts/cluster.backup.sh @@ -4,8 +4,13 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml} BACKUP_DATE=$(date "+%F_%H-%M-%S") BACKUP_FOLDER=${BACKUP_FOLDER:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/backup/${BACKUP_DATE}} diff --git a/deployment/scripts/cluster.maintenance.sh b/deployment/scripts/cluster.maintenance.sh index 3a558d7bb..b64994e9b 100755 --- a/deployment/scripts/cluster.maintenance.sh +++ b/deployment/scripts/cluster.maintenance.sh @@ -4,8 +4,14 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml} case $1 in diff --git a/deployment/scripts/cluster.reseed.sh b/deployment/scripts/cluster.reseed.sh index 705e1880a..9aba0a353 100755 --- a/deployment/scripts/cluster.reseed.sh +++ b/deployment/scripts/cluster.reseed.sh @@ -4,8 +4,14 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml} # clean & seed diff --git a/deployment/scripts/cluster.upgrade.sh b/deployment/scripts/cluster.upgrade.sh index 1aec2cf18..de0444065 100755 --- a/deployment/scripts/cluster.upgrade.sh +++ b/deployment/scripts/cluster.upgrade.sh @@ -4,16 +4,21 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml} -VALUES=${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubernetes/values. +VALUES=${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubernetes/values.yaml DOCKERHUB_OCELOT_TAG=${DOCKERHUB_OCELOT_TAG:-"latest"} # upgrade with helm helm --kubeconfig=${KUBECONFIG} upgrade ocelot \ --values ${VALUES} \ - --set appVersion="${DOCKERHUB_OCELOT_TAG}" + --set appVersion="${DOCKERHUB_OCELOT_TAG}" \ ${SCRIPT_DIR}/../src/kubernetes/ \ - --debug \ --timeout 10m \ No newline at end of file diff --git a/deployment/scripts/secret.generate.sh b/deployment/scripts/secret.generate.sh index dba958c34..cb788a7bd 100755 --- a/deployment/scripts/secret.generate.sh +++ b/deployment/scripts/secret.generate.sh @@ -7,8 +7,14 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} SECRET_FILE=${SCRIPT_DIR}/../configurations/${CONFIGURATION}/SECRET openssl rand -base64 32 > ${SECRET_FILE} \ No newline at end of file diff --git a/deployment/scripts/secrets.decrypt.sh b/deployment/scripts/secrets.decrypt.sh index 283768ad0..a7a1328b1 100755 --- a/deployment/scripts/secrets.decrypt.sh +++ b/deployment/scripts/secrets.decrypt.sh @@ -7,8 +7,14 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} SECRET=${SECRET} SECRET_FILE=${SCRIPT_DIR}/../configurations/${CONFIGURATION}/SECRET FILES=(\ diff --git a/deployment/scripts/secrets.encrypt.sh b/deployment/scripts/secrets.encrypt.sh index ef6c87e85..57be1c16e 100755 --- a/deployment/scripts/secrets.encrypt.sh +++ b/deployment/scripts/secrets.encrypt.sh @@ -7,8 +7,14 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check CONFIGURATION +if [ -z ${CONFIGURATION} ]; then + echo "You must provide a `CONFIGURATION` via environment variable" + exit 1 +fi +echo "Using CONFIGURATION=${CONFIGURATION}" + # configuration -CONFIGURATION=${CONFIGURATION:-"example"} SECRET=${SECRET} SECRET_FILE=${SCRIPT_DIR}/../configurations/${CONFIGURATION}/SECRET FILES=(\ diff --git a/deployment/src/kubernetes/templates/backend/Deployment.yaml b/deployment/src/kubernetes/templates/backend/Deployment.yaml index f475a0173..4d0f66dbc 100644 --- a/deployment/src/kubernetes/templates/backend/Deployment.yaml +++ b/deployment/src/kubernetes/templates/backend/Deployment.yaml @@ -39,6 +39,11 @@ spec: name: configmap-{{ .Release.Name }}-backend - secretRef: name: secret-{{ .Release.Name }}-backend + resources: + requests: + memory: {{ .Values.BACKEND.RESOURCE_REQUESTS_MEMORY | default "500M" | quote }} + limits: + memory: {{ .Values.BACKEND.RESOURCE_LIMITS_MEMORY | default "1G" | quote }} ports: - containerPort: 4000 protocol: TCP diff --git a/deployment/src/kubernetes/templates/maintenance/Deployment.yaml b/deployment/src/kubernetes/templates/maintenance/Deployment.yaml index fd1aa311a..ec37552d1 100644 --- a/deployment/src/kubernetes/templates/maintenance/Deployment.yaml +++ b/deployment/src/kubernetes/templates/maintenance/Deployment.yaml @@ -34,6 +34,11 @@ spec: name: configmap-{{ .Release.Name }}-webapp - secretRef: name: secret-{{ .Release.Name }}-webapp + resources: + requests: + memory: {{ .Values.MAINTENANCE.RESOURCE_REQUESTS_MEMORY | default "500M" | quote }} + limits: + memory: {{ .Values.MAINTENANCE.RESOURCE_LIMITS_MEMORY | default "1G" | quote }} ports: - containerPort: 80 restartPolicy: {{ .Values.MAINTENANCE.CONTAINER_RESTART_POLICY }} diff --git a/deployment/src/kubernetes/templates/webapp/Deployment.yaml b/deployment/src/kubernetes/templates/webapp/Deployment.yaml index a334738ec..41221185c 100644 --- a/deployment/src/kubernetes/templates/webapp/Deployment.yaml +++ b/deployment/src/kubernetes/templates/webapp/Deployment.yaml @@ -40,5 +40,10 @@ spec: name: configmap-{{ .Release.Name }}-webapp - secretRef: name: secret-{{ .Release.Name }}-webapp + resources: + requests: + memory: {{ .Values.WEBAPP.RESOURCE_REQUESTS_MEMORY | default "500M" | quote }} + limits: + memory: {{ .Values.WEBAPP.RESOURCE_LIMITS_MEMORY | default "1G" | quote }} restartPolicy: {{ .Values.WEBAPP.CONTAINER_RESTART_POLICY }} terminationGracePeriodSeconds: {{ .Values.WEBAPP.CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS }} \ No newline at end of file diff --git a/package.json b/package.json index e0e2e5752..b15175710 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social", - "version": "2.4.0", + "version": "2.6.0", "description": "Free and open source software program code available to run social networks.", "author": "ocelot.social Community", "license": "MIT", @@ -22,35 +22,33 @@ "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\")" }, "devDependencies": { - "@babel/core": "^7.9.0", - "@babel/preset-env": "^7.12.7", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", "@babel/register": "^7.12.10", "@badeball/cypress-cucumber-preprocessor": "^15.1.4", "@cypress/browserify-preprocessor": "^3.0.2", - "@faker-js/faker": "5.1.0", + "@faker-js/faker": "7.6.0", "auto-changelog": "^2.3.0", "bcryptjs": "^2.4.3", - "codecov": "^3.8.2", "cross-env": "^7.0.3", "cucumber": "^6.0.5", "cypress": "^12.6.0", "cypress-file-upload": "^3.5.3", - "date-fns": "^2.25.0", + "date-fns": "^2.30.0", "dotenv": "^8.2.0", - "expect": "^25.3.0", + "expect": "^29.5.0", "graphql-request": "^2.0.0", "import": "^0.0.6", "jsonwebtoken": "^8.5.1", "mock-socket": "^9.0.3", "neo4j-driver": "^4.3.4", "neode": "^0.4.8", - "npm-run-all": "^4.1.5", "rosie": "^2.1.0", - "slug": "^6.0.0" + "slug": "^6.0.0", + "wait-on": "^7.0.1" }, "resolutions": { "set-value": "^2.0.1", "nan": "2.17.0" - }, - "dependencies": {} -} \ No newline at end of file + } +} diff --git a/webapp/.eslintignore b/webapp/.eslintignore index be90fc8e3..a90a66efa 100644 --- a/webapp/.eslintignore +++ b/webapp/.eslintignore @@ -1,5 +1,5 @@ node_modules -build +dist .nuxt styleguide/ **/*.min.js diff --git a/webapp/.nvmrc b/webapp/.nvmrc index cb77acbfe..58b8c2a00 100644 --- a/webapp/.nvmrc +++ b/webapp/.nvmrc @@ -1 +1 @@ -v19.4.0 \ No newline at end of file +v20.2.0 \ No newline at end of file diff --git a/webapp/Dockerfile b/webapp/Dockerfile index 7952d02c1..b0ecbdd37 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # BASE (Is pushed to DockerHub for rebranding) ################################### ################################################################################## -FROM node:19.4.0-alpine3.17 as base +FROM node:20.2.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/Dockerfile.maintenance b/webapp/Dockerfile.maintenance index e148da555..a6db9e612 100644 --- a/webapp/Dockerfile.maintenance +++ b/webapp/Dockerfile.maintenance @@ -1,7 +1,7 @@ ################################################################################## # BASE ########################################################################### ################################################################################## -FROM node:19.4.0-alpine3.17 as base +FROM node:20.2.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/assets/_new/icons/svgs/book.svg b/webapp/assets/_new/icons/svgs/book.svg new file mode 100644 index 000000000..305e367ac --- /dev/null +++ b/webapp/assets/_new/icons/svgs/book.svg @@ -0,0 +1,5 @@ + + +book + + diff --git a/webapp/assets/_new/icons/svgs/calendar.svg b/webapp/assets/_new/icons/svgs/calendar.svg new file mode 100644 index 000000000..5a67a8299 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/calendar.svg @@ -0,0 +1,5 @@ + + +calendar + + diff --git a/webapp/assets/_new/styles/tokens.scss b/webapp/assets/_new/styles/tokens.scss index 66bd03ecc..863e0e0b7 100644 --- a/webapp/assets/_new/styles/tokens.scss +++ b/webapp/assets/_new/styles/tokens.scss @@ -336,10 +336,12 @@ $ease-in-sharp: cubic-bezier(0.895, 0.03, 0.685, 0.22); */ $z-index-modal: 9999; +$z-index-overlay: 9000; $z-index-dropdown: 8888; $z-index-page-submenu: 2500; $z-index-page-header: 2000; $z-index-page-sidebar: 1500; +$z-index-sticky-float: 150; $z-index-sticky: 100; $z-index-post-teaser-link: 5; $z-index-surface: 1; diff --git a/webapp/assets/styles/main.scss b/webapp/assets/styles/main.scss index 144701f83..b726758c7 100644 --- a/webapp/assets/styles/main.scss +++ b/webapp/assets/styles/main.scss @@ -95,7 +95,7 @@ blockquote { box-shadow: $box-shadow-base; position: fixed; width: 100%; - z-index: 10; + z-index: $z-index-page-submenu; a { outline: none; @@ -131,7 +131,7 @@ hr { left: 0; position: fixed; background: rgba(0, 0, 0, 0.15); - z-index: 99; + z-index: $z-index-overlay; pointer-events: none; transition: opacity 150ms ease-out; transition-delay: 50ms; diff --git a/webapp/components/AvatarMenu/AvatarMenu.vue b/webapp/components/AvatarMenu/AvatarMenu.vue index 5ec031e61..977996092 100644 --- a/webapp/components/AvatarMenu/AvatarMenu.vue +++ b/webapp/components/AvatarMenu/AvatarMenu.vue @@ -11,7 +11,15 @@ " @click.prevent="toggleMenu" > - + @@ -80,7 +88,7 @@ export default { icon: 'user', }, { - name: this.$t('header.avatarMenu.Groups'), + name: this.$t('header.avatarMenu.groups'), path: '/groups', icon: 'users', }, diff --git a/webapp/components/Button/JoinLeaveButton.vue b/webapp/components/Button/JoinLeaveButton.vue index 152039eb0..f4cc2c009 100644 --- a/webapp/components/Button/JoinLeaveButton.vue +++ b/webapp/components/Button/JoinLeaveButton.vue @@ -63,7 +63,7 @@ export default { content: this.$t('group.joinLeaveButton.tooltip'), placement: 'right', show: this.isMember && !this.isNonePendingMember && this.hovered, - trigger: this.isMember && !this.isNonePendingMember ? 'hover' : 'manual', + trigger: 'manual', } }, }, diff --git a/webapp/components/CategoriesSelect/CategoriesSelect.vue b/webapp/components/CategoriesSelect/CategoriesSelect.vue index 4f7a555a3..91fb7704c 100644 --- a/webapp/components/CategoriesSelect/CategoriesSelect.vue +++ b/webapp/components/CategoriesSelect/CategoriesSelect.vue @@ -43,6 +43,14 @@ export default { selectedCategoryIds: this.existingCategoryIds, } }, + watch: { + existingCategoryIds() { + if (!this.selectedCategoryIds.length && this.existingCategoryIds.length) { + this.selectedCategoryIds = this.existingCategoryIds + this.$forceUpdate() + } + }, + }, computed: { selectedCount() { return this.selectedCategoryIds.length diff --git a/webapp/components/ContentMenu/ContentMenu.vue b/webapp/components/ContentMenu/ContentMenu.vue index 60bcccf43..d723a9667 100644 --- a/webapp/components/ContentMenu/ContentMenu.vue +++ b/webapp/components/ContentMenu/ContentMenu.vue @@ -80,7 +80,7 @@ export default { }) } - if (this.isAdmin) { + if (this.isAdmin && !this.resource.group) { if (!this.resource.pinnedBy) { routes.push({ label: this.$t(`post.menu.pin`), diff --git a/webapp/components/ContributionForm/ContributionForm.spec.js b/webapp/components/ContributionForm/ContributionForm.spec.js index ef3b47c37..6b9db448b 100644 --- a/webapp/components/ContributionForm/ContributionForm.spec.js +++ b/webapp/components/ContributionForm/ContributionForm.spec.js @@ -15,6 +15,7 @@ const stubs = { 'client-only': true, 'nuxt-link': true, 'v-popover': true, + 'date-picker': true, } describe('ContributionForm.vue', () => { @@ -45,6 +46,7 @@ describe('ContributionForm.vue', () => { slug: 'this-is-a-title-for-a-post', content: postContent, contentExcerpt: postContent, + postType: ['Article'], }, }, }), @@ -142,6 +144,7 @@ describe('ContributionForm.vue', () => { id: null, image: null, groupId: null, + postType: 'Article', }, } postTitleInput = wrapper.find('.ds-input') @@ -268,6 +271,7 @@ describe('ContributionForm.vue', () => { image: { sensitive: false, }, + postType: 'Article', }, } }) diff --git a/webapp/components/ContributionForm/ContributionForm.vue b/webapp/components/ContributionForm/ContributionForm.vue index 8863fbc8a..997a25341 100644 --- a/webapp/components/ContributionForm/ContributionForm.vue +++ b/webapp/components/ContributionForm/ContributionForm.vue @@ -30,6 +30,7 @@ + + + +
+
+ + + + +
+ +
+
+ + + +
+
+ + + + + +
+ + + +
+ + {{ formData.eventVenue.length }}/{{ formSchema.eventVenue.max }} + + +
+
+ + +
+ + {{ formData.eventLocationName.length }}/{{ formSchema.eventLocationName.max }} + + +
+
+
+ +
+ + {{ $t('post.viewEvent.eventIsOnline') }} +
+
+ + - diff --git a/webapp/components/DonationInfo/DonationInfo.vue b/webapp/components/DonationInfo/DonationInfo.vue index b66f33305..00b9bf584 100644 --- a/webapp/components/DonationInfo/DonationInfo.vue +++ b/webapp/components/DonationInfo/DonationInfo.vue @@ -47,5 +47,6 @@ export default { display: flex; flex: 1; margin-bottom: $space-x-small; + margin-top: 16px; } diff --git a/webapp/components/Editor/nodes/Mention.js b/webapp/components/Editor/nodes/Mention.js index dad983ed6..fa1555877 100644 --- a/webapp/components/Editor/nodes/Mention.js +++ b/webapp/components/Editor/nodes/Mention.js @@ -17,7 +17,7 @@ export default class Mention extends TipTapMention { 'data-mention-id': node.attrs.id, target: '_blank', }, - `${this.options.matcher.char}${node.attrs.label}`, + `${this.options.matcher.char}${node.attrs.label} `, ] }, parseDOM: [ diff --git a/webapp/components/FilterMenu/CategoriesFilter.spec.js b/webapp/components/FilterMenu/CategoriesFilter.spec.js index 677217585..823f0ecb0 100644 --- a/webapp/components/FilterMenu/CategoriesFilter.spec.js +++ b/webapp/components/FilterMenu/CategoriesFilter.spec.js @@ -72,9 +72,7 @@ describe('CategoriesFilter.vue', () => { describe('click on an "catetories-buttons" button', () => { it('calls TOGGLE_CATEGORY when clicked', () => { - environmentAndNatureButton = wrapper - .findAll('.categories-filter .item-category .base-button') - .at(0) + environmentAndNatureButton = wrapper.findAll('.category-filter-list .base-button').at(0) environmentAndNatureButton.trigger('click') expect(mutations['posts/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4') }) diff --git a/webapp/components/FilterMenu/CategoriesFilter.vue b/webapp/components/FilterMenu/CategoriesFilter.vue index bcbfc7d1c..8b96245fd 100644 --- a/webapp/components/FilterMenu/CategoriesFilter.vue +++ b/webapp/components/FilterMenu/CategoriesFilter.vue @@ -17,18 +17,22 @@ @@ -95,3 +99,13 @@ export default { }, } + diff --git a/webapp/components/FilterMenu/FilterMenu.spec.js b/webapp/components/FilterMenu/FilterMenu.spec.js index 6e9741e79..c3a3ca113 100644 --- a/webapp/components/FilterMenu/FilterMenu.spec.js +++ b/webapp/components/FilterMenu/FilterMenu.spec.js @@ -20,6 +20,7 @@ describe('FilterMenu.vue', () => { const stubs = { FollowingFilter: true, + PostTypeFilter: true, CategoriesFilter: true, EmotionsFilter: true, LanguagesFilter: true, diff --git a/webapp/components/FilterMenu/FilterMenuComponent.vue b/webapp/components/FilterMenu/FilterMenuComponent.vue index 7a582a7c4..708c3bc7c 100644 --- a/webapp/components/FilterMenu/FilterMenuComponent.vue +++ b/webapp/components/FilterMenu/FilterMenuComponent.vue @@ -3,6 +3,7 @@

{{ $t('filter-menu.filter-by') }}

+
@@ -13,6 +14,7 @@ diff --git a/webapp/components/Group/GroupForm.vue b/webapp/components/Group/GroupForm.vue index cb407a3d9..52437d644 100644 --- a/webapp/components/Group/GroupForm.vue +++ b/webapp/components/Group/GroupForm.vue @@ -37,8 +37,6 @@ {{ $t('group.type') }} - - - - + - + @@ -43,4 +47,11 @@ export default { } } } +.eventBg { + background-color: $color-success-active; + + &::before { + border-color: $color-success-active transparent transparent $color-success-active; + } +} diff --git a/webapp/components/Select/ActionRadiusSelect.spec.js b/webapp/components/Select/ActionRadiusSelect.spec.js new file mode 100644 index 000000000..7629ac788 --- /dev/null +++ b/webapp/components/Select/ActionRadiusSelect.spec.js @@ -0,0 +1,37 @@ +import { shallowMount } from '@vue/test-utils' +import ActionRadiusSelect from './ActionRadiusSelect' + +const localVue = global.localVue +const propsData = { value: 'regional' } + +describe('ActionRadiusSelect.', () => { + let wrapper + let mocks + + beforeEach(() => { + mocks = { + $t: jest.fn(), + } + }) + + describe('mount', () => { + const Wrapper = () => { + return shallowMount(ActionRadiusSelect, { propsData, mocks, localVue }) + } + + beforeEach(() => { + wrapper = Wrapper() + }) + it('renders the select', () => { + expect(wrapper.findComponent(ActionRadiusSelect).exists()).toBe(true) + }) + + describe('when an option is selected', () => { + it('emits a change event with the new value', () => { + const select = wrapper.find('select') + select.trigger('change') + expect(wrapper.emitted().change[0]).toEqual(['regional']) + }) + }) + }) +}) diff --git a/webapp/components/Select/ActionRadiusSelect.vue b/webapp/components/Select/ActionRadiusSelect.vue new file mode 100644 index 000000000..0a090e0a5 --- /dev/null +++ b/webapp/components/Select/ActionRadiusSelect.vue @@ -0,0 +1,33 @@ + + + diff --git a/webapp/components/_new/generic/ProfileAvatar/ProfileAvatar.vue b/webapp/components/_new/generic/ProfileAvatar/ProfileAvatar.vue index 46e3968fc..d681276b5 100644 --- a/webapp/components/_new/generic/ProfileAvatar/ProfileAvatar.vue +++ b/webapp/components/_new/generic/ProfileAvatar/ProfileAvatar.vue @@ -8,7 +8,7 @@ :src="profile.avatar | proxyApiUrl" class="image" :alt="profile.name" - :title="profile.name" + :title="showProfileNameTitle ? profile.name : ''" @error="$event.target.style.display = 'none'" />
@@ -29,6 +29,10 @@ export default { type: Object, default: null, }, + showProfileNameTitle: { + type: Boolean, + default: true, + }, }, computed: { isAnonymous() { diff --git a/webapp/components/generic/SearchableInput/SearchableInput.spec.js b/webapp/components/generic/SearchableInput/SearchableInput.spec.js index cda9150b8..223ee6186 100644 --- a/webapp/components/generic/SearchableInput/SearchableInput.spec.js +++ b/webapp/components/generic/SearchableInput/SearchableInput.spec.js @@ -63,13 +63,6 @@ describe('SearchableInput.vue', () => { expect(select.element.value).toBe('abcd') }) - it('calls onDelete when the delete key is pressed', () => { - const spy = jest.spyOn(wrapper.vm, 'onDelete') - select.trigger('input') - select.trigger('keyup.delete') - expect(spy).toHaveBeenCalledTimes(1) - }) - describe('navigating to resource', () => { beforeEach(() => { propsData = { options: searchResults } diff --git a/webapp/components/generic/SearchableInput/SearchableInput.vue b/webapp/components/generic/SearchableInput/SearchableInput.vue index 2149732c5..b0e813b45 100644 --- a/webapp/components/generic/SearchableInput/SearchableInput.vue +++ b/webapp/components/generic/SearchableInput/SearchableInput.vue @@ -1,9 +1,10 @@