Skip to content

Commit

Permalink
[CST-10704][CST-14902] Adds ORCID login flow with private email
Browse files Browse the repository at this point in the history
  • Loading branch information
vins01-4science committed Sep 13, 2024
1 parent 730e875 commit 12ca1c1
Show file tree
Hide file tree
Showing 47 changed files with 3,473 additions and 245 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.RegistrationData;
import org.dspace.eperson.RegistrationTypeEnum;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.RegistrationDataService;
import org.dspace.orcid.OrcidToken;
import org.dspace.orcid.client.OrcidClient;
import org.dspace.orcid.client.OrcidConfiguration;
Expand All @@ -47,11 +50,15 @@
* ORCID authentication for DSpace.
*
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
*
*/
public class OrcidAuthenticationBean implements AuthenticationMethod {


public static final String ORCID_DEFAULT_FIRSTNAME = "Unnamed";
public static final String ORCID_DEFAULT_LASTNAME = ORCID_DEFAULT_FIRSTNAME;
public static final String ORCID_AUTH_ATTRIBUTE = "orcid-authentication";
public static final String ORCID_REGISTRATION_TOKEN = "orcid-registration-token";
public static final String ORCID_DEFAULT_REGISTRATION_URL = "/external-login/{0}";

private final static Logger LOGGER = LoggerFactory.getLogger(OrcidAuthenticationBean.class);

Expand All @@ -78,6 +85,9 @@ public class OrcidAuthenticationBean implements AuthenticationMethod {
@Autowired
private OrcidTokenService orcidTokenService;

@Autowired
private RegistrationDataService registrationDataService;

@Override
public int authenticate(Context context, String username, String password, String realm, HttpServletRequest request)
throws SQLException {
Expand Down Expand Up @@ -183,7 +193,7 @@ private int authenticateWithOrcid(Context context, String code, HttpServletReque
return ePerson.canLogIn() ? logInEPerson(context, token, ePerson) : BAD_ARGS;
}

return canSelfRegister() ? registerNewEPerson(context, person, token) : NO_SUCH_USER;
return canSelfRegister() ? createRegistrationData(context, request, person, token) : NO_SUCH_USER;

}

Expand Down Expand Up @@ -211,48 +221,59 @@ private ResearcherProfile findProfile(Context context, EPerson ePerson) throws S
}
}

private int registerNewEPerson(Context context, Person person, OrcidTokenResponseDTO token) throws SQLException {
private int createRegistrationData(
Context context, HttpServletRequest request, Person person, OrcidTokenResponseDTO token
) throws SQLException {

try {
context.turnOffAuthorisationSystem();

String email = getEmail(person)
.orElseThrow(() -> new IllegalStateException("The email is configured private on orcid"));

String orcid = token.getOrcid();

EPerson eperson = ePersonService.create(context);
RegistrationData registrationData =
this.registrationDataService.create(context, token.getOrcid(), RegistrationTypeEnum.ORCID);

eperson.setNetid(orcid);
registrationData.setEmail(getEmail(person).orElse(null));
setOrcidMetadataOnRegistration(context, registrationData, person, token);

eperson.setEmail(email);
registrationDataService.update(context, registrationData);

Optional<String> firstName = getFirstName(person);
if (firstName.isPresent()) {
eperson.setFirstName(context, firstName.get());
}

Optional<String> lastName = getLastName(person);
if (lastName.isPresent()) {
eperson.setLastName(context, lastName.get());
}
eperson.setCanLogIn(true);
eperson.setSelfRegistered(true);

setOrcidMetadataOnEPerson(context, eperson, token);

ePersonService.update(context, eperson);
context.setCurrentUser(eperson);
request.setAttribute(ORCID_REGISTRATION_TOKEN, registrationData.getToken());
context.commit();
context.dispatchEvents();

return SUCCESS;

} catch (Exception ex) {
LOGGER.error("An error occurs registering a new EPerson from ORCID", ex);
context.rollback();
return NO_SUCH_USER;
} finally {
context.restoreAuthSystemState();
return NO_SUCH_USER;
}
}

private void setOrcidMetadataOnRegistration(
Context context, RegistrationData registration, Person person, OrcidTokenResponseDTO token
) throws SQLException, AuthorizeException {
String orcid = token.getOrcid();

setRegistrationMetadata(context, registration, "eperson.firstname", getFirstName(person));
setRegistrationMetadata(context, registration, "eperson.lastname", getLastName(person));
registrationDataService.setRegistrationMetadataValue(context, registration, "eperson", "orcid", null, orcid);

for (String scope : token.getScopeAsArray()) {
registrationDataService.addMetadata(context, registration, "eperson", "orcid", "scope", scope);
}
}

private void setRegistrationMetadata(
Context context, RegistrationData registration, String metadataString, String value) {
String[] split = metadataString.split("\\.");
String qualifier = split.length > 2 ? split[2] : null;
try {
registrationDataService.setRegistrationMetadataValue(
context, registration, split[0], split[1], qualifier, value
);
} catch (SQLException | AuthorizeException ex) {
LOGGER.error("An error occurs setting metadata", ex);
throw new RuntimeException(ex);
}
}

Expand Down Expand Up @@ -295,16 +316,20 @@ private Optional<String> getEmail(Person person) {
return Optional.ofNullable(emails.get(0).getEmail());
}

private Optional<String> getFirstName(Person person) {
private String getFirstName(Person person) {
return Optional.ofNullable(person.getName())
.map(name -> name.getGivenNames())
.map(givenNames -> givenNames.getContent());
.map(name -> name.getGivenNames())
.map(givenNames -> givenNames.getContent())
.filter(StringUtils::isNotBlank)
.orElse(ORCID_DEFAULT_FIRSTNAME);
}

private Optional<String> getLastName(Person person) {
private String getLastName(Person person) {
return Optional.ofNullable(person.getName())
.map(name -> name.getFamilyName())
.map(givenNames -> givenNames.getContent());
.map(name -> name.getFamilyName())
.map(givenNames -> givenNames.getContent())
.filter(StringUtils::isNotBlank)
.orElse(ORCID_DEFAULT_LASTNAME);
}

private boolean canSelfRegister() {
Expand Down
Loading

0 comments on commit 12ca1c1

Please sign in to comment.