Skip to content

Commit 51a2fda

Browse files
committed
Merge branch 'feature/biocollect-1586' of https://github.com/AtlasOfLivingAustralia/ecodata-client-plugin into feature/biocollect-1586
2 parents cd86821 + 55ccf80 commit 51a2fda

File tree

7 files changed

+71
-42
lines changed

7 files changed

+71
-42
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ jobs:
1919
steps:
2020
- uses: actions/checkout@v3
2121

22-
- name: Set up JDK 11
22+
- name: Set up JDK 17
2323
uses: actions/setup-java@v3
2424
with:
25-
java-version: '11'
25+
java-version: '17'
2626
distribution: 'adopt'
2727

2828
- name: Install nodejs

build.gradle

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ plugins {
1717
id 'jacoco'
1818
}
1919

20-
version "7.3-SNAPSHOT"
20+
version "8.0-SNAPSHOT"
2121
group "org.grails.plugins"
2222

2323
apply plugin:"eclipse"
@@ -49,6 +49,8 @@ configurations {
4949
extendsFrom developmentOnly
5050
}
5151
}
52+
sourceCompatibility = '11'
53+
targetCompatibility = '17'
5254

5355
dependencies {
5456
developmentOnly("org.springframework.boot:spring-boot-devtools")

gradle.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
grailsVersion=6.2.0
1+
grailsVersion=6.2.3
22
gorm.version=8.1.2
33
grailsGradlePluginVersion=6.1.2
44
org.gradle.daemon=true
@@ -13,4 +13,4 @@ org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xss2048k -Xmx1024M
1313
exploded=true
1414
enableClover=false
1515
enableJacoco=true
16-
alaSecurityLibsVersion=6.3.0
16+
alaSecurityLibsVersion=7.0.0

grails-app/services/au/org/ala/ecodata/forms/EcpWebService.groovy

+9-1
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,16 @@ class EcpWebService {
181181
proxyGetRequest(response, url, authHeaderType, timeout)
182182
}
183183

184+
def proxyGetRequest(HttpServletResponse response, String url, Map params, String authHeaderType, Integer timeout = null, String externalToken = null, Map extraHeaders = null) {
185+
url = url + buildUrlParamsFromMap(params)
186+
proxyGetRequest(response, url, authHeaderType, timeout, externalToken, extraHeaders)
187+
}
188+
184189
/**
185190
* Proxies a request URL but doesn't assume the response is text based. (Used for proxying requests to
186191
* ecodata for excel-based reports)
187192
*/
188-
def proxyGetRequest(HttpServletResponse response, String url, String authHeaderType, Integer timeout = null, String externalToken = null) {
193+
def proxyGetRequest(HttpServletResponse response, String url, String authHeaderType, Integer timeout = null, String externalToken = null, Map extraHeaders = null) {
189194

190195
def readTimeout = timeout?:defaultTimeout()
191196
HttpURLConnection conn = configureConnection(url, authHeaderType, readTimeout, externalToken)
@@ -205,6 +210,9 @@ class EcpWebService {
205210
}
206211

207212
}
213+
extraHeaders?.each { header ->
214+
response.setHeader(header.key, header.value)
215+
}
208216
response.status = conn.responseCode
209217

210218
response.outputStream << conn.inputStream

grails-app/services/au/org/ala/ecodata/forms/UserInfoService.groovy

+25-16
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package au.org.ala.ecodata.forms
22

33
import au.org.ala.web.UserDetails
44
import org.grails.web.servlet.mvc.GrailsWebRequest
5+
import org.pac4j.core.adapter.FrameworkAdapter
56
import org.pac4j.core.config.Config
7+
import org.pac4j.core.context.CallContext
68
import org.pac4j.core.context.WebContext
7-
import org.pac4j.core.credentials.Credentials
8-
import org.pac4j.core.util.FindBest
9-
import org.pac4j.jee.context.JEEContextFactory
10-
import au.org.ala.ws.security.client.AlaOidcClient
9+
import org.pac4j.core.context.session.SessionStore
10+
import org.pac4j.core.credentials.TokenCredentials
11+
import org.pac4j.http.client.direct.DirectBearerAuthClient
12+
import org.pac4j.jee.context.JEEFrameworkParameters
1113
import org.springframework.beans.factory.annotation.Autowired
1214
import org.springframework.http.HttpStatus
1315

@@ -37,7 +39,8 @@ class UserInfoService {
3739
@Autowired(required = false)
3840
Config config
3941
@Autowired(required = false)
40-
AlaOidcClient alaOidcClient
42+
DirectBearerAuthClient alaOidcClient
43+
4144

4245
static String USER_NAME_HEADER_FIELD = "userName"
4346
static String AUTH_KEY_HEADER_FIELD = "authKey"
@@ -113,19 +116,25 @@ class UserInfoService {
113116
if (!authorizationHeader)
114117
authorizationHeader = request?.getHeader(AUTHORIZATION_HEADER_FIELD)
115118
if (authorizationHeader?.startsWith("Bearer")) {
116-
final WebContext context = FindBest.webContextFactory(null, config, JEEContextFactory.INSTANCE).newContext(request, response)
117-
def optCredentials = alaOidcClient.getCredentials(context, config.sessionStore)
118-
if (optCredentials.isPresent()) {
119-
Credentials credentials = optCredentials.get()
120-
def optUserProfile = alaOidcClient.getUserProfile(credentials, context, config.sessionStore)
121-
if (optUserProfile.isPresent()) {
122-
def userProfile = optUserProfile.get()
123-
String userId = userProfile?.userId ?: userProfile?.getAttribute(grailsApplication.config.getProperty('userProfile.userIdAttribute'))
124-
if (userId) {
125-
return authService.getUserForUserId(userId)
126-
}
119+
def params = new JEEFrameworkParameters(request, response)
120+
121+
FrameworkAdapter.INSTANCE.applyDefaultSettingsIfUndefined(config)
122+
final WebContext context = config.getWebContextFactory().newContext(params)
123+
final SessionStore sessionStore = config.getSessionStoreFactory().newSessionStore(params)
124+
final callContext = new CallContext(context, sessionStore, config.profileManagerFactory)
125+
126+
def credentials = alaOidcClient.getCredentials(callContext).orElse(null)
127+
credentials = alaOidcClient.validateCredentials(callContext, credentials).orElse(null)
128+
if (credentials && credentials instanceof TokenCredentials) {
129+
def userProfile = credentials.userProfile
130+
131+
//String userId = userProfile?.getAttribute(grailsApplication.config.getProperty('userProfile.userIdAttribute'))
132+
String userId = userProfile?.getAttribute("username")
133+
if (userId) {
134+
return authService.getUserForUserId(userId)
127135
}
128136
}
137+
129138
}
130139
} catch (Throwable e) {
131140
log.error("Failed to get user details from JWT", e)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@atlasoflivingaustralia/ecodata-client-plugin",
3-
"version": "7.2.0",
3+
"version": "7.3.0",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/AtlasOfLivingAustralia/ecodata-client-plugin.git"

src/test/groovy/au/org/ala/ecodata/forms/UserInfoServiceSpec.groovy

+29-19
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package au.org.ala.ecodata.forms
22

33
import au.org.ala.web.UserDetails
4-
import au.org.ala.ws.security.client.AlaOidcClient
5-
import au.org.ala.ws.security.profile.AlaOidcUserProfile
64
import grails.testing.services.ServiceUnitTest
75
import grails.testing.web.GrailsWebUnitTest
6+
import org.pac4j.core.client.DirectClient
87
import org.pac4j.core.config.Config
9-
import org.pac4j.core.credentials.AnonymousCredentials
8+
import org.pac4j.core.context.WebContextFactory
9+
import org.pac4j.core.context.session.SessionStoreFactory
1010
import org.pac4j.core.credentials.Credentials
11-
import org.pac4j.core.profile.UserProfile
11+
import org.pac4j.core.credentials.TokenCredentials
12+
import org.pac4j.http.client.direct.DirectBearerAuthClient
13+
import org.pac4j.jwt.profile.JwtProfile
1214
import spock.lang.Specification
1315

1416
/*
@@ -31,7 +33,7 @@ import spock.lang.Specification
3133
class UserInfoServiceSpec extends Specification implements ServiceUnitTest<UserInfoService>, GrailsWebUnitTest {
3234
EcpWebService webService = Mock(EcpWebService)
3335
def authService = Mock(AuthService)
34-
AlaOidcClient alaOidcClient
36+
DirectClient alaOidcClient
3537
Config pack4jConfig
3638

3739
def user
@@ -79,22 +81,26 @@ class UserInfoServiceSpec extends Specification implements ServiceUnitTest<UserI
7981
void "getUserFromJWT returns user when Authorization header is passed"() {
8082
setup:
8183
def result
82-
alaOidcClient = GroovyMock([global: true], AlaOidcClient)
84+
alaOidcClient = GroovyMock([global: true], DirectBearerAuthClient)
8385
pack4jConfig = GroovyMock([global: true], Config)
8486
service.alaOidcClient = alaOidcClient
8587
service.config = pack4jConfig
86-
AlaOidcUserProfile person = new AlaOidcUserProfile(user.userId)
87-
Optional<Credentials> credentials = new Optional<Credentials>(AnonymousCredentials.INSTANCE)
88-
Optional<UserProfile> userProfile = new Optional<UserProfile>(person)
88+
pack4jConfig.getWebContextFactory() >> Mock(WebContextFactory)
89+
pack4jConfig.getSessionStoreFactory() >> Mock(SessionStoreFactory)
90+
Credentials tokenCredentials = Mock(TokenCredentials)
91+
JwtProfile profile = Mock(JwtProfile)
92+
Optional<Credentials> credentials = Optional.of(tokenCredentials)
8993

9094
when:
9195
request.addHeader('Authorization', 'Bearer abcdef')
9296
result = service.getUserFromJWT()
9397

9498
then:
95-
alaOidcClient.getCredentials(*_) >> credentials
96-
alaOidcClient.getUserProfile(*_) >> userProfile
97-
authService.getUserForUserId(user.userId) >> userDetails
99+
1 * alaOidcClient.getCredentials(*_) >> credentials
100+
1 * alaOidcClient.validateCredentials(_, _) >> credentials
101+
1 * tokenCredentials.userProfile >> profile
102+
1 * profile.getAttribute("username") >> user.userId
103+
1 * authService.getUserForUserId(user.userId) >> userDetails
98104
result.userName == user.userName
99105
result.displayName == "${user.firstName} ${user.lastName}"
100106
result.userId == user.userId
@@ -103,13 +109,15 @@ class UserInfoServiceSpec extends Specification implements ServiceUnitTest<UserI
103109
void "getCurrentUser should get current user from CAS"() {
104110
setup:
105111
def result
106-
alaOidcClient = GroovyMock([global: true], AlaOidcClient)
112+
alaOidcClient = GroovyMock([global: true], DirectBearerAuthClient)
107113
pack4jConfig = GroovyMock([global: true], Config)
108114
service.alaOidcClient = alaOidcClient
109115
service.config = pack4jConfig
110-
AlaOidcUserProfile person = new AlaOidcUserProfile(user.userId)
111-
Optional<Credentials> credentials = new Optional<Credentials>(AnonymousCredentials.INSTANCE)
112-
Optional<UserProfile> userProfile = new Optional<UserProfile>(person)
116+
pack4jConfig.getWebContextFactory() >> Mock(WebContextFactory)
117+
pack4jConfig.getSessionStoreFactory() >> Mock(SessionStoreFactory)
118+
Credentials tokenCredentials = Mock(TokenCredentials)
119+
JwtProfile profile = Mock(JwtProfile)
120+
Optional<Credentials> credentials = Optional.of(tokenCredentials)
113121

114122
when:
115123
result = service.getCurrentUserFromSupportedMethods()
@@ -124,9 +132,11 @@ class UserInfoServiceSpec extends Specification implements ServiceUnitTest<UserI
124132
result = service.getCurrentUserFromSupportedMethods()
125133

126134
then:
127-
alaOidcClient.getCredentials(*_) >> credentials
128-
alaOidcClient.getUserProfile(*_) >> userProfile
129-
1 * authService.getUserForUserId(user.userId) >> userDetails
135+
1 * alaOidcClient.getCredentials(*_) >> credentials
136+
1 * alaOidcClient.validateCredentials(_, _) >> credentials
137+
1 * tokenCredentials.userProfile >> profile
138+
1 * profile.getAttribute("username") >> user.userId
139+
1 * authService.getUserForUserId(user.userId) >> userDetails
130140
1 * authService.userDetails() >> null
131141
result.userName == user.userName
132142
result.displayName == "first last"

0 commit comments

Comments
 (0)