From 024b75ea0352d0d91b7a57b083a8ff3538008cae Mon Sep 17 00:00:00 2001 From: EthanFreestone <54310740+EthanFreestone@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:36:25 +0000 Subject: [PATCH 1/9] chore: Post release work (#91) Bumped gradle.properties version -> 7.1.0-SNAPSHOT and added NEWS.md section MODSER-26 --- NEWS.md | 2 ++ service/gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 3e19c64..dd5c30f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,5 @@ +## 1.1.0 In progress + ## 1.0.0 2024-03-22 * Initial release for module serials-management * Manage objects relating to the concept of a "serial" diff --git a/service/gradle.properties b/service/gradle.properties index ada055c..47a9f95 100644 --- a/service/gradle.properties +++ b/service/gradle.properties @@ -11,6 +11,6 @@ gradleWrapperVersion=5.4 # Application appName=mod-serials-management -appVersion=1.0.0 +appVersion=1.1.0-SNAPSHOT dockerTagSuffix= dockerRepo=folioci From dca3c3830a01f586905a6b067a849c85afba0d91 Mon Sep 17 00:00:00 2001 From: EthanFreestone <54310740+EthanFreestone@users.noreply.github.com> Date: Thu, 4 Apr 2024 15:51:51 +0100 Subject: [PATCH 2/9] build: Dependency upgrades (#92) Bumped dependencies for security reasons MODSER-28 --- service/build.gradle | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/service/build.gradle b/service/build.gradle index edc5af3..822d2c8 100644 --- a/service/build.gradle +++ b/service/build.gradle @@ -107,7 +107,10 @@ dependencies { implementation("org.grails.plugins:events") implementation("org.grails.plugins:hibernate5") implementation("org.grails.plugins:spring-security-core:6.1.1") // NOT IN LINE WITH GRAILS PATCH VERSION - implementation("org.grails.plugins:views-json") + // 5.8.9 affected by https://security.snyk.io/vuln/SNYK-JAVA-ORGSPRINGFRAMEWORKSECURITY-6457293 + implementation("org.springframework.security:spring-security-core:5.8.11") + + implementation("org.grails.plugins:views-json") implementation("org.grails.plugins:views-json-templates") implementation("org.hibernate:hibernate-core:5.6.15.Final") @@ -136,16 +139,18 @@ dependencies { implementation "org.springframework.boot:spring-boot-starter-undertow" // Replaces spring-boot-starter-tomcat implementation "org.hibernate:hibernate-java8" runtimeOnly "com.zaxxer:HikariCP:5.1.0" // Replaces Tomcat JDBC pool - runtimeOnly "org.postgresql:postgresql:42.5.3" + runtimeOnly "org.postgresql:postgresql:42.7.3" implementation ('org.grails.plugins:database-migration:4.2.1') { exclude group: 'org.liquibase', module: 'liquibase-core' } implementation 'org.liquibase:liquibase-core:4.19.0' implementation 'com.opencsv:opencsv:5.7.1' - implementation 'commons-io:commons-io:2.6' - implementation 'io.github.virtualdogbert:logback-groovy-config:1.14.1' // Grails 5 and up no longer supports groovy files for logback config - compileOnly 'ch.qos.logback:logback-classic:1.4.7' + implementation 'commons-io:commons-io:2.7' + implementation('io.github.virtualdogbert:logback-groovy-config:1.14.1') + compileOnly 'ch.qos.logback:logback-classic:1.4.7' + // Is on runtime classpath via spring-boot-starter + runtimeOnly 'ch.qos.logback:logback-classic:1.2.13' /* ---- Manually installed testing dependencies ---- */ /* implementation "org.grails:grails-gorm-testing-support:2.6.1" @@ -161,8 +166,9 @@ dependencies { implementation 'com.github.jknack:handlebars-helpers:4.3.1' /* ---- Custom non profile deps ---- */ - implementation 'org.apache.kafka:kafka-clients:2.3.0' - implementation 'com.github.everit-org.json-schema:org.everit.json.schema:1.12.2' + implementation 'org.apache.kafka:kafka-clients:3.7.0' + implementation 'com.github.everit-org.json-schema:org.everit.json.schema:1.14.4' + // Better test reports. testImplementation( 'com.athaydes:spock-reports:2.3.2-groovy-3.0' ) { transitive = false // this avoids affecting your version of Groovy/Spock From b500a14ee0fafb8bda6c023b8ad8d5a3d3785ffc Mon Sep 17 00:00:00 2001 From: Jack-Golding <94838251+Jack-Golding@users.noreply.github.com> Date: Wed, 10 Apr 2024 07:00:32 +0100 Subject: [PATCH 3/9] UISER-99/88: Starting values ordering and missing uses (#93) * fix: initial work * refactor: Seperated starting values The starting values have now been seperated out into their own array instead of using transient values --- .../olf/PredictedPieceSetController.groovy | 28 +++++++------------ .../EnumerationTemplateMetadataRule.groovy | 4 +-- .../EnumerationNumericTMRF.groovy | 7 ++--- .../EnumerationTextualTMRF.groovy | 2 +- .../org/olf/PieceGenerationService.groovy | 4 --- .../org/olf/PieceLabellingService.groovy | 17 ++++++----- 6 files changed, 26 insertions(+), 36 deletions(-) diff --git a/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy b/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy index e9ae861..415d6a8 100644 --- a/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy +++ b/service/grails-app/controllers/org/olf/PredictedPieceSetController.groovy @@ -1,6 +1,7 @@ package org.olf import org.olf.PieceGenerationService +import org.olf.PieceLabellingService import org.olf.Serial import org.olf.SerialRuleset @@ -27,36 +28,27 @@ class PredictedPieceSetController extends OkapiTenantAwareController startingValues = data?.startingValues ?: [] + + ArrayList ips = pieceGenerationService.createPiecesTransient(ruleset, LocalDate.parse(data.startDate)) + pieceLabellingService.setLabelsForInternalPieces(ips, ruleset?.templateConfig, startingValues) - ArrayList result = pieceGenerationService.createPiecesTransient(handleStartingValues(ruleset, data), LocalDate.parse(data.startDate)) - respond result + respond ips } def generatePredictedPieces() { JSONObject data = request.JSON SerialRuleset ruleset = SerialRuleset.get(data?.id) + List startingValues = data?.startingValues ?: [] - ArrayList ips = pieceGenerationService.createPiecesTransient(handleStartingValues(ruleset, data), LocalDate.parse(data.startDate)) + ArrayList ips = pieceGenerationService.createPiecesTransient(ruleset, LocalDate.parse(data.startDate)) + pieceLabellingService.setLabelsForInternalPieces(ips, ruleset?.templateConfig, startingValues) PredictedPieceSet pps = new PredictedPieceSet([ ruleset: ruleset, diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/EnumerationTemplateMetadataRule.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/EnumerationTemplateMetadataRule.groovy index 4713e55..d3d2bda 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/EnumerationTemplateMetadataRule.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/EnumerationTemplateMetadataRule.groovy @@ -39,10 +39,10 @@ public class EnumerationTemplateMetadataRule extends TemplateMetadataRuleType im ruleFormat nullable: false, validator: TemplateMetadataRuleTypeHelpers.ruleFormatValidator } - public static EnumerationTemplateMetadata handleType(TemplateMetadataRule rule, LocalDate date, int index) { + public static EnumerationTemplateMetadata handleType(TemplateMetadataRule rule, LocalDate date, int index, Map startingValues) { final Pattern RGX_RULE_FORMAT = Pattern.compile('_([a-z])') String ruleFormatClassString = RGX_RULE_FORMAT.matcher(rule?.ruleType?.templateMetadataRuleFormat?.value).replaceAll { match -> match.group(1).toUpperCase() } Class rfc = Class.forName("org.olf.templateConfig.templateMetadataRuleFormat.${ruleFormatClassString.capitalize()}TMRF") - return rfc.handleFormat(rule, date, index) + return rfc.handleFormat(rule, date, index, startingValues) } } diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationNumericTMRF.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationNumericTMRF.groovy index aa4e1f6..9c0b23d 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationNumericTMRF.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationNumericTMRF.groovy @@ -53,15 +53,14 @@ public class EnumerationNumericTMRF extends TemplateMetadataRuleFormat implement return roman } - public static EnumerationTemplateMetadata handleFormat (TemplateMetadataRule rule, LocalDate date, int index){ + public static EnumerationTemplateMetadata handleFormat (TemplateMetadataRule rule, LocalDate date, int index, Map startingValues){ ArrayList enltmrfArray = rule?.ruleType?.ruleFormat?.levels?.sort { it?.index } ArrayList result = [] Integer adjustedIndex = 0 Integer divisor = 1 for(int i=enltmrfArray?.size()-1; i>=0; i--){ - - if(enltmrfArray[i]?.startingValue !== null){ - adjustedIndex = adjustedIndex + ((enltmrfArray[i]?.startingValue - 1)*divisor) + if(startingValues?.levels?.getAt(i)?.value !== null){ + adjustedIndex = adjustedIndex + ((startingValues?.levels.getAt(i)?.value as Integer - 1)*divisor) } Integer value = 0 diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationTextualTMRF.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationTextualTMRF.groovy index 3c9eaee..d424364 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationTextualTMRF.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/EnumerationTextualTMRF.groovy @@ -38,7 +38,7 @@ public class EnumerationTextualTMRF extends TemplateMetadataRuleFormat implement } } - public static EnumerationTemplateMetadata handleFormat (TemplateMetadataRule rule, LocalDate date, int index){ + public static EnumerationTemplateMetadata handleFormat (TemplateMetadataRule rule, LocalDate date, int index, Map startingValues){ String result = findResultIndex(rule, index + 1) return new EnumerationTemplateMetadata([value: result]) } diff --git a/service/grails-app/services/org/olf/PieceGenerationService.groovy b/service/grails-app/services/org/olf/PieceGenerationService.groovy index 3ec1a06..732e34a 100644 --- a/service/grails-app/services/org/olf/PieceGenerationService.groovy +++ b/service/grails-app/services/org/olf/PieceGenerationService.groovy @@ -207,10 +207,6 @@ public class PieceGenerationService { } } - if (!!ruleset?.templateConfig) { - pieceLabellingService.setLabelsForInternalPieces(internalPieces, ruleset?.templateConfig) - } - return internalPieces } } diff --git a/service/grails-app/services/org/olf/PieceLabellingService.groovy b/service/grails-app/services/org/olf/PieceLabellingService.groovy index 3850bed..13f1b46 100644 --- a/service/grails-app/services/org/olf/PieceLabellingService.groovy +++ b/service/grails-app/services/org/olf/PieceLabellingService.groovy @@ -31,13 +31,15 @@ public class PieceLabellingService { // This needs to take in an individual piece and ooutput a String label - public String generateTemplatedLabelForPiece(InternalPiece piece, ArrayList internalPieces, TemplateConfig templateConfig) { + public String generateTemplatedLabelForPiece(InternalPiece piece, ArrayList internalPieces, TemplateConfig templateConfig, List startingValues) { Template template = hte.createTemplate(templateConfig.templateString); // Template template = hte.createTemplate("EA {{chronology1.year}} {{chronologyArray.0.year}} {{test}}") StandardTemplateMetadata standardTM = generateStandardMetadata(piece, internalPieces) - ArrayList chronologyArray = generateChronologyMetadata(standardTM, templateConfig.rules) - ArrayList enumerationArray = generateEnumerationMetadata(standardTM, templateConfig.rules) + // Having to enforce a sort here + Set sortedRules = templateConfig.rules?.sort{ it.index } + ArrayList chronologyArray = generateChronologyMetadata(standardTM, sortedRules) + ArrayList enumerationArray = generateEnumerationMetadata(standardTM, sortedRules, startingValues) LabelTemplateBindings ltb = new LabelTemplateBindings() ltb.setupChronologyArray(chronologyArray) @@ -51,12 +53,12 @@ public class PieceLabellingService { } } - public void setLabelsForInternalPieces(ArrayList internalPieces, TemplateConfig templateConfig) { + public void setLabelsForInternalPieces(ArrayList internalPieces, TemplateConfig templateConfig, List startingValues) { ListIterator iterator = internalPieces?.listIterator() while(iterator.hasNext()){ InternalPiece currentPiece = iterator.next() if(currentPiece instanceof InternalRecurrencePiece || currentPiece instanceof InternalCombinationPiece){ - String label = generateTemplatedLabelForPiece(currentPiece, internalPieces, templateConfig) + String label = generateTemplatedLabelForPiece(currentPiece, internalPieces, templateConfig, startingValues) currentPiece.label = label currentPiece.templateString = templateConfig?.templateString } @@ -153,7 +155,7 @@ public class PieceLabellingService { return chronologyTemplateMetadataArray } - public ArrayList generateEnumerationMetadata(StandardTemplateMetadata standardTM, Set templateMetadataRules) { + public ArrayList generateEnumerationMetadata(StandardTemplateMetadata standardTM, Set templateMetadataRules, List startingValues) { ArrayList enumerationTemplateMetadataArray = [] Iterator iterator = templateMetadataRules?.iterator() while(iterator?.hasNext()){ @@ -161,7 +163,8 @@ public class PieceLabellingService { String templateMetadataType = RGX_METADATA_RULE_TYPE.matcher(currentMetadataRule?.templateMetadataRuleType?.value).replaceAll { match -> match.group(1).toUpperCase() } if(templateMetadataType == 'enumeration'){ Class tmrte = Class.forName("org.olf.templateConfig.templateMetadataRule.${templateMetadataType.capitalize()}TemplateMetadataRule") - EnumerationTemplateMetadata enumerationTemplateMetadata = tmrte.handleType(currentMetadataRule, standardTM.date, standardTM.index) + Map ruleStartingValues = startingValues.getAt(currentMetadataRule?.index) + EnumerationTemplateMetadata enumerationTemplateMetadata = tmrte.handleType(currentMetadataRule, standardTM.date, standardTM.index, ruleStartingValues) enumerationTemplateMetadataArray << enumerationTemplateMetadata } From 49406267f533fc8ff753078ebb879ce1d9f130c0 Mon Sep 17 00:00:00 2001 From: Jack-Golding <94838251+Jack-Golding@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:37:25 +0100 Subject: [PATCH 4/9] fix: Support using different languages for chronologies when generating predicted pieces (#94) * fix: Support using different languages for chronologies when generating predicted pieces Added ruleLocale field to handle using a 2 letter locale value when generating chronologies * fix: Updated tenant changelog --- .../org/olf/LocalesController.groovy | 27 +++++++++++++++++++ .../controllers/org/olf/UrlMappings.groovy | 2 ++ .../ChronologyTemplateMetadataRule.groovy | 5 ++++ .../ChronologyDateTMRF.groovy | 19 +++++-------- .../ChronologyMonthTMRF.groovy | 7 +++-- .../ChronologyYearTMRF.groovy | 4 ++- .../migrations/module-tenant-changelog.groovy | 1 + .../update-mod-serials-management-1-1.groovy | 7 +++++ .../main/okapi/ModuleDescriptor-template.json | 5 ++++ 9 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 service/grails-app/controllers/org/olf/LocalesController.groovy create mode 100644 service/grails-app/migrations/update-mod-serials-management-1-1.groovy diff --git a/service/grails-app/controllers/org/olf/LocalesController.groovy b/service/grails-app/controllers/org/olf/LocalesController.groovy new file mode 100644 index 0000000..9172d2c --- /dev/null +++ b/service/grails-app/controllers/org/olf/LocalesController.groovy @@ -0,0 +1,27 @@ +package org.olf + +import com.k_int.okapi.OkapiTenantAwareController + +import grails.gorm.multitenancy.CurrentTenant +import groovy.json.JsonOutput +import groovy.util.logging.Slf4j + +import java.util.regex.Pattern +import java.util.Locale + +@Slf4j +@CurrentTenant +class LocalesController { + + def getLocales() { + Locale[] locales = Locale.getAvailableLocales(); + ArrayList localesList = locales.collect { Locale locale -> + {[ + label: locale.getDisplayName(), + value: locale.toString() + ]} + }.sort { it.label } + + respond localesList + } + } \ No newline at end of file diff --git a/service/grails-app/controllers/org/olf/UrlMappings.groovy b/service/grails-app/controllers/org/olf/UrlMappings.groovy index fe534e4..c7d4a17 100644 --- a/service/grails-app/controllers/org/olf/UrlMappings.groovy +++ b/service/grails-app/controllers/org/olf/UrlMappings.groovy @@ -10,6 +10,8 @@ class UrlMappings { "/$domain/$property" (controller: 'refdata', action: 'lookup', method: 'GET') } } + + "/serials-management/locales" (controller: 'locales', action: 'getLocales', method: 'GET') "/serials-management/serials" (resources: 'serial') diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/ChronologyTemplateMetadataRule.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/ChronologyTemplateMetadataRule.groovy index 853a46f..59c25b5 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/ChronologyTemplateMetadataRule.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRule/ChronologyTemplateMetadataRule.groovy @@ -6,6 +6,7 @@ import org.olf.internalPiece.templateMetadata.ChronologyTemplateMetadata import java.util.regex.Pattern import java.time.LocalDate +import java.util.Locale import grails.gorm.MultiTenant import grails.databinding.BindUsing @@ -21,6 +22,8 @@ public class ChronologyTemplateMetadataRule extends TemplateMetadataRuleType imp @Defaults(['Chronology Date', 'Chronology Month', 'Chronology Year']) RefdataValue templateMetadataRuleFormat + String ruleLocale = 'en' + @BindUsing({ TemplateMetadataRuleType obj, SimpleMapDataBindingSource source -> TemplateMetadataRuleTypeHelpers.doRuleFormatBinding(obj, source) }) @@ -33,11 +36,13 @@ public class ChronologyTemplateMetadataRule extends TemplateMetadataRuleType imp static mapping = { templateMetadataRuleFormat column: 'ctmr_template_metadata_rule_format_fk' + ruleLocale column: 'ctmr_rule_locale' ruleFormat cascade: 'all-delete-orphan' } static constraints = { templateMetadataRuleFormat nullable: false + ruleLocale nullable: false ruleFormat nullable: false, validator: TemplateMetadataRuleTypeHelpers.ruleFormatValidator } diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyDateTMRF.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyDateTMRF.groovy index f06af34..5b4a44d 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyDateTMRF.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyDateTMRF.groovy @@ -8,6 +8,8 @@ import org.olf.internalPiece.templateMetadata.ChronologyTemplateMetadata import java.time.LocalDate import java.time.format.DateTimeFormatter +import java.util.Locale + import com.k_int.web.toolkit.refdata.CategoryId import com.k_int.web.toolkit.refdata.Defaults import com.k_int.web.toolkit.refdata.RefdataValue @@ -77,28 +79,21 @@ public class ChronologyDateTMRF extends TemplateMetadataRuleFormat implements Mu ] public static ChronologyTemplateMetadata handleFormat(TemplateMetadataRule rule, LocalDate date, int index) { + Locale locale = new Locale(rule?.ruleType?.ruleLocale) ChronologyDateTMRF tmrf = rule?.ruleType?.ruleFormat // TODO Dont handle if not a chronology rule - String weekday = date.format(DateTimeFormatter.ofPattern(weekdayFormatTransform.get(tmrf?.weekdayFormat?.value))) + String weekday = date.format(DateTimeFormatter.ofPattern(weekdayFormatTransform.get(tmrf?.weekdayFormat?.value), locale)) if(tmrf?.weekdayFormat?.value.endsWith('upper')){ weekday = weekday.toUpperCase() } - // FIXME IMPLEMENT THIS PROPERLY - Set allLanguages = new HashSet(); - String[] languages = Locale.getISOLanguages(); - for (int i = 0; i < languages.length; i++){ - Locale loc = new Locale(languages[i]); - allLanguages.add(loc); - } - - String monthDay = date.format(DateTimeFormatter.ofPattern('d')) + String monthDay = date.format(DateTimeFormatter.ofPattern('d', locale)) if(tmrf?.monthDayFormat?.value == 'ordinal'){ monthDay = monthDay + getDayOfMonthSuffix(Integer.parseInt(monthDay)) } - String month = date.format(DateTimeFormatter.ofPattern(monthFormatTransform.get(tmrf?.monthFormat?.value))); - String year = date.format(DateTimeFormatter.ofPattern(yearFormatTransform.get(tmrf?.yearFormat?.value))); + String month = date.format(DateTimeFormatter.ofPattern(monthFormatTransform.get(tmrf?.monthFormat?.value), locale)); + String year = date.format(DateTimeFormatter.ofPattern(yearFormatTransform.get(tmrf?.yearFormat?.value), locale)); return new ChronologyTemplateMetadata([weekday: weekday, monthDay: monthDay, month: month, year: year, templateMetadataRule: rule]) } diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyMonthTMRF.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyMonthTMRF.groovy index 4941be2..1468a50 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyMonthTMRF.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyMonthTMRF.groovy @@ -8,6 +8,8 @@ import grails.gorm.MultiTenant import java.time.LocalDate import java.time.format.DateTimeFormatter +import java.util.Locale + import com.k_int.web.toolkit.refdata.CategoryId import com.k_int.web.toolkit.refdata.Defaults import com.k_int.web.toolkit.refdata.RefdataValue @@ -33,6 +35,7 @@ public class ChronologyMonthTMRF extends TemplateMetadataRuleFormat implements M } public static ChronologyTemplateMetadata handleFormat(TemplateMetadataRule rule, LocalDate date, int index) { + Locale locale = new Locale(rule?.ruleType?.ruleLocale) ChronologyMonthTMRF tmrf = rule?.ruleType?.ruleFormat Map getYearFormat = [ slice: 'yy', @@ -45,8 +48,8 @@ public class ChronologyMonthTMRF extends TemplateMetadataRuleFormat implements M number: 'MM' ] - DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern(getMonthFormat.get(tmrf?.monthFormat?.value)); - DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern(getYearFormat.get(tmrf?.yearFormat?.value)); + DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern(getMonthFormat.get(tmrf?.monthFormat?.value), locale); + DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern(getYearFormat.get(tmrf?.yearFormat?.value), locale); String month = date.format(monthFormatter); String year = date.format(yearFormatter); diff --git a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyYearTMRF.groovy b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyYearTMRF.groovy index 2b9e48b..03c29a8 100644 --- a/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyYearTMRF.groovy +++ b/service/grails-app/domain/org/olf/templateConfig/templateMetadataRuleFormat/ChronologyYearTMRF.groovy @@ -27,13 +27,15 @@ public class ChronologyYearTMRF extends TemplateMetadataRuleFormat implements Mu } public static ChronologyTemplateMetadata handleFormat(TemplateMetadataRule rule, LocalDate date, int index) { + println(rule) + Locale locale = new Locale(rule?.ruleType?.ruleLocale) ChronologyYearTMRF tmrf = rule?.ruleType?.ruleFormat Map getYearFormat = [ slice: 'yy', full: 'yyyy', ] - DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern(getYearFormat.get(tmrf?.yearFormat?.value)); + DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern(getYearFormat.get(tmrf?.yearFormat?.value), locale); String year = date.format(yearFormatter); diff --git a/service/grails-app/migrations/module-tenant-changelog.groovy b/service/grails-app/migrations/module-tenant-changelog.groovy index aff30bc..8c66df9 100644 --- a/service/grails-app/migrations/module-tenant-changelog.groovy +++ b/service/grails-app/migrations/module-tenant-changelog.groovy @@ -1,4 +1,5 @@ databaseChangeLog = { include file: 'initial-customisations.groovy' include file: 'create-mod-serials-management.groovy' + include file: 'update-mod-serials-management-1-1.groovy' } diff --git a/service/grails-app/migrations/update-mod-serials-management-1-1.groovy b/service/grails-app/migrations/update-mod-serials-management-1-1.groovy new file mode 100644 index 0000000..11d1149 --- /dev/null +++ b/service/grails-app/migrations/update-mod-serials-management-1-1.groovy @@ -0,0 +1,7 @@ +databaseChangeLog = { + changeSet(author: "Jack-Golding (manual)", id: "20240416-1325-001") { + addColumn(tableName: "chronology_template_metadata_rule") { + column(name: "ctmr_rule_locale", type: "VARCHAR(36)") { constraints(nullable: "true") } + } + } +} \ No newline at end of file diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index c1ec049..4d56469 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -115,6 +115,11 @@ "methods": ["POST"], "pathPattern": "/serials-management/predictedPieces/create", "permissionsRequired": [ "serials-management.predictedPieces.edit" ] + }, + { + "methods": ["GET"], + "pathPattern": "/serials-management/locales", + "permissionsRequired": [ "serials-management.refdata.collection.get" ] } ] }, From e075274a825b913f3cd6a919b49fba0ce8705d5f Mon Sep 17 00:00:00 2001 From: EthanFreestone <54310740+EthanFreestone@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:26:42 +0100 Subject: [PATCH 5/9] fix: Issue with missing datasource on startup (#95) Extra affordances given on startup when attempting to grab datasource from grails. Comprises of an update to grails-okapi -> 7.1.0 refs ERM-3190 --- service/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/build.gradle b/service/build.gradle index 822d2c8..d6ae462 100644 --- a/service/build.gradle +++ b/service/build.gradle @@ -130,7 +130,7 @@ dependencies { /* ---- Manually installed dependencies ---- */ implementation 'com.k_int.grails:web-toolkit-ce:9.0.0' - implementation('com.k_int.okapi:grails-okapi:7.0.0') { + implementation('com.k_int.okapi:grails-okapi:7.1.0') { exclude group: 'com.vaadin.external.google', module: 'android-json' } From 781d07dddf43a6d6da40829b59e441814fd12fbd Mon Sep 17 00:00:00 2001 From: EthanFreestone <54310740+EthanFreestone@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:36:17 +0100 Subject: [PATCH 6/9] docs: Include patch release notes on master branch (#97) refs MODSER-33 --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index dd5c30f..7cd64b7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,11 @@ ## 1.1.0 In progress +## 1.0.1 2024-04-17 + * MODSER-34 Template does not always get data from labels or levels in the same order + * MODSER-28 Update outdated/vulnerable dependencies + * UISER-99 Level 1 number not used correctly in predicted piece preview from Create Publication Pattern + * ERM-3190 DB Connections are not being released + ## 1.0.0 2024-03-22 * Initial release for module serials-management * Manage objects relating to the concept of a "serial" From faa2e6cae50785a805cba9a00699eb6074b70664 Mon Sep 17 00:00:00 2001 From: Jack-Golding <94838251+Jack-Golding@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:57:05 +0100 Subject: [PATCH 7/9] fix: Endpoints should be protected by fine-grained permissions (#98) Added more fine grained control of the permissions within the serials management module descriptor MODSER-35 --- .../main/okapi/ModuleDescriptor-template.json | 87 ++++++++++--------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index 4d56469..b16d039 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -35,91 +35,91 @@ { "methods": ["GET"], "pathPattern": "/serials-management/serials", - "permissionsRequired": [ "serials-management.serials.view" ], + "permissionsRequired": [ "serials-management.serials.collection.get" ], "modulePermissions": ["orders.po-lines.item.get"] }, { "methods": ["GET"], "pathPattern": "/serials-management/serials/{id}", - "permissionsRequired": [ "serials-management.serials.view" ] + "permissionsRequired": [ "serials-management.serials.item.get" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/serials", - "permissionsRequired": [ "serials-management.serials.edit" ] + "permissionsRequired": [ "serials-management.serials.item.post" ] },{ "methods": ["PUT"], "pathPattern": "/serials-management/serials/{id}", - "permissionsRequired": [ "serials-management.serials.edit" ] + "permissionsRequired": [ "serials-management.serials.item.put" ] },{ "methods": ["DELETE"], "pathPattern": "/serials-management/serials/{id}", - "permissionsRequired": [ "serials-management.serials.manage" ] + "permissionsRequired": [ "serials-management.serials.item.delete" ] }, { "methods": ["GET"], "pathPattern": "/serials-management/rulesets", - "permissionsRequired": [ "serials-management.rulesets.view" ] + "permissionsRequired": [ "serials-management.rulesets.collection.get" ] }, { "methods": ["GET"], "pathPattern": "/serials-management/rulesets/{id}", - "permissionsRequired": [ "serials-management.rulesets.view" ] + "permissionsRequired": [ "serials-management.rulesets.item.get" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/rulesets", - "permissionsRequired": [ "serials-management.rulesets.edit" ] + "permissionsRequired": [ "serials-management.rulesets.item.post" ] }, { "methods": ["DELETE"], "pathPattern": "/serials-management/rulesets/{id}", - "permissionsRequired": [ "serials-management.rulesets.manage" ] + "permissionsRequired": [ "serials-management.rulesets.item.delete" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/rulesets/{id}/active", - "permissionsRequired": [ "serials-management.rulesets.edit" ] + "permissionsRequired": [ "serials-management.rulesets.item.put" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/rulesets/{id}/deprecated", - "permissionsRequired": [ "serials-management.rulesets.edit" ] + "permissionsRequired": [ "serials-management.rulesets.item.put" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/rulesets/{id}/draft", - "permissionsRequired": [ "serials-management.rulesets.edit" ] + "permissionsRequired": [ "serials-management.rulesets.item.put" ] }, { "methods": ["GET"], "pathPattern": "/serials-management/predictedPieces", - "permissionsRequired": [ "serials-management.predictedPieces.view" ] + "permissionsRequired": [ "serials-management.predictedPieceSets.collection.get" ] }, { "methods": ["GET"], "pathPattern": "/serials-management/predictedPieces/{id}", - "permissionsRequired": [ "serials-management.predictedPieces.view" ] + "permissionsRequired": [ "serials-management.predictedPieceSets.item.get" ] }, { "methods": ["PUT"], "pathPattern": "/serials-management/predictedPieces/{id}", - "permissionsRequired": [ "serials-management.predictedPieces.edit" ] + "permissionsRequired": [ "serials-management.predictedPieceSets.item.put" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/predictedPieces/generate", - "permissionsRequired": [ "serials-management.predictedPieces.edit" ] + "permissionsRequired": [ "serials-management.predictedPieceSets.item.post" ] }, { "methods": ["POST"], "pathPattern": "/serials-management/predictedPieces/create", - "permissionsRequired": [ "serials-management.predictedPieces.edit" ] + "permissionsRequired": [ "serials-management.predictedPieceSets.item.post" ] }, { "methods": ["GET"], "pathPattern": "/serials-management/locales", - "permissionsRequired": [ "serials-management.refdata.collection.get" ] + "permissionsRequired": [ "serials-management.locales.collection.get" ] } ] }, @@ -337,51 +337,56 @@ ] }, { - "permissionName": "serials-management.predictedPieces.collection.get", + "permissionName": "serials-management.predictedPieceSets.collection.get", "displayName": "Predicted pieces collection get", - "description": "Get a collection of predicted pieces records" + "description": "Get a collection of predicted piece set records" }, { - "permissionName": "serials-management.predictedPieces.item.get", + "permissionName": "serials-management.predictedPieceSets.item.get", "displayName": "Predicted pieces item get", - "description": "Get a predicted pieces record" + "description": "Get a predicted piece set record" }, { - "permissionName": "serials-management.predictedPieces.view", + "permissionName": "serials-management.predictedPieceSets.view", "subPermissions": [ - "serials-management.predictedPieces.collection.get", - "serials-management.predictedPieces.item.get" + "serials-management.predictedPieceSets.collection.get", + "serials-management.predictedPieceSets.item.get" ] }, { - "permissionName": "serials-management.predictedPieces.item.post", - "displayName": "Predicted pieces item post", - "description": "Post a predicted pieces record" + "permissionName": "serials-management.predictedPieceSets.item.post", + "displayName": "Predicted piece set item post", + "description": "Post a predicted piece set record" }, { - "permissionName": "serials-management.predictedPieces.item.put", - "displayName": "Predicted pieces item put", - "description": "Put a predicted pieces record" + "permissionName": "serials-management.predictedPieceSets.item.put", + "displayName": "Predicted piece set item put", + "description": "Put a predicted piece set record" }, { - "permissionName": "serials-management.predictedPieces.item.delete", - "displayName": "Predicted pieces item delete", - "description": "Delete a predicted pieces record" + "permissionName": "serials-management.predictedPieceSets.item.delete", + "displayName": "Predicted piece set item delete", + "description": "Delete a predicted piece set record" }, { - "permissionName": "serials-management.predictedPieces.edit", + "permissionName": "serials-management.predictedPieceSets.edit", "subPermissions": [ - "serials-management.predictedPieces.view", - "serials-management.predictedPieces.item.post", - "serials-management.predictedPieces.item.put" + "serials-management.predictedPieceSets.view", + "serials-management.predictedPieceSets.item.post", + "serials-management.predictedPieceSets.item.put" ] }, { - "permissionName": "serials-management.predictedPieces.manage", + "permissionName": "serials-management.predictedPieceSets.manage", "subPermissions": [ - "serials-management.predictedPieces.edit", - "serials-management.predictedPieces.delete" + "serials-management.predictedPieceSets.edit", + "serials-management.predictedPieceSets.delete" ] + }, + { + "permissionName": "serials-management.locales.collection.get", + "displayName": "Locales collection get", + "description": "Get the collection of locales" } ], "launchDescriptor": { From 737010d0cfb3df74aa79c220f11e2507d034a268 Mon Sep 17 00:00:00 2001 From: Jack-Golding <94838251+Jack-Golding@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:49:18 +0100 Subject: [PATCH 8/9] fix: Added missing serial delete permission (#99) --- .../main/okapi/ModuleDescriptor-template.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/service/src/main/okapi/ModuleDescriptor-template.json b/service/src/main/okapi/ModuleDescriptor-template.json index b16d039..65b9ab4 100644 --- a/service/src/main/okapi/ModuleDescriptor-template.json +++ b/service/src/main/okapi/ModuleDescriptor-template.json @@ -289,6 +289,18 @@ "serials-management.serials.item.put" ] }, + { + "permissionName": "serials-management.serials.item.delete", + "displayName": "Serial item delete", + "description": "Delete a serial record" + }, + { + "permissionName": "serials-management.serials.manage", + "subPermissions": [ + "serials-management.serials.edit", + "serials-management.serials.item.delete" + ] + }, { "permissionName": "serials-management.rulesets.collection.get", "displayName": "Ruleset collection get", @@ -333,7 +345,7 @@ "permissionName": "serials-management.rulesets.manage", "subPermissions": [ "serials-management.rulesets.edit", - "serials-management.rulesets.delete" + "serials-management.rulesets.item.delete" ] }, { @@ -380,7 +392,7 @@ "permissionName": "serials-management.predictedPieceSets.manage", "subPermissions": [ "serials-management.predictedPieceSets.edit", - "serials-management.predictedPieceSets.delete" + "serials-management.predictedPieceSets.item.delete" ] }, { From 9b6e3b5a4ef3d09cfc1e1d0f855800421e8c9b5f Mon Sep 17 00:00:00 2001 From: Jack Golding Date: Fri, 26 Apr 2024 15:42:56 +0100 Subject: [PATCH 9/9] chore: Release 1.0.3 Updated NEWS.md and incremented patch version to 1.0.3 refs MODSER-36 --- NEWS.md | 3 +++ service/gradle.properties | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index b522f4c..615218a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +## 1.0.3 2024-04-26 + * MODSER-35 Endpoints should be protected by fine-grained permissions + ## 1.0.2 2024-04-26 * MODSER-35 Endpoints should be protected by fine-grained permissions diff --git a/service/gradle.properties b/service/gradle.properties index f0c7353..0938527 100644 --- a/service/gradle.properties +++ b/service/gradle.properties @@ -11,6 +11,6 @@ gradleWrapperVersion=5.4 # Application appName=mod-serials-management -appVersion=1.0.2 +appVersion=1.0.3 dockerTagSuffix= dockerRepo=folioci