From 8f30e4c8a5857c403c52a5820b26aba0b07c291e Mon Sep 17 00:00:00 2001 From: "michele.artini" Date: Mon, 19 Oct 2020 15:12:08 +0200 Subject: [PATCH] save actions by role --- .../controller/OrganizationController.java | 35 ++++-- .../organizations/utils/DatabaseUtils.java | 116 +++++++++++++++--- .../resources/html/pages/edit/edit.html | 6 +- .../resources/html/pages/search/browse.html | 2 +- 4 files changed, 129 insertions(+), 30 deletions(-) diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java index c441bdf5..f03a819b 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java @@ -9,7 +9,6 @@ import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; @@ -26,7 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import eu.dnetlib.organizations.model.OpenaireDuplicate; -import eu.dnetlib.organizations.model.Relationship; +import eu.dnetlib.organizations.model.Organization; import eu.dnetlib.organizations.model.utils.BrowseEntry; import eu.dnetlib.organizations.model.utils.OrganizationConflict; import eu.dnetlib.organizations.model.view.ConflictGroupView; @@ -35,6 +34,7 @@ import eu.dnetlib.organizations.model.view.OpenaireDuplicateView; import eu.dnetlib.organizations.model.view.OrganizationInfoView; import eu.dnetlib.organizations.model.view.OrganizationSimpleView; import eu.dnetlib.organizations.model.view.OrganizationView; +import eu.dnetlib.organizations.repository.OrganizationRepository; import eu.dnetlib.organizations.repository.UserCountryRepository; import eu.dnetlib.organizations.repository.readonly.ConflictGroupViewRepository; import eu.dnetlib.organizations.repository.readonly.DuplicateGroupViewRepository; @@ -44,11 +44,14 @@ import eu.dnetlib.organizations.repository.readonly.OrganizationSimpleViewReposi import eu.dnetlib.organizations.repository.readonly.OrganizationViewRepository; import eu.dnetlib.organizations.repository.readonly.SuggestionInfoViewByCountryRepository; import eu.dnetlib.organizations.utils.DatabaseUtils; +import eu.dnetlib.organizations.utils.OrganizationStatus; @RestController @RequestMapping("/api/organizations") public class OrganizationController { + @Autowired + private OrganizationRepository organizationRepository; @Autowired private OrganizationViewRepository organizationViewRepository; @Autowired @@ -78,7 +81,7 @@ public class OrganizationController { } else if (StringUtils.isBlank(org.getType())) { throw new RuntimeException("Missing field: type"); } else if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), authentication.getName())) { - final String orgId = databaseUtils.insertOrUpdateOrganization(org, authentication.getName()); + final String orgId = databaseUtils.insertOrUpdateOrganization(org, authentication.getName(), UserInfo.isSimpleUser(authentication)); return Arrays.asList(orgId); } else { throw new RuntimeException("User not authorized"); @@ -118,6 +121,19 @@ public class OrganizationController { } } + @GetMapping("/delete") + public OrganizationView deleteById(@RequestParam final String id, final Authentication authentication) { + final Organization org = organizationRepository.findById(id).get(); + + if (UserInfo.isSuperAdmin(authentication) || UserInfo.isNationalAdmin(authentication) && + userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), authentication.getName())) { + databaseUtils.updateStatus(id, OrganizationStatus.deleted, authentication.getName()); + return organizationViewRepository.findById(id).get(); + } else { + throw new RuntimeException("User not authorized"); + } + } + @GetMapping("/conflicts") public List conflicts(@RequestParam final String id, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, authentication.getName())) { @@ -286,18 +302,17 @@ public class OrganizationController { } @PostMapping("/conflicts/fix/{masterId}") - public List fixConflicts(final Authentication authentication, @PathVariable final String masterId, @RequestBody final List otherIds) { + public List fixConflicts(final Authentication authentication, @PathVariable final String masterId, @RequestBody final List otherIds) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(masterId, authentication.getName())) { + final List list = new ArrayList<>(); + list.add(masterId); + list.addAll(otherIds); + final String newOrgId = databaseUtils.fixConflict(list, authentication.getName()); - return otherIds.stream() - .filter(id -> UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, authentication.getName())) - .map(id -> databaseUtils.fixDuplicate(masterId, id)) - .flatMap(List::stream) - .collect(Collectors.toList()); + return Arrays.asList(newOrgId); } else { return new ArrayList<>(); } } - } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java index 46a13e76..769ed286 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java @@ -3,9 +3,13 @@ package eu.dnetlib.organizations.utils; import java.time.OffsetDateTime; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import javax.transaction.Transactional; @@ -49,6 +53,7 @@ import eu.dnetlib.organizations.repository.RelationshipRepository; import eu.dnetlib.organizations.repository.UrlRepository; import eu.dnetlib.organizations.repository.UserCountryRepository; import eu.dnetlib.organizations.repository.UserRepository; +import eu.dnetlib.organizations.repository.readonly.OrganizationViewRepository; @Component public class DatabaseUtils { @@ -73,6 +78,9 @@ public class DatabaseUtils { private OpenaireConflictRepository openaireConflictRepository; @Autowired private OpenaireDuplicateRepository openaireDuplicateRepository; + @Autowired + private OrganizationViewRepository organizationViewRepository; + @Autowired private JdbcTemplate jdbcTemplate; @@ -88,11 +96,27 @@ public class DatabaseUtils { } @Transactional - public String insertOrUpdateOrganization(final OrganizationView orgView, final String user) { - final boolean alreadyApproved = StringUtils.equals(orgView.getStatus(), OrganizationStatus.approved.toString()); + public String insertOrUpdateOrganization(final OrganizationView orgView, final String user, final boolean isSimpleUser) { + + final String oldStatus = organizationRepository.findById(orgView.getId()) + .map(Organization::getStatus) + .orElse(null); + + final boolean alreadyApproved = StringUtils.equals(oldStatus, OrganizationStatus.approved.toString()); final String oldId = orgView.getId(); + final String newStatus; + if (!isSimpleUser) { // IS ADMIN + newStatus = OrganizationStatus.approved.toString(); + } else if (isSimpleUser && oldStatus == null) { + newStatus = OrganizationStatus.suggested.toString(); + } else if (isSimpleUser && alreadyApproved) { + newStatus = OrganizationStatus.approved.toString(); + } else { + throw new RuntimeException("User not authorized"); + } + if (StringUtils.isBlank(orgView.getId())) { orgView.setId(null); } else if (!alreadyApproved) { @@ -108,7 +132,7 @@ public class DatabaseUtils { orgView.getType(), orgView.getLat(), orgView.getLng(), orgView.getCity(), orgView.getCountry(), - OrganizationStatus.approved.toString()); + newStatus); final String newId = organizationRepository.save(org).getId(); @@ -131,12 +155,20 @@ public class DatabaseUtils { } @Transactional - public void saveDuplicates(final List simrels, final String email) { + public void saveDuplicates(final List simrels, final String user) { final OffsetDateTime now = OffsetDateTime.now(); final List list = openaireDuplicateRepository.saveAll(simrels); - list.forEach(d -> openaireDuplicateRepository.updateModificationDate(d.getLocalId(), d.getOaOriginalId(), email, now)); + list.forEach(d -> { + openaireDuplicateRepository.updateModificationDate(d.getLocalId(), d.getOaOriginalId(), user, now); + + if (d.getRelType().equals(SimilarityType.is_similar.toString())) { + updateStatus(d.getOaOriginalId(), OrganizationStatus.duplicate, user); + } else { + updateStatus(d.getOaOriginalId(), OrganizationStatus.suggested, user); + } + }); } @@ -203,26 +235,26 @@ public class DatabaseUtils { /* * @Transactional public void verifyConflictGroups(final boolean forceUpdate) { - * + * * if (forceUpdate || openaireConflictRepository.countByGroupNull() > 0) { - * + * * log.info("Recreating conflicts group..."); - * + * * openaireConflictRepository.resetGroupIds(); - * + * * final Map> groups = new HashMap<>(); for (final OpenaireConflict w : openaireConflictRepository.findAll()) { * final List list = findExistingGroupsForRel(w, groups); if (list.isEmpty()) { final String idGroup = generateGroupId(); * groups.put(idGroup, new HashSet<>()); addToGroup(groups, idGroup, w); } else if (list.size() == 1) { addToGroup(groups, list.get(0), * w); } else { final String idGroup = generateGroupId(); groups.put(idGroup, new TreeSet<>()); list.forEach(id -> * groups.get(idGroup).addAll(groups.get(id))); list.forEach(id -> groups.remove(id)); addToGroup(groups, idGroup, w); } } - * + * * for (final Entry> e : groups.entrySet()) { final String gid = e.getKey(); for (final String orgId : e.getValue()) * { for (final OpenaireConflict oc : openaireConflictRepository.findById1AndGroupIsNull(orgId)) { oc.setGroup(gid); * openaireConflictRepository.save(oc); } for (final OpenaireConflict oc : openaireConflictRepository.findById2AndGroupIsNull(orgId)) { * oc.setGroup(gid); openaireConflictRepository.save(oc); } } } - * + * * log.info("...conflict groups recreated"); } } - * + * * private String generateGroupId() { return "group::" + UUID.randomUUID(); } */ @@ -321,13 +353,65 @@ public class DatabaseUtils { } @Transactional - public List fixDuplicate(final String masterId, final String otherId) { + public void updateStatus(final String id, final OrganizationStatus status, final String user) { + organizationRepository.updateStatus(id, status.toString()); + updateHistoryFields(id, user, true); + } + + @Transactional + public String fixConflict(final List ids, final String user) { + + final List views = + ids.stream().map(organizationViewRepository::findById).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); + + // I create a new org + final OrganizationView newOrg = new OrganizationView(); + newOrg.setId(null); + newOrg.setStatus(null); + newOrg.setName(findFirstString(views, OrganizationView::getName)); + newOrg.setType(findFirstString(views, OrganizationView::getType)); + newOrg.setLat(findFirstNumber(views, OrganizationView::getLat)); + newOrg.setLng(findFirstNumber(views, OrganizationView::getLng)); + newOrg.setCity(findFirstString(views, OrganizationView::getCity)); + newOrg.setCountry(findFirstString(views, OrganizationView::getCountry)); + newOrg.setOtherIdentifiers(findAll(views, OrganizationView::getOtherIdentifiers)); + newOrg.setOtherNames(findAll(views, OrganizationView::getOtherNames)); + newOrg.setAcronyms(findAll(views, OrganizationView::getAcronyms)); + newOrg.setUrls(findAll(views, OrganizationView::getUrls)); + newOrg.setRelations(findAll(views, OrganizationView::getRelations)); + + final String masterId = insertOrUpdateOrganization(newOrg, user, false); + + // I hide the merged organizations + ids.forEach(id -> hideConflictOrgs(masterId, id)); + + // I reassign the duplicated to the new org + final List newDuplicates = ids.stream() + .map(openaireDuplicateRepository::findByLocalId) + .flatMap(l -> l.stream()) + .collect(Collectors.toList()); + newDuplicates.forEach(d -> d.setLocalId(masterId)); + saveDuplicates(newDuplicates, user); + + return masterId; + } + + private String findFirstString(final List views, final Function mapper) { + return views.stream().map(mapper).filter(StringUtils::isNotBlank).findFirst().orElse(null); + } + + private Double findFirstNumber(final List views, final Function mapper) { + return views.stream().map(mapper).filter(Objects::nonNull).filter(n -> n != 0).findFirst().orElse(0.0); + } + + private Set findAll(final List views, final Function> mapper) { + return views.stream().map(mapper).flatMap(s -> s.stream()).collect(Collectors.toCollection(LinkedHashSet::new)); + } + + private List hideConflictOrgs(final String masterId, final String otherId) { organizationRepository.updateStatus(otherId, OrganizationStatus.hidden.toString()); openaireConflictRepository.findById(new OpenaireConflictPK(masterId, otherId)).ifPresent(openaireConflictRepository::delete); openaireConflictRepository.findById(new OpenaireConflictPK(otherId, masterId)).ifPresent(openaireConflictRepository::delete); - - // TODO Merge the organizations ??? - return makeRelation(masterId, otherId, RelationType.Merges); } diff --git a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/edit/edit.html b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/edit/edit.html index 86dfb34b..2bb7d481 100644 --- a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/edit/edit.html +++ b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/edit/edit.html @@ -14,10 +14,10 @@ Metadata Management - diff --git a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/search/browse.html b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/search/browse.html index ee3e0e3e..f40b8abb 100644 --- a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/search/browse.html +++ b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/search/browse.html @@ -26,7 +26,7 @@ - - {{e.values.suggested}} + {{e.values.suggested}} -