From 4ed8e7d4dfcf04d487dc47e9b84f6e8d420d6c59 Mon Sep 17 00:00:00 2001 From: WANGF Date: Thu, 3 Apr 2025 20:40:44 -0400 Subject: [PATCH 1/5] setting option to enable/disable backup during delete record --- .../resources/catalog/components/catalog/CatalogService.js | 5 +++-- .../components/metadataactions/MetadataActionService.js | 4 ++-- web-ui/src/main/resources/catalog/locales/en-admin.json | 2 ++ .../classes/setup/sql/migrate/v447/migrate-default.sql | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js b/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js index 8706c20c7cbb..47e94b9ed6bc 100644 --- a/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js +++ b/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js @@ -61,10 +61,11 @@ * Delete a metadata from catalog * * @param {string} id Internal id of the metadata + * @param {string} backupMetadata flag to enable backup during the delete process * @return {HttpPromise} Future object */ - remove: function (id) { - return $http.delete("../api/records/" + id); + remove: function (id, backupMetadata) { + return $http.delete("../api/records/" + id, {params: {withBackup: backupMetadata}}); }, /** diff --git a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js index 51d51978d828..2bfd435db65b 100644 --- a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js +++ b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js @@ -268,7 +268,7 @@ this.deleteMd = function (md, bucket) { var deferred = $q.defer(); if (md) { - gnMetadataManager.remove(md.id).then( + gnMetadataManager.remove(md.id, gnConfig["metadata.delete.enablebackup"]).then( function (data) { $timeout(function () { $rootScope.$broadcast("search"); @@ -308,7 +308,7 @@ }; this.cancelWorkingCopy = function (md) { - return gnMetadataManager.remove(md.id); + return gnMetadataManager.remove(md.id, gnConfig["metadata.delete.enablebackup"]); }; this.getMetadataIdToEdit = function (md) { diff --git a/web-ui/src/main/resources/catalog/locales/en-admin.json b/web-ui/src/main/resources/catalog/locales/en-admin.json index 391a43a81523..e6e179707269 100644 --- a/web-ui/src/main/resources/catalog/locales/en-admin.json +++ b/web-ui/src/main/resources/catalog/locales/en-admin.json @@ -881,6 +881,8 @@ "metadata/delete": "Metadata delete", "metadata/delete/profilePublishedMetadata": "Minimum user profile allowed to delete published metadata", "metadata/delete/profilePublishedMetadata-help": "Minimum user profile allowed to delete published metadata (Editor, Reviewer or Administrator). The default value is Editor.", + "metadata/delete/enablebackup": "Enable Backup", + "metadata/delete/enablebackup-help": "Backup metadata on the server before deleting process.", "metadata/batchediting": "Metadata Batch Editing", "metadata/batchediting/accesslevel": "Select the minimum user profile allowed to access batch editing", "metadata/batchediting/accesslevel-help": "Select the minimum user profile allowed to access batch editing (Editor, Reviewer or Administrator). The default value is Editor.", diff --git a/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql b/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql index 8fecc45bfedf..e03d8298adbb 100644 --- a/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql +++ b/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql @@ -6,3 +6,5 @@ INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system ALTER TABLE Sources ADD COLUMN datahubEnabled BOOLEAN DEFAULT FALSE; ALTER TABLE Sources ADD COLUMN datahubConfiguration TEXT DEFAULT ''; + +INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/delete/enablebackup', 'true', 2, 12012, 'n'); From 17b4ed4402239105b8797daa7f277aeb59517e83 Mon Sep 17 00:00:00 2001 From: WANGF Date: Mon, 7 Apr 2025 14:39:26 -0400 Subject: [PATCH 2/5] Change default of withBackup to allow null and default with setting value. --- .../java/org/fao/geonet/kernel/setting/Settings.java | 1 + .../resources/org/fao/geonet/api/Messages.properties | 1 + .../geonet/api/records/MetadataInsertDeleteApi.java | 12 +++++++++++- .../catalog/components/catalog/CatalogService.js | 5 ++--- .../metadataactions/MetadataActionService.js | 4 ++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java b/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java index f5ee47213660..47db7708786c 100644 --- a/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java +++ b/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java @@ -144,6 +144,7 @@ public class Settings { public static final String METADATA_HISTORY_ENABLED = "metadata/history/enabled"; public static final String METADATA_HISTORY_ACCESS_LEVEL = "metadata/history/accesslevel"; public static final String METADATA_PUBLISHED_DELETE_USERPROFILE = "metadata/delete/profilePublishedMetadata"; + public static final String METADATA_DELETE_ENABLEBACKUP = "metadata/delete/enablebackup"; public static final String METADATA_PUBLISH_USERPROFILE = "metadata/publication/profilePublishMetadata"; public static final String METADATA_UNPUBLISH_USERPROFILE = "metadata/publication/profileUnpublishMetadata"; public static final String METADATA_BACKUPARCHIVE_ENABLE = "metadata/backuparchive/enable"; diff --git a/core/src/test/resources/org/fao/geonet/api/Messages.properties b/core/src/test/resources/org/fao/geonet/api/Messages.properties index f8bf6b86e795..280d28122a03 100644 --- a/core/src/test/resources/org/fao/geonet/api/Messages.properties +++ b/core/src/test/resources/org/fao/geonet/api/Messages.properties @@ -246,6 +246,7 @@ api.metadata.share.ErrorUserNotAllowedToPublish=User not allowed to publish the api.metadata.share.strategy.groupOwnerOnly=You need to be administrator, or reviewer of the metadata group. api.metadata.share.strategy.reviewerInGroup=You need to be administrator, or reviewer of the metadata group or reviewer with edit privilege on the metadata. api.metadata.status.errorSetStatusNotAllowed=Only the owner of the metadata can set the status of this record. User is not the owner of the metadata. +api.metadata.delete.errorWithBackupParamMismatch=The setting metadata/delete/enablebackup: '%s' mismatched the API parameter withBackup '%s'. feedback_subject_userFeedback=User feedback diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java index ad25403313c6..fc4f2f900302 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java @@ -215,8 +215,18 @@ public class MetadataInsertDeleteApi { @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteRecord( @Parameter(description = API_PARAM_RECORD_UUID, required = true) @PathVariable String metadataUuid, - @Parameter(description = API_PARAM_BACKUP_FIRST, required = false) @RequestParam(required = false, defaultValue = "true") boolean withBackup, + @Parameter(description = API_PARAM_BACKUP_FIRST, required = false) @RequestParam(required = false) Boolean withBackup, HttpServletRequest request) throws Exception { + boolean isMdDeleteBackupEnable = settingManager.getValueAsBool(Settings.METADATA_DELETE_ENABLEBACKUP); + if (withBackup == null) { + Log.info(LOGGER, String.format("withBackup paramter is missing. Will use setting of metadata/delete/enablebackup '%s' during the deletion process", isMdDeleteBackupEnable)); + withBackup = isMdDeleteBackupEnable; + } else if (withBackup != isMdDeleteBackupEnable) { + ResourceBundle messages = ApiUtils.getMessagesResourceBundle(request.getLocales()); + throw new IllegalArgumentException( + String.format(messages.getString("api.metadata.delete.errorWithBackupParamMismatch"), isMdDeleteBackupEnable, withBackup)); + } + AbstractMetadata metadata = ApiUtils.canEditRecord(metadataUuid, request); ServiceContext context = ApiUtils.createServiceContext(request); Store store = context.getBean("resourceStore", Store.class); diff --git a/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js b/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js index 47e94b9ed6bc..8706c20c7cbb 100644 --- a/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js +++ b/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js @@ -61,11 +61,10 @@ * Delete a metadata from catalog * * @param {string} id Internal id of the metadata - * @param {string} backupMetadata flag to enable backup during the delete process * @return {HttpPromise} Future object */ - remove: function (id, backupMetadata) { - return $http.delete("../api/records/" + id, {params: {withBackup: backupMetadata}}); + remove: function (id) { + return $http.delete("../api/records/" + id); }, /** diff --git a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js index 2bfd435db65b..51d51978d828 100644 --- a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js +++ b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js @@ -268,7 +268,7 @@ this.deleteMd = function (md, bucket) { var deferred = $q.defer(); if (md) { - gnMetadataManager.remove(md.id, gnConfig["metadata.delete.enablebackup"]).then( + gnMetadataManager.remove(md.id).then( function (data) { $timeout(function () { $rootScope.$broadcast("search"); @@ -308,7 +308,7 @@ }; this.cancelWorkingCopy = function (md) { - return gnMetadataManager.remove(md.id, gnConfig["metadata.delete.enablebackup"]); + return gnMetadataManager.remove(md.id); }; this.getMetadataIdToEdit = function (md) { From 1077817a8ce60f13f6e3887fa78f31435e9d23ad Mon Sep 17 00:00:00 2001 From: WANGF Date: Fri, 11 Apr 2025 16:41:54 -0400 Subject: [PATCH 3/5] System setting of delete record backup options --- .../fao/geonet/kernel/setting/Settings.java | 2 +- .../org/fao/geonet/api/Messages.properties | 3 +- .../api/records/MetadataInsertDeleteApi.java | 49 +++++++++++++++---- .../resources/catalog/locales/en-admin.json | 2 + .../templates/admin/settings/system.html | 25 ++++++++++ .../setup/sql/data/data-db-default.sql | 1 + .../sql/migrate/v447/migrate-default.sql | 2 - .../sql/migrate/v448/migrate-default.sql | 2 + 8 files changed, 72 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java b/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java index 47db7708786c..be9c8253d779 100644 --- a/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java +++ b/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java @@ -144,7 +144,7 @@ public class Settings { public static final String METADATA_HISTORY_ENABLED = "metadata/history/enabled"; public static final String METADATA_HISTORY_ACCESS_LEVEL = "metadata/history/accesslevel"; public static final String METADATA_PUBLISHED_DELETE_USERPROFILE = "metadata/delete/profilePublishedMetadata"; - public static final String METADATA_DELETE_ENABLEBACKUP = "metadata/delete/enablebackup"; + public static final String METADATA_DELETE_BACKUPOPTIONS = "metadata/delete/backupOptions"; public static final String METADATA_PUBLISH_USERPROFILE = "metadata/publication/profilePublishMetadata"; public static final String METADATA_UNPUBLISH_USERPROFILE = "metadata/publication/profileUnpublishMetadata"; public static final String METADATA_BACKUPARCHIVE_ENABLE = "metadata/backuparchive/enable"; diff --git a/core/src/test/resources/org/fao/geonet/api/Messages.properties b/core/src/test/resources/org/fao/geonet/api/Messages.properties index 280d28122a03..f6851d1431a2 100644 --- a/core/src/test/resources/org/fao/geonet/api/Messages.properties +++ b/core/src/test/resources/org/fao/geonet/api/Messages.properties @@ -246,7 +246,8 @@ api.metadata.share.ErrorUserNotAllowedToPublish=User not allowed to publish the api.metadata.share.strategy.groupOwnerOnly=You need to be administrator, or reviewer of the metadata group. api.metadata.share.strategy.reviewerInGroup=You need to be administrator, or reviewer of the metadata group or reviewer with edit privilege on the metadata. api.metadata.status.errorSetStatusNotAllowed=Only the owner of the metadata can set the status of this record. User is not the owner of the metadata. -api.metadata.delete.errorWithBackupParamMismatch=The setting metadata/delete/enablebackup: '%s' mismatched the API parameter withBackup '%s'. +api.metadata.delete.errorForceBackup=Cannot force the backup during deletion process because the client specified with backup parameter as: '%s'. +api.metadata.delete.errorForceNoBackup=Cannot force the no-backup during deletion process because the client specified with backup parameter as: '%s'. feedback_subject_userFeedback=User feedback diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java index fc4f2f900302..721b2a71e20b 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java @@ -217,15 +217,7 @@ public void deleteRecord( @Parameter(description = API_PARAM_RECORD_UUID, required = true) @PathVariable String metadataUuid, @Parameter(description = API_PARAM_BACKUP_FIRST, required = false) @RequestParam(required = false) Boolean withBackup, HttpServletRequest request) throws Exception { - boolean isMdDeleteBackupEnable = settingManager.getValueAsBool(Settings.METADATA_DELETE_ENABLEBACKUP); - if (withBackup == null) { - Log.info(LOGGER, String.format("withBackup paramter is missing. Will use setting of metadata/delete/enablebackup '%s' during the deletion process", isMdDeleteBackupEnable)); - withBackup = isMdDeleteBackupEnable; - } else if (withBackup != isMdDeleteBackupEnable) { - ResourceBundle messages = ApiUtils.getMessagesResourceBundle(request.getLocales()); - throw new IllegalArgumentException( - String.format(messages.getString("api.metadata.delete.errorWithBackupParamMismatch"), isMdDeleteBackupEnable, withBackup)); - } + boolean doBackup = withDeleteBackup(withBackup, request); AbstractMetadata metadata = ApiUtils.canEditRecord(metadataUuid, request); ServiceContext context = ApiUtils.createServiceContext(request); @@ -235,7 +227,7 @@ public void deleteRecord( ApplicationContextHolder.get().publishEvent(preRemoveEvent); if (metadata.getDataInfo().getType() != MetadataType.SUB_TEMPLATE - && metadata.getDataInfo().getType() != MetadataType.TEMPLATE_OF_SUB_TEMPLATE && withBackup) { + && metadata.getDataInfo().getType() != MetadataType.TEMPLATE_OF_SUB_TEMPLATE && doBackup) { MEFLib.backupRecord(metadata, context); } @@ -1036,4 +1028,41 @@ private Pair loadRecord(MetadataType metadataType, Element xmlE return Pair.read(Integer.valueOf(id.get(0)), uuid); } + /** + * Determine if the metadata backup is needed during delete API.
+ * 1) The withBackup flag missing from the API, will only overide if setting as ForceNoBackup, otherwise default to true
+ * 2) The withBackup flag designated as true from the API, will throw an error if system setting for ForceNoBackup + * 3) The withbackup flag designated as false from the API, will throw an error if system setting for ForceBackup + * + * @param withBackup API parameter from the client side + * @param request HTTP Request + * @return boolean of metadata backup and defaulted to true + */ + private boolean withDeleteBackup (Boolean withBackup, HttpServletRequest request) { + ResourceBundle messages = ApiUtils.getMessagesResourceBundle(request.getLocales()); + String mdDeleteBackupOption = settingManager.getValue(Settings.METADATA_DELETE_BACKUPOPTIONS); + if (withBackup == null) { + if (StringUtils.equals(mdDeleteBackupOption, "ForceNoBackup")) { + return false; + } + // Will default to true if setting set to NoPreference, ForceBackup or empty + return true; + } else if (withBackup == true) { + if (StringUtils.equals(mdDeleteBackupOption, "ForceNoBackup")) { + throw new IllegalArgumentException( + String.format(messages.getString("api.metadata.delete.errorForceBackup"), withBackup)); + } + return true; + } else if (withBackup = false) { + if (StringUtils.equals(mdDeleteBackupOption, "ForceBackup")) { + throw new IllegalArgumentException( + String.format(messages.getString("api.metadata.delete.errorForceNoBackup"), withBackup)); + } + return false; + } + + return true; + + } + } diff --git a/web-ui/src/main/resources/catalog/locales/en-admin.json b/web-ui/src/main/resources/catalog/locales/en-admin.json index 798b023b7d83..7a075652d2c8 100644 --- a/web-ui/src/main/resources/catalog/locales/en-admin.json +++ b/web-ui/src/main/resources/catalog/locales/en-admin.json @@ -883,6 +883,8 @@ "metadata/delete/profilePublishedMetadata-help": "Minimum user profile allowed to delete published metadata (Editor, Reviewer or Administrator). The default value is Editor.", "metadata/delete/enablebackup": "Enable Backup", "metadata/delete/enablebackup-help": "Backup metadata on the server before deleting process.", + "metadata/delete/backupOptions": "Backup Options", + "metadata/delete/backupOptions-help": "Set to override backup option from the API client parameter during deletion process. ForceBack to enforce the backup (error will return if the supplied backup from client side is set to false), ForceNoBack to disallow the backup (error will return if the supplied backup from client side is set to true), NoPreference will not enforce anything", "metadata/batchediting": "Metadata Batch Editing", "metadata/batchediting/accesslevel": "Select the minimum user profile allowed to access batch editing", "metadata/batchediting/accesslevel-help": "Select the minimum user profile allowed to access batch editing (Editor, Reviewer or Administrator). The default value is Editor.", diff --git a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html index bedc6b202550..1ca9f5e9027c 100755 --- a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html +++ b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html @@ -222,6 +222,31 @@

{{section2.name | translate}}

+ + diff --git a/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql b/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql index 1218104135ff..594db4815041 100644 --- a/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql +++ b/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql @@ -709,7 +709,7 @@ INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metada INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/history/accesslevel', 'Editor', 0, 12021, 'n'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/delete/profilePublishedMetadata', 'Editor', 0, 12011, 'n'); -INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/delete/backupOptions', 'NoPreference', 0, 12012, 'n'); +INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/delete/backupOptions', 'UseAPIParameter', 0, 12012, 'n'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/publication/profilePublishMetadata', 'Reviewer', 0, 12021, 'n'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/publication/profileUnpublishMetadata', 'Reviewer', 0, 12022, 'n'); diff --git a/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v448/migrate-default.sql b/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v448/migrate-default.sql index db4cae07463a..e27b737409cd 100644 --- a/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v448/migrate-default.sql +++ b/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v448/migrate-default.sql @@ -1,4 +1,4 @@ UPDATE Settings SET value='4.4.8' WHERE name='system/platform/version'; UPDATE Settings SET value='SNAPSHOT' WHERE name='system/platform/subVersion'; -INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/delete/backupOptions', 'NoPreference', 0, 12012, 'n'); +INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('metadata/delete/backupOptions', 'UseAPIParameter', 0, 12012, 'n'); From 2419f219552eeb2e41f5e905b46028fa0b569b94 Mon Sep 17 00:00:00 2001 From: wangf1122 <74916635+wangf1122@users.noreply.github.com> Date: Mon, 12 May 2025 09:26:54 -0400 Subject: [PATCH 5/5] update translation --- web-ui/src/main/resources/catalog/locales/en-admin.json | 3 +++ .../resources/catalog/templates/admin/settings/system.html | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/web-ui/src/main/resources/catalog/locales/en-admin.json b/web-ui/src/main/resources/catalog/locales/en-admin.json index 59e6b6930976..f077757b12f6 100644 --- a/web-ui/src/main/resources/catalog/locales/en-admin.json +++ b/web-ui/src/main/resources/catalog/locales/en-admin.json @@ -1540,6 +1540,9 @@ "doiserver-euApiText": "Publication Office of the European Union", "confirmDoiServerDelete": "Are you sure you want to delete this DOI server?", "NoTranslationProvider": "No translation provider", + "ForceBackup": "Force Backup", + "ForceNoBackup": "Force No Backup", + "UseAPIParameter": "Use API Parameter", "LibreTranslate": "Libretranslate", "userHistory": "User history", "userHistoryRevision": "Updated by {{revisionUser}} on {{revisionDate}}:", diff --git a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html index a8abecefb74c..d24f2d42f298 100755 --- a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html +++ b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html @@ -231,13 +231,13 @@

{{section2.name | translate}}

value="ForceBackup" ng-selected="'ForceBackup' == s.value" > - {{'Force backup' | translate}} + {{'ForceBackup' | translate}}