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 new file mode 100644 index 0000000..04ae5bc --- /dev/null +++ b/build.gradle @@ -0,0 +1,9 @@ +subprojects { + configurations.configureEach { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + if (details.requested.group == 'org.seleniumhq.selenium') { + details.useVersion(seleniumVersion) + } + } + } +} diff --git a/docs/build.gradle b/docs/build.gradle index 24e2aaa..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.5.3' - classpath 'org.asciidoctor:asciidoctorj-epub3:1.5.0-alpha.6' - classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.11' + 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/code/grails-app/views/error.gsp b/docs/src/docs/code/grails-app/views/error.gsp index 9a3bb8a..a2c4235 100644 --- a/docs/src/docs/code/grails-app/views/error.gsp +++ b/docs/src/docs/code/grails-app/views/error.gsp @@ -10,8 +10,8 @@ - - + +
    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 cd8ca4b..5cd8dca 100644 --- a/functional-test-app/build.gradle +++ b/functional-test-app/build.gradle @@ -5,9 +5,9 @@ buildscript { } dependencies { classpath "org.grails:grails-gradle-plugin:$grailsVersion" - classpath "com.bertramlabs.plugins:asset-pipeline-gradle:3.0.7" - classpath "org.grails.plugins:hibernate5:${gormVersion-".RELEASE"}" - classpath "gradle.plugin.com.energizedwork.webdriver-binaries:webdriver-binaries-gradle-plugin:1.4" + classpath "com.bertramlabs.plugins:asset-pipeline-gradle:5.0.1" + classpath "org.grails.plugins:hibernate5:$gormVersion" + classpath "com.github.erdi:webdriver-binaries-gradle-plugin:3.2" } } @@ -18,7 +18,7 @@ apply plugin:"eclipse" apply plugin:"idea" apply plugin:"war" apply plugin:"org.grails.grails-web" -apply plugin:"com.energizedwork.webdriver-binaries" +apply plugin:"com.github.erdi.webdriver-binaries" apply plugin:"asset-pipeline" apply plugin:"org.grails.grails-gsp" @@ -28,56 +28,53 @@ repositories { } dependencies { - compile "org.springframework.boot:spring-boot-starter-logging" - compile "org.springframework.boot:spring-boot-autoconfigure" - compile "org.grails:grails-core" - compile "org.springframework.boot:spring-boot-starter-actuator" - compile "org.springframework.boot:spring-boot-starter-tomcat" - compile "org.grails:grails-logging" - compile "org.grails:grails-plugin-rest" - compile "org.grails:grails-plugin-databinding" - compile "org.grails:grails-plugin-i18n" - compile "org.grails:grails-plugin-services" - compile "org.grails:grails-plugin-url-mappings" - compile "org.grails:grails-plugin-interceptors" - compile "org.grails:grails-web-boot" - compile "org.grails.plugins:cache" - compile "org.grails.plugins:async" - compile "org.grails.plugins:scaffolding" - compile "org.grails.plugins:events" - compile "org.grails.plugins:hibernate5" - compile "org.hibernate:hibernate-core:$hibernateCoreVersion" - compile "org.grails.plugins:gsp" + implementation "org.springframework.boot:spring-boot-starter-logging" + implementation "org.springframework.boot:spring-boot-autoconfigure" + implementation "org.grails:grails-core" + implementation "org.springframework.boot:spring-boot-starter-actuator" + implementation "org.springframework.boot:spring-boot-starter-tomcat" + implementation "org.grails:grails-logging" + implementation "org.grails:grails-plugin-rest" + implementation "org.grails:grails-plugin-databinding" + implementation "org.grails:grails-plugin-i18n" + implementation "org.grails:grails-plugin-services" + implementation "org.grails:grails-plugin-url-mappings" + implementation "org.grails:grails-plugin-interceptors" + implementation "org.grails:grails-web-boot" + 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-jakarta:$hibernateCoreVersion" + implementation "org.grails.plugins:gsp" console "org.grails:grails-console" profile "org.grails.profiles:web" - runtime "com.bertramlabs.plugins:asset-pipeline-grails:3.0.7" - runtime "org.glassfish.web:el-impl:2.1.2-b03" - runtime "org.apache.tomcat:tomcat-jdbc" - runtime "com.h2database:h2" - testCompile "org.grails:grails-gorm-testing-support" - testCompile "org.grails:grails-web-testing-support" - testCompile "io.micronaut:micronaut-http-client:$micronautVersion" - testCompile "org.grails.plugins:geb" - testRuntime "org.seleniumhq.selenium:selenium-chrome-driver:3.6.0" - testCompile "org.seleniumhq.selenium:selenium-remote-driver:3.6.0" - testCompile "org.seleniumhq.selenium:selenium-api:3.6.0" - compile project(':spring-security-acl') -} - -bootRun { - jvmArgs('-Dspring.output.ansi.enabled=always') - sourceResources sourceSets.main -} + runtimeOnly "com.bertramlabs.plugins:asset-pipeline-grails:5.0.1" + runtimeOnly "org.apache.tomcat:tomcat-jdbc" + runtimeOnly "com.h2database:h2" + testImplementation "org.grails:grails-gorm-testing-support" + testImplementation "org.grails:grails-web-testing-support" + integrationTestImplementation testFixtures('org.grails.plugins:geb') -webdriverBinaries { - chromedriver '2.35' - geckodriver '0.18.0' + 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/conf/logback.groovy b/functional-test-app/grails-app/conf/logback.groovy deleted file mode 100644 index de77ed2..0000000 --- a/functional-test-app/grails-app/conf/logback.groovy +++ /dev/null @@ -1,37 +0,0 @@ -import grails.util.BuildSettings -import grails.util.Environment -import org.springframework.boot.logging.logback.ColorConverter -import org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter - -import java.nio.charset.Charset - -conversionRule 'clr', ColorConverter -conversionRule 'wex', WhitespaceThrowableProxyConverter - -// See http://logback.qos.ch/manual/groovy.html for details on configuration -appender('STDOUT', ConsoleAppender) { - encoder(PatternLayoutEncoder) { - charset = Charset.forName('UTF-8') - - pattern = - '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} ' + // Date - '%clr(%5p) ' + // Log level - '%clr(---){faint} %clr([%15.15t]){faint} ' + // Thread - '%clr(%-40.40logger{39}){cyan} %clr(:){faint} ' + // Logger - '%m%n%wex' // Message - } -} - -def targetDir = BuildSettings.TARGET_DIR -if (Environment.isDevelopmentMode() && targetDir != null) { - appender("FULL_STACKTRACE", FileAppender) { - file = "${targetDir}/stacktrace.log" - append = true - encoder(PatternLayoutEncoder) { - pattern = "%level %logger - %msg%n" - } - } - logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false) -} -root(ERROR, ['STDOUT']) -logger('grails.plugin.springsecurity.acl', INFO, ['STDOUT'], false) diff --git a/functional-test-app/grails-app/conf/logback.xml b/functional-test-app/grails-app/conf/logback.xml new file mode 100644 index 0000000..3ae16b8 --- /dev/null +++ b/functional-test-app/grails-app/conf/logback.xml @@ -0,0 +1,21 @@ + + + + + + + + true + + UTF-8 + %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex + + + + + + + + + + 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/grails-app/views/error.gsp b/functional-test-app/grails-app/views/error.gsp index 419d666..06820cf 100644 --- a/functional-test-app/grails-app/views/error.gsp +++ b/functional-test-app/grails-app/views/error.gsp @@ -6,8 +6,8 @@ - - + +
      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 593c6c5..a1cdf3a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,11 @@ projectVersion=5.0.0-SNAPSHOT -grailsVersion=4.0.0.RC1 -gormVersion=7.0.0.RC2 -gradleWrapperVersion=4.9 +grailsVersion=7.0.0-SNAPSHOT +gormVersion=9.0.0-SNAPSHOT vcsUrl=https://github.com/grails-plugins/grails-spring-security-acl -springSecurityVersion=5.1.2.RELEASE -springSecurityCoreVersion=4.0.0.M2 -javaServletApiVersion=3.1.0 -micronautVersion=1.0.5 -hibernateCoreVersion=5.3.7.Final +springSecurityVersion=6.3.3 +springSecurityCoreVersion=7.0.0-SNAPSHOT +jakartaServletApiVersion=6.0.0 +micronautVersion=4.5.3 +hibernateCoreVersion=5.6.15.Final +ehcacheVersion=3.10.8 +seleniumVersion=4.26.0 diff --git a/gradle/artifactoryPublish.gradle b/gradle/artifactoryPublish.gradle deleted file mode 100644 index 3503228..0000000 --- a/gradle/artifactoryPublish.gradle +++ /dev/null @@ -1,13 +0,0 @@ -artifactory { - contextUrl = 'http://oss.jfrog.org' - publish { - repository { - repoKey = 'oss-snapshot-local' - username = System.getenv("BINTRAY_USER") ?: project.hasProperty("bintrayUser") ? project.bintrayUser : '' - password = System.getenv("BINTRAY_KEY") ?: project.hasProperty("bintrayKey") ? project.bintrayKey : '' - } - defaults { - publications('maven') - } - } -} \ No newline at end of file diff --git a/gradle/grailsPublish.gradle b/gradle/grailsPublish.gradle deleted file mode 100644 index 39358e4..0000000 --- a/gradle/grailsPublish.gradle +++ /dev/null @@ -1,23 +0,0 @@ -def setIfNotSet = { String name, value -> - if (!project.ext.has(name)) { - project.ext[name] = value - } -} -setIfNotSet 'issueTrackerUrl', project.vcsUrl + '/issues' -setIfNotSet 'websiteUrl', project.vcsUrl - -grailsPublish { - user = System.getenv("BINTRAY_USER") ?: project.hasProperty("bintrayUser") ? project.bintrayUser : '' - key = System.getenv("BINTRAY_KEY") ?: project.hasProperty("bintrayKey") ? project.bintrayKey : '' - userOrg = project.hasProperty('userOrg') ? project.userOrg : 'grails' - repo = project.hasProperty('repo') ? project.repo : 'plugins' - websiteUrl = project.hasProperty('websiteUrl') ? project.websiteUrl : "http://grails.org/plugin/$project.name" - license { - name = project.hasProperty('license') ? [project.license] : ['Apache-2.0'] - } - issueTrackerUrl = project.hasProperty('issueTrackerUrl') ? project.issueTrackerUrl : "https://github.com/grails-plugins/$project.name/issues" - vcsUrl = project.hasProperty('vcsUrl') ? project.vcsUrl : "https://github.com/grails-plugins/$project.name" - title = 'Grails spring-security-core plugin' - desc = '' - developers = [burtbeckwith:"Burt Beckwith"] -} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 13372ae..a4b76b9 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bd24854..df97d72 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip diff --git a/gradlew b/gradlew index 9d82f78..f5feea6 100755 --- a/gradlew +++ b/gradlew @@ -1,74 +1,130 @@ -#!/usr/bin/env bash +#!/bin/sh + +# +# Copyright © 2015-2021 the original 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 +# +# 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. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum -warn ( ) { +warn () { echo "$*" -} +} >&2 -die ( ) { +die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -77,84 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec9973..9b42019 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,22 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -8,26 +26,30 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -35,54 +57,36 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/integration-test-app/build.gradle b/integration-test-app/build.gradle index b347051..701bc6b 100644 --- a/integration-test-app/build.gradle +++ b/integration-test-app/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { classpath "org.grails:grails-gradle-plugin:$grailsVersion" - classpath "org.grails.plugins:hibernate5:${gormVersion-".RELEASE"}" + classpath "org.grails.plugins:hibernate5:$gormVersion" } } @@ -24,43 +24,37 @@ repositories { } dependencies { - compile "org.springframework.boot:spring-boot-starter-logging" - compile "org.springframework.boot:spring-boot-autoconfigure" - compile "org.grails:grails-core" - compile "org.springframework.boot:spring-boot-starter-actuator" - compile "org.springframework.boot:spring-boot-starter-tomcat" - compile "org.grails:grails-web-boot" - compile "org.grails:grails-logging" - compile "org.grails:grails-plugin-rest" - compile "org.grails:grails-plugin-databinding" - compile "org.grails:grails-plugin-i18n" - compile "org.grails:grails-plugin-services" - compile "org.grails:grails-plugin-url-mappings" - compile "org.grails:grails-plugin-interceptors" - compile "org.grails.plugins:cache" - compile "org.grails.plugins:async" - compile "org.grails.plugins:scaffolding" - compile "org.grails.plugins:events" - compile "org.grails.plugins:hibernate5" - compile "org.hibernate:hibernate-core:$hibernateCoreVersion" - compile "org.grails.plugins:gsp" + implementation "org.springframework.boot:spring-boot-starter-logging" + implementation "org.springframework.boot:spring-boot-autoconfigure" + implementation "org.grails:grails-core" + implementation "org.springframework.boot:spring-boot-starter-actuator" + implementation "org.springframework.boot:spring-boot-starter-tomcat" + implementation "org.grails:grails-web-boot" + implementation "org.grails:grails-logging" + implementation "org.grails:grails-plugin-rest" + implementation "org.grails:grails-plugin-databinding" + implementation "org.grails:grails-plugin-i18n" + implementation "org.grails:grails-plugin-services" + implementation "org.grails:grails-plugin-url-mappings" + implementation "org.grails:grails-plugin-interceptors" + 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-jakarta:$hibernateCoreVersion" + implementation "org.grails.plugins:gsp" console "org.grails:grails-console" profile "org.grails.profiles:web" - runtime "org.glassfish.web:el-impl:2.1.2-b03" - runtime "com.h2database:h2" - runtime "org.apache.tomcat:tomcat-jdbc" - testCompile "org.grails:grails-gorm-testing-support" - testCompile "org.grails:grails-web-testing-support" + runtimeOnly "com.h2database:h2" + runtimeOnly "org.apache.tomcat:tomcat-jdbc" + testImplementation "org.grails:grails-gorm-testing-support" + testImplementation "org.grails:grails-web-testing-support" - compile project(':spring-security-acl') -} - -bootRun { - jvmArgs('-Dspring.output.ansi.enabled=always') - sourceResources sourceSets.main + implementation project(':spring-security-acl') } tasks.withType(Test) { + useJUnitPlatform() beforeTest { descriptor -> logger.quiet " -- $descriptor" } testLogging { events "passed", "skipped", "failed" 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/grails-app/conf/logback.groovy b/integration-test-app/grails-app/conf/logback.groovy deleted file mode 100644 index 20f85e1..0000000 --- a/integration-test-app/grails-app/conf/logback.groovy +++ /dev/null @@ -1,36 +0,0 @@ -import grails.util.BuildSettings -import grails.util.Environment -import org.springframework.boot.logging.logback.ColorConverter -import org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter - -import java.nio.charset.Charset - -conversionRule 'clr', ColorConverter -conversionRule 'wex', WhitespaceThrowableProxyConverter - -// See http://logback.qos.ch/manual/groovy.html for details on configuration -appender('STDOUT', ConsoleAppender) { - encoder(PatternLayoutEncoder) { - charset = Charset.forName('UTF-8') - - pattern = - '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} ' + // Date - '%clr(%5p) ' + // Log level - '%clr(---){faint} %clr([%15.15t]){faint} ' + // Thread - '%clr(%-40.40logger{39}){cyan} %clr(:){faint} ' + // Logger - '%m%n%wex' // Message - } -} - -def targetDir = BuildSettings.TARGET_DIR -if (Environment.isDevelopmentMode() && targetDir != null) { - appender("FULL_STACKTRACE", FileAppender) { - file = "${targetDir}/stacktrace.log" - append = true - encoder(PatternLayoutEncoder) { - pattern = "%level %logger - %msg%n" - } - } - logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false) -} -root(ERROR, ['STDOUT']) diff --git a/integration-test-app/grails-app/conf/logback.xml b/integration-test-app/grails-app/conf/logback.xml new file mode 100644 index 0000000..70b1484 --- /dev/null +++ b/integration-test-app/grails-app/conf/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + true + + UTF-8 + %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex + + + + + + + + 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 e875193..f9b21f8 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -6,56 +6,62 @@ buildscript { } dependencies { classpath "org.grails:grails-gradle-plugin:$grailsVersion" - classpath "org.jfrog.buildinfo:build-info-extractor-gradle:latest.release" } } version projectVersion group "org.grails.plugins" +apply plugin:"java-library" apply plugin:"eclipse" apply plugin:"idea" apply plugin:"org.grails.grails-plugin" -apply plugin:"org.grails.grails-plugin-publish" apply plugin:"org.grails.grails-gsp" -apply plugin: 'com.jfrog.artifactory' +apply plugin:"maven-publish" repositories { mavenLocal() maven { url "https://repo.grails.org/grails/core" } } +configurations { + all { + exclude group: 'javax.servlet' + } +} + dependencies { - compile "org.springframework.boot:spring-boot-starter-logging" - compile "org.springframework.boot:spring-boot-autoconfigure" - compile "org.grails:grails-core" - compile "org.springframework.boot:spring-boot-starter-actuator" - compile "org.springframework.boot:spring-boot-starter-tomcat" - compile "org.grails:grails-web-boot" - compile "org.grails:grails-logging" - compile "org.grails:grails-plugin-rest" - compile "org.grails:grails-plugin-databinding" - compile "org.grails:grails-plugin-i18n" - compile "org.grails:grails-plugin-services" - compile "org.grails:grails-plugin-url-mappings" - compile "org.grails:grails-plugin-interceptors" - compile "org.grails.plugins:cache" - compile "org.grails.plugins:gsp" + implementation "org.springframework.boot:spring-boot-starter-logging" + implementation "org.springframework.boot:spring-boot-autoconfigure" + implementation "org.grails:grails-core" + implementation "org.springframework.boot:spring-boot-starter-actuator" + implementation "org.springframework.boot:spring-boot-starter-tomcat" + implementation "org.grails:grails-web-boot" + implementation "org.grails:grails-logging" + implementation "org.grails:grails-plugin-rest" + implementation "org.grails:grails-plugin-databinding" + implementation "org.grails:grails-plugin-i18n" + implementation "org.grails:grails-plugin-services" + implementation "org.grails:grails-plugin-url-mappings" + implementation "org.grails:grails-plugin-interceptors" + implementation "org.grails.plugins:gsp" console "org.grails:grails-console" profile "org.grails.profiles:web-plugin" - provided "org.grails:grails-plugin-services" - provided "org.grails:grails-plugin-domain-class" - testCompile "org.grails:grails-gorm-testing-support" - testCompile "org.grails:grails-web-testing-support" + runtimeOnly "org.grails:grails-plugin-services" + runtimeOnly "org.grails:grails-plugin-domain-class" + testImplementation "org.grails:grails-gorm-testing-support" + testImplementation "org.grails:grails-web-testing-support" - compile "org.grails.plugins:spring-security-core:$springSecurityCoreVersion" - compile "org.springframework.security:spring-security-acl:$springSecurityVersion" + implementation "org.ehcache:ehcache:$ehcacheVersion" + api "org.grails.plugins:spring-security-core:$springSecurityCoreVersion" + api "org.springframework.security:spring-security-acl:$springSecurityVersion" } -bootRun { - jvmArgs('-Dspring.output.ansi.enabled=always') - sourceResources sourceSets.main +publishing { + publications { + maven(MavenPublication) { + artifactId project.name + from components.java + } + } } - -apply from: "${rootProject.projectDir}/gradle/artifactoryPublish.gradle" -apply from: "${rootProject.projectDir}/gradle/grailsPublish.gradle" \ No newline at end of file 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 384fd4b..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.LocalVariableTableParameterNameDiscoverer - -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 LocalVariableTableParameterNameDiscoverer { - - @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 28e4e91..84e36d1 100644 --- a/plugin/src/main/groovy/grails/plugin/springsecurity/acl/SpringSecurityAclGrailsPlugin.groovy +++ b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/SpringSecurityAclGrailsPlugin.groovy @@ -16,8 +16,8 @@ package grails.plugin.springsecurity.acl import grails.plugin.springsecurity.BeanTypeResolver import grails.util.GrailsClassUtils as GCU -import org.springframework.cache.ehcache.EhCacheFactoryBean -import org.springframework.cache.ehcache.EhCacheManagerFactoryBean +import grails.plugin.springsecurity.acl.cache.SpringAclCacheFactoryBean +import org.springframework.cache.jcache.JCacheCacheManager import org.springframework.expression.spel.standard.SpelExpressionParser import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource as SpringSecuredAnnotationSecurityMetadataSource import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler @@ -41,7 +41,7 @@ import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl import org.springframework.security.acls.domain.BasePermission import org.springframework.security.acls.domain.DefaultPermissionFactory import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy -import org.springframework.security.acls.domain.EhCacheBasedAclCache +import org.springframework.security.acls.domain.SpringCacheBasedAclCache import org.springframework.security.acls.domain.SidRetrievalStrategyImpl import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.AuthorityUtils @@ -84,7 +84,7 @@ class SpringSecurityAclGrailsPlugin extends Plugin { public static final String ENCODING_IDSHA256 = "SHA-256" - String grailsVersion = '3.0.0 > *' + String grailsVersion = '7.0.0 > *' String author = 'Burt Beckwith' String authorEmail = 'burt@burtbeckwith.com' String title = 'Spring Security ACL plugin' @@ -173,14 +173,13 @@ class SpringSecurityAclGrailsPlugin extends Plugin { objectIdentityRetrievalStrategy(GormObjectIdentityRetrievalStrategy) // acl cache - aclCacheManager(EhCacheManagerFactoryBean) { - cacheManagerName = 'spring-security-acl-cache-' + UUID.randomUUID() - } - ehcacheAclCache(EhCacheFactoryBean) { + aclCacheManager(JCacheCacheManager) + aclCache(SpringAclCacheFactoryBean) { cacheManager = ref('aclCacheManager') cacheName = 'aclCache' + permissionGrantingStrategy = ref('aclPermissionGrantingStrategy') + aclAuthorizationStrategy = ref('aclAuthorizationStrategy') } - aclCache(EhCacheBasedAclCache, ref('ehcacheAclCache'), ref('aclPermissionGrantingStrategy'), ref('aclAuthorizationStrategy')) aclPermissionGrantingStrategy(DefaultPermissionGrantingStrategy, ref('aclAuditLogger')) @@ -212,8 +211,6 @@ class SpringSecurityAclGrailsPlugin extends Plugin { private configureExpressionBeans = { conf -> - parameterNameDiscoverer(ProxyAwareParameterNameDiscoverer) - permissionEvaluator(AclPermissionEvaluator, ref('aclService')) { objectIdentityRetrievalStrategy = ref('objectIdentityRetrievalStrategy') objectIdentityGenerator = ref('objectIdentityRetrievalStrategy') @@ -229,7 +226,6 @@ class SpringSecurityAclGrailsPlugin extends Plugin { } expressionHandler(DefaultMethodSecurityExpressionHandler) { - parameterNameDiscoverer = ref('parameterNameDiscoverer') permissionCacheOptimizer = ref('aclPermissionCacheOptimizer') expressionParser = ref('expressionParser') roleHierarchy = ref('roleHierarchy') @@ -487,8 +483,8 @@ class SpringSecurityAclGrailsPlugin extends Plugin { (ENCODING_ID_MD4): new Md4PasswordEncoder(), (ENCODING_ID_MD5): messsageDigestPasswordEncoderMD5, (ENCODING_ID_NOOP): NoOpPasswordEncoder.getInstance(), - (ENCODING_ID_PBKDF2): new Pbkdf2PasswordEncoder(), - (ENCODING_ID_SCRYPT): new SCryptPasswordEncoder(), + (ENCODING_ID_PBKDF2): Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8(), + (ENCODING_ID_SCRYPT): SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8(), (ENCODING_ID_SHA1): messsageDigestPasswordEncoderSHA1, (ENCODING_IDSHA256): messsageDigestPasswordEncoderSHA256, "sha256": new StandardPasswordEncoder()] 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 new file mode 100644 index 0000000..a36d682 --- /dev/null +++ b/plugin/src/main/groovy/grails/plugin/springsecurity/acl/cache/SpringAclCacheFactoryBean.groovy @@ -0,0 +1,68 @@ +/* Copyright 2024 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.cache + +import groovy.transform.CompileStatic +import org.springframework.beans.factory.FactoryBean +import org.springframework.beans.factory.InitializingBean +import org.springframework.cache.jcache.JCacheCache +import org.springframework.cache.jcache.JCacheCacheManager +import org.springframework.security.acls.domain.AclAuthorizationStrategy +import org.springframework.security.acls.domain.SpringCacheBasedAclCache +import org.springframework.security.acls.model.MutableAcl +import org.springframework.security.acls.model.PermissionGrantingStrategy +import org.springframework.util.Assert + +import javax.cache.configuration.Configuration +import javax.cache.configuration.MutableConfiguration + +@CompileStatic +class SpringAclCacheFactoryBean implements FactoryBean, InitializingBean { + + JCacheCacheManager cacheManager + String cacheName + Configuration cacheConfig + PermissionGrantingStrategy permissionGrantingStrategy + AclAuthorizationStrategy aclAuthorizationStrategy + private SpringCacheBasedAclCache springAclCache + + @Override + SpringCacheBasedAclCache getObject() throws Exception { + springAclCache + } + + @Override + Class getObjectType() { + SpringCacheBasedAclCache + } + + @Override + void afterPropertiesSet() throws Exception { + Assert.notNull(cacheManager, "cacheManager is required") + Assert.notNull(cacheName, "cacheName is required") + Assert.notNull(permissionGrantingStrategy, "permissionGrantingStrategy is required") + Assert.notNull(aclAuthorizationStrategy, "aclAuthorizationStrategy is required") + if (!cacheConfig) { + cacheConfig = new MutableConfiguration() + .setTypes(Object, MutableAcl) + .setStoreByValue(false) + } + springAclCache = new SpringCacheBasedAclCache( + new JCacheCache(cacheManager.cacheManager.createCache(cacheName, cacheConfig)), + permissionGrantingStrategy, + aclAuthorizationStrategy + ) + } +} 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