Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- enabling access to harvest APIs via JWT token
  • Loading branch information
temi committed Dec 15, 2023
1 parent 151d9b7 commit a3e6fd3
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ class ApiKeyInterceptor {

public ApiKeyInterceptor() {
// These controllers use JWT authorization instead
matchAll().excludes(controller: 'graphql').excludes(controller: 'paratoo')
matchAll().excludes(controller: 'graphql').excludes(controller: 'paratoo').excludes(controller: 'harvest')
}

boolean before() {
def controller = grailsApplication.getArtefactByLogicalPropertyName("Controller", controllerName)
Class controllerClass = controller?.clazz

// The "excludes" configuration in the constructor isn't working
if (controllerClass == ParatooController.class) {
if ( [ParatooController.class, HarvestController.class].contains( controllerClass ) ) {
return true
}

Expand Down
137 changes: 137 additions & 0 deletions grails-app/controllers/au/org/ala/ecodata/HarvestController.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package au.org.ala.ecodata

import grails.converters.JSON
import org.apache.http.HttpStatus

import java.text.SimpleDateFormat;

@au.ala.org.ws.security.RequireApiKey
class HarvestController {

RecordService recordService
ProjectService projectService
ProjectActivityService projectActivityService
UserService userService

/**
* List of supported data resource id available for harvesting.
* Note: Data Provider must be BioCollect or MERIT
*
* @param max = number
* @param offset = number
* @param order = lastUpdated
* @param sort = asc | desc
*
*/
def listHarvestDataResource() {
def result, error
try {
if (params.max && !params.max?.isNumber()) {
error = "Invalid parameter max"
} else if (params.offset && !params.offset?.isNumber()) {
error = "Invalid parameter offset"
} else if (params.sort && params.sort != "asc" && params.sort != "desc") {
error = "Invalid parameter sort"
} else if (params.order && params.order != "lastUpdated") {
error = "Invalid parameter order (Expected: lastUpdated)"
}

if (!error) {
def pagination = [
max : params.max ?: 10,
offset: params.offset ?: 0,
order : params.order ?: 'asc',
sort : params.sort ?: 'lastUpdated'
]

result = projectService.listProjectForAlaHarvesting(pagination)

} else {
response.status = HttpStatus.SC_BAD_REQUEST
result = [status: 'error', error: error]
}

} catch (Exception ex) {
response.status = HttpStatus.SC_INTERNAL_SERVER_ERROR
result << [status: 'error', error: "Unexpected error."]
}

response.setContentType("application/json")
render result as JSON
}

/**
* List records associated with the given data resource id
* Data Provider must be BioCollect or MERIT
* @param id dataResourceId
* @param max = number
* @param offset = number
* @param order = lastUpdated
* @param sort = asc | desc | default:asc
* @param lastUpdated = date | dd/MM/yyyy | default:null
* @param status = active | deleted | default:active
*
*/
def listRecordsForDataResourceId (){
def result = [], error, project
Date lastUpdated = null
try {
if(!params.id) {
error = "Invalid data resource id"
} else if (params.max && !params.max.isNumber()) {
error = "Invalid max parameter vaue"
} else if (params.offset && !params.offset.isNumber()) {
error = "Invalid offset parameter vaue"
} else if (params.order && params.order != "asc" && params.order != "desc") {
error = "Invalid order parameter value (expected: asc, desc)"
} else if (params.sort && params.sort != "lastUpdated") {
error = "Invalid sort parameter value (expected: lastUpdated)"
} else if (params.status && params.status != "active" && params.status != "deleted") {
error = "Invalid status parameter value (expected: active or deleted)"
} else if(params.id){
project = projectService.getByDataResourceId(params.id, 'active', 'basic')
error = !project ? 'No valid project found for the given data resource id' : !project.alaHarvest ? "Harvest disabled for data resource id - ${params.id}" : ''
}

if (params.lastUpdated) {
try{
def df = new SimpleDateFormat("dd/MM/yyyy")
lastUpdated = df.parse(params.lastUpdated)
} catch (Exception ex) {
error = "Invalid lastUpdated format (Expected date format - Example: dd/MM/yyyy"
}
}

if (!error && project) {
def args = [
max : params.max ?: 10,
offset : params.offset ?: 0,
order : params.order ?: 'asc',
sort : params.sort ?: 'lastUpdated',
status : params.status ?: 'active',
projectId: project.projectId
]

List<String> restrictedProjectActivities = projectActivityService.listRestrictedProjectActivityIds(null, params.id)
log.debug("Retrieving results...")
result = recordService.listByProjectId(args, lastUpdated, restrictedProjectActivities)
result?.list?.each {
it.projectName = project?.name
it.license = recordService.getLicense(it)
}
} else {
response.status = HttpStatus.SC_BAD_REQUEST
log.error(error.toString())
result = [status: 'error', error: error]
}

} catch (Exception ex) {
response.status = HttpStatus.SC_INTERNAL_SERVER_ERROR
log.error(ex.toString())
result << [status: 'error', error: "Unexpected error."]
}

response.setContentType("application/json")
render result as JSON
}
}
133 changes: 2 additions & 131 deletions grails-app/controllers/au/org/ala/ecodata/RecordController.groovy
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
package au.org.ala.ecodata

import org.apache.http.HttpStatus

import java.text.SimpleDateFormat

import static au.org.ala.ecodata.Status.*
import static javax.servlet.http.HttpServletResponse.*

import grails.converters.JSON
import groovy.json.JsonSlurper
import org.apache.commons.codec.binary.Base64
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.multipart.MultipartHttpServletRequest

import static au.org.ala.ecodata.Status.DELETED
import static javax.servlet.http.HttpServletResponse.*
/**
* Controller for record CRUD operations with support for handling images.
*/
Expand All @@ -30,130 +25,6 @@ class RecordController {

def index() {}

/**
* List of supported data resource id available for harvesting.
* Note: Data Provider must be BioCollect or MERIT
*
* @param max = number
* @param offset = number
* @param order = lastUpdated
* @param sort = asc | desc
*
*/
@PreAuthorise
def listHarvestDataResource() {
def result, error
try {
if (params.max && !params.max?.isNumber()) {
error = "Invalid parameter max"
} else if (params.offset && !params.offset?.isNumber()) {
error = "Invalid parameter offset"
} else if (params.sort && params.sort != "asc" && params.sort != "desc") {
error = "Invalid parameter sort"
} else if (params.order && params.order != "lastUpdated") {
error = "Invalid parameter order (Expected: lastUpdated)"
}

if (!error) {
def pagination = [
max : params.max ?: 10,
offset: params.offset ?: 0,
order : params.order ?: 'asc',
sort : params.sort ?: 'lastUpdated'
]

result = projectService.listProjectForAlaHarvesting(pagination)

} else {
response.status = HttpStatus.SC_BAD_REQUEST
result = [status: 'error', error: error]
}

} catch (Exception ex) {
response.status = HttpStatus.SC_INTERNAL_SERVER_ERROR
result << [status: 'error', error: "Unexpected error."]
}

response.setContentType("application/json")
render result as JSON
}

/**
* List records associated with the given data resource id
* Data Provider must be BioCollect or MERIT
* @param id dataResourceId
* @param max = number
* @param offset = number
* @param order = lastUpdated
* @param sort = asc | desc | default:asc
* @param lastUpdated = date | dd/MM/yyyy | default:null
* @param status = active | deleted | default:active
*
*/
@PreAuthorise
def listRecordsForDataResourceId (){
def result = [], error, project
Date lastUpdated = null
try {
if(!params.id) {
error = "Invalid data resource id"
} else if (params.max && !params.max.isNumber()) {
error = "Invalid max parameter vaue"
} else if (params.offset && !params.offset.isNumber()) {
error = "Invalid offset parameter vaue"
} else if (params.order && params.order != "asc" && params.order != "desc") {
error = "Invalid order parameter value (expected: asc, desc)"
} else if (params.sort && params.sort != "lastUpdated") {
error = "Invalid sort parameter value (expected: lastUpdated)"
} else if (params.status && params.status != "active" && params.status != "deleted") {
error = "Invalid status parameter value (expected: active or deleted)"
} else if(params.id){
project = projectService.getByDataResourceId(params.id, 'active', 'basic')
error = !project ? 'No valid project found for the given data resource id' : !project.alaHarvest ? "Harvest disabled for data resource id - ${params.id}" : ''
}

if (params.lastUpdated) {
try{
def df = new SimpleDateFormat("dd/MM/yyyy")
lastUpdated = df.parse(params.lastUpdated)
} catch (Exception ex) {
error = "Invalid lastUpdated format (Expected date format - Example: dd/MM/yyyy"
}
}

if (!error && project) {
def args = [
max : params.max ?: 10,
offset : params.offset ?: 0,
order : params.order ?: 'asc',
sort : params.sort ?: 'lastUpdated',
status : params.status ?: 'active',
projectId: project.projectId
]

List<String> restrictedProjectActivities = projectActivityService.listRestrictedProjectActivityIds(null, params.id)
log.debug("Retrieving results...")
result = recordService.listByProjectId(args, lastUpdated, restrictedProjectActivities)
result?.list?.each {
it.projectName = project?.name
it.license = recordService.getLicense(it)
}
} else {
response.status = HttpStatus.SC_BAD_REQUEST
log.error(error.toString())
result = [status: 'error', error: error]
}

} catch (Exception ex) {
response.status = HttpStatus.SC_INTERNAL_SERVER_ERROR
log.error(ex.toString())
result << [status: 'error', error: "Unexpected error."]
}

response.setContentType("application/json")
render result as JSON
}


/**
* Exports all active Records with lat/lng coords into a .csv suitable for use by the Biocache to create occurrence records.
Expand Down
4 changes: 2 additions & 2 deletions grails-app/controllers/au/org/ala/ecodata/UrlMappings.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class UrlMappings {
"/ws/record/images"(controller: "record"){ action = [GET:"listRecordWithImages"] }
"/ws/record/images/"(controller: "record"){ action = [GET:"listRecordWithImages"] }
"/ws/record/getRecordForOutputSpeciesId/"(controller: "record", action: "getRecordForOutputSpeciesId")
"/ws/record/listHarvestDataResource" (controller: "record", action: "listHarvestDataResource")
"/ws/record/listRecordsForDataResourceId" (controller: "record", action: "listRecordsForDataResourceId") //dataResourceId
"/ws/record/listHarvestDataResource" (controller: "harvest", action: "listHarvestDataResource")
"/ws/record/listRecordsForDataResourceId" (controller: "harvest", action: "listRecordsForDataResourceId") //dataResourceId

"/ws/record/$id"(controller: "record"){ action = [GET:"get", PUT:"update", DELETE:"delete", POST:"update"] }

Expand Down
4 changes: 2 additions & 2 deletions grails-app/services/au/org/ala/ecodata/UserService.groovy
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package au.org.ala.ecodata

import au.org.ala.userdetails.UserDetailsClient
import au.org.ala.userdetails.UserDetailsFromIdListRequest
import au.org.ala.web.AuthService
import grails.core.GrailsApplication
import grails.plugin.cache.Cacheable

class UserService {

Expand Down Expand Up @@ -104,6 +102,7 @@ class UserService {
* @param username
* @param authKey
*/
@Deprecated
String authorize(userName, authKey) {
String userId = ""

Expand Down Expand Up @@ -131,6 +130,7 @@ class UserService {
* @param username
* @param password
*/
@Deprecated
def getUserKey(String username, String password) {
webService.doPostWithParams(grailsApplication.config.getProperty('authGetKeyUrl'), [userName: username, password: password], true)
}
Expand Down

0 comments on commit a3e6fd3

Please sign in to comment.