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 195151232f6..01a878903fb 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 @@ -138,6 +138,7 @@ public class Settings { public static final String METADATA_LINK_EXCLUDEPATTERN = "metadata/link/excludedUrlPattern"; public static final String METADATA_IMPORT_RESTRICT = "metadata/import/restrict"; public static final String METADATA_IMPORT_USERPROFILE = "metadata/import/userprofile"; + public static final String METADATA_BATCH_EDITING_ACCESS_LEVEL = "metadata/batchediting/accesslevel"; public static final String METADATA_PUBLISHED_DELETE_USERPROFILE = "metadata/delete/profilePublishedMetadata"; public static final String METADATA_PUBLISH_USERPROFILE = "metadata/publication/profilePublishMetadata"; public static final String METADATA_UNPUBLISH_USERPROFILE = "metadata/publication/profileUnpublishMetadata"; diff --git a/services/src/main/java/org/fao/geonet/api/processing/DatabaseProcessApi.java b/services/src/main/java/org/fao/geonet/api/processing/DatabaseProcessApi.java index 707d970b474..7732fff4d52 100644 --- a/services/src/main/java/org/fao/geonet/api/processing/DatabaseProcessApi.java +++ b/services/src/main/java/org/fao/geonet/api/processing/DatabaseProcessApi.java @@ -36,15 +36,19 @@ import org.fao.geonet.ApplicationContextHolder; import org.fao.geonet.api.ApiParams; import org.fao.geonet.api.ApiUtils; +import org.fao.geonet.api.exception.NotAllowedException; import org.fao.geonet.api.processing.report.MetadataReplacementProcessingReport; import org.fao.geonet.api.processing.report.XsltMetadataProcessingReport; import org.fao.geonet.domain.AbstractMetadata; +import org.fao.geonet.domain.Profile; import org.fao.geonet.events.history.RecordProcessingChangeEvent; import org.fao.geonet.kernel.DataManager; import org.fao.geonet.kernel.MetadataIndexerProcessor; import org.fao.geonet.kernel.SchemaManager; import org.fao.geonet.kernel.datamanager.IMetadataUtils; import org.fao.geonet.kernel.setting.SettingManager; +import org.fao.geonet.kernel.setting.Settings; +import org.fao.geonet.util.UserUtil; import org.fao.geonet.utils.Diff; import org.fao.geonet.utils.DiffType; import org.fao.geonet.utils.Log; @@ -56,6 +60,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -91,6 +96,9 @@ public class DatabaseProcessApi { @Autowired SettingManager settingManager; + @Autowired + RoleHierarchy roleHierarchy; + @io.swagger.v3.oas.annotations.Operation( summary = "Preview of search and replace text.", description =" When errors occur during processing, the processing report is returned in JSON format.") @@ -175,6 +183,9 @@ public ResponseEntity previewProcessSearchAndReplace( Element preview = new Element("preview"); try { + ServiceContext serviceContext = ApiUtils.createServiceContext(request); + checkUserProfileToBatchEditMetadata(serviceContext.getUserSession()); + Set records = ApiUtils.getUuidsParameterOrSelection(uuids, bucket, session); final String siteURL = request.getRequestURL().toString() + "?" + request.getQueryString(); @@ -182,7 +193,7 @@ public ResponseEntity previewProcessSearchAndReplace( String id = dataMan.getMetadataId(uuid); Log.info("org.fao.geonet.services.metadata", "Processing metadata for preview with id:" + id); - ServiceContext serviceContext = ApiUtils.createServiceContext(request); + Element record = DatabaseProcessUtils.process( serviceContext, id, useRegexp, search, replace, regexpFlags, @@ -307,6 +318,8 @@ public XsltMetadataProcessingReport processSearchAndReplace( new MetadataReplacementProcessingReport(search + "-" + replace); try { + ServiceContext serviceContext = ApiUtils.createServiceContext(request); + checkUserProfileToBatchEditMetadata(serviceContext.getUserSession()); Set records = ApiUtils.getUuidsParameterOrSelection(uuids, bucket, session); UserSession userSession = ApiUtils.getUserSession(httpSession); @@ -315,7 +328,7 @@ public XsltMetadataProcessingReport processSearchAndReplace( processingReport.setTotalRecords(records.size()); BatchDatabaseUpdateMetadataReindexer m = new BatchDatabaseUpdateMetadataReindexer( - ApiUtils.createServiceContext(request), + serviceContext, dataMan, records, useRegexp, search, replace, regexpFlags, httpSession, siteURL, processingReport, request, index, updateDateStamp, userSession.getUserIdAsInt()); m.process(settingManager.getSiteId()); @@ -402,4 +415,22 @@ public void process(String catalogueId) throws Exception { } } } + + /** + * Checks if the user profile is allowed to batch edit metadata. + * + * @param userSession + */ + private void checkUserProfileToBatchEditMetadata(UserSession userSession) { + if (userSession.getProfile() != Profile.Administrator) { + String allowedUserProfileToImportMetadata = + StringUtils.defaultIfBlank(settingManager.getValue(Settings.METADATA_BATCH_EDITING_ACCESS_LEVEL), Profile.Editor.toString()); + + // Is the user profile is higher than the profile allowed to import metadata? + if (!UserUtil.hasHierarchyRole(allowedUserProfileToImportMetadata, this.roleHierarchy)) { + throw new NotAllowedException("The user has no permissions to batch edit metadata."); + } + } + + } } diff --git a/services/src/main/java/org/fao/geonet/api/records/editing/BatchEditsApi.java b/services/src/main/java/org/fao/geonet/api/records/editing/BatchEditsApi.java index d08d61ebb27..5feb506f190 100644 --- a/services/src/main/java/org/fao/geonet/api/records/editing/BatchEditsApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/editing/BatchEditsApi.java @@ -37,10 +37,12 @@ import org.fao.geonet.ApplicationContextHolder; import org.fao.geonet.api.ApiParams; import org.fao.geonet.api.ApiUtils; +import org.fao.geonet.api.exception.NotAllowedException; import org.fao.geonet.api.processing.report.IProcessingReport; import org.fao.geonet.api.processing.report.SimpleMetadataProcessingReport; import org.fao.geonet.domain.AbstractMetadata; import org.fao.geonet.domain.Pair; +import org.fao.geonet.domain.Profile; import org.fao.geonet.events.history.RecordUpdatedEvent; import org.fao.geonet.kernel.*; import org.fao.geonet.kernel.datamanager.IMetadataUtils; @@ -48,6 +50,7 @@ import org.fao.geonet.kernel.search.IndexingMode; import org.fao.geonet.kernel.setting.SettingManager; import org.fao.geonet.kernel.setting.Settings; +import org.fao.geonet.util.UserUtil; import org.fao.geonet.utils.Diff; import org.fao.geonet.utils.DiffType; import org.fao.geonet.utils.Xml; @@ -59,6 +62,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -79,6 +83,13 @@ public class BatchEditsApi implements ApplicationContextAware { @Autowired SchemaManager _schemaManager; + + @Autowired + SettingManager settingManager; + + @Autowired + RoleHierarchy roleHierarchy; + private ApplicationContext context; public synchronized void setApplicationContext(ApplicationContext context) { @@ -180,6 +191,7 @@ private Pair applyBatchEdits( ServiceContext serviceContext = ApiUtils.createServiceContext(request); + checkUserProfileToBatchEditMetadata(serviceContext.getUserSession()); final Set setOfUuidsToEdit; if (uuids == null) { SelectionManager selectionManager = @@ -294,4 +306,22 @@ private Pair applyBatchEdits( report.close(); return Pair.write(report, preview); } + + /** + * Checks if the user profile is allowed to batch edit metadata. + * + * @param userSession + */ + private void checkUserProfileToBatchEditMetadata(UserSession userSession) { + if (userSession.getProfile() != Profile.Administrator) { + String allowedUserProfileToImportMetadata = + StringUtils.defaultIfBlank(settingManager.getValue(Settings.METADATA_BATCH_EDITING_ACCESS_LEVEL), Profile.Editor.toString()); + + // Is the user profile is higher than the profile allowed to import metadata? + if (!UserUtil.hasHierarchyRole(allowedUserProfileToImportMetadata, this.roleHierarchy)) { + throw new NotAllowedException("The user has no permissions to batch edit metadata."); + } + } + + } }