diff --git a/pom.xml b/pom.xml index d71ffe95b..256ff54ca 100644 --- a/pom.xml +++ b/pom.xml @@ -53,8 +53,9 @@ 17 1.13.2 3.5.1 - 2022.06.2-SNAPSHOT + 2022.06.3-SNAPSHOT v16.0.0 + 2.8-SNAPSHOT scope,groupId,artifactId https://gist.githubusercontent.com/yagee-de/dfd3698c1b49173dbf251f74eb6a9297/raw/406460c088ff3cb6354e4ae6b40535e6f841607d/mycore_sort.xml true @@ -300,6 +301,11 @@ commons-text 1.10.0 + + org.mycore + mycore-orcid2 + ${mycore.version} + org.mycore.ubo ubo-cli diff --git a/ubo-cli/src/main/setup/classifications/accessrights.xml b/ubo-cli/src/main/setup/classifications/accessrights.xml new file mode 100644 index 000000000..aaedc9d4b --- /dev/null +++ b/ubo-cli/src/main/setup/classifications/accessrights.xml @@ -0,0 +1,28 @@ + + + diff --git a/ubo-cli/src/main/setup/classifications/nameIdentifier.xml b/ubo-cli/src/main/setup/classifications/nameIdentifier.xml index 566ad110f..6e8c4a8ec 100644 --- a/ubo-cli/src/main/setup/classifications/nameIdentifier.xml +++ b/ubo-cli/src/main/setup/classifications/nameIdentifier.xml @@ -6,18 +6,42 @@ + + + + + + diff --git a/ubo-cli/src/main/setup/classifications/peerreviewed.xml b/ubo-cli/src/main/setup/classifications/peerreviewed.xml new file mode 100644 index 000000000..62e974aef --- /dev/null +++ b/ubo-cli/src/main/setup/classifications/peerreviewed.xml @@ -0,0 +1,18 @@ + + + + diff --git a/ubo-cli/src/main/setup/classifications/typeOfResource.xml b/ubo-cli/src/main/setup/classifications/typeOfResource.xml new file mode 100644 index 000000000..57f848daa --- /dev/null +++ b/ubo-cli/src/main/setup/classifications/typeOfResource.xml @@ -0,0 +1,38 @@ + + + diff --git a/ubo-cli/src/main/setup/classifications/user_attributes.xml b/ubo-cli/src/main/setup/classifications/user_attributes.xml deleted file mode 100644 index 0fc257c3a..000000000 --- a/ubo-cli/src/main/setup/classifications/user_attributes.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/ubo-common/pom.xml b/ubo-common/pom.xml index a107f9595..a71f32382 100644 --- a/ubo-common/pom.xml +++ b/ubo-common/pom.xml @@ -233,7 +233,7 @@ org.mycore - mycore-orcid + mycore-orcid2 org.mycore @@ -344,7 +344,7 @@ org.mycore.pica2mods pica2mods-xslt - 2.5-SNAPSHOT + ${pica2mods.version} runtime diff --git a/ubo-common/src/main/java/org/mycore/ubo/importer/orcid/Orcid2WorksTransformer.java b/ubo-common/src/main/java/org/mycore/ubo/importer/orcid/Orcid2WorksTransformer.java index 1bdcebc03..a46a91775 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/importer/orcid/Orcid2WorksTransformer.java +++ b/ubo-common/src/main/java/org/mycore/ubo/importer/orcid/Orcid2WorksTransformer.java @@ -1,30 +1,78 @@ package org.mycore.ubo.importer.orcid; -import java.io.IOException; - +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.jdom2.Element; -import org.jdom2.JDOMException; import org.mycore.common.content.MCRContent; import org.mycore.common.content.MCRJDOMContent; import org.mycore.common.content.transformer.MCRContentTransformer; -import org.mycore.orcid.MCRORCIDProfile; -import org.mycore.orcid.works.MCRWorksSection; -import org.xml.sax.SAXException; +import org.mycore.orcid2.MCRORCIDUtils; +import org.mycore.orcid2.client.exception.MCRORCIDRequestException; +import org.mycore.orcid2.v3.client.MCRORCIDClientHelper; +import org.mycore.orcid2.v3.client.MCRORCIDSectionImpl; +import org.mycore.orcid2.v3.work.MCRORCIDWorkUtils; +import org.orcid.jaxb.model.v3.release.record.Work; +import org.orcid.jaxb.model.v3.release.record.summary.WorkGroup; +import org.orcid.jaxb.model.v3.release.record.summary.WorkSummary; +import org.orcid.jaxb.model.v3.release.record.summary.Works; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; -public class Orcid2WorksTransformer extends MCRContentTransformer { +public class Orcid2WorksTransformer extends MCRContentTransformer implements Comparator { + + protected Logger LOGGER = LogManager.getLogger(Orcid2WorksTransformer.class); public MCRJDOMContent transform(MCRContent source) throws IOException { - String orcid = source.asString(); + List workList = new ArrayList<>(); - MCRORCIDProfile profile = new MCRORCIDProfile(orcid); - try { - MCRWorksSection worksSection = profile.getWorksSection(); - worksSection.fetchDetails(); + Arrays.stream(source.asString().split("\\s")) + .filter(orcid -> orcid.trim().length() > 0) + .forEach(orcid -> { + try { + Works works = MCRORCIDClientHelper + .getClientFactory() + .createReadClient() + .fetch(orcid, MCRORCIDSectionImpl.WORKS, Works.class); + + works.getWorkGroup() + .stream() + .map(WorkGroup::getWorkSummary) + .filter(wg -> wg.size() > 0) + .forEach(workSummaries -> { + workSummaries.sort(this); + WorkSummary workSummary = workSummaries.get(0); - Element modsCollection = worksSection.buildMODSCollection(); - return new MCRJDOMContent(modsCollection); - } catch (JDOMException | SAXException ex) { - throw new IOException(ex); + Work work = MCRORCIDClientHelper + .getClientFactory() + .createReadClient() + .fetch(orcid, MCRORCIDSectionImpl.WORK, Work.class, workSummary.getPutCode()); + + workList.add(work); + }); + } catch (MCRORCIDRequestException e) { + LOGGER.warn("Could not get works for ORCID {}. {}", orcid, e.getMessage()); + } + }); + + List workElements = MCRORCIDWorkUtils.buildUnmergedMODSFromWorks(workList); + Element modsCollection = MCRORCIDUtils.buildMODSCollection(workElements); + + return new MCRJDOMContent(modsCollection); + } + + @Override + public int compare(WorkSummary ws1, WorkSummary ws2) { + int v = 0; + try { + v = Integer.parseInt(ws1.getDisplayIndex()) - Integer.parseInt( + ws2.getDisplayIndex()); + } catch (Exception e) { + LOGGER.error("Could not compare WorkSummaries", e); } + return v; } } diff --git a/ubo-common/src/main/java/org/mycore/ubo/ldap/picker/LDAPWithLocalService.java b/ubo-common/src/main/java/org/mycore/ubo/ldap/picker/LDAPWithLocalService.java index fd5d963ce..41f44ad37 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/ldap/picker/LDAPWithLocalService.java +++ b/ubo-common/src/main/java/org/mycore/ubo/ldap/picker/LDAPWithLocalService.java @@ -1,18 +1,31 @@ package org.mycore.ubo.ldap.picker; +import java.util.Optional; + import javax.naming.OperationNotSupportedException; +import org.mycore.common.config.MCRConfiguration2; import org.mycore.ubo.local.LocalService; import org.mycore.ubo.picker.PersonSearchResult; +import org.mycore.user2.MCRRealmFactory; public class LDAPWithLocalService extends LDAPService { + public static final String LDAP_REALM = MCRConfiguration2.getString( + "MCR.user2.IdentityManagement.UserCreation.LDAP.Realm").orElse(null); + @Override public PersonSearchResult searchPerson(String query) throws OperationNotSupportedException { PersonSearchResult results = super.searchPerson(query); LocalService localService = new LocalService(); PersonSearchResult personSearchResult = localService.searchPerson(query); results.join(personSearchResult, 0); + + if (LDAP_REALM != null) { + Optional.ofNullable(MCRRealmFactory.getRealm(LDAP_REALM)) + .ifPresent(realm -> results.join(localService.searchPerson(query, realm), 0)); + } + return results; } } diff --git a/ubo-common/src/main/java/org/mycore/ubo/local/LocalService.java b/ubo-common/src/main/java/org/mycore/ubo/local/LocalService.java index caf33a420..b802ebe6f 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/local/LocalService.java +++ b/ubo-common/src/main/java/org/mycore/ubo/local/LocalService.java @@ -11,6 +11,8 @@ import org.mycore.common.config.MCRConfiguration2; import org.mycore.ubo.picker.IdentityService; import org.mycore.ubo.picker.PersonSearchResult; +import org.mycore.user2.MCRRealm; +import org.mycore.user2.MCRRealmFactory; import org.mycore.user2.MCRUser; import org.mycore.user2.MCRUserAttribute; import org.mycore.user2.MCRUserManager; @@ -40,38 +42,42 @@ public Element searchPerson(Map paramMap) { @Override public PersonSearchResult searchPerson(String query) throws OperationNotSupportedException { + return searchPerson(query, MCRRealmFactory.getLocalRealm()); + } + + public PersonSearchResult searchPerson(String query, MCRRealm realm) { String displayName = "*" + query.trim() + "*"; - final List matchingUsers = MCRUserManager.listUsers(null, "local", displayName, null); + final List matchingUsers = MCRUserManager.listUsers(null, realm.getID(), displayName, null); List personResults = matchingUsers.stream().map(user -> { - PersonSearchResult.PersonResult personSearchResult = new PersonSearchResult.PersonResult(this); - personSearchResult.pid = user.getUserAttribute("id_" + LEAD_ID); - personSearchResult.displayName = user.getRealName().length() > 0 ? user.getRealName() : user.getUserName(); - - user.getAttributes().stream() - .filter(attr -> attr.getName().equals(USER_FIRST_NAME_ATTR)) - .findFirst() - .map(MCRUserAttribute::getValue) - .ifPresent(attrVal -> { - personSearchResult.firstName = attrVal; - }); - - user.getAttributes().stream() - .filter(attr -> attr.getName().equals(USER_LAST_NAME_ATTR)) - .findFirst() - .map(MCRUserAttribute::getValue) - .ifPresent(attrVal -> { - personSearchResult.lastName = attrVal; - }); - - if (user.getEMailAddress() != null) { - personSearchResult.information = new ArrayList<>(); - personSearchResult.information.add(user.getEMailAddress()); - } - - return personSearchResult; - }).filter(psr -> (psr.pid != null && !psr.pid.isEmpty()) || !ENFORCE_LEAD_ID_PRESENT) - .collect(Collectors.toList()); + PersonSearchResult.PersonResult personSearchResult = new PersonSearchResult.PersonResult(this); + personSearchResult.pid = user.getUserAttribute("id_" + LEAD_ID); + personSearchResult.displayName = user.getRealName().length() > 0 ? user.getRealName() : user.getUserName(); + + user.getAttributes().stream() + .filter(attr -> attr.getName().equals(USER_FIRST_NAME_ATTR)) + .findFirst() + .map(MCRUserAttribute::getValue) + .ifPresent(attrVal -> { + personSearchResult.firstName = attrVal; + }); + + user.getAttributes().stream() + .filter(attr -> attr.getName().equals(USER_LAST_NAME_ATTR)) + .findFirst() + .map(MCRUserAttribute::getValue) + .ifPresent(attrVal -> { + personSearchResult.lastName = attrVal; + }); + + if (user.getEMailAddress() != null) { + personSearchResult.information = new ArrayList<>(); + personSearchResult.information.add(user.getEMailAddress()); + } + + return personSearchResult; + }).filter(psr -> (psr.pid != null && !psr.pid.isEmpty()) || !ENFORCE_LEAD_ID_PRESENT) + .collect(Collectors.toList()); PersonSearchResult personSearchResult = new PersonSearchResult(); personSearchResult.count = personResults.size(); diff --git a/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherLDAP.java b/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherLDAP.java index f3d4b2a7a..dff84c480 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherLDAP.java +++ b/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherLDAP.java @@ -1,23 +1,5 @@ package org.mycore.ubo.matcher; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.text.Normalizer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import javax.naming.NamingException; -import javax.naming.ldap.LdapContext; - import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; @@ -35,6 +17,23 @@ import org.mycore.user2.MCRUser; import org.mycore.user2.MCRUserAttribute; +import javax.naming.NamingException; +import javax.naming.ldap.LdapContext; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.text.Normalizer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + /** * Given a MCRUser match against the users of a LDAP-Server, enriching the attributes of the MCRUser by any matched * LDAP-Users attributes. @@ -70,7 +69,7 @@ public class MCRUserMatcherLDAP implements MCRUserMatcher { private final static Logger LOGGER = LogManager.getLogger(MCRUserMatcherLDAP.class); - private final static String CONFIG_LDAP_LOGIN_ATTRIBUTENAME = "MCR.user2.LDAP.Login.AttributeName"; + protected final static String CONFIG_LDAP_LOGIN_ATTRIBUTENAME = "MCR.user2.LDAP.Login.AttributeName"; // all members regarding configuration of explicit mods/mycore nameIdentifier mapping private final static String CONFIG_EXPLICIT_NAMEIDENTIFIER_MAPPING = "MCR.user2.LDAP.Mapping.explicit"; @@ -230,7 +229,7 @@ Since currently (October 24th 2019), the LDAP and MyCoRe/UBO login is paired via return matcherDTO; } - private String getUserNameFromLDAPUser(LDAPObject ldapUser) { + protected String getUserNameFromLDAPUser(LDAPObject ldapUser) { String userName = ""; String ldapLoginAttributeName = MCRConfiguration2.getString(CONFIG_LDAP_LOGIN_ATTRIBUTENAME).orElse(""); if (StringUtils.isEmpty(ldapLoginAttributeName)) { diff --git a/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherUtils.java b/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherUtils.java index 48bbd4720..5fcf8ba96 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherUtils.java +++ b/ubo-common/src/main/java/org/mycore/ubo/matcher/MCRUserMatcherUtils.java @@ -5,9 +5,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.SortedSet; +import java.util.UUID; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -21,7 +21,7 @@ import org.mycore.common.config.MCRConfiguration2; import org.mycore.datamodel.metadata.MCRObject; import org.mycore.mods.MCRMODSWrapper; -import org.mycore.orcid.user.MCRORCIDUser; +import org.mycore.orcid2.user.MCRORCIDUser; import org.mycore.ubo.ldap.LDAPObject; import org.mycore.user2.MCRRealmFactory; import org.mycore.user2.MCRUser; @@ -115,33 +115,13 @@ public static MCRUser createNewMCRUserFromModsNameElement(Element modsNameElemen } public static MCRUser createNewMCRUserFromModsNameElement(Element modsNameElement, String realmID) { - String userName = getUserNameFromModsNameElement(modsNameElement); + String userName = UUID.randomUUID().toString(); Map nameIdentifiers = MCRUserMatcherUtils.getNameIdentifiers(modsNameElement); MCRUser mcrUser = new MCRUser(userName, realmID); enrichUserWithGivenNameIdentifiers(mcrUser, nameIdentifiers); return mcrUser; } - private static String getUserNameFromModsNameElement(Element modsNameElement) { - - XPathFactory xFactory = XPathFactory.instance(); - - XPathExpression givenNameExpr = xFactory.compile("mods:namePart[@type='given']", - Filters.element(), null, MODS_NAMESPACE); - Element givenNameElem = givenNameExpr.evaluateFirst(modsNameElement); - XPathExpression familyNameExpr = xFactory.compile("mods:namePart[@type='family']", - Filters.element(), null, MODS_NAMESPACE); - Element familyNameElem = familyNameExpr.evaluateFirst(modsNameElement); - - String userName = ""; - - if((givenNameElem != null) && (familyNameElem != null)) { - userName = (givenNameElem.getText() + "_" + familyNameElem.getText()).toLowerCase(Locale.ROOT); - } - - return userName; - } - public static String getAttributesAsURLString(List modsNameElements) { String parameters = ""; for(Element modsNameElement : modsNameElements) { diff --git a/ubo-common/src/main/java/org/mycore/ubo/orcid/DozBibORCIDUserServlet.java b/ubo-common/src/main/java/org/mycore/ubo/orcid/DozBibORCIDUserServlet.java new file mode 100644 index 000000000..28d99ab03 --- /dev/null +++ b/ubo-common/src/main/java/org/mycore/ubo/orcid/DozBibORCIDUserServlet.java @@ -0,0 +1,95 @@ +package org.mycore.ubo.orcid; + +import jakarta.servlet.http.HttpServletResponse; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.mycore.common.MCRSessionMgr; +import org.mycore.common.xml.MCRXMLFunctions; +import org.mycore.frontend.MCRFrontendUtil; +import org.mycore.frontend.servlets.MCRServlet; +import org.mycore.frontend.servlets.MCRServletJob; +import org.mycore.orcid2.user.MCRORCIDSessionUtils; +import org.mycore.orcid2.user.MCRORCIDUser; +import org.mycore.orcid2.user.MCRORCIDUserUtils; +import org.mycore.user2.MCRUser; +import org.mycore.user2.MCRUserAttribute; +import org.mycore.user2.MCRUserManager; + +import java.io.IOException; +import java.util.Set; +import java.util.SortedSet; + +/** + * Servlet removes all orcid access tokens of the current user. If you want to remove a single access token for + * a given orcid please see {@link org.mycore.orcid2.rest.resources.MCRORCIDResource#revoke(String)} )} + * + * @author shermann + * */ +public class DozBibORCIDUserServlet extends MCRServlet { + + public final static Logger LOGGER = LogManager.getLogger(DozBibORCIDUserServlet.class); + + @Override + protected void doGetPost(MCRServletJob job) throws Exception { + if (MCRXMLFunctions.isCurrentUserGuestUser()) { + job.getResponse().sendError(HttpServletResponse.SC_FORBIDDEN); + } + + String action = job.getRequest().getParameter("action"); + if (action == null) { + redirectToProfile(job); + return; + } + + MCRORCIDUser orcidUser; + try { + orcidUser = MCRORCIDSessionUtils.getCurrentUser(); + }catch(Exception e){ + LOGGER.error("Could not get orcid user for user {}", MCRUserManager.getCurrentUser(), e); + redirectToProfile(job); + return; + } + + Set orcidIdentifiers = orcidUser.getORCIDs(); + if (orcidIdentifiers.isEmpty()) { + redirectToProfile(job); + return; + } + + switch (action) { + case "sync": + toggleSync(); + break; + case "revoke": + orcidUser.getUser() + .getAttributes() + .removeIf(a -> a.getName().equals("orcid_update_profile")); + + orcidIdentifiers.forEach(orcid -> { + LOGGER.info("Unlinking ORCID {} for user {}", orcid, orcidUser.getUser().getUserID()); + MCRORCIDUserUtils.revokeCredentialByORCID(orcidUser, orcid); + }); + break; + } + + redirectToProfile(job); + } + + private void toggleSync() { + MCRUser user = MCRUserManager.getUser(MCRSessionMgr.getCurrentSession().getUserInformation().getUserID()); + SortedSet attributes = user.getAttributes(); + + attributes.stream() + .filter(attr -> attr.getName().equals("orcid_update_profile")) + .findFirst() + .ifPresentOrElse(present -> { + attributes.remove(present); + }, () -> { + attributes.add(new MCRUserAttribute("orcid_update_profile", String.valueOf(true))); + }); + } + + protected void redirectToProfile(MCRServletJob job) throws IOException { + job.getResponse().sendRedirect(MCRFrontendUtil.getBaseURL() + "servlets/MCRUserServlet?action=show"); + } +} diff --git a/ubo-common/src/main/java/org/mycore/ubo/orcid/DozBibORCIDUtils.java b/ubo-common/src/main/java/org/mycore/ubo/orcid/DozBibORCIDUtils.java new file mode 100644 index 000000000..e27b6bc53 --- /dev/null +++ b/ubo-common/src/main/java/org/mycore/ubo/orcid/DozBibORCIDUtils.java @@ -0,0 +1,130 @@ +package org.mycore.ubo.orcid; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.mycore.common.MCRSessionMgr; +import org.mycore.common.xml.MCRXMLFunctions; +import org.mycore.orcid2.client.MCRORCIDCredential; +import org.mycore.orcid2.client.MCRORCIDUserClient; +import org.mycore.orcid2.client.exception.MCRORCIDRequestException; +import org.mycore.orcid2.user.MCRORCIDSessionUtils; +import org.mycore.orcid2.user.MCRORCIDUser; +import org.mycore.orcid2.v3.client.MCRORCIDClientHelper; +import org.mycore.orcid2.v3.client.MCRORCIDSectionImpl; +import org.mycore.user2.MCRTransientUser; +import org.mycore.user2.MCRUserManager; +import org.orcid.jaxb.model.v3.release.record.summary.Works; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +public class DozBibORCIDUtils { + + protected static final Logger LOGGER = LogManager.getLogger(DozBibORCIDUtils.class); + + /** + * Get the total number of publications for all orcids connected with UBO. + * + * @return the total number of publications + * */ + public static int getNumWorks() { + MCRORCIDUser orcidUser; + try { + orcidUser = MCRORCIDSessionUtils.getCurrentUser(); + } catch (Exception ex) { + LOGGER.error("Could not get numWorks for user {}", + MCRSessionMgr.getCurrentSession().getUserInformation().getUserID(), ex); + return 0; + } + + Set orcidIdentifiers = orcidUser.getORCIDs(); + + AtomicInteger numWorks = new AtomicInteger(0); + + orcidIdentifiers.forEach(orcid -> { + MCRORCIDCredential credential = orcidUser.getCredentialByORCID(orcid); + if (credential != null) { + try { + MCRORCIDUserClient client = MCRORCIDClientHelper.getClientFactory() + .createUserClient(orcid, credential); + Works works = client.fetch(MCRORCIDSectionImpl.WORKS, Works.class); + numWorks.addAndGet(works.getWorkGroup().size()); + } catch (MCRORCIDRequestException e) { + LOGGER.error(e.getMessage(), e); + } + } + }); + + return numWorks.get(); + } + + /** + * Returns the number of publications for the given orcid. The orcid must be connected with UBO otherwise 0 + * will be returned. + * + * @param orcid the orcid for which the number of publications will be retrieved + * + * @return the number of publications for the given orcid + * */ + public static int getNumWorks(String orcid) { + MCRORCIDUser orcidUser; + try { + orcidUser = MCRORCIDSessionUtils.getCurrentUser(); + } catch (Exception ex) { + LOGGER.error("Could not get numWorks for orcid {} of user {}", orcid, + MCRSessionMgr.getCurrentSession().getUserInformation().getUserID(), ex); + return 0; + } + + MCRORCIDCredential credentialByORCID = orcidUser.getCredentialByORCID(orcid); + + MCRORCIDUserClient client = MCRORCIDClientHelper.getClientFactory().createUserClient(orcid, credentialByORCID); + AtomicInteger numWorks = new AtomicInteger(0); + + try { + Works works = client.fetch(MCRORCIDSectionImpl.WORKS, Works.class); + numWorks.addAndGet(works.getWorkGroup().size()); + } catch (MCRORCIDRequestException e) { + LOGGER.error(e.getMessage(), e); + } + + return numWorks.get(); + } + + public static String getFirstOrcidByCurrentUser() { + MCRORCIDUser orcidUser; + try { + orcidUser = MCRORCIDSessionUtils.getCurrentUser(); + } catch (Exception ex) { + String uid = MCRSessionMgr.getCurrentSession().getUserInformation().getUserID(); + LOGGER.error("Could not get first orcid for user {}", uid, ex); + return ""; + } + return orcidUser.getORCIDs().isEmpty() ? "" : orcidUser.getORCIDs().iterator().next(); + } + + public static boolean weAreTrustedParty() { + if (MCRXMLFunctions.isCurrentUserGuestUser() || DozBibORCIDUtils.isCurrentUserTransient()) { + return false; + } + Map credentials; + try { + MCRORCIDUser orcidUser = MCRORCIDSessionUtils.getCurrentUser(); + credentials = orcidUser.getCredentials(); + } catch (Exception e) { + LOGGER.error("Could not determine if ubo instance is a trusted party", e); + return false; + } + + return !credentials.isEmpty(); + } + + public static boolean isConnected(String orcid) { + return MCRORCIDSessionUtils.getCurrentUser().getCredentialByORCID(orcid) != null; + } + + public static boolean isCurrentUserTransient() { + return MCRUserManager.getCurrentUser() instanceof MCRTransientUser; + } +} diff --git a/ubo-common/src/main/java/org/mycore/ubo/picker/PersonSearchResult.java b/ubo-common/src/main/java/org/mycore/ubo/picker/PersonSearchResult.java index 7b51bc488..4be1cb441 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/picker/PersonSearchResult.java +++ b/ubo-common/src/main/java/org/mycore/ubo/picker/PersonSearchResult.java @@ -19,6 +19,7 @@ package org.mycore.ubo.picker; import java.util.List; +import java.util.stream.Collectors; public class PersonSearchResult { @@ -28,7 +29,7 @@ public class PersonSearchResult { public static class PersonResult { - public PersonResult(IdentityService identityService){ + public PersonResult(IdentityService identityService) { this.service = identityService.getClass().getSimpleName(); } @@ -70,7 +71,8 @@ public PersonResult(IdentityService identityService){ /** * Joins another {@link PersonSearchResult} with the current {@link PersonSearchResult}. The count field is updated - * automatically. + * automatically. If an item in the given {@link PersonSearchResult} is already contained (test is based on + * {@link PersonResult#pid}) it will not be added again. * * @param other the {@link PersonSearchResult} to join. * */ @@ -80,14 +82,20 @@ public void join(PersonSearchResult other) { /** * Joins another {@link PersonSearchResult} with the current {@link PersonSearchResult}. The count field is updated - * automatically. + * automatically. If an item in the given {@link PersonSearchResult} is already contained (test is based on + * {@link PersonResult#pid}) it will not be added again. * * @param other the {@link PersonSearchResult} to join. * @param index index at which to insert the first element from the specified {@link PersonSearchResult} * */ public void join(PersonSearchResult other, int index) { - this.personList.addAll(index, other.personList); - this.count += other.count; + List toAdd = other.personList.stream() + .filter(pr -> pr.pid == null || !this.personList.stream() + .anyMatch(alreadyInList -> alreadyInList.pid == pr.pid)) + .collect(Collectors.toList()); + + this.personList.addAll(index, toAdd); + this.count += toAdd.size(); } } diff --git a/ubo-common/src/main/java/org/mycore/ubo/publication/PublicationEventHandler.java b/ubo-common/src/main/java/org/mycore/ubo/publication/PublicationEventHandler.java index 0c927b4ee..6ebbe90cd 100644 --- a/ubo-common/src/main/java/org/mycore/ubo/publication/PublicationEventHandler.java +++ b/ubo-common/src/main/java/org/mycore/ubo/publication/PublicationEventHandler.java @@ -1,11 +1,5 @@ package org.mycore.ubo.publication; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; - import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -19,6 +13,7 @@ import org.mycore.common.config.MCRConfigurationException; import org.mycore.common.events.MCREvent; import org.mycore.common.events.MCREventHandlerBase; +import org.mycore.datamodel.common.MCRXMLMetadataManager; import org.mycore.datamodel.metadata.MCRObject; import org.mycore.ubo.matcher.MCRUserMatcher; import org.mycore.ubo.matcher.MCRUserMatcherDTO; @@ -29,7 +24,14 @@ import org.mycore.user2.MCRUserAttribute; import org.mycore.user2.MCRUserManager; -import static org.mycore.common.MCRConstants.XPATH_FACTORY; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +import static org.mycore.common.MCRConstants.*; import static org.mycore.ubo.matcher.MCRUserMatcherUtils.MODS_NAMESPACE; /** @@ -129,14 +131,23 @@ private String loadConnectionStrategyConfig() { return MCRConfiguration2.getString(CONFIG_CONNECTION_STRATEGY).get(); } + @Override + protected void handleObjectCreated(MCREvent evt, MCRObject obj) { + handlePublication(obj); + } + @Override protected void handleObjectUpdated(MCREvent evt, MCRObject obj) { - // TODO: remove this, since this EventHandler should only work for "ObjectCreated" events! - handleObjectCreated(evt, obj); + handlePublication(obj); } @Override - protected void handleObjectCreated(MCREvent evt, MCRObject obj) { + protected void handleObjectRepaired(MCREvent evt, MCRObject obj) { + handlePublication(obj); + MCRXMLMetadataManager.instance().update(obj.getId(), obj.createXML(), new Date()); + } + + protected void handlePublication(MCRObject obj) { // get default role for new users String defaultRole = loadDefaultRoleConfig(); @@ -176,21 +187,21 @@ protected void handleObjectCreated(MCREvent evt, MCRObject obj) { if (localMatcherDTO.wasMatchedOrEnriched()) { MCRUser mcrUserFinal = localMatcherDTO.getMCRUser(); mcrUserFinal.assignRole(defaultRole); - MCRUserManager.updateUser(mcrUserFinal); enrichModsNameElementByLeadID(modsNameElement, leadIDName, mcrUserFinal); connectModsNameElementWithMCRUser(modsNameElement, mcrUserFinal); + MCRUserManager.updateUser(mcrUserFinal); } else { if(MCRUserMatcherUtils.checkAffiliation(modsNameElement) && (MCRUserMatcherUtils.getNameIdentifiers(modsNameElement).size() > 0)) { MCRUser affiliatedUser = MCRUserMatcherUtils.createNewMCRUserFromModsNameElement(modsNameElement, UNVALIDATED_REALM); affiliatedUser.assignRole(defaultRole); - MCRUserManager.updateUser(affiliatedUser); enrichModsNameElementByLeadID(modsNameElement, leadIDName, affiliatedUser); connectModsNameElementWithMCRUser(modsNameElement, affiliatedUser); + MCRUserManager.updateUser(affiliatedUser); } else { Optional leadId = modsNameElement.getChildren("nameIdentifier", MCRConstants.MODS_NAMESPACE) .stream() - .filter(element -> element.getAttributeValue("type").equals(leadIDName)) + .filter(element -> leadIDName.equals(element.getAttributeValue("type"))) .findFirst(); if(leadId.isPresent()) { @@ -198,6 +209,7 @@ protected void handleObjectCreated(MCREvent evt, MCRObject obj) { modsNameElement, MCRRealmFactory.getLocalRealm().getID()); newLocalUser.setRealName(getRealNameFromNameElement(modsNameElement, newLocalUser)); connectModsNameElementWithMCRUser(modsNameElement, newLocalUser); + MCRUserManager.updateUser(newLocalUser); } } } @@ -218,24 +230,25 @@ protected void handleObjectCreated(MCREvent evt, MCRObject obj) { /** * Enriches the mods:name-element that corresponds to the given MCRUser with a mods:nameIdentifier-element if the * given MCRUser has an attribute with the name of the so called "lead_id" that is configured in the - * mycore.properties and given as parameter "leadIDmods". + * mycore.properties and given as parameter "leadID". * A new mods:nameIdentifier-element with type "lead_id" and its value will only be created if no other * mods:nameIdentifier-element with the same ID/type exists as a sub-element of the given modsNameElement. * @param modsNameElement the mods:name-element which will be enriched - * @param leadIDmods the "lead_id" (as configured in the mycore.properties) in mods format (no prefix "id_") + * @param leadID the "lead_id" (as configured in the mycore.properties) in mods format (no prefix "id_") * @param mcrUser the MCRUser corresponding to the modsNameElement */ - private void enrichModsNameElementByLeadID(Element modsNameElement, String leadIDmods, MCRUser mcrUser) { - String leadIDmycore = "id_" + leadIDmods; - if(StringUtils.isNotEmpty(mcrUser.getUserAttribute(leadIDmycore))) { - String leadIDValue = mcrUser.getUserAttribute(leadIDmycore); - if(StringUtils.isNotEmpty(leadIDValue)) { - if(!MCRUserMatcherUtils.containsNameIdentifierWithType(modsNameElement, leadIDmods)) { - LOGGER.info("Enriched publication for MCRUser: {}, with nameIdentifier of type: {} (lead_id) " + - "and value: {}", mcrUser.getUserName(), leadIDmods, leadIDValue); - enrichModsNameElementByNameIdentifierElement(modsNameElement, leadIDmods, leadIDValue); - } + private void enrichModsNameElementByLeadID(Element modsNameElement, String leadID, MCRUser mcrUser) { + String attributeName = "id_" + leadID; + Optional leadIDAttribute = mcrUser.getAttributes().stream() + .filter(a -> a.getName().equals(attributeName) && StringUtils.isNotEmpty(a.getValue())).findFirst(); + + if (leadIDAttribute.isPresent()) { + String leadIDValue = leadIDAttribute.get().getValue(); + if (!MCRUserMatcherUtils.containsNameIdentifierWithType(modsNameElement, leadID)) { + LOGGER.info("Enriched publication for MCRUser: {}, with nameIdentifier of type: {} (lead_id) " + + "and value: {}", mcrUser.getUserName(), leadID, leadIDValue); + enrichModsNameElementByNameIdentifierElement(modsNameElement, leadID, leadIDValue); } } } @@ -263,7 +276,6 @@ private void connectModsNameElementWithMCRUser(Element modsNameElement, MCRUser // create new UUID and persist it for mcrUser uuid = UUID.randomUUID().toString(); mcrUser.getAttributes().add(new MCRUserAttribute(CONNECTION_TYPE_NAME, uuid)); - MCRUserManager.updateUser(mcrUser); } // if not already present, persist connection in mods:name - nameIdentifier-Element if(!MCRUserMatcherUtils.containsNameIdentifierWithType(modsNameElement, modsTypeName)) { @@ -282,7 +294,7 @@ protected String getRealNameFromNameElement(Element nameElement, MCRUser mcrUser Filters.element(), null, MODS_NAMESPACE).evaluateFirst(nameElement); if((givenName != null) && (familyName != null)) { - return givenName.getText() + " " + familyName.getText(); + return familyName.getText() + ", " + givenName.getText(); } return mcrUser.getUserID(); diff --git a/ubo-common/src/main/resources/META-INF/resources/edit-admin.xed b/ubo-common/src/main/resources/META-INF/resources/edit-admin.xed index c7d9245ce..f60d2aa89 100644 --- a/ubo-common/src/main/resources/META-INF/resources/edit-admin.xed +++ b/ubo-common/src/main/resources/META-INF/resources/edit-admin.xed @@ -9,29 +9,29 @@ - - - - - - - - - - - - - - - - - -

Sie sind nicht berechtigt, dieses Formular zu verwenden.

-
-
-
- + + + + + + + + + + + + + + + + +

Sie sind nicht berechtigt, dieses Formular zu verwenden.

+
+
+
+ +
@@ -42,7 +42,10 @@ - + + + +
diff --git a/ubo-common/src/main/resources/META-INF/resources/import-editor.xed b/ubo-common/src/main/resources/META-INF/resources/import-editor.xed index 3b543c286..a4e8d8df9 100644 --- a/ubo-common/src/main/resources/META-INF/resources/import-editor.xed +++ b/ubo-common/src/main/resources/META-INF/resources/import-editor.xed @@ -7,7 +7,7 @@ - + @@ -131,13 +131,19 @@
- + + + + + + +