Skip to content

Commit

Permalink
Add JWT support for spatial calls #2992
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisala committed Nov 22, 2023
1 parent 66c8789 commit 75ed00c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 18 deletions.
11 changes: 5 additions & 6 deletions grails-app/services/au/org/ala/merit/SpatialService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class SpatialService {
Integer deleteFromSpatialPortal(String pid) {
String url = "${grailsApplication.config.getProperty('spatial.layersUrl')}${DELETE_SHAPE_PATH}/$pid"

webService.doDelete(url)
webService.doDelete(url, true)
}

/**
Expand All @@ -41,10 +41,9 @@ class SpatialService {
* attributes of that feature. eg. [shp_id: <shapefileId>, "0":[attribute1:<value>, attribute2:<value>, etc], "1":[attribute1:<value>, attribute2:<value>, etc]]]
*/
Map uploadShapefile(MultipartFile shapefile) {
String userId = userService.getCurrentUserId()
String url = "${grailsApplication.config.getProperty('spatial.layersUrl')}${UPLOAD_SHAPE_PATH}?user_id=${userId}&api_key=${grailsApplication.config.getProperty('api_key')}"
String url = "${grailsApplication.config.getProperty('spatial.layersUrl')}${UPLOAD_SHAPE_PATH}"

webService.postMultipart(url, [:], shapefile)
webService.postMultipart(url, [:], shapefile, 'files', true)
}

/**
Expand All @@ -62,11 +61,11 @@ class SpatialService {
String baseUrl = "${grailsApplication.config.getProperty('spatial.layersUrl')}${UPLOAD_SHAPE_PATH}"
String userId = userService.getCurrentUserId()

Map site = [name:objectName, description: objectDescription, user_id:userId, api_key:grailsApplication.config.getProperty('api_key')]
Map site = [name:objectName, description: objectDescription, user_id:userId]

String url = "${baseUrl}/${shapeFileId}/${featureId}"

webService.doPost(url, site)
webService.doPost(url, site, true)
}

/**
Expand Down
59 changes: 47 additions & 12 deletions grails-app/services/au/org/ala/merit/WebService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package au.org.ala.merit

import au.org.ala.ws.tokens.TokenService
import grails.converters.JSON
import grails.core.GrailsApplication
import grails.web.http.HttpHeaders
Expand All @@ -40,6 +41,8 @@ import javax.servlet.http.HttpServletResponse
@Slf4j
class WebService {

TokenService tokenService

// Used to avoid a circular dependency during initialisation
def getUserService() {
return grailsApplication.mainContext.userService
Expand Down Expand Up @@ -99,16 +102,27 @@ class WebService {
grailsApplication.config.getProperty('webservice.connectTimeout', Integer, 2000)
}

private URLConnection configureConnection(String url, boolean includeUserId, Integer timeout = null) {
private URLConnection configureConnection(String url, boolean includeUserId, Integer timeout = null, boolean useToken = false) {
URLConnection conn = createAndConfigureConnection(url, timeout)
conn.setRequestProperty("Authorization", grailsApplication.config.getProperty('api_key'));
if (!useToken) {
conn.setRequestProperty("Authorization", grailsApplication.config.getProperty('api_key'))
}
else {
conn.setRequestProperty("Authorization", getToken())
}


def user = getUserService().getUser()
if (user) {
conn.setRequestProperty(grailsApplication.config.getProperty('app.http.header.userId'), user.userId)
}
conn
}

private String getToken() {
tokenService.getAuthToken(false)?.toAuthorizationHeader()
}

private URLConnection createAndConfigureConnection(String url, Integer timeout = null) {
URLConnection conn = new URL(url).openConnection()

Expand Down Expand Up @@ -352,20 +366,26 @@ class WebService {
}
}

def doPost(String url, Map postBody) {
def doPost(String url, Map postBody, boolean useToken = false) {
def conn = null
def charEncoding = 'utf-8'
try {
conn = new URL(url).openConnection()
conn.setDoOutput(true)
conn.setRequestProperty("Content-Type", "application/json;charset=${charEncoding}");
conn.setRequestProperty("Authorization", grailsApplication.config.getProperty('api_key'));

if (useToken) {
conn.setRequestProperty("Authorization", getToken())
}
else {
conn.setRequestProperty("Authorization", grailsApplication.config.getProperty('api_key'));
}
def user = getUserService().getUser()
if (user) {
conn.setRequestProperty(grailsApplication.config.getProperty('app.http.header.userId'), user.userId) // used by ecodata
conn.setRequestProperty("Cookie", "ALA-Auth="+java.net.URLEncoder.encode(user.userName, charEncoding)) // used by specieslist
}


OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), charEncoding)
wr.write((postBody as JSON).toString())
wr.flush()
Expand All @@ -389,17 +409,26 @@ class WebService {
}
}

def doDelete(String url) {
url += (url.indexOf('?') == -1 ? '?' : '&') + "api_key=${grailsApplication.config.getProperty('api_key')}"
def doDelete(String url, boolean useToken = false) {
if (!useToken) {
url += (url.indexOf('?') == -1 ? '?' : '&') + "api_key=${grailsApplication.config.getProperty('api_key')}"
}

def conn = null
try {
conn = new URL(url).openConnection()
conn.setRequestMethod("DELETE")
conn.setRequestProperty("Authorization", grailsApplication.config.getProperty('api_key'));
if (useToken) {
conn.setRequestProperty("Authorization", getToken())
}
else {
conn.setRequestProperty("Authorization", grailsApplication.config.getProperty('api_key'))
}
def user = getUserService().getUser()
if (user) {
conn.setRequestProperty(grailsApplication.config.getProperty('app.http.header.userId'), user.userId)
}

return conn.getResponseCode()
} catch(Exception e){
println e.message
Expand All @@ -418,9 +447,9 @@ class WebService {
* @param file the Multipart file object to forward.
* @return [status:<request status>, content:<The response content from the server, assumed to be JSON>
*/
def postMultipart(url, Map params, MultipartFile file, fileParam = 'files') {
def postMultipart(url, Map params, MultipartFile file, fileParam = 'files', boolean useToken = false) {

postMultipart(url, params, file.inputStream, file.contentType, file.originalFilename, fileParam)
postMultipart(url, params, file.inputStream, file.contentType, file.originalFilename, fileParam, null, useToken)
}

/**
Expand All @@ -434,7 +463,7 @@ class WebService {
* @param successHandler optional callback for a successful service invocation. If not supplied, a Map will be returned.
* @return [status:<request status>, content:<The response content from the server, assumed to be JSON>
*/
def postMultipart(url, Map params, InputStream contentIn, contentType, originalFilename, fileParamName = 'files', Closure successHandler = null) {
def postMultipart(url, Map params, InputStream contentIn, contentType, originalFilename, fileParamName = 'files', Closure successHandler = null, boolean useToken = false) {

def result = [:]
def user = userService.getUser()
Expand All @@ -449,13 +478,19 @@ class WebService {
content.addPart(key, new StringBody(value.toString()))
}
}
headers.'Authorization' = grailsApplication.config.getProperty('api_key')
if (useToken) {
headers.'Authorization' = getToken()
}
else {
headers.'Authorization' = grailsApplication.config.getProperty('api_key')
}
if (user) {
headers[grailsApplication.config.getProperty('app.http.header.userId')] = user.userId
}
else {
log.warn("No user associated with request: ${url}")
}

request.setEntity(content)

if (successHandler) {
Expand Down

0 comments on commit 75ed00c

Please sign in to comment.