Skip to content

Commit 87152e9

Browse files
authored
Merge pull request #342 from AtlasOfLivingAustralia/dev
Preparing v7.1
2 parents 4be3626 + 1f03077 commit 87152e9

File tree

21 files changed

+4624
-7499
lines changed

21 files changed

+4624
-7499
lines changed

.github/workflows/build.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- name: Install nodejs
2929
uses: actions/setup-node@v4
3030
with:
31-
node-version: '16.x'
31+
node-version: '24.x'
3232
registry-url: 'https://npm.pkg.github.com'
3333
scope: 'AtlasOfLivingAustralia'
3434

@@ -40,19 +40,24 @@ jobs:
4040
id: pre-release-version
4141
uses: adobe/update-prerelease-npm-version@4dea8f295023f5b18126afd79bae1057a5b92d6e #v1.2.0
4242

43-
- run: npm publish
43+
- run: npm publish --tag=snapshot
4444
env:
4545
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4646

4747
- name: Setup Gradle
4848
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
4949

50+
- name: Check chromedriver is available
51+
run: echo $CHROMEWEBDRIVER
52+
53+
- name: Check chromedriver version
54+
run: $CHROMEWEBDRIVER/chromedriver --version
5055

5156
- name: Run tests and jacoco coverage report with Gradle
52-
run: ./gradlew -PenableJacoco=true check
57+
run: ./gradlew -PenableJacoco=true -Dwebdriver.chrome.driver=$CHROMEWEBDRIVER/chromedriver check
5358

5459
- name: Run javascript unit tests
55-
run: node_modules/karma/bin/karma start karma.conf.js --single-run --browsers ChromeHeadless
60+
run: npm run test
5661

5762
- name: Clean to remove clover instrumentation
5863
run: ./gradlew clean

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ plugins {
1717
id 'jacoco'
1818
}
1919

20-
version "9.0"
20+
version "9.1-SNAPSHOT"
2121
group "org.grails.plugins"
2222

2323
apply plugin:"eclipse"
@@ -108,6 +108,7 @@ dependencies {
108108
tasks.withType(Test) {
109109
systemProperty 'geb.env', System.getProperty('geb.env') ?: 'chromeHeadless'
110110
systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest")
111+
systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver')
111112

112113
testLogging {
113114
events "passed", "skipped", "failed"

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xss2048k -Xmx1024M
1313
exploded=true
1414
enableClover=false
1515
enableJacoco=true
16-
alaSecurityLibsVersion=7.0.0
16+
alaSecurityLibsVersion=7.1.0-SNAPSHOT

grails-app/assets/javascripts/forms-knockout-bindings.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@
104104

105105
}).on('fileuploadfail', function(e, data) {
106106
var jqXHR = data.jqXHR;
107-
if (jqXHR && jqXHR.status === 422) {
108-
var resp = jqXHR.responseJSON || {message: "File upload could not be processed. Possible virus detected."};
109-
error(resp.message);
107+
if (jqXHR && (jqXHR.status === 422 || jqXHR.status === 500)) {
108+
var resp = jqXHR.responseJSON || {};
109+
error(resp.message || jqXHR.responseText || 'File upload failed');
110110
}
111111
else {
112112
error(data.errorThrown);
@@ -228,9 +228,9 @@
228228

229229
}).on(eventPrefix+'fail', function(e, data) {
230230
var jqXHR = data.jqXHR;
231-
if (jqXHR && jqXHR.status === 422) {
232-
var resp = jqXHR.responseJSON || {message: "File upload could not be processed. Possible virus detected."};
233-
error(resp.message);
231+
if (jqXHR && (jqXHR.status === 422 || jqXHR.status === 500)) {
232+
var resp = jqXHR.responseJSON || {};
233+
error(resp.message || jqXHR.responseText || 'File upload failed');
234234
}
235235
else {
236236
error(data.errorThrown);

grails-app/conf/application.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ environments:
104104
appServerName: 'n/a'
105105
oidc:
106106
enabled: true
107-
discoveryUri: 'http://localhost:8080'
107+
discoveryUri: 'file://${user.dir}/src/integration-test/resources/oidcDiscovery.json'
108+
clientId: 'testClientId'
109+
secret: 'testSecret'
110+
allowUnsignedIdTokens: true
108111
jwt:
109112
enabled: false
110113

grails-app/controllers/au/org/ala/merit/FileScanInterceptor.groovy

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,29 @@ class FileScanInterceptor {
1414

1515
boolean before() {
1616
if (request.respondsTo('getFile')) {
17-
boolean clean = true
17+
List statusCodes = []
1818
def files = request.getFileNames()
1919
while(files.hasNext()) {
2020
def fileName = files.next()
2121
def file = request.getFile(fileName)
2222
if (file) {
23-
boolean isClean = scanService.isDocumentClean(file)
24-
clean &= isClean
23+
statusCodes << scanService.getDocumentScanStatus(file)
2524
}
2625
}
2726

28-
if (!clean) {
27+
if (statusCodes.any { it == HttpStatus.SC_UNPROCESSABLE_ENTITY }) {
2928
response.status = HttpStatus.SC_UNPROCESSABLE_ENTITY
3029
render contentType: 'application/json', text: [success: false, message: "File upload rejected: virus detected"] as JSON, status: HttpStatus.SC_UNPROCESSABLE_ENTITY
3130
return false
3231
}
32+
else if (statusCodes.every { it == HttpStatus.SC_OK }) {
33+
return true
34+
}
35+
else {
36+
response.status = HttpStatus.SC_INTERNAL_SERVER_ERROR
37+
render contentType: 'application/json', text: [success: false, message: "File upload failed during scanning"] as JSON, status: HttpStatus.SC_INTERNAL_SERVER_ERROR
38+
return false
39+
}
3340
}
3441

3542
true

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

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,41 @@ class EcpWebService {
9595
}
9696
}
9797

98+
/**
99+
* This method is used when the response is expected to be a stream, e.g. for downloading files.
100+
* It returns a Map with keys [statusCode: <http status code>, error: <error message if applicable>]
101+
* The supplied outputStream will be written to with the response from the web service if the call is successful.
102+
* The caller is responsible for closing the outputStream.
103+
*/
104+
Map readToStream(String url, OutputStream outputStream, boolean includeUserId = true, Integer timeout = null) {
105+
HttpURLConnection conn = null
106+
Map resp = [:]
107+
try {
108+
conn = configureConnection(url, includeUserId, timeout)
109+
try (InputStream inputStream = conn.inputStream) {
110+
outputStream << inputStream
111+
}
112+
resp = [statusCode: conn.responseCode]
113+
114+
} catch (SocketTimeoutException e) {
115+
int statusCode = conn ? (conn.responseCode ?: HttpStatus.SC_GATEWAY_TIMEOUT) : HttpStatus.SC_GATEWAY_TIMEOUT
116+
resp = [error: "Timed out calling web service. URL= ${url}.", statusCode: statusCode]
117+
log.error "Timed out calling web service. URL= ${url}.", e
118+
} catch (SocketException se) {
119+
int statusCode = conn ? (conn.responseCode ?: HttpStatus.SC_GATEWAY_TIMEOUT) : HttpStatus.SC_GATEWAY_TIMEOUT
120+
resp = [error: "Timed out calling web service. URL= ${url}.", statusCode: statusCode]
121+
122+
log.warn "Socket connection closed. ${se.getMessage()} URL= ${url}.", se
123+
} catch (Exception e) {
124+
int statusCode = conn ? (conn.responseCode ?: HttpStatus.SC_INTERNAL_SERVER_ERROR) : HttpStatus.SC_INTERNAL_SERVER_ERROR
125+
resp = [error: "Timed out calling web service. URL= ${url}.", statusCode: statusCode]
126+
127+
log.error "Failed calling web service. ${e.getClass()} ${e.getMessage()} URL= ${url}.", e
128+
}
129+
130+
resp
131+
}
132+
98133
Map getString(String url, boolean includeAuth) {
99134
URLConnection conn = null
100135
Map resp = [:]
@@ -104,7 +139,7 @@ class EcpWebService {
104139
resp.statusCode = conn.responseCode
105140
} catch (SocketTimeoutException e) {
106141
resp.error = "Timed out calling web service. URL= ${url}."
107-
resp.statusCode = HttpStatus.CONNECTION_TIMED_OUT
142+
resp.statusCode = HttpStatus.SC_GATEWAY_TIMEOUT
108143
log.warn resp.error
109144
} catch (SocketException se) {
110145
resp.error = "Socket connection closed. ${se.getMessage()} URL= ${url}."
@@ -607,9 +642,10 @@ class EcpWebService {
607642
}
608643

609644
def user = userService.getUser()
610-
String userId = user.userId
611-
String userIdHeader = grailsApplication.config.getProperty('app.http.header.userId')
645+
612646
if (user) {
647+
String userIdHeader = grailsApplication.config.getProperty('app.http.header.userId')
648+
String userId = user.userId
613649
requestBuilder.addHeader(userIdHeader, userId)
614650
} else {
615651
log.warn("No user associated with request: ${url}")
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package au.org.ala.ecodata.forms
22

3-
3+
import org.springframework.http.HttpStatus
44
import org.springframework.web.multipart.MultipartFile
55

66
class ScanService {
77
EcpWebService ecpWebService
88
def grailsApplication
99

10-
boolean isDocumentClean(MultipartFile file) {
10+
int getDocumentScanStatus(MultipartFile file) {
1111
if (file == null) {
12-
return true
12+
return HttpStatus.OK.value()
1313
}
1414

1515
if (grailsApplication.config.getProperty('scanFile.enabled', Boolean, true)) {
@@ -20,9 +20,9 @@ class ScanService {
2020

2121
baseUrl = baseUrl.replaceAll("/ws", '/reporting/ws')
2222
def result = ecpWebService.postMultipart("${baseUrl}/document/scanDocument", [:], file, "fileToScan", true)
23-
return result.statusCode == org.springframework.http.HttpStatus.OK.value()
23+
return result.statusCode
2424
}
2525

26-
return true
26+
return HttpStatus.OK.value()
2727
}
2828
}

karma.conf.js

Lines changed: 0 additions & 111 deletions
This file was deleted.

0 commit comments

Comments
 (0)