diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml new file mode 100644 index 0000000..f3a888a --- /dev/null +++ b/.github/workflows/cron.yml @@ -0,0 +1,26 @@ +name: Daily Tests + +on: + schedule: + - cron: '0 0 * * *' # Runs at 00:00 UTC every day + +jobs: + tests: + uses: ./.github/workflows/tests.yml + secrets: inherit + + notify: + needs: [ tests ] + runs-on: ubuntu-24.04 + if: ${{ always() }} + steps: + - name: Slack Notifications + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_CHANNEL: boxlang-cron + SLACK_COLOR: ${{ job.status }} # or a specific color like 'green' or '#ff00ff' + SLACK_ICON_EMOJI: ":bell:" + SLACK_MESSAGE: '${{ github.repository }} weekly tests' + SLACK_TITLE: ${{ github.repository }} Tests results + SLACK_USERNAME: CI + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a48c550..b0bf721 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,10 +6,8 @@ on: - "main" - "master" - "development" - - "releases/v*" pull_request: branches: - - "releases/v*" - development jobs: @@ -17,9 +15,10 @@ jobs: uses: ./.github/workflows/tests.yml secrets: inherit - formatCheck: + # Format PR + format_check: name: Checks Source Code Formatting - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout Repository uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 39844c2..c9069d6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,9 +16,13 @@ on: default: false type: boolean + # Manual Trigger + workflow_dispatch: env: - MODULE_ID: cbsecurity + MODULE_ID: ${{ github.event.repository.name }} + JDK: 21 SNAPSHOT: ${{ inputs.snapshot || false }} + BUILD_ID: ${{ github.run_number }} jobs: ########################################################################################## @@ -26,7 +30,12 @@ jobs: ########################################################################################## build: name: Build & Publish - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 + permissions: + checks: write + pull-requests: write + contents: write + issues: write steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -36,6 +45,12 @@ jobs: with: forgeboxAPIKey: ${{ secrets.FORGEBOX_TOKEN }} + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: ${{ env.JDK }} + - name: "Setup Environment Variables For Build Process" id: current_version run: | @@ -50,7 +65,7 @@ jobs: fi - name: Update changelog [unreleased] with latest version - uses: thomaseizinger/keep-a-changelog-new-release@1.3.0 + uses: thomaseizinger/keep-a-changelog-new-release@3.1.0 if: env.SNAPSHOT == 'false' with: changelogPath: ./changelog.md @@ -61,10 +76,10 @@ jobs: npm install -g markdownlint-cli markdownlint changelog.md --fix box install commandbox-docbox - box task run taskfile=build/Build target=run :version=${{ env.VERSION }} :projectName=${{ env.MODULE_ID }} :buildID=${{ github.run_number }} :branch=${{ env.BRANCH }} + box task run taskfile=build/Build target=run :version=${{ env.VERSION }} :projectName=${{ env.MODULE_ID }} :buildID=${{ env.BUILD_ID }} :branch=${{ env.BRANCH }} - - name: Commit Changelog To Master - uses: EndBug/add-and-commit@v9.1.3 + - name: Commit Changelog [unreleased] with latest version + uses: EndBug/add-and-commit@v9.1.4 if: env.SNAPSHOT == 'false' with: author_name: Github Actions @@ -118,7 +133,7 @@ jobs: box forgebox publish --force - name: Create Github Release - uses: taiki-e/create-gh-release-action@v1.8.0 + uses: taiki-e/create-gh-release-action@v1.8.2 continue-on-error: true if: env.SNAPSHOT == 'false' with: @@ -127,14 +142,31 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} ref: refs/tags/v${{ env.VERSION }} + - name: Inform Slack + if: ${{ always() }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_CHANNEL: coding + SLACK_COLOR: ${{ job.status }} # or a specific color like 'green' or '#ff00ff' + SLACK_ICON_EMOJI: ":bell:" + SLACK_MESSAGE: "Module ${{ env.MODULE_ID }} v${{ env.VERSION }} Built with ${{ job.status }}!" + SLACK_TITLE: "ColdBox Module ${{ env.MODULE_ID }}" + SLACK_USERNAME: CI + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} + ########################################################################################## # Prep Next Release ########################################################################################## prep_next_release: name: Prep Next Release if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 needs: [ build ] + permissions: + checks: write + pull-requests: write + contents: write + issues: write steps: # Checkout development - name: Checkout Repository @@ -165,7 +197,7 @@ jobs: # Commit it back to development - name: Commit Version Bump - uses: EndBug/add-and-commit@v9.1.3 + uses: EndBug/add-and-commit@v9.1.4 with: author_name: Github Actions author_email: info@ortussolutions.com diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 63aca2e..50c8392 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -5,6 +5,13 @@ on: branches: - 'development' + workflow_dispatch: + +# Unique group name per workflow-branch/tag combo +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: ########################################################################################## # Module Tests @@ -18,7 +25,10 @@ jobs: ########################################################################################## format: name: Code Auto-Formatting - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 + permissions: + contents: write + checks: write steps: - uses: actions/checkout@v4 @@ -28,7 +38,7 @@ jobs: cmd: run-script format - name: Commit Format Changes - uses: stefanzweifel/git-auto-commit-action@v4 + uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: Apply cfformat changes @@ -39,5 +49,10 @@ jobs: uses: ./.github/workflows/release.yml needs: [ tests, format ] secrets: inherit + permissions: + checks: write + pull-requests: write + contents: write + issues: write with: snapshot: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5766983..6ca8fd9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ on: jobs: tests: name: Tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 env: DB_USER: root DB_PASSWORD: root @@ -18,16 +18,16 @@ jobs: strategy: fail-fast: false matrix: - cfengine: [ "lucee@5", "adobe@2018", "adobe@2021", "adobe@2023" ] - coldboxVersion: [ "^6.0.0", "^7.0.0" ] + cfengine: [ "boxlang-cfml@1", "lucee@5", "lucee@6", "adobe@2021", "adobe@2023" ] + coldboxVersion: [ "^7.0.0" ] experimental: [ false ] - # Here we tests all engines against ColdBox@BE + # Experimental: ColdBox BE vs All Engines include: - coldboxVersion: "be" cfengine: "lucee@5" experimental: true - coldboxVersion: "be" - cfengine: "adobe@2018" + cfengine: "lucee@6" experimental: true - coldboxVersion: "be" cfengine: "adobe@2021" @@ -35,17 +35,13 @@ jobs: - coldboxVersion: "be" cfengine: "adobe@2023" experimental: true + - coldboxVersion: "be" + cfengine: "boxlang-cfml@1" + experimental: true steps: - name: Checkout Repository uses: actions/checkout@v4 - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: "temurin" - java-version: "11" - - name: Setup Database and Fixtures run: | sudo systemctl start mysql.service @@ -54,6 +50,12 @@ jobs: # Import Database mysql -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} < test-harness/tests/resources/cbsecurity.sql + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "21" + - name: Setup Environment For Testing Process run: | # Setup .env diff --git a/.markdownlint.json b/.markdownlint.json index 8189ee3..21bc843 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -8,9 +8,9 @@ "no-multiple-blanks": { "maximum": 2 }, - "no-duplicate-heading" : false, "no-duplicate-header" : { "siblings_only" : true }, + "no-duplicate-heading" : false, "no-inline-html" : false } diff --git a/box.json b/box.json index f9c3754..f5a2254 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"ColdBox Security", - "version":"3.4.3", + "version":"3.5.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsecurity/@build.version@/cbsecurity-@build.version@.zip", "author":"Ortus Solutions.com ", "slug":"cbsecurity", @@ -28,10 +28,9 @@ "cbcsrf":"^3.0.0" }, "devDependencies":{ + "commandbox-boxlang":"*", "commandbox-cfformat":"*", - "commandbox-docbox":"*", - "commandbox-dotenv":"*", - "commandbox-cfconfig":"*" + "commandbox-docbox":"*" }, "ignore":[ "**/.*", @@ -48,18 +47,12 @@ "format":"cfformat run handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc --overwrite", "format:watch":"cfformat watch handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc ./.cfformat.json", "format:check":"cfformat check handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc", - "install:dependencies":"install && cd test-harness && install", + "install:dependencies":"install --force && cd test-harness && install --force", "start:lucee":"server start serverConfigFile=server-lucee@5.json", - "start:2018":"server start serverConfigFile=server-adobe@2018.json", - "start:2021":"server start serverConfigFile=server-adobe@2021.json", "start:2023":"server start serverConfigFile=server-adobe@2023.json", "stop:lucee":"server stop serverConfigFile=server-lucee@5.json", - "stop:2018":"server stop serverConfigFile=server-adobe@2018.json", - "stop:2021":"server stop serverConfigFile=server-adobe@2021.json", "stop:2023":"server stop serverConfigFile=server-adobe@2023.json", "logs:lucee":"server log serverConfigFile=server-lucee@5.json --follow", - "logs:2018":"server log serverConfigFile=server-adobe@2018.json --follow", - "logs:2021":"server log serverConfigFile=server-adobe@2021.json --follow", "logs:2023":"server log serverConfigFile=server-adobe@2023.json --follow" }, "installPaths":{ diff --git a/changelog.md b/changelog.md index 9fa0567..e82a200 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- BoxLang certification +- Github Actions updates + ## [3.4.3] - 2024-05-09 ## [3.4.2] - 2024-01-10 @@ -387,6 +392,9 @@ settings = { [Unreleased]: https://github.com/coldbox-modules/cbsecurity/compare/v3.4.3...HEAD +[3.4.3]: https://github.com/coldbox-modules/cbsecurity/compare/v3.4.2...v3.4.3 +[Unreleased]: https://github.com/coldbox-modules/cbsecurity/compare/v3.4.3...HEAD + [3.4.3]: https://github.com/coldbox-modules/cbsecurity/compare/v3.4.2...v3.4.3 [3.4.2]: https://github.com/coldbox-modules/cbsecurity/compare/v3.4.1...v3.4.2 diff --git a/models/jwt/JwtService.cfc b/models/jwt/JwtService.cfc index 857b611..aa1ad37 100644 --- a/models/jwt/JwtService.cfc +++ b/models/jwt/JwtService.cfc @@ -441,7 +441,7 @@ component accessors="true" singleton threadsafe { // Announce the invalid claims variables.interceptorService.announce( "cbSecurity_onJWTInvalidClaims", - { token : arguments.token, payload : decodedToken } + { token : token, payload : decodedToken } ); throw( @@ -652,7 +652,7 @@ component accessors="true" singleton threadsafe { function toEpoch( required target ){ return dateDiff( "s", - dateConvert( "utc2local", "January 1 1970 00:00" ), + dateConvert( "utc2local", "1970-01-01T00:00:00Z" ), arguments.target ); } @@ -666,7 +666,7 @@ component accessors="true" singleton threadsafe { return dateAdd( "s", arguments.target, // should be in utc - dateConvert( "utc2local", "January 1 1970 00:00" ) + dateConvert( "utc2local", "1970-01-01T00:00:00Z" ) ); } diff --git a/server-adobe@2021.json b/server-adobe@2021.json index 39b2bdc..a43ff4b 100644 --- a/server-adobe@2021.json +++ b/server-adobe@2021.json @@ -17,7 +17,8 @@ } }, "jvm":{ - "heapSize":"1024" + "heapSize":"1024", + "javaVersion":"openjdk11_jre" }, "openBrowser":"false", "cfconfig":{ diff --git a/server-boxlang-cfml@1.json b/server-boxlang-cfml@1.json new file mode 100644 index 0000000..50158b5 --- /dev/null +++ b/server-boxlang-cfml@1.json @@ -0,0 +1,32 @@ +{ + "name":"cbsecurity-boxlang-cfml@1", + "app":{ + "serverHomeDirectory":".engine/boxlang", + "cfengine":"boxlang@be" + }, + "web":{ + "http":{ + "port":"60299" + }, + "rewrites":{ + "enable":"true" + }, + "webroot":"test-harness", + "aliases":{ + "/moduleroot/cbsecurity":"../" + } + }, + "JVM":{ + "heapSize":"1024", + "javaVersion":"openjdk21_jre", + "args":"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888" + }, + "openBrowser":"false", + "cfconfig":{ + "file":".cfconfig.json" + }, + "env":{}, + "scripts":{ + "onServerInitialInstall":"install bx-compat-cfml,bx-esapi,bx-mysql --noSave" + } +} diff --git a/server-adobe@2018.json b/server-lucee@6.json similarity index 76% rename from server-adobe@2018.json rename to server-lucee@6.json index 2f498c3..9457279 100644 --- a/server-adobe@2018.json +++ b/server-lucee@6.json @@ -1,8 +1,8 @@ { - "name":"cbsecurity-adobe@2018", + "name":"cbsecurity-lucee@6", "app":{ - "serverHomeDirectory":".engine/adobe2018", - "cfengine":"adobe@2018" + "serverHomeDirectory":".engine/lucee6", + "cfengine":"lucee@6" }, "web":{ "http":{ diff --git a/test-harness/box.json b/test-harness/box.json index 308e694..629a8ca 100644 --- a/test-harness/box.json +++ b/test-harness/box.json @@ -5,14 +5,11 @@ "private":true, "description":"", "dependencies":{ - "coldbox":"^6.0.0", - "cbauth":"^6.0.0", - "BCrypt":"^2.0.0", - "jwt-cfml":"^1.0.0", - "cbcsrf":"^3.0.0" + "coldbox":"^7", + "BCrypt":"^3.1.0+4" }, "devDependencies":{ - "cbdebugger":"^4.0.0", + "cbdebugger":"^4.0.0", "testbox":"*", "route-visualizer":"*" }, diff --git a/test-harness/handlers/Public.cfc b/test-harness/handlers/Public.cfc index 529a439..9114e79 100644 --- a/test-harness/handlers/Public.cfc +++ b/test-harness/handlers/Public.cfc @@ -37,11 +37,11 @@ component { } function toEpoch( required target ){ - return dateDiff( "s", dateConvert( "utc2local", "January 1 1970 00:00" ), arguments.target ); + return dateDiff( "s", dateConvert( "utc2local", "1970-01-01T00:00:00Z" ), arguments.target ); } function fromEpoch( required target ){ - return dateAdd( "s", arguments.target, dateConvert( "utc2local", "January 1 1970 00:00" ) ); + return dateAdd( "s", arguments.target, dateConvert( "utc2local", "1970-01-01T00:00:00Z" ) ); } } diff --git a/test-harness/tests/Application.cfc b/test-harness/tests/Application.cfc index ea12dfe..8ba0b8d 100644 --- a/test-harness/tests/Application.cfc +++ b/test-harness/tests/Application.cfc @@ -52,7 +52,7 @@ component { // If hitting the runner or specs, prep our virtual app if ( getBaseTemplatePath().replace( expandPath( "/tests" ), "" ).reFindNoCase( "(runner|specs)" ) ) { - request.coldBoxVirtualApp.startup(); + request.coldBoxVirtualApp.startup( true ); } return true; diff --git a/test-harness/tests/specs/integration/JWTSpec.cfc b/test-harness/tests/specs/integration/JWTSpec.cfc index 403745b..cb8403c 100644 --- a/test-harness/tests/specs/integration/JWTSpec.cfc +++ b/test-harness/tests/specs/integration/JWTSpec.cfc @@ -48,6 +48,8 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/root" { variables.jwtService.getSettings().jwt.tokenStorage.enabled = true; variables.jwtService.getSettings().jwt.tokenStorage.driver = "cachebox"; variables.jwtService.getSettings().jwt.tokenStorage.properties = { "cacheName" : "default" }; + + variables.defaultIssuer = variables.jwtService.getSettings().jwt.issuer; // Recreate Token Storage variables.jwtService.getTokenStorage( force: true ); } @@ -79,6 +81,7 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/root" { beforeEach( function( currentSpec ){ variables.jwtService.getSettings().jwt.enableAutoRefreshValidator = true; variables.jwtAuthValidator = getInstance( "JwtAuthValidator@cbsecurity" ); + variables.jwtService.getSettings().jwt.issuer = variables.defaultIssuer; } ); afterEach( function( currentSpec ){ variables.jwtService.getSettings().jwt.enableAutoRefreshValidator = false; @@ -103,6 +106,7 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/root" { } ); given( "Auto refresh is on and an expired access token is sent but no refresh token is sent", function(){ then( "the validation should fail", function(){ + // variables.jwtService.getSettings().jwt.issuer = "http://127.0.0.1:56596/"; getRequestContext().setValue( "x-auth-token", variables.expired_token ); var results = variables.jwtAuthValidator.validateSecurity( "" ); expect( results.allow ).toBeFalse( results.toString() ); @@ -388,10 +392,13 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/root" { given( "a valid jwt token put in to storage", function(){ then( "it should use the exp on the token for the storage timeout", function(){ - var originalTokenStorage = duplicate( variables.jwtService.getTokenStorage() ); + var originalTokenStorage = variables.jwtService.getTokenStorage(); try { - variables.jwtService.getTokenStorage().clearAll(); - var tokenStorageMock = prepareMock( variables.jwtService.getTokenStorage() ); + var tokenStorageMock = prepareMock( + new cbsecurity.models.jwt.storages.CacheTokenStorage() + ); + getWirebox().autowire( tokenStorageMock ); + variables.jwtService.setTokenStorage( tokenStorageMock ); tokenStorageMock.$( "set", tokenStorageMock ); var expirationSeconds = 100; var expirationTime = variables.jwtService.toEpoch(