Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4565 builtin table #4993

Merged
merged 14 commits into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions scripts/database/upgrades/upgrade_v4.9.2_to_v4.9.3.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE builtinuser DROP COLUMN affiliation;
ALTER TABLE builtinuser DROP COLUMN email;
ALTER TABLE builtinuser DROP COLUMN firstname;
ALTER TABLE builtinuser DROP COLUMN lastname;
ALTER TABLE builtinuser DROP COLUMN position;
2 changes: 1 addition & 1 deletion src/main/java/edu/harvard/iq/dataverse/LoginPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public String login() {
}
authReq.setIpAddress( dvRequestService.getDataverseRequest().getSourceAddress() );
try {
AuthenticatedUser r = authSvc.getCreateAuthenticatedUser(credentialsAuthProviderId, authReq);
AuthenticatedUser r = authSvc.getUpdateAuthenticatedUser(credentialsAuthProviderId, authReq);
logger.log(Level.FINE, "User authenticated: {0}", r.getEmail());
session.setUser(r);

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/edu/harvard/iq/dataverse/Shib.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ public void init() {
existingBuiltInUserFoundByEmail = shibService.findBuiltInUserByAuthUserIdentifier(existingAuthUserFoundByEmail.getUserIdentifier());
if (existingBuiltInUserFoundByEmail != null) {
state = State.PROMPT_TO_CONVERT_EXISTING_ACCOUNT;
existingDisplayName = existingBuiltInUserFoundByEmail.getDisplayName();

debugSummary = "getting username from the builtin user we looked up via email";
builtinUsername = existingBuiltInUserFoundByEmail.getUserName();
} else {
Expand Down
14 changes: 8 additions & 6 deletions src/main/java/edu/harvard/iq/dataverse/api/Admin.java
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,9 @@ public Response createAuthenicatedUser(JsonObject jsonObject) {
@Path("authenticatedUsers/id/{id}/convertShibToBuiltIn")
@Deprecated
public Response convertShibUserToBuiltin(@PathParam("id") Long id, String newEmailAddress) {
try {
AuthenticatedUser user = findAuthenticatedUserOrDie();
AuthenticatedUser user;
try {
user = findAuthenticatedUserOrDie();
if (!user.isSuperuser()) {
return error(Response.Status.FORBIDDEN, "Superusers only.");
}
Expand All @@ -399,7 +400,7 @@ public Response convertShibUserToBuiltin(@PathParam("id") Long id, String newEma
+ " could not be converted from Shibboleth to BuiltIn. An Exception was not thrown.");
}
JsonObjectBuilder output = Json.createObjectBuilder();
output.add("email", builtinUser.getEmail());
output.add("email", user.getEmail());
output.add("username", builtinUser.getUserName());
return ok(output);
} catch (Throwable ex) {
Expand All @@ -419,8 +420,9 @@ public Response convertShibUserToBuiltin(@PathParam("id") Long id, String newEma
@PUT
@Path("authenticatedUsers/id/{id}/convertRemoteToBuiltIn")
public Response convertOAuthUserToBuiltin(@PathParam("id") Long id, String newEmailAddress) {
try {
AuthenticatedUser user = findAuthenticatedUserOrDie();
AuthenticatedUser user;
try {
user = findAuthenticatedUserOrDie();
if (!user.isSuperuser()) {
return error(Response.Status.FORBIDDEN, "Superusers only.");
}
Expand All @@ -434,7 +436,7 @@ public Response convertOAuthUserToBuiltin(@PathParam("id") Long id, String newEm
+ " could not be converted from remote to BuiltIn. An Exception was not thrown.");
}
JsonObjectBuilder output = Json.createObjectBuilder();
output.add("email", builtinUser.getEmail());
output.add("email", user.getEmail());
output.add("username", builtinUser.getUserName());
return ok(output);
} catch (Throwable ex) {
Expand Down
38 changes: 20 additions & 18 deletions src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
import javax.ws.rs.core.Response.Status;
import java.util.Date;
import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json;
import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json;
import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json;
import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json;

/**
* REST API bean for managing {@link BuiltinUser}s.
Expand All @@ -40,13 +43,6 @@ public class BuiltinUsers extends AbstractApiBean {
private static final Logger logger = Logger.getLogger(BuiltinUsers.class.getName());

private static final String API_KEY_IN_SETTINGS = "BuiltinUsers.KEY";
/**
* Users have not requested the ability to retrieve their API token using
* their email address but we could. Here's the issue for which we are
* enabling login via email address:
* https://github.com/IQSS/dataverse/issues/2115
*/
public static boolean retrievingApiTokenViaEmailEnabled = false;

@EJB
protected BuiltinUserServiceBean builtinUserSvc;
Expand All @@ -63,11 +59,9 @@ public Response getApiToken( @PathParam("username") String username, @QueryParam
return error(Status.FORBIDDEN, "This API endpoint has been disabled.");
}
BuiltinUser u = null;
if (retrievingApiTokenViaEmailEnabled) {
u = builtinUserSvc.findByUsernameOrEmail(username);
} else {
u = builtinUserSvc.findByUserName(username);
}

u = builtinUserSvc.findByUserName(username);

if ( u == null ) return badRequest("Bad username or password");

boolean passwordOk = PasswordEncryption.getVersion(u.getPasswordEncryptionVersion())
Expand All @@ -81,6 +75,19 @@ public Response getApiToken( @PathParam("username") String username, @QueryParam
return (t != null ) ? ok(t.getTokenString()) : notFound("User " + username + " does not have an API token");
}


//These two endpoints take in a BuiltinUser as json. To support these endpoints
//with the removal of attributes from BuiltinUser in 4565, BuiltinUser supports
//the extended attributes as transient (not stored to the database). They are
//immediately used to create an AuthenticatedUser.
//If this proves to be too confusing, we can parse the json more manually
//and use the values to create BuiltinUser/AuthenticatedUser.
//--MAD 4.9.3
@POST
public Response save(BuiltinUser user, @QueryParam("password") String password, @QueryParam("key") String key) {
return internalSave(user, password, key);
}

/**
* Created this new API command because the save method could not be run
* from the RestAssured API. RestAssured doesn't allow a Post request to
Expand All @@ -98,11 +105,6 @@ public Response create(BuiltinUser user, @PathParam("password") String password,
return internalSave(user, password, key);
}

@POST
public Response save(BuiltinUser user, @QueryParam("password") String password, @QueryParam("key") String key) {
return internalSave(user, password, key);
}

private Response internalSave(BuiltinUser user, String password, String key) {
String expectedKey = settingsSvc.get(API_KEY_IN_SETTINGS);

Expand Down Expand Up @@ -131,7 +133,7 @@ private Response internalSave(BuiltinUser user, String password, String key) {
AuthenticatedUser au = authSvc.createAuthenticatedUser(
new UserRecordIdentifier(BuiltinAuthenticationProvider.PROVIDER_ID, user.getUserName()),
user.getUserName(),
user.getDisplayInfo(),
user.getDisplayInfoForApiCreation(),
false);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void startup() {

// First, set up the factories
try {
registerProviderFactory( new BuiltinAuthenticationProviderFactory(builtinUserServiceBean, passwordValidatorService) );
registerProviderFactory( new BuiltinAuthenticationProviderFactory(builtinUserServiceBean, passwordValidatorService, this) );
registerProviderFactory( new ShibAuthenticationProviderFactory() );
registerProviderFactory( new OAuth2AuthenticationProviderFactory() );

Expand Down Expand Up @@ -337,7 +337,7 @@ public AuthenticatedUser getAuthenticatedUserByEmail( String email ) {
* @return The authenticated user for the passed provider id and authentication request.
* @throws AuthenticationFailedException
*/
public AuthenticatedUser getCreateAuthenticatedUser( String authenticationProviderId, AuthenticationRequest req ) throws AuthenticationFailedException {
public AuthenticatedUser getUpdateAuthenticatedUser( String authenticationProviderId, AuthenticationRequest req ) throws AuthenticationFailedException {
AuthenticationProvider prv = getAuthenticationProvider(authenticationProviderId);
if ( prv == null ) throw new IllegalArgumentException("No authentication provider listed under id " + authenticationProviderId );
if ( ! (prv instanceof CredentialsAuthenticationProvider) ) {
Expand All @@ -354,8 +354,9 @@ public AuthenticatedUser getCreateAuthenticatedUser( String authenticationProvid
}

if ( user == null ) {
return createAuthenticatedUser(
new UserRecordIdentifier(authenticationProviderId, resp.getUserId()), resp.getUserId(), resp.getUserDisplayInfo(), true );
throw new IllegalStateException("Authenticated user does not exist. The functionality to support creating one at this point in authentication has been removed.");
//return createAuthenticatedUser(
// new UserRecordIdentifier(authenticationProviderId, resp.getUserId()), resp.getUserId(), resp.getUserDisplayInfo(), true );
} else {
if (BuiltinAuthenticationProvider.PROVIDER_ID.equals(user.getAuthenticatedUserLookup().getAuthenticationProviderId())) {
return user;
Expand Down Expand Up @@ -734,10 +735,6 @@ public BuiltinUser convertRemoteToBuiltIn(Long idOfAuthUserToConvert, String new
}
BuiltinUser builtinUser = new BuiltinUser();
builtinUser.setUserName(authenticatedUser.getUserIdentifier());
builtinUser.setFirstName(authenticatedUser.getFirstName());
builtinUser.setLastName(authenticatedUser.getLastName());
// Bean Validation will check for null and invalid email addresses
builtinUser.setEmail(newEmailAddress);
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<BuiltinUser>> violations = validator.validate(builtinUser);
Expand Down Expand Up @@ -796,7 +793,7 @@ public AuthenticatedUser canLogInAsBuiltinUser(String username, String password)

String credentialsAuthProviderId = BuiltinAuthenticationProvider.PROVIDER_ID;
try {
AuthenticatedUser au = getCreateAuthenticatedUser(credentialsAuthProviderId, authReq);
AuthenticatedUser au = getUpdateAuthenticatedUser(credentialsAuthProviderId, authReq);
logger.fine("User authenticated:" + au.getEmail());
return au;
} catch (AuthenticationFailedException ex) {
Expand All @@ -808,7 +805,7 @@ public AuthenticatedUser canLogInAsBuiltinUser(String username, String password)
* AuthenticationServiceBean.convertBuiltInToShib
*/
logger.info("AuthenticationFailedException caught in canLogInAsBuiltinUser: The username and/or password entered is invalid: " + ex.getResponse().getMessage() + " - Maybe the user (" + username + ") hasn't upgraded their password? Checking the old password...");
BuiltinUser builtinUser = builtinUserServiceBean.findByUsernameOrEmail(username);
BuiltinUser builtinUser = builtinUserServiceBean.findByUserName(username);
if (builtinUser != null) {
boolean userAuthenticated = PasswordEncryption.getVersion(builtinUser.getPasswordEncryptionVersion()).check(password, builtinUser.getEncryptedPassword());
if (userAuthenticated == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import edu.harvard.iq.dataverse.authorization.AuthenticationProviderDisplayInfo;
import edu.harvard.iq.dataverse.authorization.AuthenticationRequest;
import edu.harvard.iq.dataverse.authorization.AuthenticationResponse;
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
import edu.harvard.iq.dataverse.authorization.CredentialsAuthenticationProvider;
import java.util.Arrays;
import java.util.List;
import static edu.harvard.iq.dataverse.authorization.CredentialsAuthenticationProvider.Credential;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.passwordreset.PasswordResetException;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean;
Expand All @@ -26,10 +28,12 @@ public class BuiltinAuthenticationProvider implements CredentialsAuthenticationP
private static List<Credential> CREDENTIALS_LIST;

final BuiltinUserServiceBean bean;
final AuthenticationServiceBean authBean;
private PasswordValidatorServiceBean passwordValidatorService;

public BuiltinAuthenticationProvider( BuiltinUserServiceBean aBean, PasswordValidatorServiceBean passwordValidatorService ) {
public BuiltinAuthenticationProvider( BuiltinUserServiceBean aBean, PasswordValidatorServiceBean passwordValidatorService, AuthenticationServiceBean auBean ) {
this.bean = aBean;
this.authBean = auBean;
this.passwordValidatorService = passwordValidatorService;
KEY_USERNAME_OR_EMAIL = BundleUtil.getStringFromBundle("login.builtin.credential.usernameOrEmail");
KEY_PASSWORD = BundleUtil.getStringFromBundle("login.builtin.credential.password");
Expand Down Expand Up @@ -73,18 +77,6 @@ public void updatePassword(String userIdInProvider, String newPassword) {
PasswordEncryption.getLatestVersionNumber());
bean.save(biUser);
}

@Override
public void updateUserInfo(String userIdInProvider, AuthenticatedUserDisplayInfo updatedUserData) {
BuiltinUser biUser = bean.findByUserName( userIdInProvider );
biUser.setFirstName(updatedUserData.getFirstName());
biUser.setLastName(updatedUserData.getLastName());
biUser.setEmail( updatedUserData.getEmailAddress());
biUser.setAffiliation( updatedUserData.getAffiliation() );
biUser.setPosition(updatedUserData.getPosition());

bean.save(biUser);
}

/**
* Validates that the passed password is indeed the password of the user.
Expand All @@ -103,7 +95,7 @@ public Boolean verifyPassword( String userIdInProvider, String password ) {

@Override
public AuthenticationResponse authenticate( AuthenticationRequest authReq ) {
BuiltinUser u = bean.findByUsernameOrEmail(authReq.getCredential(KEY_USERNAME_OR_EMAIL) );
BuiltinUser u = bean.findByUserName(authReq.getCredential(KEY_USERNAME_OR_EMAIL) );
if ( u == null ) return AuthenticationResponse.makeFail("Bad username, email address, or password");

boolean userAuthenticated = PasswordEncryption.getVersion(u.getPasswordEncryptionVersion())
Expand Down Expand Up @@ -133,7 +125,10 @@ public AuthenticationResponse authenticate( AuthenticationRequest authReq ) {
return AuthenticationResponse.makeError("Error while attempting to upgrade password", ex);
}
}
return AuthenticationResponse.makeSuccess(u.getUserName(), u.getDisplayInfo());

AuthenticatedUser authUser = authBean.getAuthenticatedUser(u.getUserName());

return AuthenticationResponse.makeSuccess(u.getUserName(), authUser.getDisplayInfo());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package edu.harvard.iq.dataverse.authorization.providers.builtin;

import edu.harvard.iq.dataverse.authorization.AuthenticationProvider;
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
import edu.harvard.iq.dataverse.authorization.exceptions.AuthorizationSetupException;
import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderFactory;
import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderRow;
Expand All @@ -16,8 +17,8 @@ public class BuiltinAuthenticationProviderFactory implements AuthenticationProvi

private final BuiltinAuthenticationProvider provider;

public BuiltinAuthenticationProviderFactory(BuiltinUserServiceBean busBean, PasswordValidatorServiceBean passwordValidatorService) {
provider = new BuiltinAuthenticationProvider(busBean, passwordValidatorService);
public BuiltinAuthenticationProviderFactory(BuiltinUserServiceBean busBean, PasswordValidatorServiceBean passwordValidatorService, AuthenticationServiceBean authBean ) {
provider = new BuiltinAuthenticationProvider(busBean, passwordValidatorService, authBean);
}

@Override
Expand Down