package eu.dnetlib.organizations.controller; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; 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.Organization; import eu.dnetlib.organizations.model.utils.BrowseEntry; import eu.dnetlib.organizations.model.utils.OrganizationConflict; import eu.dnetlib.organizations.model.view.ConflictGroupView; import eu.dnetlib.organizations.model.view.DuplicateGroupView; 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; import eu.dnetlib.organizations.repository.readonly.OpenaireDuplicateViewRepository; import eu.dnetlib.organizations.repository.readonly.OrganizationInfoViewRepository; import eu.dnetlib.organizations.repository.readonly.OrganizationSimpleViewRepository; import eu.dnetlib.organizations.repository.readonly.OrganizationViewRepository; import eu.dnetlib.organizations.repository.readonly.SuggestionInfoViewByCountryRepository; import eu.dnetlib.organizations.utils.DatabaseUtils; @RestController @RequestMapping("/api/organizations") public class OrganizationController { @Autowired private OrganizationRepository organizationRepository; @Autowired private OrganizationViewRepository organizationViewRepository; @Autowired private OrganizationInfoViewRepository organizationInfoViewRepository; @Autowired private OrganizationSimpleViewRepository organizationSimpleViewRepository; @Autowired private OpenaireDuplicateViewRepository openaireDuplicateViewRepository; @Autowired private ConflictGroupViewRepository conflictGroupViewRepository; @Autowired private SuggestionInfoViewByCountryRepository suggestionInfoViewByCountryRepository; @Autowired private UserCountryRepository userCountryRepository; @Autowired private DuplicateGroupViewRepository duplicateGroupViewRepository; @Autowired private DatabaseUtils databaseUtils; @PostMapping("/save") public List save(@RequestBody final OrganizationView org, final Authentication authentication) { if (StringUtils.isBlank(org.getName())) { throw new RuntimeException("Missing field: name"); } else if (StringUtils.isBlank(org.getCountry())) { throw new RuntimeException("Missing field: country"); } 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(), UserInfo.isSimpleUser(authentication)); return Arrays.asList(orgId); } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/info") public OrganizationInfoView infoById(@RequestParam final String id, final Authentication authentication) { return organizationInfoViewRepository.findById(id).get(); } @GetMapping("/suggestionsInfo") public SuggestionInfo suggestionsInfo(final Authentication authentication) { final SuggestionInfo info = new SuggestionInfo(); if (UserInfo.isSuperAdmin(authentication)) { suggestionInfoViewByCountryRepository.findAll().forEach(info::add); } else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { userCountryRepository.getCountriesForUser(authentication.getName()) .stream() .map(suggestionInfoViewByCountryRepository::findById) .filter(Optional::isPresent) .map(Optional::get) .forEach(info::add); } return info; } @GetMapping("/get") public OrganizationView findById(@RequestParam final String id, final Authentication authentication) { final OrganizationView org = organizationViewRepository.findById(id).get(); if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForCountry(org.getCountry(), authentication.getName())) { return org; } else { throw new RuntimeException("User not authorized"); } } @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())) { return databaseUtils.markAsDeleted(id, authentication.getName()); } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/discard") public OrganizationView discardById(@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())) { return databaseUtils.markAsDiscarded(id, authentication.getName()); } 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())) { return databaseUtils.listConflictsForId(id); } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/duplicates") public List duplicates(@RequestParam final String id, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForId(id, authentication.getName())) { return openaireDuplicateViewRepository.findByLocalId(id); } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/conflicts/byCountry/{country}") public Collection> findConflictsByCountry(@PathVariable final String country, final Authentication authentication) { // databaseUtils.verifyConflictGroups(false); if (UserInfo.isSuperAdmin(authentication)) { return groupConflicts(conflictGroupViewRepository.findByCountry1OrCountry2(country, country).stream()); } else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { final Stream list = userCountryRepository.getCountriesForUser(authentication.getName()) .stream() .filter(country::equalsIgnoreCase) .map(c -> conflictGroupViewRepository.findByCountry1OrCountry2(c, c).stream()) .findFirst() .orElse(Stream.empty()); return groupConflicts(list); } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/duplicates/byCountry/{country}") public Iterable findDuplicatesByCountry(@PathVariable final String country, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication)) { return duplicateGroupViewRepository.findByCountry(country); } else if (UserInfo.isSimpleUser(authentication) || UserInfo.isNationalAdmin(authentication)) { return userCountryRepository.getCountriesForUser(authentication.getName()) .stream() .filter(country::equalsIgnoreCase) .map(duplicateGroupViewRepository::findByCountry) .findFirst() .orElse(new ArrayList()); } else { throw new RuntimeException("User not authorized"); } } private Collection> groupConflicts(final Stream stream) { final Map> map = new TreeMap<>(); stream.forEach(c -> { if (!map.containsKey(c.getGroup())) { map.put(c.getGroup(), new TreeSet<>()); } map.get(c.getGroup()).add(new OrganizationConflict(c.getId1(), c.getName1(), c.getType1(), c.getCity1(), c.getCountry1())); map.get(c.getGroup()).add(new OrganizationConflict(c.getId2(), c.getName2(), c.getType2(), c.getCity2(), c.getCountry2())); }); return map.values(); } @PostMapping("/duplicates") public List duplicates(@RequestBody final List simrels, final Authentication authentication) { if (simrels.isEmpty()) { return new ArrayList<>(); } final boolean b = UserInfo.isSuperAdmin(authentication) || simrels.stream() .map(OpenaireDuplicate::getLocalId) .distinct() .allMatch(id -> userCountryRepository.verifyAuthorizationForId(id, authentication.getName())); if (b) { databaseUtils.saveDuplicates(simrels, authentication.getName()); return openaireDuplicateViewRepository.findByLocalId(simrels.get(0).getLocalId()); } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/search/{page}/{size}") public Page search(@PathVariable final int page, @PathVariable final int size, @RequestParam final String q, @RequestParam(required = false, defaultValue = "suggested,approved") final String status, final Authentication authentication) { return UserInfo.isSuperAdmin(authentication) ? organizationSimpleViewRepository.search(q, Arrays.asList(status.split(",")), PageRequest.of(page, size)) : organizationSimpleViewRepository.searchForUser(q, authentication.getName(), Arrays.asList(status.split(",")), PageRequest.of(page, size)); } @GetMapping("/byCountry/{status}/{code}/{page}/{size}") public Page findByCountry(@PathVariable final String status, @PathVariable final String code, @PathVariable final int page, @PathVariable final int size, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForCountry(code, authentication.getName())) { if (status.equalsIgnoreCase("all")) { return organizationSimpleViewRepository.findByCountryOrderByName(code, PageRequest.of(page, size)); } else { return organizationSimpleViewRepository.findByCountryAndStatusOrderByName(code, status, PageRequest.of(page, size)); } } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/byCountry/{status}/{code}") public Iterable findOrgsByStatusAndCountry(@PathVariable final String status, @PathVariable final String code, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication) || userCountryRepository.verifyAuthorizationForCountry(code, authentication.getName())) { if (status.equalsIgnoreCase("all")) { return organizationSimpleViewRepository.findByCountryOrderByName(code); } else { return organizationSimpleViewRepository.findByCountryAndStatusOrderByName(code, status); } } else { throw new RuntimeException("User not authorized"); } } @GetMapping("/byType/{status}/{type}/{page}/{size}") public Page findByType(@PathVariable final String status, @PathVariable final String type, @PathVariable final int page, @PathVariable final int size, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication)) { if (status.equalsIgnoreCase("all")) { return organizationSimpleViewRepository.findByTypeOrderByName(type, PageRequest.of(page, size)); } else { return organizationSimpleViewRepository.findByTypeAndStatusOrderByName(type, status, PageRequest.of(page, size)); } } else { if (status.equalsIgnoreCase("all")) { return organizationSimpleViewRepository.findByTypeForUser(type, authentication.getName(), PageRequest.of(page, size)); } else { return organizationSimpleViewRepository.findByTypeAndStatusForUser(type, status, authentication.getName(), PageRequest.of(page, size)); } } } @GetMapping("/browse/countries") public List browseCountries(final Authentication authentication) { return UserInfo.isSuperAdmin(authentication) ? databaseUtils.browseCountries() : databaseUtils.browseCountriesForUser(authentication.getName()); } @GetMapping("/browse/types") public List browseOrganizationTypes(final Authentication authentication) { return UserInfo.isSuperAdmin(authentication) ? databaseUtils.browseTypes() : databaseUtils.browseTypesForUser(authentication.getName()); } @PostMapping("/conflicts/fix/{masterId}") 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 Arrays.asList(newOrgId); } else { return new ArrayList<>(); } } }