diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..b3cf179 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,56 @@ +name: Java CI +on: + push: + branches: + - '[5-9]+.[0-9]+.x' + pull_request: + branches: + - '[5-9]+.[0-9]+.x' + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + env: + WORKSPACE: ${{ github.workspace }} + GRADLE_OPTS: -Xmx1500m -Dfile.encoding=UTF-8 + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + - name: Run Tests + if: github.event_name == 'pull_request' + id: tests + uses: gradle/gradle-build-action@v2 + with: + arguments: check -Dgeb.env=chromeHeadless + - name: Run Build + if: github.event_name == 'push' + id: build + uses: gradle/gradle-build-action@v2 + env: + GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} + with: + arguments: build -Dgeb.env=chromeHeadless + - name: Publish Test Report + if: steps.build.outcome == 'failure' || steps.tests.outcome == 'failure' + uses: scacap/action-surefire-report@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + report_paths: '**/build/test-results/test/TEST-*.xml' + - name: Publish to repo.grails.org + id: publish + uses: gradle/gradle-build-action@v2 + if: steps.build.outcome == 'success' && github.event_name == 'push' + env: + ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} + ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} + with: + arguments: -Dorg.gradle.internal.publish.checksums.insecure=true publish + - name: Build Documentation + id: docs + uses: gradle/gradle-build-action@v2 + with: + arguments: docs:docs diff --git a/README.md b/README.md index fd59714..63a82d9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![Build Status](https://travis-ci.org/grails-plugins/grails-spring-security-acl.svg?branch=master) - Grails Spring Security ACL Plugin ================================== diff --git a/build.gradle b/build.gradle index 92fc468..04ae5bc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,8 @@ subprojects { configurations.configureEach { resolutionStrategy.eachDependency { DependencyResolveDetails details -> - if ((details.requested.group == 'org.codehaus.groovy' || details.requested.group == 'org.apache.groovy') && details.requested.name != 'groovy-bom') { - String groovyVersion = findProperty('groovyVersion') ?: libs.versions.groovy.get() - details.useTarget(group: 'org.apache.groovy', name: details.requested.name, version: groovyVersion) - details.because "The dependency coordinates are changed in Apache Groovy 4, plus ensure version" + if (details.requested.group == 'org.seleniumhq.selenium') { + details.useVersion(seleniumVersion) } } } diff --git a/docs/build.gradle b/docs/build.gradle index c8ac3e7..0a7c9b5 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -3,14 +3,17 @@ buildscript { maven { url 'https://repo.grails.org/grails/core' } } dependencies { - classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.6.1' - classpath 'org.asciidoctor:asciidoctorj-epub3:2.1.3' - classpath 'org.asciidoctor:asciidoctorj-pdf:2.3.18' + classpath 'org.asciidoctor:asciidoctor-gradle-jvm:4.0.3' + classpath "org.asciidoctor:asciidoctor-gradle-jvm-epub:4.0.3" + classpath "org.asciidoctor:asciidoctor-gradle-jvm-pdf:4.0.3" + classpath "org.asciidoctor:asciidoctor-gradle-jvm-gems:4.0.3" } } -import org.apache.tools.ant.taskdefs.condition.Os -apply plugin: 'org.asciidoctor.convert' +apply plugin: "org.asciidoctor.jvm.gems" +apply plugin: 'org.asciidoctor.jvm.convert' +apply plugin: "org.asciidoctor.jvm.pdf" +apply plugin: "org.asciidoctor.jvm.epub" def asciidoctorAttributes = [ copyright : 'Apache License, Version 2.0', @@ -34,28 +37,62 @@ def asciidoctorAttributes = [ projectVersion : project.projectVersion, ] +repositories { + mavenCentral() + maven { url 'https://repo.grails.org/grails/core' } + ruby.gems() +} -import org.apache.tools.ant.taskdefs.condition.Os -import org.asciidoctor.gradle.AsciidoctorTask +dependencies { + asciidoctorGems 'rubygems:rouge:4.4.0' +} -tasks.withType(AsciidoctorTask) { +asciidoctor { + sourceDir file('src/docs') + sources { + include 'index.adoc' + } + outputDir = new File(buildDir, 'docs') attributes asciidoctorAttributes - outputDir new File(buildDir, 'docs') - separateOutputDirs = false +} + +asciidoctorPdf { + dependsOn asciidoctorGemsPrepare sourceDir = file('src/docs') sources { include 'index.adoc' } + outputDir = new File(buildDir, 'docs') + + asciidoctorj { + requires 'rouge' + attributes asciidoctorAttributes + } } +asciidoctorEpub { + dependsOn asciidoctorGemsPrepare + sourceDir = file('src/docs') + sources { + include 'index.adoc' + } + outputDir = new File(buildDir, 'docs') -task asciidoc(type: AsciidoctorTask, description: 'Generates single-page HTML, PDF, and EPUB3') { - group 'documentation' - backends 'html5', 'pdf', 'epub3' + asciidoctorj { + requires 'rouge' + attributes asciidoctorAttributes + } + + ebookFormats = ["EPUB3"] +} + +tasks.named("asciidoctor").configure { + dependsOn = ['asciidoctorPdf', 'asciidoctorEpub'] } -task docs(dependsOn: [asciidoc]) { - group 'documentation' +tasks.register("docs") { + group = "documentation" + dependsOn = ["asciidoctor"] doLast { File dir = new File(buildDir, 'docs') ['epub', 'pdf'].each { String ext -> @@ -73,4 +110,4 @@ task docs(dependsOn: [asciidoc]) { include '**/*.png' } } -} \ No newline at end of file +} diff --git a/docs/src/docs/index.adoc b/docs/src/docs/index.adoc index fa5c95a..11e1d7b 100644 --- a/docs/src/docs/index.adoc +++ b/docs/src/docs/index.adoc @@ -1,3 +1,4 @@ +:includedir: src/docs/ = Spring Security ACL Plugin - Reference Documentation Burt Beckwith @@ -8,20 +9,20 @@ Burt Beckwith :toclevels: 2 :numbered: -include::introduction.adoc[] +include::{includedir}introduction.adoc[] -include::installing.adoc[] +include::{includedir}installing.adoc[] -include::usage.adoc[] +include::{includedir}usage.adoc[] -include::tutorial.adoc[] +include::{includedir}tutorial.adoc[] -include::sampleApp.adoc[] +include::{includedir}sampleApp.adoc[] -include::AclUtilService.adoc[] +include::{includedir}AclUtilService.adoc[] -include::Scripts.adoc[] +include::{includedir}Scripts.adoc[] -include::TagLibraries.adoc[] +include::{includedir}TagLibraries.adoc[] -include::history.adoc[] \ No newline at end of file +include::{includedir}history.adoc[] \ No newline at end of file diff --git a/functional-test-app/build.gradle b/functional-test-app/build.gradle index 1fe4693..5cd8dca 100644 --- a/functional-test-app/build.gradle +++ b/functional-test-app/build.gradle @@ -7,7 +7,7 @@ buildscript { classpath "org.grails:grails-gradle-plugin:$grailsVersion" classpath "com.bertramlabs.plugins:asset-pipeline-gradle:5.0.1" classpath "org.grails.plugins:hibernate5:$gormVersion" - classpath "gradle.plugin.com.github.erdi.webdriver-binaries:webdriver-binaries-gradle-plugin:2.7" + classpath "com.github.erdi:webdriver-binaries-gradle-plugin:3.2" } } @@ -41,12 +41,11 @@ dependencies { implementation "org.grails:grails-plugin-url-mappings" implementation "org.grails:grails-plugin-interceptors" implementation "org.grails:grails-web-boot" - implementation "org.grails.plugins:cache" implementation "org.grails.plugins:async" implementation "org.grails.plugins:scaffolding" implementation "org.grails.plugins:events" implementation "org.grails.plugins:hibernate5" - implementation "org.hibernate:hibernate-core:$hibernateCoreVersion" + implementation "org.hibernate:hibernate-core-jakarta:$hibernateCoreVersion" implementation "org.grails.plugins:gsp" console "org.grails:grails-console" profile "org.grails.profiles:web" @@ -55,24 +54,27 @@ dependencies { runtimeOnly "com.h2database:h2" testImplementation "org.grails:grails-gorm-testing-support" testImplementation "org.grails:grails-web-testing-support" - testImplementation "io.micronaut:micronaut-http-client:$micronautVersion" - testImplementation "org.grails.plugins:geb" - testRuntimeOnly "org.seleniumhq.selenium:selenium-chrome-driver:4.19.1" - testImplementation "org.seleniumhq.selenium:selenium-remote-driver:4.19.1" - testImplementation "org.seleniumhq.selenium:selenium-api:4.19.1" - implementation project(':spring-security-acl') -} + integrationTestImplementation testFixtures('org.grails.plugins:geb') -webdriverBinaries { - chromedriver '2.46.0' - geckodriver '0.29.1' + testRuntimeOnly "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion" + testRuntimeOnly "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion" + testRuntimeOnly "org.seleniumhq.selenium:selenium-safari-driver:$seleniumVersion" + testImplementation "org.seleniumhq.selenium:selenium-remote-driver:$seleniumVersion" + testImplementation "org.seleniumhq.selenium:selenium-api:$seleniumVersion" + implementation project(':spring-security-acl') } tasks.withType(Test) { useJUnitPlatform() systemProperty "geb.env", System.getProperty('geb.env') - systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver') - systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver') + systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest") + if (System.getenv('CHROMEWEBDRIVER')) { + systemProperty 'webdriver.chrome.driver', "${System.getenv('CHROMEWEBDRIVER')}/chromedriver" + } + if (System.getenv('GECKOWEBDRIVER')) { + systemProperty 'webdriver.gecko.driver', "${System.getenv('GECKOWEBDRIVER')}/geckodriver" + } + beforeTest { descriptor -> logger.quiet " -- $descriptor" } testLogging { events "passed", "skipped", "failed" diff --git a/functional-test-app/grails-app/conf/application.yml b/functional-test-app/grails-app/conf/application.yml index 4d17859..551d12b 100644 --- a/functional-test-app/grails-app/conf/application.yml +++ b/functional-test-app/grails-app/conf/application.yml @@ -1,33 +1,65 @@ ---- -grails: - profile: web - codegen: - defaultPackage: misc.functional.test.app - spring: - transactionManagement: - proxies: false - gorm: - reactor: - # Whether to translate GORM events into Reactor events - # Disabled by default for performance reasons - events: false info: - app: - name: '@info.app.name@' - version: '@info.app.version@' - grailsVersion: '@info.app.grailsVersion@' -spring: - main: - banner-mode: "off" - groovy: - template: - check-template-location: false - -# Spring Actuator Endpoints are Disabled by Default -endpoints: - enabled: false - jmx: - enabled: true + app: + name: '@info.app.name@' + version: '@info.app.version@' + grailsVersion: '@info.app.grailsVersion@' +grails: + mime: + disable: + accept: + header: + userAgents: + - Gecko + - WebKit + - Presto + - Trident + types: + all: '*/*' + atom: application/atom+xml + css: text/css + csv: text/csv + form: application/x-www-form-urlencoded + html: + - text/html + - application/xhtml+xml + js: text/javascript + json: + - application/json + - text/json + multipartForm: multipart/form-data + pdf: application/pdf + rss: application/rss+xml + text: text/plain + hal: + - application/hal+json + - application/hal+xml + xml: + - text/xml + - application/xml + views: + gsp: + encoding: UTF-8 + htmlcodec: xml + codecs: + expression: html + scriptlet: html + taglib: none + staticparts: none + default: + codec: html +dataSource: + url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE + driverClassName: org.h2.Driver + username: sa + password: '' + pooled: true + jmxExport: true + dbCreate: update +hibernate: + cache: + queries: false + use_second_level_cache: false + use_query_cache: false --- grails: @@ -35,103 +67,3 @@ grails: springsecurity: userLookup: user-domain-class-name: com.testacl.User - mime: - disable: - accept: - header: - userAgents: - - Gecko - - WebKit - - Presto - - Trident - types: - all: '*/*' - atom: application/atom+xml - css: text/css - csv: text/csv - form: application/x-www-form-urlencoded - html: - - text/html - - application/xhtml+xml - js: text/javascript - json: - - application/json - - text/json - multipartForm: multipart/form-data - pdf: application/pdf - rss: application/rss+xml - text: text/plain - hal: - - application/hal+json - - application/hal+xml - xml: - - text/xml - - application/xml - urlmapping: - cache: - maxsize: 1000 - controllers: - defaultScope: singleton - converters: - encoding: UTF-8 - views: - default: - codec: html - gsp: - encoding: UTF-8 - htmlcodec: xml - codecs: - expression: html - scriptlets: html - taglib: none - staticparts: none -endpoints: - jmx: - unique-names: true - ---- -hibernate: - cache: - queries: false - use_second_level_cache: false - use_query_cache: false - -dataSource: - pooled: true - jmxExport: true - driverClassName: org.h2.Driver - username: sa - password: '' - -environments: - development: - dataSource: - dbCreate: create-drop - url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE - test: - dataSource: - dbCreate: update - url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE - production: - dataSource: - dbCreate: none - url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE - properties: - jmxEnabled: true - initialSize: 5 - maxActive: 50 - minIdle: 5 - maxIdle: 25 - maxWait: 10000 - maxAge: 600000 - timeBetweenEvictionRunsMillis: 5000 - minEvictableIdleTimeMillis: 60000 - validationQuery: SELECT 1 - validationQueryTimeout: 3 - validationInterval: 15000 - testOnBorrow: true - testWhileIdle: true - testOnReturn: false - jdbcInterceptors: ConnectionState - defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED - diff --git a/functional-test-app/grails-app/controllers/com/testacl/ErrorsController.groovy b/functional-test-app/grails-app/controllers/com/testacl/ErrorsController.groovy index a71f6d2..4529276 100644 --- a/functional-test-app/grails-app/controllers/com/testacl/ErrorsController.groovy +++ b/functional-test-app/grails-app/controllers/com/testacl/ErrorsController.groovy @@ -7,11 +7,6 @@ import groovy.transform.CompileStatic @Secured('permitAll') class ErrorsController { - def error403() { - // Line necessary due to: https://github.com/grails/grails-core/issues/10582 - [view: 'error403'] - } - def error404() { String uri = 'request.forwardURI' if (!uri.contains('favicon.ico')) { diff --git a/functional-test-app/grails-app/controllers/com/testacl/UrlMappings.groovy b/functional-test-app/grails-app/controllers/com/testacl/UrlMappings.groovy index 2a720f4..4d622d3 100644 --- a/functional-test-app/grails-app/controllers/com/testacl/UrlMappings.groovy +++ b/functional-test-app/grails-app/controllers/com/testacl/UrlMappings.groovy @@ -13,7 +13,7 @@ class UrlMappings { "403"(controller: 'errors', action: 'error403') "404"(controller: 'errors', action: 'error404') "500"(controller: 'errors', action: 'error500') - "500"(controller: 'errors', action: 'error403', exception: AccessDeniedException) - "500"(controller: 'errors', action: 'error403', exception: NotFoundException) + "500"(view: 'errors/error403', exception: AccessDeniedException) + "500"(controller: 'errors', action: 'error404', exception: NotFoundException) } } diff --git a/functional-test-app/grails-app/domain/com/testacl/User.groovy b/functional-test-app/grails-app/domain/com/testacl/User.groovy index 2dd9ab3..543a582 100644 --- a/functional-test-app/grails-app/domain/com/testacl/User.groovy +++ b/functional-test-app/grails-app/domain/com/testacl/User.groovy @@ -24,4 +24,8 @@ class User implements Serializable { username blank: false, unique: true password blank: false } + + static mapping = { + table name: '`user`' + } } diff --git a/functional-test-app/grails-app/domain/com/testacl/UserRole.groovy b/functional-test-app/grails-app/domain/com/testacl/UserRole.groovy index 48b20f2..fdc68cb 100644 --- a/functional-test-app/grails-app/domain/com/testacl/UserRole.groovy +++ b/functional-test-app/grails-app/domain/com/testacl/UserRole.groovy @@ -2,7 +2,8 @@ package com.testacl import grails.gorm.DetachedCriteria import groovy.transform.ToString -import org.apache.commons.lang.builder.HashCodeBuilder +import org.apache.commons.lang3.builder.HashCodeBuilder +import org.hibernate.ObjectNotFoundException @ToString(cache=true, includeNames=true, includePackage=false) class UserRole implements Serializable { @@ -86,7 +87,11 @@ class UserRole implements Serializable { if (ur.user == null || ur.user.id == null) return boolean existing = false UserRole.withNewSession { - existing = UserRole.exists(ur.user.id, r.id) + try { + existing = UserRole.exists(ur.user.id, r.id) + } catch (ObjectNotFoundException ignored) { + // no-op + } } if (existing) { return 'userRole.exists' diff --git a/functional-test-app/grails-app/init/com/testacl/BootStrap.groovy b/functional-test-app/grails-app/init/com/testacl/BootStrap.groovy index 5c8799e..cff71db 100644 --- a/functional-test-app/grails-app/init/com/testacl/BootStrap.groovy +++ b/functional-test-app/grails-app/init/com/testacl/BootStrap.groovy @@ -2,9 +2,6 @@ package com.testacl class BootStrap { - TestDataService testDataService - def init = { - testDataService.reset() } } diff --git a/functional-test-app/grails-app/services/com/testacl/ReportService.groovy b/functional-test-app/grails-app/services/com/testacl/ReportService.groovy index be1cbba..65a6d7b 100644 --- a/functional-test-app/grails-app/services/com/testacl/ReportService.groovy +++ b/functional-test-app/grails-app/services/com/testacl/ReportService.groovy @@ -8,6 +8,7 @@ import org.springframework.security.acls.domain.BasePermission import org.springframework.security.acls.domain.PermissionFactory import org.springframework.security.acls.model.Permission import grails.gorm.transactions.Transactional +import org.springframework.security.core.parameters.P class ReportService { @@ -17,13 +18,13 @@ class ReportService { @PreAuthorize('hasPermission(#report, admin)') @Transactional - void addPermission(Report report, String username, int permission) { + void addPermission(@P("report") Report report, String username, int permission) { addPermission report, username, aclPermissionFactory.buildFromMask(permission) } @PreAuthorize('hasPermission(#report, admin)') @Transactional - void addPermission(Report report, String username, Permission permission) { + void addPermission(@P("report") Report report, String username, Permission permission) { aclUtilService.addPermission report, username, permission } @@ -40,7 +41,7 @@ class ReportService { } @PreAuthorize('hasPermission(#id, "com.testacl.Report", read) or hasPermission(#id, "com.testacl.Report", admin)') - Report get(long id) { + Report get(@P("id") long id) { Report.get id } @@ -56,13 +57,13 @@ class ReportService { @Transactional @PreAuthorize('hasPermission(#report, write) or hasPermission(#report, admin)') - void update(Report report, String name) { + void update(@P("report") Report report, String name) { report.name = name } @Transactional @PreAuthorize('hasPermission(#report, delete) or hasPermission(#report, admin)') - void delete(Report report) { + void delete(@P("report") Report report) { report.delete() // Delete the ACL information as well diff --git a/functional-test-app/grails-app/services/com/testacl/TestDataService.groovy b/functional-test-app/grails-app/services/com/testacl/TestDataService.groovy index fa414a7..da394e5 100644 --- a/functional-test-app/grails-app/services/com/testacl/TestDataService.groovy +++ b/functional-test-app/grails-app/services/com/testacl/TestDataService.groovy @@ -9,6 +9,7 @@ import grails.plugin.springsecurity.acl.AclSid import grails.plugin.springsecurity.acl.AclUtilService import grails.gorm.transactions.Transactional import groovy.util.logging.Slf4j +import jakarta.annotation.PostConstruct import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.authority.SimpleGrantedAuthority @@ -26,6 +27,11 @@ class TestDataService { AclUtilService aclUtilService ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy + @PostConstruct + void init() { + reset() + } + void reset() { deleteAll() createData() diff --git a/functional-test-app/src/integration-test/groovy/test/AbstractSecuritySpec.groovy b/functional-test-app/src/integration-test/groovy/test/AbstractSecuritySpec.groovy index 41ac33b..69ef12b 100644 --- a/functional-test-app/src/integration-test/groovy/test/AbstractSecuritySpec.groovy +++ b/functional-test-app/src/integration-test/groovy/test/AbstractSecuritySpec.groovy @@ -1,12 +1,13 @@ package test import geb.spock.GebReportingSpec +import grails.gorm.transactions.Rollback import grails.testing.mixin.integration.Integration import pages.LoginPage import spock.lang.Shared @Integration -@grails.gorm.transactions.Rollback +@Rollback abstract class AbstractSecuritySpec extends GebReportingSpec { @Shared boolean reset = false diff --git a/functional-test-app/src/integration-test/resources/GebConfig.groovy b/functional-test-app/src/integration-test/resources/GebConfig.groovy index 17723e5..adb480e 100644 --- a/functional-test-app/src/integration-test/resources/GebConfig.groovy +++ b/functional-test-app/src/integration-test/resources/GebConfig.groovy @@ -1,21 +1,41 @@ import org.openqa.selenium.chrome.ChromeDriver import org.openqa.selenium.chrome.ChromeOptions - -reportsDir = new File('build/geb-reports') +import org.openqa.selenium.firefox.FirefoxDriver +import org.openqa.selenium.firefox.FirefoxOptions +import org.openqa.selenium.safari.SafariDriver environments { - // run via “./gradlew -Dgeb.env=chrome iT” - chrome { - driver = { new ChromeDriver() } - } + // You need to configure in Safari -> Develop -> Allowed Remote Automation + safari { + driver = { new SafariDriver() } + } + + // run via “./gradlew -Dgeb.env=chrome iT” + chrome { + driver = { new ChromeDriver() } + } + + // run via “./gradlew -Dgeb.env=chromeHeadless iT” + chromeHeadless { + driver = { + ChromeOptions o = new ChromeOptions() + o.addArguments('headless') + new ChromeDriver(o) + } + } + + // run via “./gradlew -Dgeb.env=firefoxHeadless iT” + firefoxHeadless { + driver = { + FirefoxOptions o = new FirefoxOptions() + o.addArguments('-headless') + new FirefoxDriver(o) + } + } - // run via “./gradlew -Dgeb.env=chromeHeadless iT” - chromeHeadless { - driver = { - ChromeOptions o = new ChromeOptions() - o.addArguments('headless') - new ChromeDriver(o) - } - } -} + // run via “./gradlew -Dgeb.env=firefox iT” + firefox { + driver = { new FirefoxDriver() } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 5652d90..a1cdf3a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ springSecurityCoreVersion=7.0.0-SNAPSHOT jakartaServletApiVersion=6.0.0 micronautVersion=4.5.3 hibernateCoreVersion=5.6.15.Final -groovyVersion=4.0.23 ehcacheVersion=3.10.8 +seleniumVersion=4.26.0 diff --git a/integration-test-app/build.gradle b/integration-test-app/build.gradle index d5f2e4b..701bc6b 100644 --- a/integration-test-app/build.gradle +++ b/integration-test-app/build.gradle @@ -37,12 +37,11 @@ dependencies { implementation "org.grails:grails-plugin-services" implementation "org.grails:grails-plugin-url-mappings" implementation "org.grails:grails-plugin-interceptors" - implementation "org.grails.plugins:cache" implementation "org.grails.plugins:async" implementation "org.grails.plugins:scaffolding" implementation "org.grails.plugins:events" implementation "org.grails.plugins:hibernate5" - implementation "org.hibernate:hibernate-core:$hibernateCoreVersion" + implementation "org.hibernate:hibernate-core-jakarta:$hibernateCoreVersion" implementation "org.grails.plugins:gsp" console "org.grails:grails-console" profile "org.grails.profiles:web" diff --git a/integration-test-app/grails-app/conf/application.yml b/integration-test-app/grails-app/conf/application.yml index 570acf8..d87bb9a 100644 --- a/integration-test-app/grails-app/conf/application.yml +++ b/integration-test-app/grails-app/conf/application.yml @@ -1,114 +1,63 @@ ---- -grails: - profile: web - codegen: - defaultPackage: grails.plugin.springsecurity.acl - spring: - transactionManagement: - proxies: false - gorm: - reactor: - # Whether to translate GORM events into Reactor events - # Disabled by default for performance reasons - events: false -info: - app: - name: '@info.app.name@' - version: '@info.app.version@' - grailsVersion: '@info.app.grailsVersion@' -spring: - main: - banner-mode: "off" - groovy: - template: - check-template-location: false - -# Spring Actuator Endpoints are Disabled by Default -endpoints: - enabled: false - jmx: - enabled: true ---- +info: + app: + name: '@info.app.name@' + version: '@info.app.version@' + grailsVersion: '@info.app.grailsVersion@' grails: - mime: - disable: - accept: - header: - userAgents: - - Gecko - - WebKit - - Presto - - Trident - types: - all: '*/*' - atom: application/atom+xml - css: text/css - csv: text/csv - form: application/x-www-form-urlencoded - html: - - text/html - - application/xhtml+xml - js: text/javascript - json: - - application/json - - text/json - multipartForm: multipart/form-data - pdf: application/pdf - rss: application/rss+xml - text: text/plain - hal: - - application/hal+json - - application/hal+xml - xml: - - text/xml - - application/xml - urlmapping: - cache: - maxsize: 1000 - controllers: - defaultScope: singleton - converters: - encoding: UTF-8 - views: - default: - codec: html - gsp: - encoding: UTF-8 - htmlcodec: xml - codecs: - expression: html - scriptlets: html - taglib: none - staticparts: none -endpoints: - jmx: - unique-names: true - ---- -hibernate: - cache: - queries: false - use_query_cache: false - use_second_level_cache: false - format_sql: true - use_sql_comments: true - -#dataSource: -# dbCreate: update -# driverClassName: com.mysql.jdbc.Driver -# dialect: org.hibernate.dialect.MySQL5InnoDBDialect -# jmxExport: false -# password: root -# pooled: true -# url: jdbc:mysql://127.0.0.1:8889/acl -# username: root - + mime: + disable: + accept: + header: + userAgents: + - Gecko + - WebKit + - Presto + - Trident + types: + all: '*/*' + atom: application/atom+xml + css: text/css + csv: text/csv + form: application/x-www-form-urlencoded + html: + - text/html + - application/xhtml+xml + js: text/javascript + json: + - application/json + - text/json + multipartForm: multipart/form-data + pdf: application/pdf + rss: application/rss+xml + text: text/plain + hal: + - application/hal+json + - application/hal+xml + xml: + - text/xml + - application/xml + views: + gsp: + encoding: UTF-8 + htmlcodec: xml + codecs: + expression: html + scriptlet: html + taglib: none + staticparts: none + default: + codec: html dataSource: - pooled: true - jmxExport: true - driverClassName: org.h2.Driver - username: sa - password: '' - dbCreate: create-drop - url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE + url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE + driverClassName: org.h2.Driver + username: sa + password: '' + pooled: true + jmxExport: true + dbCreate: update +hibernate: + cache: + queries: false + use_second_level_cache: false + use_query_cache: false diff --git a/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/AclServiceSpec.groovy b/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/AclServiceSpec.groovy index b700937..98d89a5 100644 --- a/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/AclServiceSpec.groovy +++ b/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/AclServiceSpec.groovy @@ -15,7 +15,7 @@ package grails.plugin.springsecurity.acl import grails.gorm.transactions.Rollback -import net.sf.ehcache.Ehcache +import org.springframework.cache.CacheManager import org.springframework.security.acls.domain.BasePermission import org.springframework.security.acls.domain.CumulativePermission import org.springframework.security.acls.domain.GrantedAuthoritySid @@ -55,14 +55,14 @@ class AclServiceSpec extends AbstractIntegrationSpec { AclCache aclCache AclService aclService - Ehcache ehcacheAclCache + CacheManager aclCacheManager void setup() { principalSid = new PrincipalSid(authenticate('ben', 'ROLE_ADMIN')) } void cleanup() { - ehcacheAclCache.removeAll() + aclCacheManager.getCache("aclCache").clear() } void 'test lifecycle'() { diff --git a/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/jdbc/GormAclLookupStrategySpec.groovy b/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/jdbc/GormAclLookupStrategySpec.groovy index 26cb770..e2a7c3b 100644 --- a/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/jdbc/GormAclLookupStrategySpec.groovy +++ b/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/acl/jdbc/GormAclLookupStrategySpec.groovy @@ -20,7 +20,7 @@ import grails.plugin.springsecurity.acl.AclClass import grails.plugin.springsecurity.acl.AclEntry import grails.plugin.springsecurity.acl.AclObjectIdentity import grails.plugin.springsecurity.acl.AclSid -import net.sf.ehcache.Ehcache +import org.springframework.cache.CacheManager import org.springframework.security.acls.domain.BasePermission import org.springframework.security.acls.domain.ObjectIdentityImpl import org.springframework.security.acls.domain.PrincipalSid @@ -50,7 +50,7 @@ class GormAclLookupStrategySpec extends AbstractIntegrationSpec { private AclObjectIdentity aclObjectIdentity GormAclLookupStrategy aclLookupStrategy - Ehcache ehcacheAclCache + CacheManager aclCacheManager void buildData() { @@ -107,7 +107,7 @@ class GormAclLookupStrategySpec extends AbstractIntegrationSpec { } void cleanup() { - ehcacheAclCache.removeAll() + aclCacheManager.getCache("aclCache").clear() } void 'acls retrieval with default batch size'() { diff --git a/plugin/build.gradle b/plugin/build.gradle index 0c8c4af..f9b21f8 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -44,7 +44,6 @@ dependencies { implementation "org.grails:grails-plugin-services" implementation "org.grails:grails-plugin-url-mappings" implementation "org.grails:grails-plugin-interceptors" - implementation "org.grails.plugins:cache" implementation "org.grails.plugins:gsp" console "org.grails:grails-console" profile "org.grails.profiles:web-plugin" diff --git a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/ProxyAwareParameterNameDiscoverer.groovy b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/ProxyAwareParameterNameDiscoverer.groovy deleted file mode 100644 index e89c65d..0000000 --- a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/ProxyAwareParameterNameDiscoverer.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright 2009-2015 the original author or authors. - * - * 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 - * - * http://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 grails.plugin.springsecurity.acl - -import grails.plugin.springsecurity.acl.util.ProxyUtils -import groovy.transform.CompileStatic -import org.springframework.core.StandardReflectionParameterNameDiscoverer - -import java.lang.reflect.Constructor -import java.lang.reflect.Method - -/** - * CGLIB proxies confuse parameter name discovery since the classes aren't compiled with - * debug, so find the corresponding method or constructor in the target and use that. - * - * @author Burt Beckwith - */ -@CompileStatic -class ProxyAwareParameterNameDiscoverer extends StandardReflectionParameterNameDiscoverer { - - @Override - String[] getParameterNames(Method method) { - super.getParameterNames ProxyUtils.unproxy(method) - } - - @Override - String[] getParameterNames(Constructor constructor) { - super.getParameterNames ProxyUtils.unproxy(constructor) - } -} diff --git a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/SpringSecurityAclGrailsPlugin.groovy b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/SpringSecurityAclGrailsPlugin.groovy index 2c7673d..84e36d1 100644 --- a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/SpringSecurityAclGrailsPlugin.groovy +++ b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/SpringSecurityAclGrailsPlugin.groovy @@ -177,7 +177,7 @@ class SpringSecurityAclGrailsPlugin extends Plugin { aclCache(SpringAclCacheFactoryBean) { cacheManager = ref('aclCacheManager') cacheName = 'aclCache' - aclPermissionGrantingStrategy = ref('aclPermissionGrantingStrategy') + permissionGrantingStrategy = ref('aclPermissionGrantingStrategy') aclAuthorizationStrategy = ref('aclAuthorizationStrategy') } @@ -211,8 +211,6 @@ class SpringSecurityAclGrailsPlugin extends Plugin { private configureExpressionBeans = { conf -> - parameterNameDiscoverer(ProxyAwareParameterNameDiscoverer) - permissionEvaluator(AclPermissionEvaluator, ref('aclService')) { objectIdentityRetrievalStrategy = ref('objectIdentityRetrievalStrategy') objectIdentityGenerator = ref('objectIdentityRetrievalStrategy') @@ -228,7 +226,6 @@ class SpringSecurityAclGrailsPlugin extends Plugin { } expressionHandler(DefaultMethodSecurityExpressionHandler) { - parameterNameDiscoverer = ref('parameterNameDiscoverer') permissionCacheOptimizer = ref('aclPermissionCacheOptimizer') expressionParser = ref('expressionParser') roleHierarchy = ref('roleHierarchy') diff --git a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/cache/SpringAclCacheFactoryBean.groovy b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/cache/SpringAclCacheFactoryBean.groovy index 14ca201..a36d682 100644 --- a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/cache/SpringAclCacheFactoryBean.groovy +++ b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/cache/SpringAclCacheFactoryBean.groovy @@ -55,8 +55,8 @@ class SpringAclCacheFactoryBean implements FactoryBean Assert.notNull(permissionGrantingStrategy, "permissionGrantingStrategy is required") Assert.notNull(aclAuthorizationStrategy, "aclAuthorizationStrategy is required") if (!cacheConfig) { - cacheConfig = new MutableConfiguration() - .setTypes(String, MutableAcl) + cacheConfig = new MutableConfiguration() + .setTypes(Object, MutableAcl) .setStoreByValue(false) } springAclCache = new SpringCacheBasedAclCache( diff --git a/publish-docs.sh b/publish-docs.sh deleted file mode 100755 index 2704c47..0000000 --- a/publish-docs.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo "Generating Docs" - -./gradlew docs --stacktrace - -git config --global user.name "$GIT_NAME" -git config --global user.email "$GIT_EMAIL" -git config --global credential.helper "store --file=~/.git-credentials" -echo "https://$GH_TOKEN:@github.com" > ~/.git-credentials - - -echo "Publishing Documentation" - -git clone https://${GH_TOKEN}@github.com/grails-plugins/grails-spring-security-acl.git -b gh-pages gh-pages --single-branch > /dev/null - -cd gh-pages - -git rm v3/spring-security-acl-*.epub -mv ../build/docs/spring-security-acl-*.epub v3 -git add v3/spring-security-acl-*.epub - -git rm v3/spring-security-acl-*.pdf -mv ../build/docs/spring-security-acl-*.pdf v3 -git add v3/spring-security-acl-*.pdf - -mv ../build/docs/index.html v3 -git add v3/index.html - -mv ../build/docs/ghpages.html index.html -git add index.html - -git commit -a -m "Updating docs for Travis build: https://travis-ci.org/$TRAVIS_REPO_SLUG/builds/$TRAVIS_BUILD_ID" -git push origin HEAD - -cd .. - -rm -rf gh-pages diff --git a/travis-build.sh b/travis-build.sh deleted file mode 100755 index 63d9ffb..0000000 --- a/travis-build.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env bash - -set -e - -EXIT_STATUS=0 - -echo "TRAVIS_BRANCH:" -echo $TRAVIS_BRANCH -echo "TRAVIS_TAG:" -echo $TRAVIS_TAG - - -./gradlew check -Dgeb.env=chromeHeadless || EXIT_STATUS=$? - -if [[ $EXIT_STATUS -ne 0 ]]; then - echo "Check failed" - exit $EXIT_STATUS -fi - -./gradlew :integration-test-app:check -Dgeb.env=chromeHeadless || EXIT_STATUS=$? - -if [[ $EXIT_STATUS -ne 0 ]]; then - echo "Integration Tests Check failed" - exit $EXIT_STATUS -fi - -./gradlew :functional-test-app:check -Dgeb.env=chromeHeadless || EXIT_STATUS=$? - -if [[ $EXIT_STATUS -ne 0 ]]; then - echo "Integration Tests Check failed" - exit $EXIT_STATUS -fi - - - -./gradlew :spring-security-acl:assemble --stacktrace || EXIT_STATUS=$? -if [[ $EXIT_STATUS -ne 0 ]]; then - echo ":spring-security-acl:assemble failed" - exit $EXIT_STATUS -fi - -# Only publish if the branch is on master, and it is not a PR -if [[ -n $TRAVIS_TAG ]] || [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then - echo "Publishing archives for branch $TRAVIS_BRANCH" - - if [[ -n $TRAVIS_TAG ]]; then - echo "Pushing build to Bintray" - ./gradlew :spring-security-acl:bintrayUpload || EXIT_STATUS=$? - if [[ $EXIT_STATUS -ne 0 ]]; then - echo "Publishing to Bintray Failed" - exit $EXIT_STATUS - fi - else - echo "Publishing snapshot to OJO" - ./gradlew :spring-security-acl:artifactoryPublish || EXIT_STATUS=$? - if [[ $EXIT_STATUS -ne 0 ]]; then - echo "Publishing to OJO Failed" - exit $EXIT_STATUS - fi - fi - - - ./gradlew :docs:docs || EXIT_STATUS=$? - if [[ $EXIT_STATUS -ne 0 ]]; then - echo "Generating docs failed" - exit $EXIT_STATUS - fi - - git config --global user.name "$GIT_NAME" - git config --global user.email "$GIT_EMAIL" - git config --global credential.helper "store --file=~/.git-credentials" - echo "https://$GH_TOKEN:@github.com" > ~/.git-credentials - - git clone https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git -b gh-pages gh-pages --single-branch > /dev/null - cd gh-pages - - # If this is the master branch then update the snapshot - if [[ $TRAVIS_BRANCH == 'master' ]]; then - mkdir -p snapshot - cp -r ../docs/build/docs/. ./snapshot/ - git add snapshot/* - fi - - # If there is a tag present then this becomes the latest - if [[ -n $TRAVIS_TAG ]]; then - git rm -rf latest/ - mkdir -p latest - cp -r ../docs/build/docs/. ./latest/ - git add latest/* - - version="$TRAVIS_TAG" # eg: v3.0.1 - version=${version:1} # 3.0.1 - majorVersion=${version:0:4} # 3.0. - majorVersion="${majorVersion}x" # 3.0.x - - mkdir -p "$version" - cp -r ../docs/build/docs/. "./$version/" - git add "$version/*" - - git rm -rf "$majorVersion" - cp -r ../docs/build/docs/. "./$majorVersion/" - git add "$majorVersion/*" - fi - - if [[ -n $TRAVIS_TAG ]] || [[ $TRAVIS_BRANCH == 'master' ]]; then - git commit -a -m "Updating docs for Travis build: https://travis-ci.org/$TRAVIS_REPO_SLUG/builds/$TRAVIS_BUILD_ID" - git push origin HEAD - fi - - cd .. - rm -rf gh-pages -fi - -exit $EXIT_STATUS \ No newline at end of file