From cebfbae01b9d289007069ee68fdbfd9e2080b2ab Mon Sep 17 00:00:00 2001 From: Sushant G <105408469+sughics@users.noreply.github.com> Date: Mon, 31 Jul 2023 13:38:03 +1000 Subject: [PATCH 01/10] Bumping SNAPSHOT version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f77ceebb..9c05dd0a 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ plugins { id "com.gorylenko.gradle-git-properties" version "2.4.1" } -version "4.0.0-SNAPSHOT" +version "4.1.0-SNAPSHOT" group "au.org.ala" apply plugin:"eclipse" From c8b67a127dde87ae345b293def346b92c41bead4 Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Thu, 17 Aug 2023 12:28:44 +1000 Subject: [PATCH 02/10] format contactRole view --- grails-app/views/shared/contactRole.gsp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grails-app/views/shared/contactRole.gsp b/grails-app/views/shared/contactRole.gsp index 764deb4b..0faf0600 100644 --- a/grails-app/views/shared/contactRole.gsp +++ b/grails-app/views/shared/contactRole.gsp @@ -30,21 +30,21 @@ ${cf.contact?.buildName()} for ${command.name} - + : - + ${entityNameLower}. - + ${entityNameLower}. - + : ${entityNameLower}. From aa3719e22daefcaeefd210d728595291dfb7ceb8 Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Fri, 18 Aug 2023 09:18:46 +1000 Subject: [PATCH 03/10] Update providerMaps admin pages --- grails-app/conf/logback.xml | 4 +++- grails-app/views/providerCode/list.gsp | 6 +++--- grails-app/views/providerMap/_form.gsp | 8 ++++---- grails-app/views/providerMap/list.gsp | 23 ++++++++++++----------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/grails-app/conf/logback.xml b/grails-app/conf/logback.xml index c64e87a0..479d28cf 100644 --- a/grails-app/conf/logback.xml +++ b/grails-app/conf/logback.xml @@ -11,7 +11,9 @@ + + - \ No newline at end of file + diff --git a/grails-app/views/providerCode/list.gsp b/grails-app/views/providerCode/list.gsp index a8553b3a..b74c37f4 100644 --- a/grails-app/views/providerCode/list.gsp +++ b/grails-app/views/providerCode/list.gsp @@ -12,7 +12,7 @@
  • -
  • +
@@ -30,9 +30,9 @@ - + ${fieldValue(bean: providerCodeInstance, field: "code")} - + diff --git a/grails-app/views/providerMap/_form.gsp b/grails-app/views/providerMap/_form.gsp index 475f01e2..44409286 100644 --- a/grails-app/views/providerMap/_form.gsp +++ b/grails-app/views/providerMap/_form.gsp @@ -12,12 +12,12 @@
- + - + - +
@@ -118,4 +118,4 @@ $('#institutionSelect').change(function() { }); } }); - \ No newline at end of file + diff --git a/grails-app/views/providerMap/list.gsp b/grails-app/views/providerMap/list.gsp index 803a245f..9a1be1f6 100644 --- a/grails-app/views/providerMap/list.gsp +++ b/grails-app/views/providerMap/list.gsp @@ -14,6 +14,7 @@
  • +
@@ -27,7 +28,7 @@ - + @@ -35,33 +36,33 @@ - + - + - + - + - + - + - + - + - + - + From 7f6c84aa2353f8263f794587363b470448b69ed1 Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Mon, 21 Aug 2023 17:10:02 +1000 Subject: [PATCH 04/10] remember connection parameters in admin UI --- grails-app/assets/javascripts/contribution.js | 133 ++++++++++++++++++ .../collectory/ProviderGroupController.groovy | 40 +++++- .../ala/collectory/CollectoryTagLib.groovy | 105 ++++++++------ .../views/dataResource/contribution.gsp | 133 +----------------- 4 files changed, 232 insertions(+), 179 deletions(-) create mode 100644 grails-app/assets/javascripts/contribution.js diff --git a/grails-app/assets/javascripts/contribution.js b/grails-app/assets/javascripts/contribution.js new file mode 100644 index 00000000..8b27e73a --- /dev/null +++ b/grails-app/assets/javascripts/contribution.js @@ -0,0 +1,133 @@ +function instrument() { + var availableTags = [ + "institutionCode", + "collectionCode", + "catalogNumber", + "occurrenceID", + "recordNumber" + ]; + + function split( val ) { + return val.split( /,\s*/ ); + } + + function extractLast( term ) { + return split( term ).pop(); + } + + $( "input#termsForUniqueKey:enabled" ) + // don't navigate away from the field on tab when selecting an item + .bind( "keydown", function( event ) { + if ( event.keyCode === $.ui.keyCode.TAB && + $( this ).data( "autocomplete" ).menu.active ) { + event.preventDefault(); + } + }) + .autocomplete({ + minLength: 0, + source: function( request, response ) { + // delegate back to autocomplete, but extract the last term + response( $.ui.autocomplete.filter( + availableTags, extractLast( request.term ) ) ); + }, + focus: function() { + // prevent value inserted on focus + return false; + }, + select: function( event, ui ) { + var terms = split( this.value ); + // remove the current input + terms.pop(); + // add the selected item + terms.push( ui.item.value ); + // add placeholder to get the comma-and-space at the end + terms.push( "" ); + this.value = terms.join( ", " ); + return false; + } + }); +} + +function changeProtocol() { + var protocol = $('#protocolSelector').val(); + // remove autocomplete binding + // $('input#termsForUniqueKey:enabled').autocomplete('destroy'); + // $('input#termsForUniqueKey:enabled').unbind('keydown'); + // clear all + $('div.labile').css('display','none'); + $('div.labile input,textArea').attr('disabled','true'); + + // show the selected + console.log("Displaying protocol : " + protocol); + $.each(connectionParameters, function(key, obj) { + $.each(obj, function(j, p) { + if (p == protocol) { + $('div#connection_' + key).css('display','block'); + $('div#connection_' + key).removeAttr('style'); + $('div#connection_' + key + ' input,textArea').removeAttr('disabled'); + } + }) + }) + + // re-enable the autocomplete functionality + instrument(); +} + +instrument(); +//$('[name="start_date"]').datepicker({dateFormat: 'yy-mm-dd'}); +/* this expands lists of urls into an array of text inputs */ +// create a delete element that removes the element before it and itself +var $deleteLink = $(' ') + .click(function() { + $(this).prev().remove(); + $(this).remove(); + }); +// handle all urls (including hidden ones) +var urlInputs = $('input[name="url"]'); +$('input[name="url"]').addClass('input-xxlarge'); +$.each(urlInputs, function(i, obj) { + var urls = $(obj).val().split(','); + if (urls.length > 1) { + // more than one url so create an input for each extra one + $.each(urls,function(i,url) { + if (i == 0) { + // existing input gets the first url + $(obj).val(url); + } + else { + // clone the existing field and inject the next value - adding a delete link + $(obj).clone() + .val(url.trim()) + .css('width','93%') + .addClass('form-control') + .insertAfter($(obj).parent().children('input,span').last()) + .after($deleteLink.clone(true)); + } + }); + } +}); +/* this injects 'add another' functionality to urls */ +$.each(urlInputs, function(i, obj) { + $('Add another') + .insertAfter($(obj).parent().children('input,span').last()) + .click(function() { + // clone the original input + var $clone = $(obj).clone(); + $clone.val(''); + $clone.insertBefore(this); + $clone.after($deleteLink.clone(true)); // add delete link + }); +}); +/* this binds the code to add a new term to the list */ +$('#more-terms').click(function() { + var term = $('#otherKey').val(); + // check that term doesn't already exist + if ($('#'+term).length > 0) { + alert(term + " is already present"); + } + else { + var newField = "
" + + "
"; + $('#add-another').parent().append(newField); + } +}); diff --git a/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy b/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy index 510ad193..d1a9c0c8 100644 --- a/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy +++ b/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy @@ -1,6 +1,6 @@ package au.org.ala.collectory - +import au.org.ala.collectory.resources.PP import grails.converters.JSON import org.springframework.dao.DataIntegrityViolationException import org.springframework.web.context.request.RequestContextHolder @@ -598,10 +598,46 @@ abstract class ProviderGroupController { } else { // are they allowed to edit if (isAuthorisedToEdit(pg.uid)) { + def connectionParams = metadataService.getConnectionParameters() + // set the default value for 'darwin core terms that uniquely identify a record' + try { + JSON.parse(pg.connectionParameters).each { k, v -> + + var item = connectionParams.find { ck, cv -> cv.paramName == k } + + if (item?.value) { + var defaultValue = v + if (item.value.paramName == 'termsForUniqueKey') { + defaultValue = v.join(',').replaceAll('"',"") + } else if (item.value.type == 'delimiter') { + def str = v + str = str.replaceAll('HT', PP.HT_CHAR) + str = str.replaceAll('LF', PP.LF_CHAR) + str = str.replaceAll('VT', PP.VT_CHAR) + str = str.replaceAll('FF', PP.FF_CHAR) + str = str.replaceAll('CR', PP.CR_CHAR) + defaultValue = str + } else if (item.value.paramName == 'url') { + if (v instanceof List) { + def normalised = [] + v.each { + if (it.trim().length() > 0) { + normalised << it.trim() + } + } + defaultValue = normalised.join(',').replaceAll('"',"") + } + } + + item.value.putAt('defaultValue', defaultValue) + } + } + } catch (ignored) { + } render(view:'upload', model:[ instance: pg, connectionProfiles: metadataService.getConnectionProfilesWithFileUpload(), - connectionParams: metadataService.getConnectionParameters() + connectionParams: connectionParams ]) } else { response.setHeader("Content-type", "text/plain; charset=UTF-8") diff --git a/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy b/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy index 9ce1cd55..7f395e26 100644 --- a/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy +++ b/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy @@ -1833,6 +1833,9 @@ class CollectoryTagLib { onchange:'changeProtocol()') out << "" + // map each parameter only once + var mappedParams = [:] + // create the widgets for each protocol (profile) metadataService.getConnectionProfilesAsList().each { // is this the selected protocol? @@ -1842,62 +1845,72 @@ class CollectoryTagLib { it.params.each { ppName -> def pp = metadataService.getConnectionParameter(ppName) + if (mappedParams[pp.paramName] != null) { + mappedParams[pp.paramName].add(it.name) + } else { + mappedParams[pp.paramName] = [it.name] - // get value from object - def displayedValue = cp?."${pp.paramName}"?:"" + // get value from object + def displayedValue = cp?."${pp.paramName}" ?: "" - // inject default if no value - if (!displayedValue && pp.defaultValue) { - displayedValue = pp.defaultValue - } + // inject default if no value + if (!displayedValue && pp.defaultValue) { + displayedValue = pp.defaultValue + } - // unravel any JSON lists - if (displayedValue instanceof JSONArray) { - displayedValue = displayedValue.collect {it}.join(', ') as String - } + // unravel any JSON lists + if (displayedValue instanceof JSONArray) { + displayedValue = displayedValue.collect { it }.join(', ') as String + } - // handle unprintable chars - if (pp.type == 'delimiter') { - displayedValue = encodeControlChars(displayedValue) - } + // handle unprintable chars + if (pp.type == 'delimiter') { + displayedValue = encodeControlChars(displayedValue) + } - def attributes = [name:pp.paramName, value:displayedValue, class:'form-control'] - if (!selected) { - attributes << [disabled:true] - } - if (pp.paramName == "termsForUniqueKey") { - // handle terms specially - out << """
""" - out << """
Don't change the following terms unless you know what you are doing. Incorrect values can cause major devastation.
""" - out << "
" - out << """
""" - out << """""" - out << textField(attributes) - out << "
" - } else if (pp.type == 'boolean') { - attributes.remove('class') - out << """
""" - out << """
" - } else { - // all others - def widget - switch (pp.type) { - case 'textArea': widget = 'textArea'; break - default: widget = 'textField'; break + def attributes = [name: pp.paramName, value: displayedValue, class: 'form-control'] + if (!selected) { + attributes << [disabled: true] + } + if (pp.paramName == "termsForUniqueKey") { + // handle terms specially + out << """
""" + out << """
Don't change the following terms unless you know what you are doing. Incorrect values can cause major devastation.
""" + out << "
" + out << """
""" + out << """""" + out << textField(attributes) + out << "
" + } else if (pp.type == 'boolean') { + attributes.remove('class') + out << """
""" + out << """
" + } else { + // all others + def widget + switch (pp.type) { + case 'textArea': widget = 'textArea'; break + default: widget = 'textField'; break + } + out << """
""" + out << """""" + out << "${widget}"(attributes) + out << "
" } - out << """
""" - out << """""" - out << "${widget}"(attributes) - out << "
" } } } + out << "" + } def lastChecked = { attrs -> diff --git a/grails-app/views/dataResource/contribution.gsp b/grails-app/views/dataResource/contribution.gsp index 0ea2d221..37bf7c41 100644 --- a/grails-app/views/dataResource/contribution.gsp +++ b/grails-app/views/dataResource/contribution.gsp @@ -13,6 +13,7 @@ }; + - - function instrument() { - var availableTags = [ - "institutionCode", - "collectionCode", - "catalogNumber", - "occurrenceID", - "recordNumber" - ]; - - function split( val ) { - return val.split( /,\s*/ ); - } - - function extractLast( term ) { - return split( term ).pop(); - } - - $( "input#termsForUniqueKey:enabled" ) - // don't navigate away from the field on tab when selecting an item - .bind( "keydown", function( event ) { - if ( event.keyCode === $.ui.keyCode.TAB && - $( this ).data( "autocomplete" ).menu.active ) { - event.preventDefault(); - } - }) - .autocomplete({ - minLength: 0, - source: function( request, response ) { - // delegate back to autocomplete, but extract the last term - response( $.ui.autocomplete.filter( - availableTags, extractLast( request.term ) ) ); - }, - focus: function() { - // prevent value inserted on focus - return false; - }, - select: function( event, ui ) { - var terms = split( this.value ); - // remove the current input - terms.pop(); - // add the selected item - terms.push( ui.item.value ); - // add placeholder to get the comma-and-space at the end - terms.push( "" ); - this.value = terms.join( ", " ); - return false; - } - }); - } - - function changeProtocol() { - var protocol = $('#protocolSelector').val(); - // remove autocomplete binding - $('input#termsForUniqueKey:enabled').autocomplete('destroy'); - $('input#termsForUniqueKey:enabled').unbind('keydown'); - // clear all - $('div.labile').css('display','none'); - $('div.labile input,textArea').attr('disabled','true'); - - // show the selected - console.log("Displaying protocol: " + protocol); - $('div#' + protocol).css('display','block'); - $('div#' + protocol).removeAttr('style'); - $('div#' + protocol + ' input,textArea').removeAttr('disabled'); - - // re-enable the autocomplete functionality - instrument(); - } - - instrument(); - //$('[name="start_date"]').datepicker({dateFormat: 'yy-mm-dd'}); - /* this expands lists of urls into an array of text inputs */ - // create a delete element that removes the element before it and itself - %{--var deleteImageUrl = "${resource(dir:'/images/ala',file:'delete.png')}";--}% - var $deleteLink = $(' ') - .click(function() { - $(this).prev().remove(); - $(this).remove(); - }); - // handle all urls (including hidden ones) - var urlInputs = $('input[name="url"]'); - $('input[name="url"]').addClass('input-xxlarge'); - $.each(urlInputs, function(i, obj) { - var urls = $(obj).val().split(','); - if (urls.length > 1) { - // more than one url so create an input for each extra one - $.each(urls,function(i,url) { - if (i == 0) { - // existing input gets the first url - $(obj).val(url); - } - else { - // clone the existing field and inject the next value - adding a delete link - $(obj).clone() - .val(url.trim()) - .css('width','93%') - .addClass('form-control') - .insertAfter($(obj).parent().children('input,span').last()) - .after($deleteLink.clone(true)); - } - }); - } - }); - /* this injects 'add another' functionality to urls */ - $.each(urlInputs, function(i, obj) { - $('Add another') - .insertAfter($(obj).parent().children('input,span').last()) - .click(function() { - // clone the original input - var $clone = $(obj).clone(); - $clone.val(''); - $clone.insertBefore(this); - $clone.after($deleteLink.clone(true)); // add delete link - }); - }); - /* this binds the code to add a new term to the list */ - $('#more-terms').click(function() { - var term = $('#otherKey').val(); - // check that term doesn't already exist - if ($('#'+term).length > 0) { - alert(term + " is already present"); - } - else { - var newField = "
" + - "
"; - $('#add-another').parent().append(newField); - } - }); -
- \ No newline at end of file + From 730d0b2c59350ed09452189b8d19001e4c0a1872 Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Thu, 5 Oct 2023 08:20:59 +1000 Subject: [PATCH 05/10] add sitemap --- gradle.properties | 2 +- grails-app/conf/application.yml | 10 +- .../org/ala/collectory/AdminController.groovy | 8 +- .../ala/collectory/SitemapController.groovy | 30 +++++ .../au/org/ala/collectory/UrlMappings.groovy | 2 + grails-app/i18n/messages.properties | 1 + grails-app/init/collectory/Application.groovy | 6 +- .../org/ala/collectory/SitemapService.groovy | 127 ++++++++++++++++++ grails-app/views/manage/index.gsp | 6 +- grails-app/views/manage/list.gsp | 12 ++ 10 files changed, 196 insertions(+), 8 deletions(-) create mode 100644 grails-app/controllers/au/org/ala/collectory/SitemapController.groovy create mode 100644 grails-app/services/au/org/ala/collectory/SitemapService.groovy diff --git a/gradle.properties b/gradle.properties index cb00d8fc..d92011b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ webdriverBinariesVersion=2.6 chromeDriverVersion=2.45.0 geckodriverVersion=0.24.0 seleniumSafariDriverVersion=3.14.0 -alaSecurityLibsVersion=6.0.4 \ No newline at end of file +alaSecurityLibsVersion=6.1.0 diff --git a/grails-app/conf/application.yml b/grails-app/conf/application.yml index 8677a258..70f9bc72 100644 --- a/grails-app/conf/application.yml +++ b/grails-app/conf/application.yml @@ -178,7 +178,7 @@ security: - /css.* - /js.* - /static.* - appServerName: http://dev.ala.org.au:8080 + appServerName: http://localhost:8080 casServerUrlPrefix: https://auth-test.ala.org.au/cas loginUrl: https://auth-test.ala.org.au/cas/login logoutUrl: https://auth-test.ala.org.au/cas/logout @@ -400,7 +400,9 @@ environments: active: false dataSource: dbCreate: none - url: jdbc:mysql://localhost:3306/collectory?autoReconnect=true&connectTimeout=0&useUnicode=true&characterEncoding=UTF-8 + url: jdbc:mysql://localhost:3306/collectory?autoReconnect=true&connectTimeout=0&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Australia/Sydney + username: specieslist + password: "specieslist" test: grails: assets: @@ -449,3 +451,7 @@ openapi: url: https://www.mozilla.org/en-US/MPL/1.1/ version: '@info.app.version@' cachetimeoutms: 0 + +sitemap: + dir: /data/collectory + enabled: true diff --git a/grails-app/controllers/au/org/ala/collectory/AdminController.groovy b/grails-app/controllers/au/org/ala/collectory/AdminController.groovy index ac0a99f8..ba43e236 100644 --- a/grails-app/controllers/au/org/ala/collectory/AdminController.groovy +++ b/grails-app/controllers/au/org/ala/collectory/AdminController.groovy @@ -8,7 +8,7 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver class AdminController { - def dataLoaderService, idGeneratorService, metadataService + def dataLoaderService, idGeneratorService, metadataService, sitemapService def index = { redirect(controller: 'manage') @@ -299,4 +299,10 @@ class AdminController { } return g } + + def buildSitemap() { + sitemapService.build() + + render text: 'done' + } } diff --git a/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy b/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy new file mode 100644 index 00000000..541fc17c --- /dev/null +++ b/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy @@ -0,0 +1,30 @@ +package au.org.ala.collectory + +class SitemapController { + + def index(Integer idx) { + if (!grailsApplication.config.sitemap.enabled) { + response.status = 404 + return + } + + File index = new File(grailsApplication.config.sitemap.dir + '/sitemap.xml') + if (!index.exists()) { + response.status = 404 + return + } + + if (idx == null) { + // return sitemap index + response.outputStream << index.newInputStream() + } else { + // return sitemap urls + File part = new File(grailsApplication.config.sitemap.dir + '/sitemap' + idx + ".xml") + if (!part.exists()) { + response.status = 404 + return + } + response.outputStream << part.newInputStream() + } + } +} diff --git a/grails-app/controllers/au/org/ala/collectory/UrlMappings.groovy b/grails-app/controllers/au/org/ala/collectory/UrlMappings.groovy index b4acfde0..3678512b 100644 --- a/grails-app/controllers/au/org/ala/collectory/UrlMappings.groovy +++ b/grails-app/controllers/au/org/ala/collectory/UrlMappings.groovy @@ -207,6 +207,8 @@ class UrlMappings { "/public/resources(.$format)"(controller: 'public', action: 'resources') "/public/condensed(.$format)"(controller: 'public', action: 'condensed') + "/sitemap($idx)?.xml"(controller: "sitemap", action: "index") + "/"(controller: 'public', action: 'map') "/error"(view: '/error') diff --git a/grails-app/i18n/messages.properties b/grails-app/i18n/messages.properties index 833c31f4..8aaf0d10 100644 --- a/grails-app/i18n/messages.properties +++ b/grails-app/i18n/messages.properties @@ -1276,6 +1276,7 @@ manage.list.addtools.des11=View and edit all known collection and institution co manage.list.addtools.mpm=Provider maps manage.list.addtools.des12=View and edit the allocation of collection and institution codes to collections manage.list.addtools.eadaj=Export all data as JSON +manage.list.addtools.buildsitemap=Build sitemap manage.list.addtools.des13=All tables exported verbatim as JSON manage.list.addtools.vae=Audit events manage.list.addtools.des14=All audit events diff --git a/grails-app/init/collectory/Application.groovy b/grails-app/init/collectory/Application.groovy index 5f87bfb0..b3284e36 100644 --- a/grails-app/init/collectory/Application.groovy +++ b/grails-app/init/collectory/Application.groovy @@ -4,10 +4,14 @@ import grails.boot.GrailsApp import grails.boot.config.GrailsAutoConfiguration import groovy.transform.CompileStatic +import org.springframework.context.annotation.ComponentScan +import org.springframework.scheduling.annotation.EnableScheduling +@ComponentScan('au.org.ala.collectory') @CompileStatic +@EnableScheduling class Application extends GrailsAutoConfiguration { static void main(String[] args) { GrailsApp.run(Application, args) } -} \ No newline at end of file +} diff --git a/grails-app/services/au/org/ala/collectory/SitemapService.groovy b/grails-app/services/au/org/ala/collectory/SitemapService.groovy new file mode 100644 index 00000000..32777b25 --- /dev/null +++ b/grails-app/services/au/org/ala/collectory/SitemapService.groovy @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2022 Atlas of Living Australia + * All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + */ +package au.org.ala.collectory + +import org.springframework.scheduling.annotation.Scheduled + +import java.text.SimpleDateFormat + +class SitemapService { + + def grailsApplication + + + String URLSET_HEADER = "" + String URLSET_FOOTER = "" + + int MAX_URLS = 50000 // maximum number of URLs in a sitemap file + int MAX_SIZE = 9*1024*1024 // use 9MB to keep the actual file size below 10MB (a gateway limit) + + File currentFile + int fileCount = 0 + int countUrls = 0 + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd") + + FileWriter fw + + // run daily, initial delay 1hr + @Scheduled(fixedDelay = 86400000L, initialDelay = 3600000L) + def build() throws Exception { + initWriter() + buildSitemap() + closeWriter() + + buildSitemapIndex() + } + + def buildSitemapIndex() { + + // write parent sitemap file + fw = new FileWriter(grailsApplication.config.sitemap.dir + "/sitemap.xml") + fw.write("") + + for (int i=0;i" + grailsApplication.config.grails.serverURL + "/sitemap" + i + ".xml" + "") + fw.write("" + simpleDateFormat.format(new Date()) + "") + } + + fw.write("") + fw.flush() + fw.close() + } + + def initWriter() { + currentFile = new File(grailsApplication.config.sitemap.dir + "/sitemap" + fileCount + ".xml.tmp") + + fw = new FileWriter(currentFile) + + fw.write(URLSET_HEADER) + + countUrls = 0 + fileCount++ + } + + def closeWriter() { + fw.write(URLSET_FOOTER) + fw.flush() + fw.close() + } + + def writeUrl(Date lastUpdated, String changefreq, String encodedUrl) { + if (countUrls >= MAX_URLS || currentFile.size() >= MAX_SIZE) { + closeWriter() + initWriter() + } + + fw.write("") + fw.write("" + encodedUrl + "") + fw.write("" + simpleDateFormat.format(lastUpdated) + "") + fw.write("" + changefreq + "") + fw.write("") + + fw.flush() + + countUrls++ + } + + def buildSitemap() throws Exception { + + Collection.findAll().each {Collection it -> + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + } + + Institution.findAll().each {Institution it -> + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + } + + DataProvider.findAll().each {DataProvider it -> + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + } + + DataResource.findAllByIsPrivate(false).each {DataResource it -> + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + } + } +} diff --git a/grails-app/views/manage/index.gsp b/grails-app/views/manage/index.gsp index 982f04b9..0429e3c8 100644 --- a/grails-app/views/manage/index.gsp +++ b/grails-app/views/manage/index.gsp @@ -7,10 +7,10 @@ /> - +
- +
@@ -51,4 +51,4 @@
- \ No newline at end of file + diff --git a/grails-app/views/manage/list.gsp b/grails-app/views/manage/list.gsp index b6e84399..dbfb3df9 100644 --- a/grails-app/views/manage/list.gsp +++ b/grails-app/views/manage/list.gsp @@ -237,6 +237,18 @@ %{-- --}% + +
+
+ +
+ + %{--
--}% + %{-- --}% + %{--

--}% + %{--
--}% + +

Data sync with GBIF

From bbc4a54d6366a54ee0047ea907e3022f609a83a4 Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Thu, 5 Oct 2023 08:21:30 +1000 Subject: [PATCH 06/10] add sitemap --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9c05dd0a..bda19662 100644 --- a/build.gradle +++ b/build.gradle @@ -107,7 +107,7 @@ dependencies { // See: https://github.com/AtlasOfLivingAustralia/collectory/issues/84#issuecomment-1070670979 // before updating mysql-connector-java implementation "mysql:mysql-connector-java:8.0.22" - implementation "org.grails.plugins:ala-bootstrap3:4.1.0" + implementation "org.grails.plugins:ala-bootstrap3:4.3.0" implementation "au.org.ala.plugins.grails:ala-charts-plugin:2.3.0" implementation "org.grails.plugins:ala-auth:$alaSecurityLibsVersion" implementation "org.grails.plugins:ala-ws-security-plugin:$alaSecurityLibsVersion" From 2399901f670d3ea3c5e9627904b8a677ee92051e Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Thu, 26 Oct 2023 12:18:29 +1000 Subject: [PATCH 07/10] grails6, ala-bootstrap3, alaSecurityLibsVersion --- .travis.yml | 10 +- build.gradle | 103 +++++++++--------- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 18 ++- gradlew.bat | 15 ++- .../ala/collectory/SitemapController.groovy | 2 + grails-wrapper.jar | Bin 5473 -> 5463 bytes grailsw | 1 - settings.gradle | 20 ++++ 10 files changed, 105 insertions(+), 72 deletions(-) create mode 100644 settings.gradle diff --git a/.travis.yml b/.travis.yml index 09eb38fa..aeea0607 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,10 @@ language: groovy jdk: - openjdk11 -sudo: false branches: only: - master - develop - - /^feature\/.*$/ - - /^bugfix\/.*$/ - before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ @@ -19,6 +15,10 @@ cache: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ +install: + - 'travis_wait 30 ./gradlew clean' + - './gradlew assemble' + after_success: - './gradlew bootJar' - '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && travis_retry ./gradlew publish' @@ -27,4 +27,4 @@ env: global: - JAVA_TOOL_OPTIONS=-Dhttps.protocols=TLSv1.2 - secure: G31IscTcNtjjFA0R2pDRaZ2Std1d5F3pIfr3NUe0PsKcj8F2ubFd6xZ3LCccKu/HdDdlJ/6K6Khn1EfwHie5NRP+Uu7oAUOVkTXSeI4KfQFywpf3TvKLILh8/2NUe0451ESivKQ28UW4jPOehmLtCyd7MbxnO9GIrYyaWjNEJJw= - - secure: g7txXzs6g/DzF9bwI5UZ4wG2QxB4aqQeAK1TxL3P0DfMHB8hXs/BydKrFaA9TnJiB/g0fwabNCuJWr+IgOL3EPA1txwVu9VVttHqKiJXthoen1eN0QJtsCWhlE2/ldC1mENaJVXBQs7++sNutytUIOr9m2Yk78mXnu2RIfk7U/k= \ No newline at end of file + - secure: g7txXzs6g/DzF9bwI5UZ4wG2QxB4aqQeAK1TxL3P0DfMHB8hXs/BydKrFaA9TnJiB/g0fwabNCuJWr+IgOL3EPA1txwVu9VVttHqKiJXthoen1eN0QJtsCWhlE2/ldC1mENaJVXBQs7++sNutytUIOr9m2Yk78mXnu2RIfk7U/k= diff --git a/build.gradle b/build.gradle index bda19662..e6ebcfeb 100644 --- a/build.gradle +++ b/build.gradle @@ -1,35 +1,22 @@ -buildscript { - repositories { - mavenLocal() - maven { url "https://nexus.ala.org.au/content/groups/public/" } - maven { url "https://repo.grails.org/grails/core" } - } - dependencies { - classpath "org.grails:grails-gradle-plugin:$grailsVersion" - classpath "org.grails.plugins:hibernate5:${gormVersion}" - classpath "gradle.plugin.com.github.erdi.webdriver-binaries:webdriver-binaries-gradle-plugin:$webdriverBinariesVersion" - classpath "com.bertramlabs.plugins:asset-pipeline-gradle:3.4.6" - classpath 'org.grails.plugins:database-migration:4.2.0' - } -} - plugins { + id "groovy" + id "org.grails.grails-gsp" + id "org.grails.grails-web" + id "com.github.erdi.webdriver-binaries" version "3.0" + id "war" + id "idea" + id "com.bertramlabs.asset-pipeline" + id "application" + id "eclipse" + id "com.gorylenko.gradle-git-properties" version "2.4.1" + + id "maven-publish" } -version "4.1.0-SNAPSHOT" +version "5.0.0-SNAPSHOT" group "au.org.ala" -apply plugin:"eclipse" -apply plugin:"idea" -apply plugin:"war" -apply plugin:"org.grails.grails-web" -apply plugin:"com.github.erdi.webdriver-binaries" -apply plugin:"com.bertramlabs.asset-pipeline" -apply plugin:"org.grails.grails-gsp" -apply plugin:"maven-publish" - - publishing { targetCompatibility = 1.11 repositories { @@ -51,12 +38,22 @@ publishing { bootWar { launchScript() + dependsOn(compileGroovyPages) +} + +war { + dependsOn(compileGroovyPages) +} + +java { + sourceCompatibility = JavaVersion.toVersion("11") } repositories { mavenLocal() maven { url "https://nexus.ala.org.au/content/groups/public/" } - maven { url "https://repo.grails.org/grails/core" } + mavenCentral() + maven { url "https://repo.grails.org/grails/core/" } } configurations { @@ -94,7 +91,7 @@ dependencies { implementation "org.grails.plugins:scaffolding" implementation "org.grails.plugins:events" implementation "org.grails.plugins:hibernate5" - implementation "org.hibernate:hibernate-core:5.4.18.Final" + implementation("org.hibernate:hibernate-core:5.6.15.Final") implementation "org.grails.plugins:gsp" implementation "com.opencsv:opencsv:3.7" @@ -106,8 +103,8 @@ dependencies { // See: https://github.com/AtlasOfLivingAustralia/collectory/issues/84#issuecomment-1070670979 // before updating mysql-connector-java - implementation "mysql:mysql-connector-java:8.0.22" - implementation "org.grails.plugins:ala-bootstrap3:4.3.0" + implementation 'mysql:mysql-connector-java:8.0.33' + implementation "org.grails.plugins:ala-bootstrap3:4.4.0" implementation "au.org.ala.plugins.grails:ala-charts-plugin:2.3.0" implementation "org.grails.plugins:ala-auth:$alaSecurityLibsVersion" implementation "org.grails.plugins:ala-ws-security-plugin:$alaSecurityLibsVersion" @@ -123,23 +120,23 @@ dependencies { runtimeOnly "com.h2database:h2" runtimeOnly "org.apache.tomcat:tomcat-jdbc" runtimeOnly "javax.xml.bind:jaxb-api:2.3.1" - runtimeOnly "com.bertramlabs.plugins:asset-pipeline-grails:3.4.6" + 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" - testImplementation "org.grails.plugins:geb" - testImplementation "org.seleniumhq.selenium:selenium-remote-driver:$seleniumVersion" - testImplementation "org.seleniumhq.selenium:selenium-api:$seleniumVersion" - testImplementation "org.seleniumhq.selenium:selenium-support:$seleniumVersion" - runtimeOnly "net.sourceforge.htmlunit:htmlunit:2.18" - testImplementation "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1" - testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion" - testImplementation "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion" - testImplementation "org.seleniumhq.selenium:selenium-safari-driver:$seleniumSafariDriverVersion" +// testImplementation "org.grails.plugins:geb" +// testImplementation "org.seleniumhq.selenium:selenium-remote-driver:$seleniumVersion" +// testImplementation "org.seleniumhq.selenium:selenium-api:$seleniumVersion" +// testImplementation "org.seleniumhq.selenium:selenium-support:$seleniumVersion" +// runtimeOnly "net.sourceforge.htmlunit:htmlunit:2.18" +// testImplementation "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1" +// testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion" +// testImplementation "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion" +// testImplementation "org.seleniumhq.selenium:selenium-safari-driver:$seleniumSafariDriverVersion" implementation 'org.grails.plugins:sentry:11.7.25' // db-migration - implementation 'org.liquibase:liquibase-core:4.19.0' + implementation 'org.liquibase:liquibase-core:4.20.0' implementation('org.grails.plugins:database-migration:4.2.0') { // spring-boot-cli exclusion required since Grails5 upgrade to prevent NullPointerException Error: https://github.com/grails/grails-database-migration/issues/268 exclude module: 'spring-boot-cli' @@ -157,18 +154,18 @@ bootRun { String springProfilesActive = 'spring.profiles.active' systemProperty springProfilesActive, System.getProperty(springProfilesActive) } - -tasks.withType(Test) { - systemProperty "geb.env", System.getProperty('geb.env') - systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest") - systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver') - systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver') -} - -webdriverBinaries { - chromedriver "$chromeDriverVersion" - geckodriver "$geckodriverVersion" -} +// +//tasks.withType(Test) { +// systemProperty "geb.env", System.getProperty('geb.env') +// systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest") +// systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver') +// systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver') +//} +// +//webdriverBinaries { +// chromedriver "$chromeDriverVersion" +// geckodriver "$geckodriverVersion" +//} assets { minifyJs = true diff --git a/gradle.properties b/gradle.properties index d92011b4..2e1fd502 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,7 @@ -grailsVersion=5.2.1 +grailsVersion=6.0.0 +grailsGradlePluginVersion=6.0.0 gormVersion=7.2.1 +org.gradle.caching=true org.gradle.daemon=true org.gradle.parallel=true org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx1024M @@ -10,4 +12,4 @@ webdriverBinariesVersion=2.6 chromeDriverVersion=2.45.0 geckodriverVersion=0.24.0 seleniumSafariDriverVersion=3.14.0 -alaSecurityLibsVersion=6.1.0 +alaSecurityLibsVersion=6.2.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a25..98debb84 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c7873..65dcd68d 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -205,6 +209,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f9..6689b85b 100755 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy b/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy index 541fc17c..899cfc12 100644 --- a/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy +++ b/grails-app/controllers/au/org/ala/collectory/SitemapController.groovy @@ -14,6 +14,8 @@ class SitemapController { return } + response.contentType = "application/xml" + if (idx == null) { // return sitemap index response.outputStream << index.newInputStream() diff --git a/grails-wrapper.jar b/grails-wrapper.jar index 6b6da64fe2dbac9d01e295cd9bdaa523cb70766c..bc85146c130e69264ce20e079987784615201b35 100644 GIT binary patch delta 3408 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/dev/null` diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..464e7af9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,20 @@ +pluginManagement { + repositories { + mavenLocal() + maven { url "https://nexus.ala.org.au/content/groups/public/" } + maven { url "https://repo.grails.org/grails/core/" } + gradlePluginPortal() + } + plugins { + id "org.grails.grails-web" version "6.0.0" + id "org.grails.grails-gsp" version "6.0.0" + id "com.bertramlabs.asset-pipeline" version "4.3.0" +// classpath "org.grails:grails-gradle-plugin:$grailsVersion" +// classpath "org.grails.plugins:hibernate5:${gormVersion}" +// classpath "gradle.plugin.com.github.erdi.webdriver-binaries:webdriver-binaries-gradle-plugin:$webdriverBinariesVersion" +// classpath "com.bertramlabs.plugins:asset-pipeline-gradle:3.4.6" +// classpath 'org.grails.plugins:database-migration:4.2.0' + } +} + +rootProject.name='collectory' From f119ab9ae6f88a2d186905b3176f0b0f1860f9bc Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Mon, 30 Oct 2023 08:19:25 +1000 Subject: [PATCH 08/10] add entity prefix to sitemap urls --- .../services/au/org/ala/collectory/SitemapService.groovy | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grails-app/services/au/org/ala/collectory/SitemapService.groovy b/grails-app/services/au/org/ala/collectory/SitemapService.groovy index 32777b25..6ff59561 100644 --- a/grails-app/services/au/org/ala/collectory/SitemapService.groovy +++ b/grails-app/services/au/org/ala/collectory/SitemapService.groovy @@ -109,19 +109,19 @@ class SitemapService { def buildSitemap() throws Exception { Collection.findAll().each {Collection it -> - writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/co" + it.id) } Institution.findAll().each {Institution it -> - writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/in" + it.id) } DataProvider.findAll().each {DataProvider it -> - writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/dp" + it.id) } DataResource.findAllByIsPrivate(false).each {DataResource it -> - writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/" + it.id) + writeUrl(it.lastUpdated, "weekly", grailsApplication.config.grails.serverURL + "/public/show/dr" + it.id) } } } From fd1845a2218afa2ec531f256626afbd82cdb017c Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Tue, 14 Nov 2023 11:43:17 +1000 Subject: [PATCH 09/10] fix isAuthorisedToEdit --- grails-app/conf/logback.xml | 1 + .../collectory/ProviderCodeController.groovy | 35 +++++++++---------- .../collectory/ProviderGroupController.groovy | 2 +- .../collectory/CollectoryAuthService.groovy | 8 +---- .../collectory/ProviderGroupService.groovy | 3 +- .../ala/collectory/CollectoryTagLib.groovy | 6 ++-- 6 files changed, 25 insertions(+), 30 deletions(-) diff --git a/grails-app/conf/logback.xml b/grails-app/conf/logback.xml index 479d28cf..b739243f 100644 --- a/grails-app/conf/logback.xml +++ b/grails-app/conf/logback.xml @@ -11,6 +11,7 @@ + diff --git a/grails-app/controllers/au/org/ala/collectory/ProviderCodeController.groovy b/grails-app/controllers/au/org/ala/collectory/ProviderCodeController.groovy index 2aed73b4..d5dc668e 100644 --- a/grails-app/controllers/au/org/ala/collectory/ProviderCodeController.groovy +++ b/grails-app/controllers/au/org/ala/collectory/ProviderCodeController.groovy @@ -68,8 +68,8 @@ class ProviderCodeController { if (version != null) { if (providerCodeInstance.version > version) { providerCodeInstance.errors.rejectValue("version", "default.optimistic.locking.failure", - [message(code: 'providerCode.label', default: 'ProviderCode')] as Object[], - "Another user has updated this ProviderCode while you were editing") + [message(code: 'providerCode.label', default: 'ProviderCode')] as Object[], + "Another user has updated this ProviderCode while you were editing") render(view: "edit", model: [providerCodeInstance: providerCodeInstance]) return } @@ -89,23 +89,22 @@ class ProviderCodeController { @Transactional def delete(Long id) { if (collectoryAuthService?.userInRole(grailsApplication.config.ROLE_ADMIN)) { - def providerCodeInstance = ProviderCode.get(id) - if (!providerCodeInstance) { - flash.message = message(code: 'default.not.found.message', args: [message(code: 'providerCode.label', default: 'ProviderCode'), id]) - redirect(action: "list") - return - } + def providerCodeInstance = ProviderCode.get(id) + if (!providerCodeInstance) { + flash.message = message(code: 'default.not.found.message', args: [message(code: 'providerCode.label', default: 'ProviderCode'), id]) + redirect(action: "list") + return + } - try { - providerCodeInstance.delete(flush: true) - flash.message = message(code: 'default.deleted.message', args: [message(code: 'providerCode.label', default: 'ProviderCode'), id]) - redirect(action: "list") - } - catch (DataIntegrityViolationException e) { - flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'providerCode.label', default: 'ProviderCode'), id]) - redirect(action: "show", id: id) - } - } else{ + try { + providerCodeInstance.delete(flush: true) + flash.message = message(code: 'default.deleted.message', args: [message(code: 'providerCode.label', default: 'ProviderCode'), id]) + redirect(action: "list") + } catch (DataIntegrityViolationException e) { + flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'providerCode.label', default: 'ProviderCode'), id]) + redirect(action: "show", id: id) + } + } else { response.setHeader("Content-type", "text/plain; charset=UTF-8") render(message(code: "provider.group.controller.04", default: "You are not authorised to access this page.")) } diff --git a/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy b/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy index d1a9c0c8..8d24d5f3 100644 --- a/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy +++ b/grails-app/controllers/au/org/ala/collectory/ProviderGroupController.groovy @@ -906,7 +906,7 @@ abstract class ProviderGroupController { if (isAdmin()) { return true } else { - def email = RequestContextHolder.currentRequestAttributes()?.getUserPrincipal()?.name + def email = collectoryAuthService.authService.email ProviderGroup pg = providerGroupService?._get(uid) if (email && pg) { if(pg){ diff --git a/grails-app/services/au/org/ala/collectory/CollectoryAuthService.groovy b/grails-app/services/au/org/ala/collectory/CollectoryAuthService.groovy index 2b983712..fa378b2f 100644 --- a/grails-app/services/au/org/ala/collectory/CollectoryAuthService.groovy +++ b/grails-app/services/au/org/ala/collectory/CollectoryAuthService.groovy @@ -41,13 +41,7 @@ class CollectoryAuthService{ static final API_KEY_COOKIE = "ALA-API-Key" def username() { - def username = 'not available' - if(RequestContextHolder.currentRequestAttributes()?.getUserPrincipal()?.name) - username = RequestContextHolder.currentRequestAttributes()?.getUserPrincipal()?.name - else { - if(authService) - username = authService.getUserName() - } + def username = authService.getDisplayName() return (username) ? username : 'not available' } diff --git a/grails-app/services/au/org/ala/collectory/ProviderGroupService.groovy b/grails-app/services/au/org/ala/collectory/ProviderGroupService.groovy index 60b3befd..9e283e0d 100644 --- a/grails-app/services/au/org/ala/collectory/ProviderGroupService.groovy +++ b/grails-app/services/au/org/ala/collectory/ProviderGroupService.groovy @@ -13,6 +13,7 @@ class ProviderGroupService { def collectoryAuthService def grailsApplication def messageSource + def authService def siteLocale = new Locale.Builder().setLanguageTag(Holders.config.siteDefaultLanguage as String).build() def serviceMethod() {} @@ -473,7 +474,7 @@ class ProviderGroupService { if (!grailsApplication.config.security.oidc.enabled.toBoolean() || isAdmin()) { return true } else { - def email = RequestContextHolder.currentRequestAttributes()?.getUserPrincipal()?.name + def email = authService.email if (email) { return _get(uid)?.isAuthorised(email) } diff --git a/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy b/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy index 7f395e26..e93267bf 100644 --- a/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy +++ b/grails-app/taglib/au/org/ala/collectory/CollectoryTagLib.groovy @@ -14,7 +14,7 @@ import java.text.SimpleDateFormat class CollectoryTagLib { - def collectoryAuthService, metadataService, providerGroupService + def collectoryAuthService, metadataService, providerGroupService, authService static namespace = 'cl' @@ -196,7 +196,7 @@ class CollectoryTagLib { * @attrs uid - the uid of the entity */ def isAuth = { attrs, body -> - if (isAuthorisedToEdit(attrs.uid, request.getRemoteUser())) { + if (isAuthorisedToEdit(attrs.uid, authService.email)) { out << body() } else { out << ' You are not authorised to change this record '// + debugString @@ -1536,7 +1536,7 @@ class CollectoryTagLib { * @body the label for the button - defaults to 'Edit' if not specified */ def editButton = { attrs, body -> - if (isAuthorisedToEdit(attrs.uid, request.getRemoteUser())) { + if (isAuthorisedToEdit(attrs.uid, authService.email)) { def paramsMap // anchor class paramsMap = [class:'edit btn btn-default'] From 62430f686a6881eb2ada59b54da0c8095bce7565 Mon Sep 17 00:00:00 2001 From: Adam Collins Date: Thu, 16 Nov 2023 11:29:28 +1000 Subject: [PATCH 10/10] fix meta app.version --- build.gradle | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index e6ebcfeb..8794a08c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,8 @@ +buildscript { + version "5.0.0-SNAPSHOT" + group "au.org.ala" +} + plugins { id "groovy" id "org.grails.grails-gsp" @@ -14,9 +19,6 @@ plugins { id "maven-publish" } -version "5.0.0-SNAPSHOT" -group "au.org.ala" - publishing { targetCompatibility = 1.11 repositories {
Institution CodesCollection Codes
${fieldValue(bean: providerMapInstance, field: "id")} ${fieldValue(bean: providerMapInstance, field: "institution")} ${fieldValue(bean: providerMapInstance, field: "collection")}${providerMapInstance.getInstitutionCodes().join(' ')}${providerMapInstance.getCollectionCodes().join(' ')}