diff --git a/.github/workflows/build-and-test-oauth.yml b/.github/workflows/build-and-test-oauth.yml
new file mode 100644
index 00000000..d2ceccf2
--- /dev/null
+++ b/.github/workflows/build-and-test-oauth.yml
@@ -0,0 +1,128 @@
+# Copyright 2020 SkillTree
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Continuous Integration with OAuth
+
+#on:
+# push:
+# paths-ignore:
+# - 'README.md'
+# pull_request:
+# paths-ignore:
+# - 'README.md'
+on:
+ schedule:
+ - cron: '0 6 * * *'
+
+
+jobs:
+ ci:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Install Emoji Support
+ run: sudo apt-get install fonts-noto-color-emoji
+
+ - uses: actions/checkout@v2
+
+ - name: Checkout skills-client
+ uses: actions/checkout@v2
+ with:
+ repository: NationalSecurityAgency/skills-client
+ path: skills-client
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install -DskipTests
+
+ - name: run hyrda oauth service
+ run: |
+ cd skills-client/
+ ./.github/workflows/scripts/runHydra.sh
+ cd ../
+
+ - name: Check running containers
+ run: docker ps -a
+
+ - name: Caputre Hydra Oauth Service logs
+ run: |
+ mkdir -p ./e2e-tests/logs
+ docker logs hydra > ./e2e-tests/logs/hydra.out &
+ docker container logs -f hydra_consent > ./e2e-tests/logs/hydra_consent.out &
+ docker container logs -f hydra_postgres > ./e2e-tests/logs/hydra_postgres.out &
+
+ - name: Register hydra client
+ run: |
+ docker-compose -f ./skills-client/skills-client-integration/skills-int-e2e-test/hydra/quickstart.yml exec -T hydra \
+ hydra clients create \
+ --endpoint http://localhost:4445/ \
+ --id skilltree-test \
+ --secret client-secret \
+ --grant-types authorization_code,refresh_token \
+ --response-types code \
+ --scope openid \
+ --callbacks http://localhost:8080/login/oauth2/code/hydra
+
+ - name: Start services for Cypress tests
+ run: |
+ cd e2e-tests
+ npm install
+ npm run cyServices:start:skills-service:oauth
+ npm run cyServices:start:client-display:oauth
+ cd ..
+
+ - name: Run Cypress tests
+ uses: cypress-io/github-action@v2
+ with:
+ working-directory: e2e-tests
+ record: true
+ parallel: false
+ group: 'skills-service with OAuth'
+ tag: "${{ github.workflow }}"
+ env: oauthMode=true
+ env:
+ # pass the Dashboard record key as an environment variable
+ CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
+ # pass GitHub token to allow accurately detecting a build vs a re-run build
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.jar
+ ./service/target/*.log
+ ./e2e-tests/logs
diff --git a/.github/workflows/build-and-test-postgres.yml b/.github/workflows/build-and-test-postgres.yml
new file mode 100644
index 00000000..27e4e6be
--- /dev/null
+++ b/.github/workflows/build-and-test-postgres.yml
@@ -0,0 +1,113 @@
+# Copyright 2020 SkillTree
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Test against PostgreSQL
+
+#on:
+# push:
+# paths-ignore:
+# - 'README.md'
+# pull_request:
+# paths-ignore:
+# - 'README.md'
+on:
+ schedule:
+ - cron: '0 5 * * *'
+
+
+jobs:
+ ci:
+ runs-on: ubuntu-latest
+
+ services:
+ postgres:
+ # Docker Hub image
+ image: postgres
+ # Provide the password for postgres
+ env:
+ POSTGRES_PASSWORD: skillsPassword
+ POSTGRES_DB: skills
+ # Set health checks to wait until postgres has started
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ # Maps tcp port 5432 on service container to the host
+ - 5432:5432
+
+ steps:
+ - name: Install Emoji Support
+ run: sudo apt-get install fonts-noto-color-emoji
+
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install -Dspring.datasource.url=jdbc:postgresql://localhost:5432/skills -Dspring.datasource.username=postgres -Dspring.datasource.password=skillsPassword
+
+ - name: Start Services for Cypress tests
+ run: |
+ cd e2e-tests
+ npm install
+ npm run backend:dropAllDBTables:postgres
+ npm run cyServices:start:skills-service:postgresql
+ npm run cyServices:start:client-display
+ cd ..
+
+ - name: Run Cypress tests
+ uses: cypress-io/github-action@v2
+ with:
+ working-directory: e2e-tests
+ record: true
+ parallel: false
+ group: 'skills-service against postgres'
+ tag: "${{ github.workflow }}"
+ env: db=postgres
+ env:
+ # pass the Dashboard record key as an environment variable
+ CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
+ # pass GitHub token to allow accurately detecting a build vs a re-run build
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.jar
+ ./service/target/*.log
+ ./e2e-tests/logs
diff --git a/.github/workflows/build-and-test-rabbitmq.yml b/.github/workflows/build-and-test-rabbitmq.yml
new file mode 100644
index 00000000..d3cbd5fe
--- /dev/null
+++ b/.github/workflows/build-and-test-rabbitmq.yml
@@ -0,0 +1,102 @@
+# Copyright 2020 SkillTree
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Test Web Sockets over STOMP using RabbitMQ
+
+#on:
+# push:
+# paths-ignore:
+# - 'README.md'
+# pull_request:
+# paths-ignore:
+# - 'README.md'
+on:
+ schedule:
+ - cron: '0 6 * * *'
+
+
+jobs:
+ ci:
+ runs-on: ubuntu-latest
+
+ services:
+ rabbitmq:
+ image: skilltree/skills-stomp-broker:1.0.0
+ ports:
+ # Maps port 15672 and 61613 on service container to the host
+ - 15672:15672
+ - 61613:61613
+
+ steps:
+ - name: Install Emoji Support
+ run: sudo apt-get install fonts-noto-color-emoji
+
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install -DskipTests
+
+ - name: Start services for Cypress tests
+ run: |
+ cd e2e-tests
+ npm install
+ npm run cyServices:start:skills-service:rabbitmq
+ npm run cyServices:start:client-display
+ cd ..
+
+ - name: Run Cypress tests
+ uses: cypress-io/github-action@v2
+ with:
+ working-directory: e2e-tests
+ record: true
+ parallel: false
+ group: 'skills-service with STOMP using RabbitMQ'
+ tag: "${{ github.workflow }}"
+ env:
+ # pass the Dashboard record key as an environment variable
+ CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
+ # pass GitHub token to allow accurately detecting a build vs a re-run build
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.jar
+ ./service/target/*.log
+ ./e2e-tests/logs
diff --git a/.github/workflows/build-and-test-redis.yml b/.github/workflows/build-and-test-redis.yml
new file mode 100644
index 00000000..bfbba637
--- /dev/null
+++ b/.github/workflows/build-and-test-redis.yml
@@ -0,0 +1,106 @@
+# Copyright 2020 SkillTree
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Test storing HttpSession in Redis
+
+#on:
+# push:
+# paths-ignore:
+# - 'README.md'
+# pull_request:
+# paths-ignore:
+# - 'README.md'
+on:
+ schedule:
+ - cron: '0 6 * * *'
+
+
+jobs:
+ ci:
+ runs-on: ubuntu-latest
+
+ services:
+ redis:
+ image: redis
+ # Set health checks to wait until redis has started
+ options: >-
+ --health-cmd "redis-cli ping"
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ # Maps port 6379 on service container to the host
+ - 6379:6379
+
+ steps:
+ - name: Install Emoji Support
+ run: sudo apt-get install fonts-noto-color-emoji
+
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install -DskipTests
+
+ - name: Start services for Cypress tests
+ run: |
+ cd e2e-tests
+ npm install
+ npm run cyServices:start:skills-service:redis
+ npm run cyServices:start:client-display
+ cd ..
+
+ - name: Run Cypress tests
+ uses: cypress-io/github-action@v2
+ with:
+ working-directory: e2e-tests
+ record: true
+ parallel: false
+ group: 'skills-service with Redis'
+ tag: "${{ github.workflow }}"
+ env:
+ # pass the Dashboard record key as an environment variable
+ CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
+ # pass GitHub token to allow accurately detecting a build vs a re-run build
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.jar
+ ./service/target/*.log
+ ./e2e-tests/logs
diff --git a/.github/workflows/build-and-test-ssl.yml b/.github/workflows/build-and-test-ssl.yml
new file mode 100644
index 00000000..da2dfb47
--- /dev/null
+++ b/.github/workflows/build-and-test-ssl.yml
@@ -0,0 +1,135 @@
+# Copyright 2020 SkillTree
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Run integration tests using two way ssl
+
+on:
+ schedule:
+ - cron: '0 7 * * *'
+#on:
+# push:
+# paths-ignore:
+# - 'README.md'
+# - '.github/workflows/build-and-test-postgres.yml'
+# - '.github/workflows/build-and-test-redis.yml'
+# - '.gitlab-ci.yml'
+# pull_request:
+# paths-ignore:
+# - 'README.md'
+# - '.github/workflows/build-and-test-postgres.yml'
+# - '.github/workflows/build-and-test-redis.yml'
+# - '.gitlab-ci.yml'
+
+
+jobs:
+ service-tests-against-h2:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install
+ env:
+ SPRING_PROFILES_ACTIVE: pki
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.log
+
+
+ service-against-postgresql:
+ runs-on: ubuntu-latest
+
+ services:
+ postgres:
+ image: postgres
+ # Provide the password for postgres
+ env:
+ POSTGRES_PASSWORD: skillsPassword
+ POSTGRES_DB: skills
+ # Set health checks to wait until postgres has started
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ # Maps tcp port 5432 on service container to the host
+ - 5432:5432
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode test -Dspring.datasource.url=jdbc:postgresql://localhost:5432/skills -Dspring.datasource.username=postgres -Dspring.datasource.password=skillsPassword
+ env:
+ SPRING_PROFILES_ACTIVE: pki
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.log
+
+
+
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 00000000..d8ad6ec0
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,268 @@
+# Copyright 2020 SkillTree
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Continuous Integration
+
+on:
+ push:
+ paths-ignore:
+ - 'README.md'
+ - '.github/workflows/build-and-test-postgres.yml'
+ - '.github/workflows/build-and-test-redis.yml'
+ - '.gitlab-ci.yml'
+ pull_request:
+ paths-ignore:
+ - 'README.md'
+ - '.github/workflows/build-and-test-postgres.yml'
+ - '.github/workflows/build-and-test-redis.yml'
+ - '.gitlab-ci.yml'
+
+jobs:
+ pre_job:
+ # continue-on-error: true # Uncomment once integration is finished
+ runs-on: ubuntu-latest
+ # Map a step output to a job output
+ outputs:
+ should_skip: ${{ steps.skip_check.outputs.should_skip }}
+ steps:
+ - id: skip_check
+ uses: fkirc/skip-duplicate-actions@master
+ with:
+ github_token: ${{ github.token }}
+ paths_ignore: '["**/README.md"]'
+
+ service-tests-against-h2:
+ needs: pre_job
+ if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.log
+
+ build-skills-service-for-ui-tests:
+ needs: pre_job
+ if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode install -DskipTests
+
+ - name: upload service jar
+ uses: actions/upload-artifact@v2
+ with:
+ name: service jar
+ path: ./service/target/*.jar
+
+ ui-tests-against-h2:
+ runs-on: ubuntu-latest
+ needs: [build-skills-service-for-ui-tests]
+ strategy:
+ # when one test fails, DO NOT cancel the other
+ # containers, because this will kill Cypress processes
+ # leaving the Dashboard hanging ...
+ # https://github.com/cypress-io/github-action/issues/48
+ fail-fast: false
+ matrix:
+ # run 4 copies of the current job in parallel
+ containers: [1, 2, 3, 4]
+
+ steps:
+ - name: Install Emoji Support
+ run: sudo apt-get install fonts-noto-color-emoji
+
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - uses: actions/download-artifact@v2
+ with:
+ name: service jar
+ path: ./service/target/
+
+ - name: Prep Services for Cypress tests
+ run: |
+ cd e2e-tests
+ npm install
+ npm run cyServices:start
+ cd ..
+
+ - name: Run Cypress tests
+ uses: cypress-io/github-action@v2
+ with:
+ working-directory: e2e-tests
+ record: true
+ parallel: true
+ group: 'skills-service tests'
+ tag: "${{ github.workflow }}"
+ env:
+ # pass the Dashboard record key as an environment variable
+ CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
+ # pass GitHub token to allow accurately detecting a build vs a re-run build
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts ${{ matrix.container }}
+ path: |
+ ./service/target/*.log
+ ./e2e-tests/logs
+
+ service-against-postgresql:
+ needs: pre_job
+ if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
+ runs-on: ubuntu-latest
+
+ services:
+ postgres:
+ image: postgres
+ # Provide the password for postgres
+ env:
+ POSTGRES_PASSWORD: skillsPassword
+ POSTGRES_DB: skills
+ # Set health checks to wait until postgres has started
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ # Maps tcp port 5432 on service container to the host
+ - 5432:5432
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: actions/setup-node@v2-beta
+ with:
+ node-version: '14'
+
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '11.X.X' # The JDK version to make available on the path.
+
+ - name: Print Versions
+ run: |
+ mvn --version
+ java -version
+
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ - name: Build skills-service
+ run: mvn --batch-mode test -Dspring.datasource.url=jdbc:postgresql://localhost:5432/skills -Dspring.datasource.username=postgres -Dspring.datasource.password=skillsPassword
+
+ - name: upload result artifacts
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: CI result artifacts
+ path: |
+ ./service/target/*.log
+ ./e2e-tests/logs
+
+ publish-snapshot-docker-image:
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
+ needs: [ui-tests-against-h2, service-against-postgresql]
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: actions/download-artifact@v2
+ with:
+ name: service jar
+ path: ./service/target/
+
+ - name: Build image
+ env:
+ docker_username: ${{ secrets.DOCKERUSERNAME }}
+ docker_password: ${{ secrets.DOCKERPASSWORD }}
+ run: |
+ cd docker
+ bash build-and-push.sh "skilltree/skills-service-ci"
+
+
diff --git a/.gitignore b/.gitignore
index 2dc5545d..afc5f3e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,11 @@ target
rebel.xml
rebel.xml.lock
package-lock.json
-backend/src/main/resources/public/**
+service/src/main/resources/public/**
.vscode
+.history
+/e2e-tests/cypress/screenshots/
+/e2e-tests/cypress/snapshots/**/__diff_output__
+
+/dashboard/build/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 1b07cd2e..00000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,154 +0,0 @@
-stages:
- - build
- - testCypress
- - pushToNexus
- - deploy
-
-
-build:
- except:
- variables:
- - $TYPE == "postgrestest"
- image: maven:3.6.0-jdk-11
- stage: build
- before_script:
- - ./ci/installNode.sh
- - ./ci/setupRepos.sh
- script:
- - mvn --batch-mode install
- artifacts:
- paths:
- - backend/pom.xml
- - backend/target/backend-*.jar
- - backend/target/skills-service-tests.log
-
-postgres-test:on-schedule:
- only:
- variables:
- - $TYPE == "postgrestest"
- image: maven:3.6.0-jdk-11
- stage: build
- services:
- - postgres:latest
- variables:
- POSTGRES_PASSWORD: skillsPassword
- POSTGRES_DB: skills
- before_script:
- - ./ci/installNode.sh
- - ./ci/setupRepos.sh
- script:
- - mvn --batch-mode test -Dspring.datasource.url=jdbc:postgresql://postgres:5432/skills -Dspring.datasource.username=postgres -Dspring.datasource.password=skillsPassword
- artifacts:
- paths:
- - backend/target/backend-*.jar
- - backend/target/skills-service-tests.log
-
-# all jobs that actually run tests can use the same definition
-cypress_test:
- except:
- variables:
- - $TYPE == "postgrestest"
- image: amazonlinux:2
- stage: testCypress
- before_script:
- - cat /etc/os-release
- - uname -a
- # install packaged fonts
- - yum install -y fontconfig
- - cp -r e2e-tests/cypress/fonts/* /usr/share/fonts/
- - fc-cache -fv
- - fc-list | wc
- - fc-list
-# - yum install -y gtk2.x86_64
- - yum install -y which
- - yum update -y
- - yum install -y gtk3
- - yum install -y libnotify-devel
- - yum install -y GConf2
- - yum install -y libXScrnSaver
-# - yum install -y libnss3
-# - yum install -y libxss1
- - yum install -y nss
-# - yum install -y libasound2
- - yum install -y xorg-x11-server-Xvfb
- - amazon-linux-extras install -y java-openjdk11
- - java --version
- - yum install -y gcc-c++ make
- - curl -sL https://rpm.nodesource.com/setup_12.x | bash -
- - yum install -y nodejs
- - node -v
- - npm -v
- - echo "@skills:registry=http://$NEXUS_SERVER/repository/skills-registry/" > ~/.npmrc
- - cat ~/.npmrc
- script:
- # start the server in the background
- - cd e2e-tests
- - npm run backend:start:ci &
- - cd ../client-display
- - npm install
- - npm run serve &
- - cd ../e2e-tests
- - npm install
- - npm run backend:waitToStart
- - npx wait-on -t 40000 http://localhost:8083
- # run tests
- - npm run cy:run
- artifacts:
- when: always
- paths:
- - e2e-tests/cypress/videos/*.mp4
- - e2e-tests/cypress/videos/**/*.mp4
- - e2e-tests/cypress/screenshots/*.png
- - e2e-tests/cypress/screenshots/**/*.png
- - e2e-tests/cypress/snapshots/**/*
- - e2e-tests/cypress/snapshots/client-display/**/*
- - e2e-tests/cypress/snapshots/client-display/**/__diff_output__/*
- expire_in: 1 day
-
-pushToNexus:
- except:
- variables:
- - $TYPE == "postgrestest"
- image: maven:3.6.0-jdk-11
- stage: pushToNexus
- script:
- - echo "@skills:registry=http://$NEXUS_SERVER/repository/skills-registry/" > ~/.npmrc
- - cat ~/.npmrc
- - echo "nexus-snapshotsadmin$NEXUS_PASSnexus-releasesadmin$NEXUS_PASScentralcentralhttp://$NEXUS_SERVER/repository/maven-public/*" > ~/.m2/settings.xml
- - cat ~/.m2/settings.xml
- - backendJar=$(ls backend/target/backend-*.jar)
- - echo $backendJar
- - mvn --batch-mode deploy:deploy-file -DpomFile=backend/pom.xml -Dfile=${backendJar} -Durl=http://ip-10-113-80-244.evoforge.org/repository/maven-snapshots/ -DrepositoryId=nexus-snapshots
- artifacts:
- paths:
- - backend/target/backend-*.jar
- - backend/target/skills-service-tests.log
- only:
- refs:
- - branches
- variables:
- - $BRANCH_TO_DEPLOY_SKILLS_SERVICE == $CI_COMMIT_REF_NAME
-
-deploy:
- except:
- variables:
- - $TYPE == "postgrestest"
- image: alpine:latest
- stage: deploy
- before_script:
- - apk --update --no-cache add sshpass openssh git
- script:
- - git clone https://${GITLAB_DEPLOY_USERNAME}:${GITLAB_DEPLOY_PASSWORD}@gitlab.evoforge.org/skills/skills-deploy.git
- - TIMESTAMP=`date +%s`
- - TMP_DIR="deploy_${TIMESTAMP}"
- - DEST_PATH="/home/${CI_USERNAME}/$TMP_DIR"
- - sshpass -p $CI_PASSWORD ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password -o PubkeyAuthentication=no $CI_USERNAME@$CI_IP "rm -rf /home/${CI_USERNAME}/deploy_* && mkdir -p ${DEST_PATH}"
- - cp backend/target/backend-*.jar backend.jar
- - sshpass -p $CI_PASSWORD scp -r skills-deploy ${CI_USERNAME}@${CI_IP}:${DEST_PATH}
- - sshpass -p $CI_PASSWORD scp -r backend.jar ${CI_USERNAME}@${CI_IP}:${DEST_PATH}/skills-deploy
- - sshpass -p $CI_PASSWORD ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password -o PubkeyAuthentication=no $CI_USERNAME@$CI_IP "cd ${DEST_PATH}/skills-deploy && ./runDeploy.sh"
- only:
- refs:
- - branches
- variables:
- - $BRANCH_TO_DEPLOY_SKILLS_SERVICE == $CI_COMMIT_REF_NAME
diff --git a/CONTRIBUTING_IO.md b/CONTRIBUTING_IO.md
new file mode 100644
index 00000000..0231ca28
--- /dev/null
+++ b/CONTRIBUTING_IO.md
@@ -0,0 +1,12 @@
+
+## Legal
+
+Consistent with Section D.6. of the GitHub Terms of Service as of 2019, and Section 5. of the Apache License, Version 2.0, the project maintainer for this project accepts contributions using the inbound=outbound model.
+When you submit a pull request to this repository (inbound), you are agreeing to license your contribution under the same terms as specified in [LICENSE] (outbound).
+
+This is an open source project.
+Contributions you make to this public U.S. Government ("USG") repository are completely voluntary.
+When you submit an issue, bug report, question, enhancement, pull request, etc., you are offering your contribution without expectation of payment, you expressly waive any future pay claims against the USG related to your contribution, and you acknowledge that this does not create an obligation on the part of the USG of any kind.
+Furthermore, your contributing to this project does not create an employer-employee relationship between the United States ("U.S.") Government and the contributor.
+
+[LICENSE]: LICENSE.txt
\ No newline at end of file
diff --git a/DISCLAIMER.md b/DISCLAIMER.md
new file mode 100644
index 00000000..a33b5994
--- /dev/null
+++ b/DISCLAIMER.md
@@ -0,0 +1,13 @@
+# Disclaimer of Warranty
+
+This Work is provided "AS IS."
+Any express or implied warranties, including but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed.
+In no event shall the United States Government be liable for any direct, indirect, incidental, special, exemplary or consequential damages (including, but not limited to, procurement of substitute goods or services, loss of use, data or profits, or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this Work, even if advised of the possibility of such damage.
+
+The User of this Work agrees to hold harmless and indemnify the United States Government, its agents and employees from every claim or liability (whether in tort or in contract), including attorney's fees, court costs, and expenses, arising in direct consequence of Recipient's use of the item, including, but not limited to, claims or liabilities made for injury to or death of personnel of User or third parties, damage to or destruction of property of User or third parties, and infringement or other violations of intellectual property or technical data rights.
+
+# Disclaimer of Endorsement
+
+Nothing in this Work is intended to constitute an endorsement, explicit or implied, by the United States Government of any particular manufacturer's product or service.
+
+Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise, in this Work does not constitute an endorsement, recommendation, or favoring by the United States Government and shall not be used for advertising or product endorsement purposes.
diff --git a/INTENT.md b/INTENT.md
new file mode 100644
index 00000000..e8015369
--- /dev/null
+++ b/INTENT.md
@@ -0,0 +1,19 @@
+## Licensing Intent
+
+The intent is that this software and documentation ("Project") should be treated
+as if it is licensed under the license associated with the Project ("License")
+in the LICENSE file. However, because we are part of the United States (U.S.)
+Federal Government, it is not that simple.
+
+The portions of this Project written by U.S. Federal Government employees within
+the scope of their federal employment are ineligible for copyright protection in
+the U.S.; this is generally understood to mean that these portions of the
+Project are placed in the public domain.
+
+In countries where copyright protection is available (which does not include the
+U.S.), contributions made by U.S. Federal Government employees are released
+under the License. Merged contributions from private contributors are released
+under the License.
+
+The SkillTree software is released under the Apache License, Version 2.0
+("Apache 2.0").
\ No newline at end of file
diff --git a/README.md b/README.md
index e69de29b..a9cf9acc 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,21 @@
+
+
+# SkillTree Service, Dashboard and Client Display
+SkillTree is a micro-learning gamification platform providing out-of-the-box UI visualizations, convenient client integration libaries, and a dashboard for mananging the creation and administration of Gamified Training Profiles.
+
+To learn more about the SkillTree platform please visit our [Official Documentation](https://code.nsa.gov/skills-docs/).
+These pages provide in-depth guidance on installation, usage and contribution.
+
+
+# Workflows Status
+
+[](https://github.com/NationalSecurityAgency/skills-service/actions?query=workflow%3A%22Continuous+Integration%22)
+
+
+[](https://github.com/NationalSecurityAgency/skills-service/actions?query=workflow%3A%22Test+against+PostgreSQL%22)
+
+[](https://github.com/NationalSecurityAgency/skills-service/actions?query=workflow%3A%22Test+storing+HttpSession+in+Redis%22)
+
+[](https://github.com/NationalSecurityAgency/skills-service/actions?query=workflow%3A%22Test+Web+Sockets+over+STOMP+using+RabbitMQ%22)
+
+[](https://github.com/NationalSecurityAgency/skills-service/actions?query=workflow%3A%22Run+integration+tests+using+two+way+ssl%22)
diff --git a/backend/src/main/java/skills/WebSocketConfig.groovy b/backend/src/main/java/skills/WebSocketConfig.groovy
deleted file mode 100644
index aa183008..00000000
--- a/backend/src/main/java/skills/WebSocketConfig.groovy
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills
-
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Value
-import org.springframework.context.annotation.Configuration
-import org.springframework.core.annotation.Order
-import org.springframework.messaging.Message
-import org.springframework.messaging.MessageChannel
-import org.springframework.messaging.simp.config.ChannelRegistration
-import org.springframework.messaging.simp.config.MessageBrokerRegistry
-import org.springframework.messaging.simp.stomp.StompCommand
-import org.springframework.messaging.simp.stomp.StompHeaderAccessor
-import org.springframework.messaging.support.ChannelInterceptor
-import org.springframework.messaging.support.MessageHeaderAccessor
-import org.springframework.security.authentication.AbstractAuthenticationToken
-import org.springframework.security.authentication.AuthenticationDetailsSource
-import org.springframework.security.core.Authentication
-import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor
-import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails
-import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetailsSource
-import org.springframework.security.oauth2.provider.authentication.TokenExtractor
-import org.springframework.security.web.UnsupportedOperationExceptionInvocationHandler
-import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
-import org.springframework.web.socket.config.annotation.StompEndpointRegistry
-import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
-import skills.auth.AuthMode
-import skills.auth.form.oauth2.SkillsOAuth2AuthenticationManager
-
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletRequestWrapper
-import javax.servlet.http.HttpSession
-import java.lang.reflect.Proxy
-
-@Configuration
-@Slf4j
-@Order(-2147483549) // Ordered.HIGHEST_PRECEDENCE + 99 (see https://github.com/spring-projects/spring-framework/blob/master/src/docs/asciidoc/web/websocket.adoc#token-authentication)
-@EnableWebSocketMessageBroker
-class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
-
- static final String AUTHORIZATION = 'Authorization'
-
- @Value('#{"${skills.websocket.enableStompBrokerRelay:false}"}')
- Boolean enableStompBrokerRelay
-
- @Value('#{"${skills.websocket.relayHost:skills-stomp-broker}"}')
- String relayHost
-
- @Value('#{"${skills.websocket.relayPort:61613}"}')
- Integer relayPort
-
- // injected by the SkillsOAuth2AuthenticationManager itself (only when using SecurityMode.FormAuth)
- SkillsOAuth2AuthenticationManager oAuth2AuthenticationManager
-
- @Value('${skills.authorization.authMode:#{T(skills.auth.AuthMode).DEFAULT_AUTH_MODE}}')
- AuthMode authMode
-
- @Override
- void configureMessageBroker(MessageBrokerRegistry registry) {
- if (enableStompBrokerRelay) {
- registry.enableStompBrokerRelay('/topic', '/queue')
- .setRelayHost(relayHost)
- .setRelayPort(relayPort)
- .setUserRegistryBroadcast('/topic/registry')
- .setUserDestinationBroadcast('/topic/unresolved-user-destination')
- } else {
- registry.enableSimpleBroker('/topic', '/queue')
- }
- registry.setApplicationDestinationPrefixes('/app')
- }
-
- @Override
- void registerStompEndpoints(StompEndpointRegistry registry) {
- registry.addEndpoint('/skills-websocket')
- .setAllowedOrigins("*")
- .withSockJS()
- }
-
- @Override
- void configureClientInboundChannel(ChannelRegistration registration) {
- if (authMode == AuthMode.FORM) { // only injected when using SecurityMode.FormAuth
- log.info('Initializing websocket registration interceptor.')
- registration.interceptors(new ChannelInterceptor() {
- TokenExtractor tokenExtractor = new BearerTokenExtractor()
- AuthenticationDetailsSource authenticationDetailsSource = new OAuth2AuthenticationDetailsSource();
-
- @Override
- Message> preSend(Message> message, MessageChannel channel) {
- StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class)
- if (StompCommand.CONNECT == accessor.getCommand()) {
- List authHeaders = accessor.getNativeHeader(AUTHORIZATION)
- if (authHeaders) {
- log.debug("Found Authorization headers on websocket connection: [{}]", authHeaders)
- WebSocketHttpServletRequest request = new WebSocketHttpServletRequest(headers: [(AUTHORIZATION): Collections.enumeration(authHeaders)])
- Authentication authentication = tokenExtractor.extract(request)
- if (authentication) {
- request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
- if (authentication instanceof AbstractAuthenticationToken) {
- AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;
- needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));
- }
- Authentication authResult = oAuth2AuthenticationManager.authenticate(authentication);
- if (authResult.authenticated) {
- log.debug("Setting OAuth user [{}] on websocket connection", authResult)
- accessor.setUser(authResult)
- }
- }
- }
- }
- return message
- }
- })
- }
- }
-
- static class WebSocketHttpServletRequest extends HttpServletRequestWrapper {
- private static final HttpServletRequest UNSUPPORTED_REQUEST = (HttpServletRequest) Proxy
- .newProxyInstance(WebSocketHttpServletRequest.class.getClassLoader(),
- [ HttpServletRequest.class ] as Class>[],
- new UnsupportedOperationExceptionInvocationHandler())
-
- String remoteAddr
- Map attributes = [:]
- Map> headers = [:]
-
- WebSocketHttpServletRequest() { super(UNSUPPORTED_REQUEST) }
-
- Object getAttribute(String attributeName) { return attributes.get(attributeName) }
- void setAttribute(String name, Object o) { attributes.put(name, o) }
-
- Enumeration getHeaders(String name) { return headers.get(name) }
-
- HttpSession getSession(boolean create) { return null }
- }
-}
diff --git a/backend/src/main/java/skills/auth/PortalWebSecurityHelper.groovy b/backend/src/main/java/skills/auth/PortalWebSecurityHelper.groovy
deleted file mode 100644
index d65c094f..00000000
--- a/backend/src/main/java/skills/auth/PortalWebSecurityHelper.groovy
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.auth
-
-import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.stereotype.Component
-import skills.storage.model.auth.RoleName
-
-@Component
-class PortalWebSecurityHelper {
- HttpSecurity configureHttpSecurity(HttpSecurity http) {
- http
- .csrf().disable()
- .authorizeRequests()
- .antMatchers("/", "/favicon.ico", "/icons/**", "/static/**", "/skills.ico", "/skills.jpeg", "/error", "/oauth/**", "/app/oAuthProviders", "/login*", "/bootstrap/**", "/performLogin", "/createAccount", "/createRootAccount", '/grantFirstRoot', '/userExists/**', "/app/userInfo", "/app/users/validExistingDashboardUserId/*", "/app/oAuthProviders", "index.html", "/public/**", "/skills-websocket/**").permitAll()
- .antMatchers('/admin/**').hasRole('PROJECT_ADMIN')
- .antMatchers('/supervisor/**').hasAnyAuthority(RoleName.ROLE_SUPERVISOR.name(), RoleName.ROLE_SUPER_DUPER_USER.name())
- .antMatchers('/root/isRoot').hasAnyAuthority(RoleName.values().collect {it.name()}.toArray(new String[0]))
- .antMatchers('/root/**').hasRole('SUPER_DUPER_USER')
- .anyRequest().authenticated()
- http.headers().frameOptions().disable()
-
- return http
- }
-}
diff --git a/backend/src/main/java/skills/auth/form/oauth2/OAuth2UserConverterService.groovy b/backend/src/main/java/skills/auth/form/oauth2/OAuth2UserConverterService.groovy
deleted file mode 100644
index e2db3a27..00000000
--- a/backend/src/main/java/skills/auth/form/oauth2/OAuth2UserConverterService.groovy
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.auth.form.oauth2
-
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.annotation.Conditional
-import org.springframework.security.oauth2.core.user.OAuth2User
-import org.springframework.stereotype.Component
-import skills.auth.SecurityMode
-import skills.auth.SkillsAuthorizationException
-import skills.auth.UserAuthService
-import skills.auth.UserInfo
-
-import javax.annotation.Resource
-
-@Component
-@Conditional(SecurityMode.FormAuth)
-class OAuth2UserConverterService {
-
- @Autowired
- UserAuthService userAuthService
-
- @Resource(name='oauth2UserConverters')
- Map lookup = [:]
-
- UserInfo convert(String clientId, OAuth2User oAuth2User) {
- UserInfo userInfo
- OAuth2UserConverter converter = lookup.get(clientId.toLowerCase())
- if (converter) {
- userInfo = converter.convert(clientId, oAuth2User)
- } else {
- throw new SkillsAuthorizationException("No OAuth2UserConverter configured for clientId [${clientId}]")
- }
- return userInfo
- }
-
- static interface OAuth2UserConverter {
- String getClientId()
- UserInfo convert(String clientId, OAuth2User oAuth2User)
- }
-
- static class GitHubUserConverter implements OAuth2UserConverter {
- static final String NAME = 'name'
- static final String EMAIL = 'email'
-
- String clientId = 'github'
-
- @Override
- UserInfo convert(String clientId, OAuth2User oAuth2User) {
- String username = oAuth2User.getName()
- assert username, "Error getting name attribute of oAuth2User [${oAuth2User}] from clientId [$clientId]"
- String email = oAuth2User.attributes.get(EMAIL)
- if (!email) {
- throw new SkillsAuthorizationException("Email must be available in your public Github profile")
- }
- String name = oAuth2User.attributes.get(NAME)
- if (!name) {
- throw new SkillsAuthorizationException("Name must be available in your public Github profile")
- }
- String firstName = name?.tokenize()?.first()
- List tokens = name?.tokenize()
- tokens?.pop()
- String lastName = tokens?.join(' ')
- return new UserInfo(
- username: "${username}-${clientId}",
- email:email,
- firstName: firstName,
- lastName: lastName,
- )
- }
- }
-
- static class GoogleUserConverter implements OAuth2UserConverter {
- static final String FIRST_NAME = 'given_name'
- static final String LAST_NAME = 'family_name'
- static final String EMAIL = 'email'
-
- String clientId = 'google'
-
- @Override
- UserInfo convert(String clientId, OAuth2User oAuth2User) {
- String username = oAuth2User.getName()
- assert username, "Error getting name attribute of oAuth2User [${oAuth2User}] from clientId [$clientId]"
- String firstName = oAuth2User.attributes.get(FIRST_NAME)
- String lastName = oAuth2User.attributes.get(LAST_NAME)
- String email = oAuth2User.attributes.get(EMAIL)
- assert firstName && lastName && email, "First Name [$firstName], Last Name [$lastName], and email [$email] must be available in your public Google profile"
-
- return new UserInfo(
- username: "${username}-${clientId}",
- email:email,
- firstName: firstName,
- lastName: lastName,
- )
- }
- }
-}
diff --git a/backend/src/main/java/skills/controller/AdminMetricsController.groovy b/backend/src/main/java/skills/controller/AdminMetricsController.groovy
deleted file mode 100644
index beef5324..00000000
--- a/backend/src/main/java/skills/controller/AdminMetricsController.groovy
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.controller
-
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.web.bind.annotation.*
-import skills.services.AdminUsersService
-import skills.metrics.ChartParams
-import skills.metrics.MetricsService
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.profile.EnableCallStackProf
-
-@RestController
-@RequestMapping("/admin")
-@Slf4j
-@EnableCallStackProf
-class AdminMetricsController {
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Autowired
- MetricsService metricsService
-
- @RequestMapping(value = "/projects/{projectId}/{section}/{sectionId}/metrics", method = RequestMethod.GET, produces = "application/json")
- List getAllSectionMetricsCharts(@PathVariable("projectId") String projectId,
- @PathVariable("section") Section section,
- @PathVariable(ChartParams.SECTION_ID) String sectionId,
- @RequestParam Map chartProps) {
- chartProps.put(ChartParams.SECTION_ID, sectionId)
- return metricsService.loadChartsForSection(section, projectId, chartProps)
- }
-
- @RequestMapping(value = "/projects/{projectId}/{section}/{sectionId}/metrics/{chartBuilderId}", method = RequestMethod.GET, produces = "application/json")
- MetricsChart getSectionMetricsChart(@PathVariable("projectId") String projectId,
- @PathVariable("section") Section section,
- @PathVariable(ChartParams.SECTION_ID) String sectionId,
- @PathVariable(ChartParams.CHART_BUILDER_ID) String chartBuilderId,
- @RequestParam Map chartProps) {
- chartProps.put(ChartParams.SECTION_ID, sectionId)
- return metricsService.loadChartForSection(chartBuilderId, section, projectId, chartProps)
- }
-
-}
diff --git a/backend/src/main/java/skills/controller/GlobalMetricsController.groovy b/backend/src/main/java/skills/controller/GlobalMetricsController.groovy
deleted file mode 100644
index dfdcd325..00000000
--- a/backend/src/main/java/skills/controller/GlobalMetricsController.groovy
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.controller
-
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.web.bind.annotation.*
-import skills.metrics.ChartParams
-import skills.metrics.MetricsService
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.profile.EnableCallStackProf
-import skills.services.AdminUsersService
-
-@RestController
-@RequestMapping("/metrics")
-@Slf4j
-@EnableCallStackProf
-class GlobalMetricsController {
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Autowired
- MetricsService metricsService
-
- @RequestMapping(value = "/{section}", method = RequestMethod.GET, produces = "application/json")
- List getAllGlobalSectionMetricsCharts(@PathVariable("section") Section section){
- return metricsService.loadChartsForSection(section, null, [:])
- }
-
- @RequestMapping(value = "/{section}/{sectionId}/metric/{chartBuilderId}", method = RequestMethod.GET, produces = "application/json")
- MetricsChart getGlobalSectionMetricsChart(@PathVariable("section") Section section,
- @PathVariable(ChartParams.SECTION_ID) String sectionId,
- @PathVariable(ChartParams.CHART_BUILDER_ID) String chartBuilderId,
- @RequestParam Map chartProps){
-
- chartProps.put(ChartParams.SECTION_ID, sectionId)
- return metricsService.loadChartForSection(chartBuilderId, section, null, chartProps)
- }
-}
diff --git a/backend/src/main/java/skills/controller/PublicConfigController.groovy b/backend/src/main/java/skills/controller/PublicConfigController.groovy
deleted file mode 100644
index ba4e0ab8..00000000
--- a/backend/src/main/java/skills/controller/PublicConfigController.groovy
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.controller
-
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.web.bind.annotation.CrossOrigin
-import org.springframework.web.bind.annotation.RequestMapping
-import org.springframework.web.bind.annotation.RequestMethod
-import org.springframework.web.bind.annotation.ResponseBody
-import org.springframework.web.bind.annotation.RestController
-import skills.HealthChecker
-import skills.UIConfigProperties
-import skills.profile.EnableCallStackProf
-
-@RestController
-@RequestMapping("/public")
-@Slf4j
-@EnableCallStackProf
-class PublicConfigController {
-
- @Autowired
- HealthChecker healthChecker
-
- @Autowired
- UIConfigProperties uiConfigProperties
-
- @RequestMapping(value = "/config", method = RequestMethod.GET, produces = "application/json")
- @ResponseBody
- Map getConfig(){
- return uiConfigProperties.ui
- }
-
- final private static Map statusRes = [
- status: "OK",
- ]
-
- @CrossOrigin
- @RequestMapping(value = "/status", method = RequestMethod.GET, produces = "application/json")
- @ResponseBody
- def status() {
- healthChecker.checkRequiredServices()
- return statusRes
- }
-}
diff --git a/backend/src/main/java/skills/controller/UserTokenController.groovy b/backend/src/main/java/skills/controller/UserTokenController.groovy
deleted file mode 100644
index 90ec9079..00000000
--- a/backend/src/main/java/skills/controller/UserTokenController.groovy
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.controller
-
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.annotation.Conditional
-import org.springframework.http.MediaType
-import org.springframework.http.ResponseEntity
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
-import org.springframework.security.oauth2.common.OAuth2AccessToken
-import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
-import org.springframework.web.bind.annotation.PathVariable
-import org.springframework.web.bind.annotation.RequestMapping
-import org.springframework.web.bind.annotation.RequestMethod
-import org.springframework.web.bind.annotation.ResponseBody
-import org.springframework.web.bind.annotation.RestController
-import skills.auth.SecurityMode
-import skills.services.InceptionProjectService
-
-@Conditional(SecurityMode.FormAuth)
-@RestController
-@skills.profile.EnableCallStackProf
-class UserTokenController {
-
- @Autowired
- TokenEndpoint tokenEndpoint
-
- /**
- * token for inception
- * @param userId
- * @return
- */
- @RequestMapping(value = "/app/projects/Inception/users/{userId}/token", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
- @ResponseBody
- ResponseEntity getUserToken(@PathVariable("userId") String userId) {
- return createToken(InceptionProjectService.inceptionProjectId, userId)
- }
-
-
- /**
- * utilized by client-display within a project that previews that project's points
- * @param projectId
- * @param userId
- * @return
- */
- @RequestMapping(value = "/admin/projects/{projectId}/token/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
- @ResponseBody
- ResponseEntity getUserToken(@PathVariable("projectId") String projectId, @PathVariable("userId") String userId) {
- return createToken(projectId, userId)
- }
-
- private ResponseEntity createToken(String projectId, String userId) {
- skills.controller.exceptions.SkillsValidator.isNotBlank(projectId, "Project Id")
- skills.controller.exceptions.SkillsValidator.isNotBlank(userId, "User Id")
-
- UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(projectId, null, [])
- Map parameters = [grant_type: 'client_credentials', proxy_user: userId]
- return tokenEndpoint.postAccessToken(principal, parameters)
- }
-}
diff --git a/backend/src/main/java/skills/metrics/ChartParams.groovy b/backend/src/main/java/skills/metrics/ChartParams.groovy
deleted file mode 100644
index 29c1e1f1..00000000
--- a/backend/src/main/java/skills/metrics/ChartParams.groovy
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics
-
-import groovy.transform.CompileStatic
-
-@CompileStatic
-class ChartParams {
- public static final String CHART_BUILDER_ID = 'chartBuilderId'
- public static final String NUM_DAYS = 'numDays' // limit data to X days
- public static final String NUM_MONTHS = 'numMonths' // limit data to X months
- public static final String LOAD_DATA_FOR_FIRST = 'loadDataForFirst' // only load the first X charts data for a section
- public static final String SECTION_ID = 'sectionId'
-
- static String getValue(Map props, String key, String defaultVal=null) {
- String value = defaultVal
- if (props.get(key)) {
- value = props.get(key)
- }
- return value
- }
-
- static Integer getIntValue(Map props, String key, Integer defaultVal=null) {
- Integer value = defaultVal
- if (props.get(key)?.isInteger()) {
- value = props.get(key).toInteger()
- }
- return value
- }
-}
diff --git a/backend/src/main/java/skills/metrics/MetricsService.groovy b/backend/src/main/java/skills/metrics/MetricsService.groovy
deleted file mode 100644
index 10c1730d..00000000
--- a/backend/src/main/java/skills/metrics/MetricsService.groovy
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics
-
-import groovy.transform.CompileStatic
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.ApplicationContext
-import org.springframework.stereotype.Service
-import skills.controller.exceptions.ErrorCode
-import skills.controller.exceptions.SkillException
-import skills.metrics.model.ChartOption
-import skills.metrics.model.MetricsChart
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.Section
-
-import javax.annotation.PostConstruct
-
-@Service
-@Slf4j
-@CompileStatic
-class MetricsService {
-
- @Autowired
- ApplicationContext appContext
-
- Map> chartBuildersMap
-
- @PostConstruct
- void init() {
- chartBuildersMap = appContext.getBeansOfType(MetricsChartBuilder).values().groupBy { it.section }
- chartBuildersMap.each { section, builders ->
- assert builders.size() == builders.collect { it.displayOrder }.unique().size()
- builders.sort { it.displayOrder }
- }
- }
-
- List loadChartsForSection(Section section, String projectId, Map props) {
- int loadFirst = ChartParams.getIntValue(props, ChartParams.LOAD_DATA_FOR_FIRST, -1)
- int i = 0
- return chartBuildersMap.get(section)?.collect { builder ->
- boolean loadData = loadFirst < 0 || ++i <= loadFirst
- MetricsChart chart = builder.build(projectId, props, loadData)
- if(chart != null) {
- chart.dataLoaded = loadData
- if (loadData) {
- clearDataItemsIfAllValuesZero(chart)
- }
- chart.chartOptions.put(ChartOption.chartBuilderId, builder.class.name)
- }
- return chart
- }?.findAll { it != null }
- }
-
- MetricsChart loadChartForSection(String builderId, Section section, String projectId, Map props) {
- MetricsChartBuilder chartBuilder = chartBuildersMap.get(section).find { it.class.name == builderId}
- if (!chartBuilder) {
- SkillException ex = new SkillException("Unknown chart builder id [$builderId]")
- ex.errorCode = ErrorCode.BadParam
- throw ex
- }
- MetricsChart chart = chartBuilder.build(projectId, props, true)
- if (chart != null) {
- chart.chartOptions.put(ChartOption.chartBuilderId, chartBuilder.class.name)
- chart.dataLoaded = true
- clearDataItemsIfAllValuesZero(chart)
- }
- return chart
- }
-
- private void clearDataItemsIfAllValuesZero(MetricsChart chart) {
- if (chart.dataItems) {
- if (chart.dataItems?.collect({ it.count })?.unique() == [0]) {
- chart.dataItems.clear()
- }
- }
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/badges/AchievedPerMonthChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/badges/AchievedPerMonthChartBuilder.groovy
deleted file mode 100644
index 84b3e029..00000000
--- a/backend/src/main/java/skills/metrics/builders/badges/AchievedPerMonthChartBuilder.groovy
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.badges
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.ChartParams
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component('badges-AchievedPerMonthChartBuilder')
-@CompileStatic
-class AchievedPerMonthChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- static final Integer NUM_MONTHS_DEFAULT = 6
-
- final Integer displayOrder = 1
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.badges
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- Integer numMonths = skills.metrics.ChartParams.getIntValue(props, skills.metrics.ChartParams.NUM_MONTHS, NUM_MONTHS_DEFAULT)
- assert numMonths > 1, "Property [${skills.metrics.ChartParams.NUM_MONTHS}] with value [${numMonths}] must be greater than 1"
-
- String badgeId = ChartParams.getValue(props, ChartParams.SECTION_ID)
- assert badgeId, "badgeId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = (loadData ? adminUsersService.getBadgesPerMonth(projectId, badgeId, numMonths) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Distinct # of Users per Month',
- (ChartOption.yAxisLabel): 'Distinct # of Users',
- (ChartOption.dataLabel) : 'Distinct Users',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/badges/DistinctUsersOverTimeChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/badges/DistinctUsersOverTimeChartBuilder.groovy
deleted file mode 100644
index 3aca9887..00000000
--- a/backend/src/main/java/skills/metrics/builders/badges/DistinctUsersOverTimeChartBuilder.groovy
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.badges
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.services.AdminUsersService
-
-@Component('badges-DistinctUsersOverTimeChartBuilder')
-@CompileStatic
-class DistinctUsersOverTimeChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- static final Integer NUM_DAYS_DEFAULT = 120
-
- final Integer displayOrder = 0
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- skills.metrics.model.Section getSection() {
- return skills.metrics.model.Section.badges
- }
-
- @Override
- skills.metrics.model.MetricsChart build(String projectId, Map props, boolean loadData=true) {
- Integer numDays = skills.metrics.ChartParams.getIntValue(props, skills.metrics.ChartParams.NUM_DAYS, NUM_DAYS_DEFAULT)
- assert numDays > 1, "Property [${skills.metrics.ChartParams.NUM_DAYS}] with value [${numDays}] must be greater than 1"
-
- String badgeId = skills.metrics.ChartParams.getValue(props, skills.metrics.ChartParams.SECTION_ID)
- assert badgeId, "badgeId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = (loadData ? adminUsersService.getBadgesPerDay(projectId, badgeId, numDays) : []) as List
-
- skills.metrics.model.MetricsChart metricsChart = new skills.metrics.model.MetricsChart(
- chartType: skills.metrics.model.ChartType.Line,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (skills.metrics.model.ChartOption.title) : 'Distinct # of Users over Time',
- (skills.metrics.model.ChartOption.xAxisType) : 'datetime',
- (skills.metrics.model.ChartOption.yAxisLabel): 'Distinct # of Users',
- (skills.metrics.model.ChartOption.dataLabel) : 'Distinct Users',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/global/NumUsersPerProjectBuilder.groovy b/backend/src/main/java/skills/metrics/builders/global/NumUsersPerProjectBuilder.groovy
deleted file mode 100644
index 677313f6..00000000
--- a/backend/src/main/java/skills/metrics/builders/global/NumUsersPerProjectBuilder.groovy
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.global
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.controller.result.model.LabelCountItem
-import skills.controller.result.model.ProjectResult
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-import skills.services.admin.ProjAdminService
-
-@Component
-@CompileStatic
-class NumUsersPerProjectBuilder implements MetricsChartBuilder{
-
- @Autowired
- AdminUsersService usersService
-
- @Autowired
- ProjAdminService projAdminService
-
- @Override
- Section getSection() {
- return Section.global
- }
-
- @Override
- Integer getDisplayOrder() {
- return 8
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData) {
-
- List projectResults = projAdminService.getProjects()
- if (projectResults.size() < 2){
- return null
- }
-
- List chartData = []
- projectResults.each {
- LabelCountItem item = new LabelCountItem()
- item.value = it.name
- item.count = (int)usersService.countTotalProjUsers(it.projectId)
- chartData.add(item)
- }
-
- MetricsChart chart = new MetricsChart(
- dataItems: chartData,
- chartType: ChartType.HorizontalBar,
- chartOptions: getChartOptions()
- )
-
- return chart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Number of users per project',
- (ChartOption.showDataLabels): true,
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/global/SkillCountPerProjectBuilder.groovy b/backend/src/main/java/skills/metrics/builders/global/SkillCountPerProjectBuilder.groovy
deleted file mode 100644
index f259604e..00000000
--- a/backend/src/main/java/skills/metrics/builders/global/SkillCountPerProjectBuilder.groovy
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.global
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.controller.result.model.LabelCountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-import skills.services.admin.ProjAdminService
-
-@Component
-@CompileStatic
-class SkillCountPerProjectBuilder implements MetricsChartBuilder{
-
- @Autowired
- AdminUsersService usersService
-
- @Autowired
- ProjAdminService projAdminService
-
- @Override
- Section getSection() {
- return Section.global
- }
-
- @Override
- Integer getDisplayOrder() {
- return 9
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData) {
-
- def projectResults = projAdminService.getProjects()
- if (projectResults.size() < 2){
- return null
- }
-
- List chartData = []
-
- projectResults.each{
- def item = new LabelCountItem(count: (int) projAdminService.countNumberOfSkills(it.projectId), value: it.name)
- chartData.add(item)
- }
-
- MetricsChart chart = new MetricsChart(
- dataItems: chartData,
- chartType: ChartType.VerticalBar,
- chartOptions: getChartOptions()
- )
-
- return chart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Number of Skills per project',
- (ChartOption.showDataLabels): true,
- (ChartOption.sort) : 'asc',
- (ChartOption.dataLabel) : 'Number of Skills'
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/AchievedSkillsChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/AchievedSkillsChartBuilder.groovy
deleted file mode 100644
index 3c6bede5..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/AchievedSkillsChartBuilder.groovy
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class AchievedSkillsChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 2
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- List dataItems = (loadData ? adminUsersService.getAchievementCountsPerSubject(projectId, 5) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.HorizontalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Achieved Skills By Subject (for ALL users)',
- (ChartOption.showDataLabels) : true,
- (ChartOption.dataLabel) : 'Achieved Skills',
- (ChartOption.distributed) : true,
- (ChartOption.dataLabelPosition): 'top',
- (ChartOption.sort) : 'asc',
- (ChartOption.palette) : 'palette2',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/ContinuedUsageChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/ContinuedUsageChartBuilder.groovy
deleted file mode 100644
index 4e185572..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/ContinuedUsageChartBuilder.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class ContinuedUsageChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 6
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- List dataItems = [] //(loadData ? adminUsersService.getUserCountsPerLevel(projectId) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Continued Usage',
- (ChartOption.subtitle) : 'Do they stick around?',
- (ChartOption.icon) : 'fa fa-suitcase',
- (ChartOption.description): 'Once a particular skill is achieve, do users continue using that skill?',
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/DistinctUsersOverTimeChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/DistinctUsersOverTimeChartBuilder.groovy
deleted file mode 100644
index bb0c810a..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/DistinctUsersOverTimeChartBuilder.groovy
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.ChartParams
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class DistinctUsersOverTimeChartBuilder implements MetricsChartBuilder {
-
- static final Integer NUM_DAYS_DEFAULT = 120
-
- final Integer displayOrder = 0
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- Integer numDays = ChartParams.getIntValue(props, ChartParams.NUM_DAYS, NUM_DAYS_DEFAULT)
- assert numDays > 1, "Property [${ChartParams.NUM_DAYS}] with value [${numDays}] must be greater than 1"
-
- List dataItems = (loadData ? adminUsersService.getProjectUsage(projectId, numDays) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.Line,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Distinct # of Users over Time',
- (ChartOption.xAxisType) : 'datetime',
- (ChartOption.yAxisLabel): 'Distinct # of Users',
- (ChartOption.dataLabel) : 'Distinct Users',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/NumUsersPerBadgeChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/NumUsersPerBadgeChartBuilder.groovy
deleted file mode 100644
index e8985041..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/NumUsersPerBadgeChartBuilder.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class NumUsersPerBadgeChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 7
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- List dataItems = [] //(loadData ? adminUsersService.getUserCountsPerLevel(projectId) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Badges',
- (ChartOption.subtitle) : 'Number of users per badge',
- (ChartOption.icon) : 'fa fa-award',
- (ChartOption.description): 'Breakdown of number of users per badge.',
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/NumUsersPerLevelChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/NumUsersPerLevelChartBuilder.groovy
deleted file mode 100644
index 74ce2bfa..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/NumUsersPerLevelChartBuilder.groovy
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.controller.result.model.LabelCountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class NumUsersPerLevelChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 1
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData = true) {
- List dataItems = loadData ? adminUsersService.getUserCountsPerLevel(projectId) : []
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems as List,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Number Users for each Level',
- (ChartOption.showDataLabels): false,
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/OverlookedSkillsChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/OverlookedSkillsChartBuilder.groovy
deleted file mode 100644
index 561b2485..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/OverlookedSkillsChartBuilder.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class OverlookedSkillsChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 4
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- List dataItems = [] //(loadData ? adminUsersService.getUserCountsPerLevel(projectId) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Overlooked skills',
- (ChartOption.subtitle) : 'Users seem to ignore these',
- (ChartOption.icon) : 'fas fa-sad-tear',
- (ChartOption.description): 'These skills have low to no usage at all. Explore these skills and see if they need to be improved or removed.',
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/TimeToAchieveChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/TimeToAchieveChartBuilder.groovy
deleted file mode 100644
index 7f6d8274..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/TimeToAchieveChartBuilder.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class TimeToAchieveChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 5
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- List dataItems = [] //(loadData ? adminUsersService.getUserCountsPerLevel(projectId) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Time to Achieve',
- (ChartOption.subtitle) : 'How long did it take them?',
- (ChartOption.icon) : 'fa fa-calendar-alt',
- (ChartOption.description): 'Provides a breakdown of how long it takes users to achieve each level.',
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/projects/TopAchievedChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/projects/TopAchievedChartBuilder.groovy
deleted file mode 100644
index cbbdb50c..00000000
--- a/backend/src/main/java/skills/metrics/builders/projects/TopAchievedChartBuilder.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.projects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.builders.MetricsChartBuilder
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component
-@CompileStatic
-class TopAchievedChartBuilder implements MetricsChartBuilder {
-
- final Integer displayOrder = 3
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.projects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
- List dataItems = [] //(loadData ? adminUsersService.getUserCountsPerLevel(projectId) : []) as List
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Top Achieved',
- (ChartOption.subtitle) : 'The Olympians of Skills',
- (ChartOption.icon) : 'fa fa-trophy',
- (ChartOption.description): 'This stat depicts most achieved skills. It will display top skills and number of users that achieved those skills.',
- (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/skills/DistinctUsersOverTimeChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/skills/DistinctUsersOverTimeChartBuilder.groovy
deleted file mode 100644
index 9e38a026..00000000
--- a/backend/src/main/java/skills/metrics/builders/skills/DistinctUsersOverTimeChartBuilder.groovy
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.skills
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.services.AdminUsersService
-
-@Component('skills-DistinctUsersOverTimeChartBuilder')
-@CompileStatic
-class DistinctUsersOverTimeChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- static final Integer NUM_DAYS_DEFAULT = 120
-
- final Integer displayOrder = 0
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- skills.metrics.model.Section getSection() {
- return skills.metrics.model.Section.skills
- }
-
- @Override
- skills.metrics.model.MetricsChart build(String projectId, Map props, boolean loadData=true) {
- Integer numDays = skills.metrics.ChartParams.getIntValue(props, skills.metrics.ChartParams.NUM_DAYS, NUM_DAYS_DEFAULT)
- assert numDays > 1, "Property [${skills.metrics.ChartParams.NUM_DAYS}] with value [${numDays}] must be greater than 1"
-
- String skillId = skills.metrics.ChartParams.getValue(props, skills.metrics.ChartParams.SECTION_ID)
- assert skillId, "skillId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = (loadData ? adminUsersService.getSubjectUsage(projectId, skillId, numDays) : []) as List
-
- skills.metrics.model.MetricsChart metricsChart = new skills.metrics.model.MetricsChart(
- chartType: skills.metrics.model.ChartType.Line,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (skills.metrics.model.ChartOption.title) : 'Distinct # of Users over Time',
- (skills.metrics.model.ChartOption.xAxisType) : 'datetime',
- (skills.metrics.model.ChartOption.yAxisLabel): 'Distinct # of Users',
- (skills.metrics.model.ChartOption.dataLabel) : 'Distinct Users',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/subjects/AchievedSkillsChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/subjects/AchievedSkillsChartBuilder.groovy
deleted file mode 100644
index f9b0f09e..00000000
--- a/backend/src/main/java/skills/metrics/builders/subjects/AchievedSkillsChartBuilder.groovy
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.subjects
-
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.data.domain.PageRequest
-import org.springframework.data.domain.Sort
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component('subjects-AchievedSkillsChartBuilder')
-@CompileStatic
-class AchievedSkillsChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- final Integer displayOrder = 2
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.subjects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
-
- String subjectId = skills.metrics.ChartParams.getValue(props, skills.metrics.ChartParams.SECTION_ID)
- assert subjectId, "subjectId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = (loadData ? adminUsersService.getAchievementCountsPerSkill(projectId, subjectId, 5) : []) as List
- // filter empty
- dataItems = dataItems.findAll({it.count > 0})
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.HorizontalBar,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Top 5 Achieved Skills',
- (ChartOption.showDataLabels) : true,
- (ChartOption.dataLabel) : 'Achieved Skills',
- (ChartOption.distributed) : true,
- (ChartOption.dataLabelPosition): 'top',
- (ChartOption.sort) : 'asc',
- (ChartOption.palette) : 'palette2',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/subjects/DistinctUsersOverTimeChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/subjects/DistinctUsersOverTimeChartBuilder.groovy
deleted file mode 100644
index 7c20009d..00000000
--- a/backend/src/main/java/skills/metrics/builders/subjects/DistinctUsersOverTimeChartBuilder.groovy
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.subjects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.services.AdminUsersService
-
-@Component('subjects-DistinctUsersOverTimeChartBuilder')
-@CompileStatic
-class DistinctUsersOverTimeChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- static final Integer NUM_DAYS_DEFAULT = 120
-
- final Integer displayOrder = 0
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- skills.metrics.model.Section getSection() {
- return skills.metrics.model.Section.subjects
- }
-
- @Override
- skills.metrics.model.MetricsChart build(String projectId, Map props, boolean loadData=true) {
- Integer numDays = skills.metrics.ChartParams.getIntValue(props, skills.metrics.ChartParams.NUM_DAYS, NUM_DAYS_DEFAULT)
- assert numDays > 1, "Property [${skills.metrics.ChartParams.NUM_DAYS}] with value [${numDays}] must be greater than 1"
-
- String subjectId = skills.metrics.ChartParams.getValue(props, skills.metrics.ChartParams.SECTION_ID)
- assert subjectId, "subjectId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = (loadData ? adminUsersService.getSubjectUsage(projectId, subjectId, numDays) : []) as List
-
- skills.metrics.model.MetricsChart metricsChart = new skills.metrics.model.MetricsChart(
- chartType: skills.metrics.model.ChartType.Line,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (skills.metrics.model.ChartOption.title) : 'Distinct # of Users over Time',
- (skills.metrics.model.ChartOption.xAxisType) : 'datetime',
- (skills.metrics.model.ChartOption.yAxisLabel): 'Distinct # of Users',
- (skills.metrics.model.ChartOption.dataLabel) : 'Distinct Users',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/subjects/NumUsersPerLevelChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/subjects/NumUsersPerLevelChartBuilder.groovy
deleted file mode 100644
index 542058b3..00000000
--- a/backend/src/main/java/skills/metrics/builders/subjects/NumUsersPerLevelChartBuilder.groovy
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.subjects
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.controller.result.model.CountItem
-import skills.controller.result.model.LabelCountItem
-import skills.metrics.model.ChartOption
-import skills.metrics.model.ChartType
-import skills.metrics.model.MetricsChart
-import skills.metrics.model.Section
-import skills.services.AdminUsersService
-
-@Component('subjects-NumUsersPerLevelChartBuilder')
-@CompileStatic
-class NumUsersPerLevelChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- final Integer displayOrder = 1
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Override
- Section getSection() {
- return Section.subjects
- }
-
- @Override
- MetricsChart build(String projectId, Map props, boolean loadData=true) {
-
- String subjectId = skills.metrics.ChartParams.getValue(props, skills.metrics.ChartParams.SECTION_ID)
- assert subjectId, "subjectId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = loadData ? adminUsersService.getUserCountsPerLevel(projectId, subjectId) : []
-
- MetricsChart metricsChart = new MetricsChart(
- chartType: ChartType.VerticalBar,
- dataItems: dataItems as List,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (ChartOption.title) : 'Number Users for each Level',
- (ChartOption.showDataLabels): false,
-// (ChartOption.sort) : 'asc',
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/builders/users/PointHistoryChartBuilder.groovy b/backend/src/main/java/skills/metrics/builders/users/PointHistoryChartBuilder.groovy
deleted file mode 100644
index 9ad5fcfc..00000000
--- a/backend/src/main/java/skills/metrics/builders/users/PointHistoryChartBuilder.groovy
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.builders.users
-
-import groovy.transform.CompileStatic
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.services.AdminUsersService
-import skills.skillLoading.SkillsLoader
-
-@Component('user-PointHistoryChartBuilder')
-@CompileStatic
-class PointHistoryChartBuilder implements skills.metrics.builders.MetricsChartBuilder {
-
- static final Integer NUM_DAYS_DEFAULT = 365
-
- final Integer displayOrder = 0
-
- @Autowired
- AdminUsersService adminUsersService
-
- @Autowired
- SkillsLoader skillsLoader
-
- @Override
- skills.metrics.model.Section getSection() {
- return skills.metrics.model.Section.users
- }
-
- @Override
- skills.metrics.model.MetricsChart build(String projectId, Map props, boolean loadData=true) {
- Integer numDays = skills.metrics.ChartParams.getIntValue(props, skills.metrics.ChartParams.NUM_DAYS, NUM_DAYS_DEFAULT)
- assert numDays > 1, "Property [${skills.metrics.ChartParams.NUM_DAYS}] with value [${numDays}] must be greater than 1"
-
- String userId = skills.metrics.ChartParams.getValue(props, skills.metrics.ChartParams.SECTION_ID)
- assert userId, "userId must be specified via ${skills.metrics.ChartParams.SECTION_ID} url param"
-
- List dataItems = []
- if (loadData) {
- dataItems = skillsLoader.loadPointHistorySummary(projectId, userId, numDays).pointsHistory.collect {
- new skills.controller.result.model.TimestampCountItem(value: it.dayPerformed.time, count: it.points)
- } as List
- }
-
- skills.metrics.model.MetricsChart metricsChart = new skills.metrics.model.MetricsChart(
- chartType: skills.metrics.model.ChartType.Area,
- dataItems: dataItems,
- chartOptions: getChartOptions(),
- )
- return metricsChart
- }
-
- private Map getChartOptions() {
- Map chartOptions = [
- (skills.metrics.model.ChartOption.title) : 'Point History',
- (skills.metrics.model.ChartOption.xAxisType) : 'datetime',
-// (ChartOption.yAxisLabel) : '# of Points',
- (skills.metrics.model.ChartOption.dataLabel) : 'Points',
- (skills.metrics.model.ChartOption.showDataLabels): false,
- ] as Map
- return chartOptions
- }
-}
diff --git a/backend/src/main/java/skills/metrics/model/ChartOption.java b/backend/src/main/java/skills/metrics/model/ChartOption.java
deleted file mode 100644
index d0a5e3d5..00000000
--- a/backend/src/main/java/skills/metrics/model/ChartOption.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.metrics.model;
-
-public enum ChartOption {
- chartBuilderId,
- description,
- title,
- titleSize, // ex: 16px
- titleColor, // ex: #008FFB
- titlePosition, // left, center, right
- subtitle,
- xAxisLabel,
- xAxisType, // datetime, ?
- yAxisLabel,
- yAxisType, // datetime, ?
- distributed, // true/false
- dataLabel,
- showDataLabels, // true/false
- dataLabelPosition, // top, center, bottom
- sort, // asc, desc
- palette, // ex. palette2
- icon,
- labels
-}
diff --git a/backend/src/main/java/skills/services/events/pointsAndAchievements/PointsAndAchievementsHandler.groovy b/backend/src/main/java/skills/services/events/pointsAndAchievements/PointsAndAchievementsHandler.groovy
deleted file mode 100644
index 84c0813f..00000000
--- a/backend/src/main/java/skills/services/events/pointsAndAchievements/PointsAndAchievementsHandler.groovy
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.services.events.pointsAndAchievements
-
-import callStack.profiler.Profile
-import groovy.transform.CompileStatic
-import groovy.util.logging.Slf4j
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import skills.services.LevelDefinitionStorageService
-import skills.services.events.CompletionItem
-import skills.services.events.CompletionTypeUtil
-import skills.services.events.SkillEventResult
-import skills.storage.model.*
-import skills.storage.repos.SkillEventsSupportRepo
-import skills.storage.repos.SkillRelDefRepo
-import skills.storage.repos.UserAchievedLevelRepo
-import skills.storage.repos.UserPointsRepo
-
-@Component
-@Slf4j
-@CompileStatic
-class PointsAndAchievementsHandler {
-
- @Autowired
- UserPointsRepo userPointsRepo
-
- @Autowired
- UserAchievedLevelRepo userAchievedLevelRepo
-
- @Autowired
- UserAchievedLevelRepo achievedLevelRepo
-
- @Autowired
- SkillRelDefRepo skillRelDefRepo
-
- @Autowired
- LevelDefinitionStorageService levelDefService
-
- @Autowired
- SkillEventsSupportRepo skillEventsSupportRepo
-
- @Autowired
- PointsAndAchievementsSaver saver
-
- @Autowired
- PointsAndAchievementsDataLoader dataLoader
-
- @Profile
- List updatePointsAndAchievements(String userId, SkillEventsSupportRepo.SkillDefMin skillDef, Date incomingSkillDate){
- LoadedData loadedData = dataLoader.loadData(skillDef.projectId, userId, incomingSkillDate, skillDef)
-
- PointsAndAchievementsBuilder builder = new PointsAndAchievementsBuilder(
- userId: userId,
- projectId: skillDef.projectId,
- skillId: skillDef.skillId,
- skillRefId: skillDef.id,
- loadedData: loadedData,
- pointIncrement: skillDef.pointIncrement,
- incomingSkillDate: incomingSkillDate,
- levelDefService: levelDefService,
- )
- PointsAndAchievementsBuilder.PointsAndAchievementsResult result = builder.build()
- saver.save(result.dataToSave)
- return result.completionItems
- }
-
-
-
- @Profile
- void checkParentGraph(Date incomingSkillDate, SkillEventResult res, String userId, SkillEventsSupportRepo.SkillDefMin skillDef, boolean decrement) {
- updateByTraversingUpSkillDefs(incomingSkillDate, res, skillDef, skillDef, userId, decrement)
-
- // updated project level
- UserPoints totalPoints = updateUserPoints(userId, skillDef, incomingSkillDate, null, decrement)
- if (!decrement) {
- List levelDefs = skillEventsSupportRepo.findLevelsByProjectId(skillDef.projectId)
- SkillEventsSupportRepo.TinyProjectDef totalProjectPoints = skillEventsSupportRepo.getTinyProjectDef(skillDef.projectId)
- LevelDefinitionStorageService.LevelInfo levelInfo = levelDefService.getLevelInfo(skillDef.projectId, levelDefs, totalProjectPoints.totalPoints, totalPoints.points)
- CompletionItem completionItem = calculateLevels(levelInfo, totalPoints, null, userId, "OVERALL", decrement)
- if (completionItem?.level && completionItem?.level > 0) {
- res.completed.add(completionItem)
- }
- }
- }
-
- /**
- * @param skillId if null then will document it at overall project level
- */
- UserPoints updateUserPoints(String userId, SkillEventsSupportRepo.SkillDefMin requestedSkill, Date incomingSkillDate, String skillId = null, boolean decrement) {
- doUpdateUserPoints(requestedSkill, userId, incomingSkillDate, skillId, decrement)
- UserPoints res = doUpdateUserPoints(requestedSkill, userId, null, skillId, decrement)
- return res
- }
-
- @Profile
- private UserPoints doUpdateUserPoints(SkillEventsSupportRepo.SkillDefMin requestedSkill, String userId, Date incomingSkillDate, String skillId, boolean decrement) {
- Date day = incomingSkillDate ? new Date(incomingSkillDate.time).clearTime() : null
- UserPoints userPoints = getUserPoints(requestedSkill, userId, skillId, day)
- if (!userPoints) {
- assert !decrement
- userPoints = new UserPoints(userId: userId?.toLowerCase(), projectId: requestedSkill.projectId,
- skillId: skillId,
- skillRefId: skillId ? requestedSkill.id : null,
- points: requestedSkill.pointIncrement, day: day)
- } else {
- if (decrement) {
- userPoints.points -= requestedSkill.pointIncrement
- } else {
- userPoints.points += requestedSkill.pointIncrement
- }
- }
-
- UserPoints res
- if (decrement && userPoints.points <= 0) {
- userPointsRepo.delete(userPoints)
- res = new UserPoints(userId: userId?.toLowerCase(), projectId: requestedSkill.projectId,
- skillId: skillId,
- skillRefId: skillId ? requestedSkill.id : null,
- points: 0, day: day)
- } else {
- res = saveUserPoints(userPoints)
- log.debug("Updated points [{}]", res)
- }
- res
- }
-
- @Profile
- private UserPoints saveUserPoints(UserPoints subjectPoints) {
- userPointsRepo.save(subjectPoints)
- }
-
- @Profile
- private UserPoints getUserPoints(SkillEventsSupportRepo.SkillDefMin requestedSkill, String userId, String skillId, Date day) {
- userPointsRepo.findByProjectIdAndUserIdAndSkillIdAndDay(requestedSkill.projectId, userId, skillId, day)
- }
-
- @Profile
- private void updateByTraversingUpSkillDefs(Date incomingSkillDate, SkillEventResult res,
- SkillEventsSupportRepo.SkillDefMin currentDef,
- SkillEventsSupportRepo.SkillDefMin requesterDef,
- String userId, boolean decrement) {
- if (shouldEvaluateForAchievement(currentDef)) {
- UserPoints updatedPoints = updateUserPoints(userId, requesterDef, incomingSkillDate, currentDef.skillId, decrement)
-
- List levelDefs = skillEventsSupportRepo.findLevelsBySkillId(currentDef.id)
- if (!levelDefs) {
- if (!decrement && updatedPoints.points >= currentDef.totalPoints) {
- UserAchievement groupAchievement = new UserAchievement(userId: userId.toLowerCase(), projectId: currentDef.projectId, skillId: currentDef.skillId, skillRefId: currentDef?.id,
- pointsWhenAchieved: updatedPoints.points)
- achievedLevelRepo.save(groupAchievement)
-
- res.completed.add(new CompletionItem(type: CompletionTypeUtil.getCompletionType(currentDef.type), id: currentDef.skillId, name: currentDef.name))
- } else if (decrement && updatedPoints.points <= currentDef.totalPoints) {
- // we are decrementing, there are no levels defined and points are less that total points so we need
- // to delete previously added achievement if it exists
- achievedLevelRepo.deleteByProjectIdAndSkillIdAndUserIdAndLevel(currentDef.projectId, currentDef.skillId, userId, null)
- }
- } else {
- int currentScore = decrement ? updatedPoints.points + requesterDef.pointIncrement : updatedPoints.points
- LevelDefinitionStorageService.LevelInfo levelInfo = levelDefService.getLevelInfo(currentDef.projectId, levelDefs, currentDef.totalPoints, currentScore)
- CompletionItem completionItem = calculateLevels(levelInfo, updatedPoints, currentDef, userId, currentDef.name, decrement)
- if (!decrement && completionItem?.level && completionItem?.level > 0) {
- res.completed.add(completionItem)
- }
- }
- }
-
- List parentsRels = skillEventsSupportRepo.findParentSkillsByChildIdAndType(currentDef.id, SkillRelDef.RelationshipType.RuleSetDefinition)
- parentsRels?.each {
- updateByTraversingUpSkillDefs(incomingSkillDate, res, it, requesterDef, userId, decrement)
- }
- }
-
- private boolean shouldEvaluateForAchievement(SkillEventsSupportRepo.SkillDefMin skillDef) {
- skillDef.type == SkillDef.ContainerType.Subject
- }
-
- @Profile
- private CompletionItem calculateLevels(LevelDefinitionStorageService.LevelInfo levelInfo, UserPoints userPts, SkillEventsSupportRepo.SkillDefMin skillDef, String userId, String name, boolean decrement) {
- CompletionItem res
-
- List userAchievedLevels = achievedLevelRepo.findAllByUserIdAndProjectIdAndSkillId(userId, userPts.projectId, userPts.skillId)
- boolean levelAlreadyAchieved = userAchievedLevels?.find { it.level == levelInfo.level }
- if (!levelAlreadyAchieved && !decrement) {
- UserAchievement newLevel = new UserAchievement(userId: userId.toLowerCase(), projectId: userPts.projectId, skillId: userPts.skillId, skillRefId: skillDef?.id,
- level: levelInfo.level, pointsWhenAchieved: userPts.points)
- achievedLevelRepo.save(newLevel)
- log.debug("Achieved new level [{}]", newLevel)
-
- res = new CompletionItem(
- level: newLevel.level, name: name,
- id: userPts.skillId ?: "OVERALL",
- type: userPts.skillId ? CompletionItem.CompletionItemType.Subject : CompletionItem.CompletionItemType.Overall)
- } else if (decrement) {
- // we are decrementing, so we need to remove any level that is greater than the current level (there should only be one)
- List levelsToRemove = userAchievedLevels?.findAll { it.level >= levelInfo.level }
- if (levelsToRemove) {
- assert levelsToRemove.size() == 1, "we are decrementing a single skill so we should not be remove multiple (${levelsToRemove.size()} levels)"
- achievedLevelRepo.delete(levelsToRemove.first())
- }
- }
-
- return res
- }
-
-
-}
diff --git a/backend/src/test/java/skills/intTests/metrics/MetricsSpec.groovy b/backend/src/test/java/skills/intTests/metrics/MetricsSpec.groovy
deleted file mode 100644
index 10e11a4b..00000000
--- a/backend/src/test/java/skills/intTests/metrics/MetricsSpec.groovy
+++ /dev/null
@@ -1,294 +0,0 @@
-/**
- * Copyright 2020 SkillTree
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package skills.intTests.metrics
-
-import groovy.util.logging.Slf4j
-import org.springframework.http.HttpStatus
-import skills.intTests.utils.DefaultIntSpec
-import skills.intTests.utils.SkillsClientException
-import skills.intTests.utils.SkillsFactory
-import skills.intTests.utils.TestUtils
-
-@Slf4j
-class MetricsSpec extends DefaultIntSpec {
-
- TestUtils testUtils = new TestUtils()
-
- def badge
-
- static final String projId = "TestProject1"
- static final String projId2 = "TestProject2"
-
- static final Map> sectionBuilders = [
- projects : [
- 'skills.metrics.builders.projects.AchievedSkillsChartBuilder',
- 'skills.metrics.builders.projects.ContinuedUsageChartBuilder',
- 'skills.metrics.builders.projects.DistinctUsersOverTimeChartBuilder',
- 'skills.metrics.builders.projects.NumUsersPerBadgeChartBuilder',
- 'skills.metrics.builders.projects.NumUsersPerLevelChartBuilder',
- 'skills.metrics.builders.projects.OverlookedSkillsChartBuilder',
- 'skills.metrics.builders.projects.TimeToAchieveChartBuilder',
- 'skills.metrics.builders.projects.TopAchievedChartBuilder',
- ],
- subjects : [
- 'skills.metrics.builders.subjects.AchievedSkillsChartBuilder',
- 'skills.metrics.builders.subjects.DistinctUsersOverTimeChartBuilder',
- 'skills.metrics.builders.subjects.NumUsersPerLevelChartBuilder',
-
- ],
- badges : [
- 'skills.metrics.builders.badges.AchievedPerMonthChartBuilder',
- 'skills.metrics.builders.badges.DistinctUsersOverTimeChartBuilder',
- ],
- skills : [
- 'skills.metrics.builders.skills.DistinctUsersOverTimeChartBuilder',
- ],
- users : [
- 'skills.metrics.builders.users.PointHistoryChartBuilder',
- ],
- ]
-
- static final Map sectionIds = [
- projects : "TestProject1",
- subjects : "subj1",
- badges : "badge1",
- skills : "s12",
- users : "User0",
- ]
-
- def setup() {
- List