diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a65d26f87..6b2096572 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,7 +15,6 @@ env: jobs: core-tests: - if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -30,12 +29,12 @@ jobs: arguments: | check --refresh-dependencies - -Dgeb.env=chromeHeadless + --continue functional-test: - if: github.event_name == 'pull_request' runs-on: ubuntu-latest strategy: + fail-fast: false matrix: test-config: [ 'static', 'annotation', 'requestmap', 'basic', 'basicCacheUsers', 'misc', 'putWithParams', 'bcrypt', 'issue503' ] steps: @@ -49,7 +48,6 @@ jobs: with: arguments: | examples-functional-test-app:check - -Dgeb.env=chromeHeadless -DTESTCONFIG=${{ matrix.test-config }} build: @@ -69,7 +67,6 @@ jobs: arguments: | spring-security-core:build --refresh-dependencies - -Dgeb.env=chromeHeadless -x javadoc - name: Publish Snapshot artifacts to Artifactory (repo.grails.org) diff --git a/build.gradle b/build.gradle index f98482a9c..928f5017f 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,8 @@ if (isReleaseVersion) { } } subprojects { + apply plugin: 'groovy' + version = rootProject.version repositories { mavenCentral() @@ -36,6 +38,9 @@ subprojects { } } } + dependencies { + implementation platform(libs.grails.bom) + } } // Do not generate extra load on Nexus with new staging repository if signing fails diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 034a10fa8..e288ecc2a 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -12,8 +12,6 @@ dependencies { // which is causes a version conflict for Gradle exclude group: 'org.apache.groovy', module: 'groovy-xml' } - implementation buildsrcLibs.webdriver.binaries.gradle.plugin - testImplementation buildsrcLibs.spock.core } diff --git a/examples/functional-test-app/build.gradle b/examples/functional-test-app/build.gradle index 8185ded74..056ed2a55 100644 --- a/examples/functional-test-app/build.gradle +++ b/examples/functional-test-app/build.gradle @@ -8,12 +8,6 @@ plugins { group = 'examples.test' -configurations { - all { - exclude group: 'io.micronaut', module:'micronaut-inject-groovy' - } -} - dependencies { implementation project(':spring-security-core') diff --git a/examples/functional-test-app/grails-app/views/layouts/application.gsp b/examples/functional-test-app/grails-app/views/layouts/main.gsp similarity index 100% rename from examples/functional-test-app/grails-app/views/layouts/application.gsp rename to examples/functional-test-app/grails-app/views/layouts/main.gsp diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/AbstractHyphenatedSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/AbstractHyphenatedSecuritySpec.groovy index 1e82cad5e..4b527401b 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/AbstractHyphenatedSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/AbstractHyphenatedSecuritySpec.groovy @@ -1,5 +1,8 @@ package specs +import grails.testing.mixin.integration.Integration + +@Integration abstract class AbstractHyphenatedSecuritySpec extends AbstractSecuritySpec { protected void resetDatabase() { @@ -11,10 +14,6 @@ abstract class AbstractHyphenatedSecuritySpec extends AbstractSecuritySpec { getContent 'hack/get-session-value?name=' + name } - protected void login(String username) { - super.login username, 'password' - } - protected String getUserProperty(String user, String propertyName) { getContent "hack/get-user-property?user=$user&propName=$propertyName" } diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/AbstractSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/AbstractSecuritySpec.groovy index 206fda776..fe15019d0 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/AbstractSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/AbstractSecuritySpec.groovy @@ -1,8 +1,9 @@ package specs import com.testapp.TestDataService +import functional.test.app.Application import geb.driver.CachingDriverFactory -import geb.spock.GebReportingSpec +import grails.plugin.geb.ContainerGebSpec import grails.plugin.springsecurity.SpringSecurityCoreGrailsPlugin import grails.plugin.springsecurity.SpringSecurityUtils import grails.testing.mixin.integration.Integration @@ -10,24 +11,16 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.crypto.password.MessageDigestPasswordEncoder import pages.LoginPage import spock.lang.Shared -import spock.lang.Stepwise -@Integration(applicationClass = functional.test.app.Application) -@Stepwise -abstract class AbstractSecuritySpec extends GebReportingSpec { +@Integration(applicationClass = Application) +abstract class AbstractSecuritySpec extends ContainerGebSpec { private @Shared boolean databaseReset = false @Autowired TestDataService testDataService - void setup() { - if ( hasProperty('serverPort') ) { - browser.baseUrl = "http://localhost:${getProperty('serverPort')}/" - } else { - browser.baseUrl = 'http://localhost:8080/' - } - + def setup() { logout() // call resetDatabase() once per suite, before the first test; would @@ -63,7 +56,7 @@ abstract class AbstractSecuritySpec extends GebReportingSpec { browser.driver.pageSource } - protected void login(String user, String pwd, boolean remember = false) { + protected void login(String user, String pwd = 'password', boolean remember = false) { to LoginPage username = user password = pwd @@ -76,6 +69,7 @@ abstract class AbstractSecuritySpec extends GebReportingSpec { protected void logout() { go SpringSecurityUtils.securityConfig.logout.filterProcessesUrl browser.clearCookies() + browser.go("/") } protected void assertContentContains(String expected) { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/AnnotationSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/AnnotationSecuritySpec.groovy index 12137d569..d087553ed 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/AnnotationSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/AnnotationSecuritySpec.groovy @@ -1,5 +1,6 @@ package specs +import grails.testing.mixin.integration.Integration import pages.IndexPage import pages.LoginPage import pages.role.CreateRolePage @@ -10,6 +11,7 @@ import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'annotation' }) class AnnotationSecuritySpec extends AbstractSecuritySpec { @@ -354,7 +356,6 @@ class AnnotationSecuritySpec extends AbstractSecuritySpec { action << ['thing', 'thing/index', 'thing/show/1', 'thing/create', 'thing/edit', 'thing/delete'] } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'authenticated user can access secured restful domain'() { given: login 'admin1', 'password1' @@ -366,7 +367,6 @@ class AnnotationSecuritySpec extends AbstractSecuritySpec { $().text() == '[]' } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'generated Resource controllers can have inherited secured actions'() { when: go 'customer/index' diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/BCryptSpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/BCryptSpec.groovy index 308bf22b8..adc5a7d8a 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/BCryptSpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/BCryptSpec.groovy @@ -1,10 +1,12 @@ package specs +import grails.testing.mixin.integration.Integration import pages.user.CreateUserPage import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'bcrypt' }) class BCryptSpec extends AbstractSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthCacheUsersSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthCacheUsersSecuritySpec.groovy index 2be33d916..7d80f0a42 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthCacheUsersSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthCacheUsersSecuritySpec.groovy @@ -1,5 +1,6 @@ package specs +import grails.testing.mixin.integration.Integration import org.springframework.security.core.userdetails.UserCache import pages.LoginPage import pages.role.CreateRolePage @@ -10,6 +11,7 @@ import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'basicCacheUsers' }) class BasicAuthCacheUsersSecuritySpec extends AbstractSecuritySpec { @@ -115,7 +117,6 @@ class BasicAuthCacheUsersSecuritySpec extends AbstractSecuritySpec { userRows.size() == 2 } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'check userDetails caching'() { when: diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthSecuritySpec.groovy index da3ca4fd7..be87b3aab 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/BasicAuthSecuritySpec.groovy @@ -1,5 +1,6 @@ package specs +import grails.testing.mixin.integration.Integration import pages.LoginPage import pages.role.CreateRolePage import pages.role.ListRolePage @@ -9,6 +10,7 @@ import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'basic' }) class BasicAuthSecuritySpec extends AbstractSecuritySpec { @@ -172,7 +174,6 @@ class BasicAuthSecuritySpec extends AbstractSecuritySpec { 401 == connection.responseCode } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'check allowed for admin1'() { // Check with admin1 auth, some @Secure actions are accessible @@ -244,7 +245,6 @@ class BasicAuthSecuritySpec extends AbstractSecuritySpec { assertContentContains 'Error 403 Forbidden' } - @IgnoreIf({ System.getProperty('geb.env') == "htmlUnit" }) void 'check allowed for admin2'() { // Check that with admin2 auth, some @Secure actions are accessible @@ -329,8 +329,6 @@ class BasicAuthSecuritySpec extends AbstractSecuritySpec { } private void getWithoutAuth(String uri) { - def url = new URI(getBaseUrlRequired()).resolve(new URI(uri)).toURL() - connection = url.openConnection() - connection.instanceFollowRedirects = false + connection = download("/${uri}") } } diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/DisableSpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/DisableSpec.groovy index b76801357..dd58768dc 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/DisableSpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/DisableSpec.groovy @@ -1,8 +1,11 @@ package specs +import grails.testing.mixin.integration.Integration import pages.IndexPage import spock.lang.IgnoreIf + +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'misc' }) class DisableSpec extends AbstractHyphenatedSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/InheritanceSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/InheritanceSecuritySpec.groovy index fc8b08eef..6f2889941 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/InheritanceSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/InheritanceSecuritySpec.groovy @@ -1,9 +1,11 @@ package specs +import grails.testing.mixin.integration.Integration import pages.IndexPage import pages.LoginPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'annotation' }) class InheritanceSecuritySpec extends AbstractSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/MiscSpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/MiscSpec.groovy index 339344067..1a41bae9f 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/MiscSpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/MiscSpec.groovy @@ -1,11 +1,13 @@ package specs import geb.module.TextInput +import grails.testing.mixin.integration.Integration import org.springframework.security.crypto.password.PasswordEncoder import pages.IndexPage import spock.lang.IgnoreIf import spock.lang.Issue +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'misc' }) class MiscSpec extends AbstractHyphenatedSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/NamespaceSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/NamespaceSecuritySpec.groovy index 868991e56..123181b22 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/NamespaceSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/NamespaceSecuritySpec.groovy @@ -1,11 +1,13 @@ package specs +import grails.testing.mixin.integration.Integration import groovy.json.JsonSlurper import pages.IndexPage import pages.LoginPage import spock.lang.IgnoreIf import spock.lang.Unroll +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'annotation' }) class NamespaceSecuritySpec extends AbstractSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSecuritySpec.groovy index c7d1217fe..fbe23f4ea 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSecuritySpec.groovy @@ -1,6 +1,7 @@ package specs import com.testapp.TestDataService +import grails.testing.mixin.integration.Integration import pages.IndexPage import pages.LoginPage import pages.requestmap.CreateRequestmapPage @@ -14,6 +15,7 @@ import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'requestmap' }) class RequestmapSecuritySpec extends AbstractSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSpec.groovy index bf8c55503..806b21735 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/RequestmapSpec.groovy @@ -1,12 +1,14 @@ package specs import com.testapp.TestDataService +import grails.testing.mixin.integration.Integration import pages.requestmap.CreateRequestmapPage import pages.requestmap.EditRequestmapPage import pages.requestmap.ListRequestmapPage import pages.requestmap.ShowRequestmapPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'requestmap' }) class RequestmapSpec extends AbstractSecuritySpec { @@ -75,7 +77,6 @@ class RequestmapSpec extends AbstractSecuritySpec { configAttribute == 'ROLE_ADMINX' } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'delete requestmap'() { when: go 'testRequestmap/list?max=100' diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/RoleSpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/RoleSpec.groovy index 950c13855..89fa0d5b9 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/RoleSpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/RoleSpec.groovy @@ -1,11 +1,13 @@ package specs +import grails.testing.mixin.integration.Integration import pages.role.CreateRolePage import pages.role.EditRolePage import pages.role.ListRolePage import pages.role.ShowRolePage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ !( System.getProperty('TESTCONFIG') == 'annotation' || System.getProperty('TESTCONFIG') == 'basic' || @@ -80,7 +82,6 @@ class RoleSpec extends AbstractSecuritySpec { at ShowRolePage } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'delete role'() { when: to ListRolePage diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/StaticSecuritySpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/StaticSecuritySpec.groovy index 592ab7c94..39a9dcdd3 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/StaticSecuritySpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/StaticSecuritySpec.groovy @@ -1,5 +1,6 @@ package specs +import grails.testing.mixin.integration.Integration import pages.IndexPage import pages.role.CreateRolePage import pages.role.ListRolePage @@ -9,6 +10,7 @@ import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ System.getProperty('TESTCONFIG') != 'static' }) class StaticSecuritySpec extends AbstractSecuritySpec { diff --git a/examples/functional-test-app/src/integration-test/groovy/specs/UserSpec.groovy b/examples/functional-test-app/src/integration-test/groovy/specs/UserSpec.groovy index 77729618f..a9af3bb24 100644 --- a/examples/functional-test-app/src/integration-test/groovy/specs/UserSpec.groovy +++ b/examples/functional-test-app/src/integration-test/groovy/specs/UserSpec.groovy @@ -1,11 +1,13 @@ package specs +import grails.testing.mixin.integration.Integration import pages.user.CreateUserPage import pages.user.EditUserPage import pages.user.ListUserPage import pages.user.ShowUserPage import spock.lang.IgnoreIf +@Integration @IgnoreIf({ !( System.getProperty('TESTCONFIG') == 'annotation' || System.getProperty('TESTCONFIG') == 'basic' || @@ -87,7 +89,6 @@ class UserSpec extends AbstractSecuritySpec { at ShowUserPage } - @IgnoreIf({ !System.getProperty('geb.env') }) void 'delete user'() { when: to ListUserPage diff --git a/examples/functional-test-app/src/integration-test/resources/GebConfig.groovy b/examples/functional-test-app/src/integration-test/resources/GebConfig.groovy deleted file mode 100644 index 9e41451af..000000000 --- a/examples/functional-test-app/src/integration-test/resources/GebConfig.groovy +++ /dev/null @@ -1,74 +0,0 @@ -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.firefox.FirefoxDriver -import org.openqa.selenium.firefox.FirefoxOptions -import org.openqa.selenium.firefox.GeckoDriverService - -private static FirefoxDriver createFirefoxDriver(FirefoxOptions options = new FirefoxOptions()) { - def osName = System.getProperty('os.name').toLowerCase() - def profileRoot = osName.contains('linux') && new File('/snap/firefox').exists() ? createProfileRootInUserHome() : null - profileRoot ? new FirefoxDriver(createGeckoDriverService(profileRoot), options) : new FirefoxDriver(options) -} - -private static String createProfileRootInUserHome() { - def profileRoot = [System.getProperty('user.home'), 'snap/firefox/common/.firefox-profile-root'] as File - if ( ! profileRoot.exists()) { - if ( ! profileRoot.mkdirs()) { - return null - } - } - profileRoot.absolutePath -} - -private static GeckoDriverService createGeckoDriverService(String tmpProfileDir) { - new GeckoDriverService.Builder() { - @Override - protected List createArgs() { - def args = new ArrayList(super.createArgs()) - def idx = args.indexOf('--profile-root') - if (idx > -1) { - args.remove(idx + 1) - args.remove(idx) - } - args.add '--profile-root' - args.add tmpProfileDir - args - } - }.build() -} - -environments { - - // 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' - o.addArguments '--remote-allow-origins=*' - new ChromeDriver(o) - } - } - - // run via “./gradlew -Dgeb.env=firefox iT” - firefox { - driver = { createFirefoxDriver() } - } - - firefoxHeadless { - driver = { - FirefoxOptions o = new FirefoxOptions() - o.addArguments '-headless' - createFirefoxDriver o - } - } -} - -waiting { - timeout = 10 - retryInterval = 0.5 -} \ No newline at end of file diff --git a/examples/integration-test-app/build.gradle b/examples/integration-test-app/build.gradle index 4c7dac804..080b998ce 100644 --- a/examples/integration-test-app/build.gradle +++ b/examples/integration-test-app/build.gradle @@ -32,15 +32,12 @@ dependencies { runtimeOnly libs.springboot.starter.tomcat runtimeOnly libs.tomcat.jdbc - compileOnly libs.micronaut.inject.groovy compileOnly libs.jakarta.servlet.api compileOnly libs.slf4j.nop testImplementation libs.spock.core testImplementation libs.spring.tx testImplementation libs.bundles.grails.testing.support - - testCompileOnly libs.micronaut.inject.groovy } apply from: rootProject.layout.projectDirectory.file('gradle/java-config.gradle') diff --git a/examples/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/SpringSecurityUtilsIntegrationSpec.groovy b/examples/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/SpringSecurityUtilsIntegrationSpec.groovy index 718821070..738d96db3 100644 --- a/examples/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/SpringSecurityUtilsIntegrationSpec.groovy +++ b/examples/integration-test-app/src/integration-test/groovy/grails/plugin/springsecurity/SpringSecurityUtilsIntegrationSpec.groovy @@ -14,6 +14,7 @@ */ package grails.plugin.springsecurity +import org.sitemesh.webapp.SiteMeshFilter import org.springframework.web.filter.FormContentFilter import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE @@ -85,7 +86,7 @@ class SpringSecurityUtilsIntegrationSpec extends AbstractIntegrationSpec { def map = SpringSecurityUtils.configuredOrderedFilters expect: - 10 == map.size() + 11 == map.size() map[Integer.MIN_VALUE + 10] instanceof SecurityRequestHolderFilter map[SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order] instanceof SecurityContextPersistenceFilter map[SecurityFilterPosition.LOGOUT_FILTER.order] instanceof MutableLogoutFilter @@ -94,6 +95,7 @@ class SpringSecurityUtilsIntegrationSpec extends AbstractIntegrationSpec { map[SecurityFilterPosition.REMEMBER_ME_FILTER.order] instanceof GrailsRememberMeAuthenticationFilter map[SecurityFilterPosition.ANONYMOUS_FILTER.order] instanceof GrailsAnonymousAuthenticationFilter map[SecurityFilterPosition.EXCEPTION_TRANSLATION_FILTER.order-10] instanceof FormContentFilter + map[SecurityFilterPosition.EXCEPTION_TRANSLATION_FILTER.order-5] instanceof SiteMeshFilter map[SecurityFilterPosition.EXCEPTION_TRANSLATION_FILTER.order] instanceof ExceptionTranslationFilter map[SecurityFilterPosition.FILTER_SECURITY_INTERCEPTOR.order] instanceof FilterSecurityInterceptor @@ -122,7 +124,7 @@ class SpringSecurityUtilsIntegrationSpec extends AbstractIntegrationSpec { SpringSecurityUtils.clientRegisterFilter 'dummyFilter', SecurityFilterPosition.LOGOUT_FILTER.order + 10 then: - 11 == map.size() + 12 == map.size() map[SecurityFilterPosition.LOGOUT_FILTER.order + 10] instanceof DummyFilter when: @@ -138,8 +140,9 @@ class SpringSecurityUtilsIntegrationSpec extends AbstractIntegrationSpec { filters[6] instanceof GrailsRememberMeAuthenticationFilter filters[7] instanceof GrailsAnonymousAuthenticationFilter filters[8] instanceof FormContentFilter - filters[9] instanceof ExceptionTranslationFilter - filters[10] instanceof FilterSecurityInterceptor + filters[9] instanceof SiteMeshFilter + filters[10] instanceof ExceptionTranslationFilter + filters[11] instanceof FilterSecurityInterceptor } void 'reauthenticate'() { diff --git a/examples/misc-functional-test-app/grails-spring-security-group/build.gradle b/examples/misc-functional-test-app/grails-spring-security-group/build.gradle index 6d17ceb46..868816d4d 100644 --- a/examples/misc-functional-test-app/grails-spring-security-group/build.gradle +++ b/examples/misc-functional-test-app/grails-spring-security-group/build.gradle @@ -19,6 +19,7 @@ dependencies { implementation libs.spring.beans runtimeOnly libs.gorm.hibernate5 + runtimeOnly libs.grails.gsp runtimeOnly libs.grails.i18n runtimeOnly libs.grails.interceptors runtimeOnly libs.grails.services @@ -28,8 +29,6 @@ dependencies { runtimeOnly libs.springboot.starter.tomcat runtimeOnly libs.h2database runtimeOnly libs.tomcat.jdbc - - compileOnly libs.micronaut.inject.groovy } apply from: rootProject.layout.projectDirectory.file('gradle/java-config.gradle') diff --git a/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/error.gsp b/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/error.gsp new file mode 100644 index 000000000..6f0332432 --- /dev/null +++ b/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/error.gsp @@ -0,0 +1,22 @@ + + + + Grails Runtime Exception + + + + + + + + + + + + + diff --git a/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/index.gsp b/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/index.gsp new file mode 100644 index 000000000..11f08b2af --- /dev/null +++ b/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/index.gsp @@ -0,0 +1,9 @@ + + + + Welcome to Grails + + +

Welcome to Grails

+ + diff --git a/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/notFound.gsp b/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/notFound.gsp new file mode 100644 index 000000000..cf84e412e --- /dev/null +++ b/examples/misc-functional-test-app/grails-spring-security-group/grails-app/views/notFound.gsp @@ -0,0 +1,12 @@ + + + + Page Not Found + + + + + diff --git a/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/groovy/demo/SecuredControllerSpec.groovy b/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/groovy/demo/SecuredControllerSpec.groovy index 79f38a181..4e84f43d2 100644 --- a/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/groovy/demo/SecuredControllerSpec.groovy +++ b/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/groovy/demo/SecuredControllerSpec.groovy @@ -1,15 +1,14 @@ package demo -import geb.spock.GebSpec +import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration import grails.gorm.transactions.Rollback @Rollback @Integration(applicationClass = Application) -class SecuredControllerSpec extends GebSpec { +class SecuredControllerSpec extends ContainerGebSpec { def setup() { - browser.baseUrl = "http://localhost:${serverPort}/" if ( !User.findByUsername('sherlock') ) { final boolean flush = true final boolean failOnError = true @@ -34,6 +33,7 @@ class SecuredControllerSpec extends GebSpec { } def "test login as sherlock, sherlock belongs to detective groups. All detectives have the role ADMIN"() { + when: to SecuredPage @@ -51,6 +51,7 @@ class SecuredControllerSpec extends GebSpec { } def "test login as watson, watson belongs to detective groups. All detectives have the role ADMIN"() { + when: to SecuredPage diff --git a/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/resources/GebConfig.groovy b/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/resources/GebConfig.groovy deleted file mode 100644 index 9e41451af..000000000 --- a/examples/misc-functional-test-app/grails-spring-security-group/src/integration-test/resources/GebConfig.groovy +++ /dev/null @@ -1,74 +0,0 @@ -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.firefox.FirefoxDriver -import org.openqa.selenium.firefox.FirefoxOptions -import org.openqa.selenium.firefox.GeckoDriverService - -private static FirefoxDriver createFirefoxDriver(FirefoxOptions options = new FirefoxOptions()) { - def osName = System.getProperty('os.name').toLowerCase() - def profileRoot = osName.contains('linux') && new File('/snap/firefox').exists() ? createProfileRootInUserHome() : null - profileRoot ? new FirefoxDriver(createGeckoDriverService(profileRoot), options) : new FirefoxDriver(options) -} - -private static String createProfileRootInUserHome() { - def profileRoot = [System.getProperty('user.home'), 'snap/firefox/common/.firefox-profile-root'] as File - if ( ! profileRoot.exists()) { - if ( ! profileRoot.mkdirs()) { - return null - } - } - profileRoot.absolutePath -} - -private static GeckoDriverService createGeckoDriverService(String tmpProfileDir) { - new GeckoDriverService.Builder() { - @Override - protected List createArgs() { - def args = new ArrayList(super.createArgs()) - def idx = args.indexOf('--profile-root') - if (idx > -1) { - args.remove(idx + 1) - args.remove(idx) - } - args.add '--profile-root' - args.add tmpProfileDir - args - } - }.build() -} - -environments { - - // 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' - o.addArguments '--remote-allow-origins=*' - new ChromeDriver(o) - } - } - - // run via “./gradlew -Dgeb.env=firefox iT” - firefox { - driver = { createFirefoxDriver() } - } - - firefoxHeadless { - driver = { - FirefoxOptions o = new FirefoxOptions() - o.addArguments '-headless' - createFirefoxDriver o - } - } -} - -waiting { - timeout = 10 - retryInterval = 0.5 -} \ No newline at end of file diff --git a/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/groovy/demo/SecuredControllerSpec.groovy b/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/groovy/demo/SecuredControllerSpec.groovy index 1098d3a0b..2be143b61 100644 --- a/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/groovy/demo/SecuredControllerSpec.groovy +++ b/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/groovy/demo/SecuredControllerSpec.groovy @@ -1,14 +1,10 @@ package demo -import geb.spock.GebSpec +import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration @Integration(applicationClass = Application) -class SecuredControllerSpec extends GebSpec { - - def setup() { - browser.baseUrl = "http://localhost:${serverPort}/" - } +class SecuredControllerSpec extends ContainerGebSpec { def "test RoleHierarchyEntry lifecycle"() { when: diff --git a/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/resources/GebConfig.groovy b/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/resources/GebConfig.groovy deleted file mode 100644 index 9e41451af..000000000 --- a/examples/misc-functional-test-app/grails-spring-security-hierarchical-roles/src/integration-test/resources/GebConfig.groovy +++ /dev/null @@ -1,74 +0,0 @@ -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.firefox.FirefoxDriver -import org.openqa.selenium.firefox.FirefoxOptions -import org.openqa.selenium.firefox.GeckoDriverService - -private static FirefoxDriver createFirefoxDriver(FirefoxOptions options = new FirefoxOptions()) { - def osName = System.getProperty('os.name').toLowerCase() - def profileRoot = osName.contains('linux') && new File('/snap/firefox').exists() ? createProfileRootInUserHome() : null - profileRoot ? new FirefoxDriver(createGeckoDriverService(profileRoot), options) : new FirefoxDriver(options) -} - -private static String createProfileRootInUserHome() { - def profileRoot = [System.getProperty('user.home'), 'snap/firefox/common/.firefox-profile-root'] as File - if ( ! profileRoot.exists()) { - if ( ! profileRoot.mkdirs()) { - return null - } - } - profileRoot.absolutePath -} - -private static GeckoDriverService createGeckoDriverService(String tmpProfileDir) { - new GeckoDriverService.Builder() { - @Override - protected List createArgs() { - def args = new ArrayList(super.createArgs()) - def idx = args.indexOf('--profile-root') - if (idx > -1) { - args.remove(idx + 1) - args.remove(idx) - } - args.add '--profile-root' - args.add tmpProfileDir - args - } - }.build() -} - -environments { - - // 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' - o.addArguments '--remote-allow-origins=*' - new ChromeDriver(o) - } - } - - // run via “./gradlew -Dgeb.env=firefox iT” - firefox { - driver = { createFirefoxDriver() } - } - - firefoxHeadless { - driver = { - FirefoxOptions o = new FirefoxOptions() - o.addArguments '-headless' - createFirefoxDriver o - } - } -} - -waiting { - timeout = 10 - retryInterval = 0.5 -} \ No newline at end of file diff --git a/gradle/buildsrc.libs.versions.toml b/gradle/buildsrc.libs.versions.toml index 71c3ce95e..c218be701 100644 --- a/gradle/buildsrc.libs.versions.toml +++ b/gradle/buildsrc.libs.versions.toml @@ -1,13 +1,11 @@ [versions] asciidoctorj = '4.0.3' -asset-pipeline-gradle = '5.0.1' +asset-pipeline-gradle = '5.0.4' grails-gradle-plugin = '7.0.0-SNAPSHOT' -webdriver-binaries = '3.2' spock = '2.3-groovy-3.0' [libraries] asciidoctorj = { module = 'org.asciidoctor:asciidoctor-gradle-jvm', version.ref = 'asciidoctorj' } asset-pipeline-gradle = { module = 'com.bertramlabs.plugins:asset-pipeline-gradle', version.ref = 'asset-pipeline-gradle' } grails-gradle-plugin = { module = 'org.grails:grails-gradle-plugin', version.ref = 'grails-gradle-plugin' } -webdriver-binaries-gradle-plugin = { module = 'com.github.erdi:webdriver-binaries-gradle-plugin', version.ref = 'webdriver-binaries' } spock-core = { module = 'org.spockframework:spock-core', version.ref = 'spock' } \ No newline at end of file diff --git a/gradle/integrationTest.gradle b/gradle/integrationTest.gradle index aba7fc528..b2b6f1414 100644 --- a/gradle/integrationTest.gradle +++ b/gradle/integrationTest.gradle @@ -1,18 +1,15 @@ -apply plugin: 'com.github.erdi.webdriver-binaries' - dependencies { add('testImplementation', libs.micronaut.httpclient) - add('testImplementation', libs.micronaut.inject.groovy) add('testImplementation', libs.bundles.grails.testing.support) - add('integrationTestImplementation', libs.bundles.geb) - add('integrationTestRuntimeOnly', libs.bundles.selenium) + + integrationTestImplementation testFixtures(libs.geb.plugin) } tasks.named('integrationTest', Test) { systemProperty 'geb.build.reportsDir', reporting.file("$project.projectDir/build/geb-reports") systemProperties System.properties doFirst { - logger.quiet "\n - Running tests for configuration: ${System.getProperty('TESTCONFIG') ?: 'N/S'} with GEB env: ${System.getProperty('geb.env') ?: 'N/S'} and Grails: $grailsVersion" + logger.quiet "\n - Running tests for configuration: ${System.getProperty('TESTCONFIG') ?: 'N/S'} and Grails: $grailsVersion" } beforeTest { descriptor -> logger.quiet " -- $descriptor" } } diff --git a/gradle/java-config.gradle b/gradle/java-config.gradle index 3132d5647..08e4f289b 100644 --- a/gradle/java-config.gradle +++ b/gradle/java-config.gradle @@ -1,5 +1,6 @@ +compileJava.options.release = 17 + java { - sourceCompatibility = JavaVersion.VERSION_17 withJavadocJar() withSourcesJar() } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aafd31f4f..e39a8ab85 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,97 +1,66 @@ [versions] -asset-pipeline = '5.0.1' -bytebuddy = '1.15.10' -commons-text = '1.12.0' +asset-pipeline = '5.0.4' ehcache = '3.10.8' -geb = '7.0' -gorm-hibernate5 = '9.0.0-SNAPSHOT' grails = '7.0.0-SNAPSHOT' grails-async-and-events = '7.0.0-SNAPSHOT' -grails-datamapping = '9.0.0-SNAPSHOT' -grails-gsp = '7.0.0-SNAPSHOT' -grails-converters = '6.0.0-SNAPSHOT' -grails-testing-support = '4.0.0-SNAPSHOT' -groovy = '4.0.22' -h2database = '2.3.232' -jakarta-annotation-api = '3.0.0' -jakarta-servlet-api = '6.0.0' +groovy = '4.0.24' micronaut = '4.5.3' -selenium = '4.19.1' -selenium-safari = '4.19.1' -slf4j = '2.0.16' -spock = '2.3-groovy-4.0' -spring = '6.1.12' -springboot = '3.3.3' -spring-security = '6.3.3' -tomcat = '10.1.29' [libraries] -commons-text = { module = 'org.apache.commons:commons-text', version.ref = 'commons-text' } +commons-text = { module = 'org.apache.commons:commons-text' } ehcache = { module = 'org.ehcache:ehcache', version.ref = 'ehcache' } -bytebuddy = { module = 'net.bytebuddy:byte-buddy', version.ref = 'bytebuddy' } -geb-core = { module = 'org.gebish:geb-core', version.ref = 'geb' } -geb-spock = { module = 'org.gebish:geb-spock', version.ref = 'geb' } -gorm-hibernate5 = { module = 'org.grails.plugins:hibernate5', version.ref = 'gorm-hibernate5' } +bytebuddy = { module = 'net.bytebuddy:byte-buddy' } +gorm-hibernate5 = { module = 'org.grails.plugins:hibernate5' } grails-asset-pipeline = { module = 'com.bertramlabs.plugins:asset-pipeline-grails', version.ref = 'asset-pipeline' } -grails-core = { module = 'org.grails:grails-core', version.ref = 'grails' } -grails-bootstrap = { module = 'org.grails:grails-bootstrap', version.ref = 'grails' } -grails-converters = { module = 'org.grails.plugins:converters', version.ref = 'grails-converters' } -grails-datastore-core = { module = 'org.grails:grails-datastore-core', version.ref = 'grails-datamapping' } -grails-datastore-gorm = { module = 'org.grails:grails-datastore-gorm', version.ref = 'grails-datamapping' } -grails-domain = { module = 'org.grails:grails-plugin-domain-class', version.ref = 'grails' } +grails-bom = { module = 'org.grails:grails-bom', version.ref = 'grails' } +grails-core = { module = 'org.grails:grails-core' } +grails-bootstrap = { module = 'org.grails:grails-bootstrap' } +grails-converters = { module = 'org.grails.plugins:converters' } +grails-datastore-core = { module = 'org.grails:grails-datastore-core'} +grails-datastore-gorm = { module = 'org.grails:grails-datastore-gorm'} +grails-domain = { module = 'org.grails:grails-plugin-domain-class' } grails-events-transform = { module = 'org.grails:grails-events-transform', version.ref = 'grails-async-and-events' } -grails-gsp = { module = 'org.grails.plugins:gsp', version.ref = 'grails-gsp' } -grails-i18n = { module = 'org.grails:grails-plugin-i18n', version.ref = 'grails' } -grails-interceptors = { module = 'org.grails:grails-plugin-interceptors', version.ref = 'grails' } -grails-mimetypes = { module = 'org.grails:grails-plugin-mimetypes', version.ref = 'grails' } +grails-gsp = { module = 'org.grails.plugins:gsp' } +grails-i18n = { module = 'org.grails:grails-plugin-i18n' } +grails-interceptors = { module = 'org.grails:grails-plugin-interceptors' } +grails-mimetypes = { module = 'org.grails:grails-plugin-mimetypes' } grails-plugin-async = { module = 'org.grails.plugins:async', version.ref = 'grails-async-and-events' } -grails-rest = { module = 'org.grails:grails-plugin-rest', version.ref = 'grails' } -grails-services = { module = 'org.grails:grails-plugin-services', version.ref = 'grails' } -grails-testing-support-gorm = { module = 'org.grails:grails-gorm-testing-support', version.ref = 'grails-testing-support' } -grails-testing-support-web = { module = 'org.grails:grails-web-testing-support', version.ref = 'grails-testing-support' } -grails-urlmappings = { module = 'org.grails:grails-plugin-url-mappings', version.ref = 'grails' } -grails-validation = { module = 'org.grails:grails-plugin-validation', version.ref = 'grails' } -grails-web-common = { module = 'org.grails:grails-web-common', version.ref = 'grails' } -grails-web-urlmappings = { module = 'org.grails:grails-web-url-mappings', version.ref = 'grails' } -groovy-core = { module = 'org.apache.groovy:groovy', version.ref = 'groovy' } -jakarta-annotation-api = { module = 'jakarta.annotation:jakarta.annotation-api', version.ref = 'jakarta-annotation-api' } -jakarta-servlet-api = { module = 'jakarta.servlet:jakarta.servlet-api', version.ref = 'jakarta-servlet-api' } -h2database = { module = 'com.h2database:h2', version.ref = 'h2database' } +grails-plugin-events = { module = 'org.grails.plugins:events', version.ref = 'grails-async-and-events' } +grails-rest = { module = 'org.grails:grails-plugin-rest' } +grails-services = { module = 'org.grails:grails-plugin-services' } +grails-testing-support-gorm = { module = 'org.grails:grails-gorm-testing-support' } +grails-testing-support-web = { module = 'org.grails:grails-web-testing-support' } +grails-urlmappings = { module = 'org.grails:grails-plugin-url-mappings' } +grails-validation = { module = 'org.grails:grails-plugin-validation' } +grails-web-common = { module = 'org.grails:grails-web-common' } +grails-web-urlmappings = { module = 'org.grails:grails-web-url-mappings' } +groovy-core = { module = 'org.apache.groovy:groovy' } +jakarta-annotation-api = { module = 'jakarta.annotation:jakarta.annotation-api' } +jakarta-servlet-api = { module = 'jakarta.servlet:jakarta.servlet-api' } +h2database = { module = 'com.h2database:h2' } micronaut-httpclient = { module = 'io.micronaut:micronaut-http-client', version.ref = 'micronaut' } -micronaut-inject-groovy = { module = 'io.micronaut:micronaut-inject-groovy', version.ref = 'micronaut' } micronaut-jackson-databind = { module = 'io.micronaut:micronaut-jackson-databind', version.ref = 'micronaut' } -selenium-api = { module = 'org.seleniumhq.selenium:selenium-api', version.ref = 'selenium' } -selenium-chrome-driver = { module = 'org.seleniumhq.selenium:selenium-chrome-driver', version.ref = 'selenium' } -selenium-chromium-driver = { module = 'org.seleniumhq.selenium:selenium-chromium-driver', version.ref = 'selenium' } -selenium-devtools-v85 = { module = 'org.seleniumhq.selenium:selenium-devtools-v85', version.ref = 'selenium' } -selenium-firefox-driver = { module = 'org.seleniumhq.selenium:selenium-firefox-driver', version.ref = 'selenium' } -selenium-http = { module = 'org.seleniumhq.selenium:selenium-http', version.ref = 'selenium' } -selenium-json = { module = 'org.seleniumhq.selenium:selenium-json', version.ref = 'selenium' } -selenium-remote-driver = { module = 'org.seleniumhq.selenium:selenium-remote-driver', version.ref = 'selenium' } -selenium-safari-driver = { module = 'org.seleniumhq.selenium:selenium-safari-driver', version.ref = 'selenium-safari' } -selenium-support = { module = 'org.seleniumhq.selenium:selenium-support', version.ref = 'selenium' } -slf4j-nop = { module = 'org.slf4j:slf4j-nop', version.ref = 'slf4j' } -spock-core = { module = 'org.spockframework:spock-core', version.ref = 'spock' } -spring-beans = { module = 'org.springframework:spring-beans', version.ref = 'spring' } -spring-core = { module = 'org.springframework:spring-core', version.ref = 'spring' } -spring-context-core = { module = 'org.springframework:spring-context', version.ref = 'spring' } -spring-context-support = { module = 'org.springframework:spring-context-support', version.ref = 'spring' } -spring-expression = { module = 'org.springframework:spring-expression', version.ref = 'spring' } -spring-security-core = { module = 'org.springframework.security:spring-security-core', version.ref = 'spring-security' } -spring-security-config = { module = 'org.springframework.security:spring-security-config', version.ref = 'spring-security' } -spring-security-crypto = { module = 'org.springframework.security:spring-security-crypto', version.ref = 'spring-security' } -spring-security-web = { module = 'org.springframework.security:spring-security-web', version.ref = 'spring-security' } -spring-test = { module = 'org.springframework:spring-test', version.ref = 'spring' } -spring-tx = { module = 'org.springframework:spring-tx', version.ref = 'spring' } -spring-web = { module = 'org.springframework:spring-web', version.ref = 'spring' } -springboot-autoconfigure = { module = 'org.springframework.boot:spring-boot-autoconfigure', version.ref = 'springboot' } -springboot-core = { module = 'org.springframework.boot:spring-boot', version.ref = 'springboot' } -springboot-starter-logging = { module = 'org.springframework.boot:spring-boot-starter-logging', version.ref = 'springboot' } -springboot-starter-test = { module = 'org.springframework.boot:spring-boot-starter-test', version.ref = 'springboot' } -springboot-starter-tomcat = { module = 'org.springframework.boot:spring-boot-starter-tomcat', version.ref = 'springboot' } -tomcat-jdbc = { module = 'org.apache.tomcat:tomcat-jdbc', version.ref = 'tomcat' } +slf4j-nop = { module = 'org.slf4j:slf4j-nop' } +spock-core = { module = 'org.spockframework:spock-core' } +geb-plugin = { module = 'org.grails.plugins:geb' } +spring-beans = { module = 'org.springframework:spring-beans' } +spring-core = { module = 'org.springframework:spring-core' } +spring-context-core = { module = 'org.springframework:spring-context' } +spring-context-support = { module = 'org.springframework:spring-context-support' } +spring-expression = { module = 'org.springframework:spring-expression' } +spring-security-core = { module = 'org.springframework.security:spring-security-core' } +spring-security-config = { module = 'org.springframework.security:spring-security-config' } +spring-security-crypto = { module = 'org.springframework.security:spring-security-crypto' } +spring-security-web = { module = 'org.springframework.security:spring-security-web' } +spring-test = { module = 'org.springframework:spring-test' } +spring-tx = { module = 'org.springframework:spring-tx' } +spring-web = { module = 'org.springframework:spring-web' } +springboot-autoconfigure = { module = 'org.springframework.boot:spring-boot-autoconfigure' } +springboot-core = { module = 'org.springframework.boot:spring-boot' } +springboot-starter-logging = { module = 'org.springframework.boot:spring-boot-starter-logging' } +springboot-starter-test = { module = 'org.springframework.boot:spring-boot-starter-test' } +springboot-starter-tomcat = { module = 'org.springframework.boot:spring-boot-starter-tomcat' } +tomcat-jdbc = { module = 'org.apache.tomcat:tomcat-jdbc' } [bundles] -geb = ['geb-core', 'geb-spock'] grails-testing-support = ['grails-testing-support-gorm', 'grails-testing-support-web', 'springboot-starter-test'] -selenium = ['selenium-api', 'selenium-chrome-driver', 'selenium-chromium-driver', 'selenium-devtools-v85', 'selenium-firefox-driver', 'selenium-http', 'selenium-json', 'selenium-remote-driver', 'selenium-safari-driver', 'selenium-support'] diff --git a/plugin/build.gradle b/plugin/build.gradle index e02e8cba5..41433195d 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -17,6 +17,7 @@ dependencies { api libs.grails.events.transform // API because used in templates api libs.grails.mimetypes api libs.grails.plugin.async // AsyncGrailsWebRequest is used in public API + implementation libs.grails.plugin.events // Events Plugin is required to implement EventBus api libs.grails.web.common api libs.grails.web.urlmappings api libs.spring.beans diff --git a/plugin/grails-app/views/layouts/main.gsp b/plugin/grails-app/views/layouts/main.gsp new file mode 100644 index 000000000..e40d8978b --- /dev/null +++ b/plugin/grails-app/views/layouts/main.gsp @@ -0,0 +1,15 @@ + + + + + + + <g:layoutTitle default="Grails"/> + + + + + + + + diff --git a/plugin/src/docs/code/s2-quickstart/build.gradle b/plugin/src/docs/code/s2-quickstart/build.gradle index c0d001900..a42f5d064 100644 --- a/plugin/src/docs/code/s2-quickstart/build.gradle +++ b/plugin/src/docs/code/s2-quickstart/build.gradle @@ -24,7 +24,6 @@ repositories { } dependencies { - compileOnly "io.micronaut:micronaut-inject-groovy" console "org.grails:grails-console" implementation "org.springframework.boot:spring-boot-starter-logging" implementation "org.springframework.boot:spring-boot-starter-validation" @@ -54,7 +53,6 @@ dependencies { runtimeOnly "org.apache.tomcat:tomcat-jdbc" runtimeOnly "javax.xml.bind:jaxb-api:2.3.1" runtimeOnly "com.bertramlabs.plugins:asset-pipeline-grails:4.3.0" - testImplementation "io.micronaut:micronaut-inject-groovy" testImplementation "org.grails:grails-gorm-testing-support" testImplementation "org.mockito:mockito-core" testImplementation "org.grails:grails-web-testing-support" diff --git a/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityFilterPosition.java b/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityFilterPosition.java index 15413f110..5e18cf8ae 100644 --- a/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityFilterPosition.java +++ b/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityFilterPosition.java @@ -20,7 +20,6 @@ * Equivalent to org.springframework.security.config.http.SecurityFilters which * unfortunately is package-default. * - * @author Burt Beckwith */ public enum SecurityFilterPosition { @@ -68,6 +67,8 @@ public enum SecurityFilterPosition { FORM_LOGIN_FILTER, + DEFAULT_RESOURCES_FILTER, + LOGIN_PAGE_FILTER, LOGOUT_PAGE_FILTER, diff --git a/plugin/src/main/groovy/grails/plugin/springsecurity/SpringSecurityCoreGrailsPlugin.groovy b/plugin/src/main/groovy/grails/plugin/springsecurity/SpringSecurityCoreGrailsPlugin.groovy index 0c1f90f73..a38e85a32 100644 --- a/plugin/src/main/groovy/grails/plugin/springsecurity/SpringSecurityCoreGrailsPlugin.groovy +++ b/plugin/src/main/groovy/grails/plugin/springsecurity/SpringSecurityCoreGrailsPlugin.groovy @@ -668,7 +668,7 @@ to default to 'Annotation'; setting value to 'Annotation' // if sitemesh 3 is installed, the filter should be applied a second time // as part of the security filter chain so that pages are decorated using the security context if (applicationContext.containsBean('sitemesh')) { - filterNames[SecurityFilterPosition.EXCEPTION_TRANSLATION_FILTER.order - 10] = 'sitemesh' + filterNames[SecurityFilterPosition.EXCEPTION_TRANSLATION_FILTER.order - 5] = 'sitemesh' } SpringSecurityUtils.buildFilterChains filterNames, conf.filterChain.chainMap ?: [], securityFilterChains, applicationContext