From 00d4c0667ec19af9e41099eb15ea68286f816655 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 23 Apr 2019 12:45:04 -0400 Subject: [PATCH 01/12] assert bug: multiple of same username allowed (lower and upper) #3575 --- .../edu/harvard/iq/dataverse/api/UsersIT.java | 22 +++++++++++++++++++ .../edu/harvard/iq/dataverse/api/UtilIT.java | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index 6daaeeec920..395474243c6 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -319,6 +319,28 @@ public void convertNonBcryptUserFromBuiltinToShib() { } + @Test + public void testUsernameCaseSensitivity() { + String randomUsername = UtilIT.getRandomIdentifier(); + String lowercaseUsername = randomUsername.toLowerCase(); + String uppercaseUsername = randomUsername.toUpperCase(); + String randomEmailForLowercaseuser = UtilIT.getRandomIdentifier() + "@mailinator.com"; + String randomEmailForUppercaseuser = UtilIT.getRandomIdentifier() + "@mailinator.com"; + + // Create first user (username all lower case). + Response createLowercaseUser = UtilIT.createUser(lowercaseUsername, randomEmailForLowercaseuser); + createLowercaseUser.prettyPrint(); + createLowercaseUser.then().assertThat() + .statusCode(OK.getStatusCode()); + + // Attempt to create second user (same username but all UPPER CASE). + Response createUppercaseUser = UtilIT.createUser(uppercaseUsername, randomEmailForUppercaseuser); + createUppercaseUser.prettyPrint(); + createUppercaseUser.then().assertThat() + // FIXME: This should not return a 200 (OK) response. It should fail and report that the username has been taken. + .statusCode(OK.getStatusCode()); + } + private Response convertUserFromBcryptToSha1(long idOfBcryptUserToConvert, String password) { JsonObjectBuilder data = Json.createObjectBuilder(); data.add("builtinUserId", idOfBcryptUserToConvert); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 678e88fc036..fcdb5cba5c5 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -103,6 +103,28 @@ public static Response createRandomUser() { return createRandomUser("user"); } + public static Response createUser(String username, String email) { + logger.info("Creating user " + username); + String userAsJson = getUserAsJsonString(username, username, username, email); + String password = getPassword(userAsJson); + Response response = given() + .body(userAsJson) + .contentType(ContentType.JSON) + .post("/api/builtin-users?key=" + BUILTIN_USER_KEY + "&password=" + password); + return response; + } + + private static String getUserAsJsonString(String username, String firstName, String lastName, String email) { + JsonObjectBuilder builder = Json.createObjectBuilder(); + builder.add(USERNAME_KEY, username); + builder.add("firstName", firstName); + builder.add("lastName", lastName); + builder.add(EMAIL_KEY, email); + String userAsJson = builder.build().toString(); + logger.fine("User to create: " + userAsJson); + return userAsJson; + } + private static String getUserAsJsonString(String username, String firstName, String lastName) { JsonObjectBuilder builder = Json.createObjectBuilder(); builder.add(USERNAME_KEY, username); From 682c4faf06154464e76fe1fd8c264584514d5f2e Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 23 Apr 2019 14:14:01 -0400 Subject: [PATCH 02/12] show database error via API/actionlogrecord, not "null" #3575 --- .../java/edu/harvard/iq/dataverse/api/BuiltinUsers.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java b/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java index e85f4454b24..21cb97f83cc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java @@ -176,12 +176,13 @@ private Response internalSave(BuiltinUser user, String password, String key) { } catch ( EJBException ejbx ) { alr.setActionResult(ActionLogRecord.Result.InternalError); - alr.setInfo( alr.getInfo() + "// " + ejbx.getMessage()); + String errorMessage = ejbx.getCausedByException().getLocalizedMessage(); + alr.setInfo( alr.getInfo() + "// " + errorMessage); if ( ejbx.getCausedByException() instanceof IllegalArgumentException ) { - return error(Status.BAD_REQUEST, "Bad request: can't save user. " + ejbx.getCausedByException().getMessage()); + return error(Status.BAD_REQUEST, "Bad request: can't save user. " + errorMessage); } else { logger.log(Level.WARNING, "Error saving user: ", ejbx); - return error(Status.INTERNAL_SERVER_ERROR, "Can't save user: " + ejbx.getMessage()); + return error(Status.INTERNAL_SERVER_ERROR, "Can't save user: " + errorMessage); } } catch (Exception e) { From 60cd16939972f3522df6fc8144a9f0d2caf88c62 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 23 Apr 2019 14:20:57 -0400 Subject: [PATCH 03/12] add database constraint: unique on lowercase username #3575 --- scripts/database/reference_data.sql | 1 + src/main/resources/db/migration/V4.13.0.1__3575-usernames.sql | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/main/resources/db/migration/V4.13.0.1__3575-usernames.sql diff --git a/scripts/database/reference_data.sql b/scripts/database/reference_data.sql index cb12db7c882..41370a22013 100644 --- a/scripts/database/reference_data.sql +++ b/scripts/database/reference_data.sql @@ -30,6 +30,7 @@ INSERT INTO guestbook( -- gets an answer. See also https://github.com/IQSS/dataverse/issues/2598#issuecomment-158219334 CREATE UNIQUE INDEX dataverse_alias_unique_idx on dataverse (LOWER(alias)); CREATE UNIQUE INDEX index_authenticateduser_lower_email ON authenticateduser (lower(email)); +CREATE UNIQUE INDEX index_authenticateduser_lower_useridentifier ON authenticateduser (lower(useridentifier)); -- this field has been removed from builtinuser; CREATE UNIQUE INDEX index_builtinuser_lower_email ON builtinuser (lower(email)); --Edit Dataset: Investigate and correct multiple draft issue: https://github.com/IQSS/dataverse/issues/2132 diff --git a/src/main/resources/db/migration/V4.13.0.1__3575-usernames.sql b/src/main/resources/db/migration/V4.13.0.1__3575-usernames.sql new file mode 100644 index 00000000000..0b1804bdfc4 --- /dev/null +++ b/src/main/resources/db/migration/V4.13.0.1__3575-usernames.sql @@ -0,0 +1 @@ +CREATE UNIQUE INDEX index_authenticateduser_lower_useridentifier ON authenticateduser (lower(useridentifier)); From 0a0dc255fc1311ad227e3127385b5e500d22f010 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 23 Apr 2019 14:27:10 -0400 Subject: [PATCH 04/12] assert duplicate usernames no longer created #3575 --- src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index 395474243c6..1e54109b8e1 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -15,6 +15,7 @@ import javax.json.JsonObjectBuilder; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.CREATED; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; @@ -337,8 +338,8 @@ public void testUsernameCaseSensitivity() { Response createUppercaseUser = UtilIT.createUser(uppercaseUsername, randomEmailForUppercaseuser); createUppercaseUser.prettyPrint(); createUppercaseUser.then().assertThat() - // FIXME: This should not return a 200 (OK) response. It should fail and report that the username has been taken. - .statusCode(OK.getStatusCode()); + // TODO: consider returning "BAD REQUEST" (400) instead of a 500. + .statusCode(INTERNAL_SERVER_ERROR.getStatusCode()); } private Response convertUserFromBcryptToSha1(long idOfBcryptUserToConvert, String password) { From 392d26ea1a727d7af14faa3b00dd63dfd8a1f931 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 25 Apr 2019 11:55:56 -0400 Subject: [PATCH 05/12] make countOfIdentifier case insensitive #3575 --- .../edu/harvard/iq/dataverse/api/BuiltinUsers.java | 6 +++--- .../authorization/users/AuthenticatedUser.java | 2 +- .../java/edu/harvard/iq/dataverse/api/UsersIT.java | 11 ++++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java b/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java index 21cb97f83cc..515184e50b8 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/BuiltinUsers.java @@ -123,9 +123,9 @@ private Response internalSave(BuiltinUser user, String password, String key) { user.updateEncryptedPassword(PasswordEncryption.get().encrypt(password), PasswordEncryption.getLatestVersionNumber()); } - // Make sure the identifier is unique - if ( (builtinUserSvc.findByUserName(user.getUserName()) != null) - || ( authSvc.identifierExists(user.getUserName())) ) { + // Make sure the identifier is unique, case insensitive. "DATAVERSEADMIN" is not allowed to be created if "dataverseAdmin" exists. + if ((builtinUserSvc.findByUserName(user.getUserName()) != null) + || (authSvc.identifierExists(user.getUserName()))) { return error(Status.BAD_REQUEST, "username '" + user.getUserName() + "' already exists"); } user = builtinUserSvc.save(user); diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java index 287cce366b6..edf3013804c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java @@ -49,7 +49,7 @@ @NamedQuery( name="AuthenticatedUser.findByEmail", query="select au from AuthenticatedUser au WHERE LOWER(au.email)=LOWER(:email)"), @NamedQuery( name="AuthenticatedUser.countOfIdentifier", - query="SELECT COUNT(a) FROM AuthenticatedUser a WHERE a.userIdentifier=:identifier"), + query="SELECT COUNT(a) FROM AuthenticatedUser a WHERE LOWER(a.userIdentifier)=LOWER(:identifier)"), @NamedQuery( name="AuthenticatedUser.filter", query="select au from AuthenticatedUser au WHERE (" + "au.userIdentifier like :query OR " diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java index 1e54109b8e1..19ddf61f5bb 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UsersIT.java @@ -15,7 +15,6 @@ import javax.json.JsonObjectBuilder; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.CREATED; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; @@ -338,8 +337,14 @@ public void testUsernameCaseSensitivity() { Response createUppercaseUser = UtilIT.createUser(uppercaseUsername, randomEmailForUppercaseuser); createUppercaseUser.prettyPrint(); createUppercaseUser.then().assertThat() - // TODO: consider returning "BAD REQUEST" (400) instead of a 500. - .statusCode(INTERNAL_SERVER_ERROR.getStatusCode()); + .statusCode(BAD_REQUEST.getStatusCode()) + /** + * Technically, it's the lowercase version that exists but the + * point gets across. There's currently no way to bubble up the + * exact username it's in conflict with, even if we wanted to. + */ + .body("message", equalTo("username '" + uppercaseUsername + "' already exists")); + ; } private Response convertUserFromBcryptToSha1(long idOfBcryptUserToConvert, String password) { From e046f4c7cce83382d73917d03a4b32ef91c85b1c Mon Sep 17 00:00:00 2001 From: Gustavo Durand Date: Mon, 29 Apr 2019 16:17:14 -0400 Subject: [PATCH 06/12] Update ChangeUserIdentifierCommand.java allow changeIdentifier to be called on same user (in order to change case of username) --- .../engine/command/impl/ChangeUserIdentifierCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ChangeUserIdentifierCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ChangeUserIdentifierCommand.java index 122aac00ed6..13868432ec5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ChangeUserIdentifierCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ChangeUserIdentifierCommand.java @@ -49,7 +49,7 @@ public ChangeUserIdentifierCommand(DataverseRequest aRequest, AuthenticatedUser public void executeImpl(CommandContext ctxt) throws CommandException { AuthenticatedUser authenticatedUserTestNewIdentifier = ctxt.authentication().getAuthenticatedUser(newIdentifier); - if (authenticatedUserTestNewIdentifier != null) { + if (authenticatedUserTestNewIdentifier != null && !authenticatedUserTestNewIdentifier.equals(au)) { String logMsg = " User " + newIdentifier + " already exists. Cannot use this as new identifier"; throw new IllegalCommandException("Validation of submitted data failed. Details: " + logMsg, this); } From 70eb08ad687ea49c6f845dee0140bade630b7ef7 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 1 May 2019 10:13:15 -0400 Subject: [PATCH 07/12] #3575 allow user to login with any case of their username --- src/main/java/edu/harvard/iq/dataverse/LoginPage.java | 2 +- .../dataverse/authorization/providers/builtin/BuiltinUser.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/LoginPage.java b/src/main/java/edu/harvard/iq/dataverse/LoginPage.java index d5c57311008..b8f2abadbad 100644 --- a/src/main/java/edu/harvard/iq/dataverse/LoginPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/LoginPage.java @@ -160,7 +160,7 @@ public String login() { logger.info("Credential list is null!"); return null; } - for ( FilledCredential fc : filledCredentialsList ) { + for ( FilledCredential fc : filledCredentialsList ) { authReq.putCredential(fc.getCredential().getKey(), fc.getValue()); } authReq.setIpAddress( dvRequestService.getDataverseRequest().getSourceAddress() ); diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/builtin/BuiltinUser.java b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/builtin/BuiltinUser.java index 142ca23052d..fd7231e827c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/builtin/BuiltinUser.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/builtin/BuiltinUser.java @@ -27,7 +27,7 @@ @NamedQuery( name="BuiltinUser.findAll", query = "SELECT u FROM BuiltinUser u ORDER BY u.userName"), @NamedQuery( name="BuiltinUser.findByUserName", - query = "SELECT u FROM BuiltinUser u WHERE u.userName=:userName"), + query = "SELECT u FROM BuiltinUser u WHERE LOWER(u.userName)=LOWER(:userName)"), @NamedQuery( name="BuiltinUser.listByUserNameLike", query = "SELECT u FROM BuiltinUser u WHERE u.userName LIKE :userNameLike") }) From 5ef2565db12bc48f6b685c3772d915e6334bc5ba Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 1 May 2019 12:19:23 -0400 Subject: [PATCH 08/12] #3575 update additional Auth user query --- .../iq/dataverse/authorization/users/AuthenticatedUser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java index edf3013804c..449ca56e89e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/users/AuthenticatedUser.java @@ -45,14 +45,14 @@ @NamedQuery( name="AuthenticatedUser.findSuperUsers", query="SELECT au FROM AuthenticatedUser au WHERE au.superuser = TRUE"), @NamedQuery( name="AuthenticatedUser.findByIdentifier", - query="select au from AuthenticatedUser au WHERE au.userIdentifier=:identifier"), + query="select au from AuthenticatedUser au WHERE LOWER(au.userIdentifier)=LOWER(:identifier)"), @NamedQuery( name="AuthenticatedUser.findByEmail", query="select au from AuthenticatedUser au WHERE LOWER(au.email)=LOWER(:email)"), @NamedQuery( name="AuthenticatedUser.countOfIdentifier", query="SELECT COUNT(a) FROM AuthenticatedUser a WHERE LOWER(a.userIdentifier)=LOWER(:identifier)"), @NamedQuery( name="AuthenticatedUser.filter", query="select au from AuthenticatedUser au WHERE (" - + "au.userIdentifier like :query OR " + + "LOWER(au.userIdentifier) like LOWER(:query) OR " + "lower(concat(au.firstName,' ',au.lastName)) like lower(:query))"), @NamedQuery( name="AuthenticatedUser.findAdminUser", query="select au from AuthenticatedUser au WHERE " From e3fbaba50093848355720587bcf0775ed98ddb5e Mon Sep 17 00:00:00 2001 From: Derek Murphy Date: Wed, 1 May 2019 14:12:19 -0400 Subject: [PATCH 09/12] Add release notes for #3575 --- doc/release-notes/3575-usernames.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 doc/release-notes/3575-usernames.md diff --git a/doc/release-notes/3575-usernames.md b/doc/release-notes/3575-usernames.md new file mode 100644 index 00000000000..e1ea02d5210 --- /dev/null +++ b/doc/release-notes/3575-usernames.md @@ -0,0 +1,4 @@ +* In an effort to prevent accidental duplicate accounts, user spoofing, or other username-based confusion, this release introduces a database constraint that no longer allows usernames that are exactly the same but use different capitalization, e.g. Bob11 vs. bob11. You may need to do some cleanup before upgrading to deal with existing usernames like this. +* To check whether you have any usernames like this that need cleaning up, run the case insensitive duplicate queries from our Useful Queries doc. +* Once you identify the usernames that need cleaning up, you should use either merge endpoint (if it’s the same person) or rename endpoint (if they are different people). +* After the cleanup you can safely upgrade without issue. From 5b5af3208e7aed181a460b5e2b2bab605215daff Mon Sep 17 00:00:00 2001 From: Derek Murphy Date: Wed, 1 May 2019 14:15:06 -0400 Subject: [PATCH 10/12] Fix link syntax in 3575 release notes --- doc/release-notes/3575-usernames.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/3575-usernames.md b/doc/release-notes/3575-usernames.md index e1ea02d5210..7100c7ba209 100644 --- a/doc/release-notes/3575-usernames.md +++ b/doc/release-notes/3575-usernames.md @@ -1,4 +1,4 @@ * In an effort to prevent accidental duplicate accounts, user spoofing, or other username-based confusion, this release introduces a database constraint that no longer allows usernames that are exactly the same but use different capitalization, e.g. Bob11 vs. bob11. You may need to do some cleanup before upgrading to deal with existing usernames like this. -* To check whether you have any usernames like this that need cleaning up, run the case insensitive duplicate queries from our Useful Queries doc. +* To check whether you have any usernames like this that need cleaning up, run the case insensitive duplicate queries from our[Useful Queries doc](https://docs.google.com/document/d/1-Y_iUduSxdDNeK1yiGUxe7t-Md7Fy965jp4o4m1XEoE/edit?usp=sharing "Useful Queries doc"). * Once you identify the usernames that need cleaning up, you should use either merge endpoint (if it’s the same person) or rename endpoint (if they are different people). * After the cleanup you can safely upgrade without issue. From 5cdd71f614b498529d30e2d0b22c09a286e633e2 Mon Sep 17 00:00:00 2001 From: Derek Murphy Date: Wed, 1 May 2019 14:15:31 -0400 Subject: [PATCH 11/12] Fix link syntax again for 3575 release notes --- doc/release-notes/3575-usernames.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/3575-usernames.md b/doc/release-notes/3575-usernames.md index 7100c7ba209..62734934b20 100644 --- a/doc/release-notes/3575-usernames.md +++ b/doc/release-notes/3575-usernames.md @@ -1,4 +1,4 @@ * In an effort to prevent accidental duplicate accounts, user spoofing, or other username-based confusion, this release introduces a database constraint that no longer allows usernames that are exactly the same but use different capitalization, e.g. Bob11 vs. bob11. You may need to do some cleanup before upgrading to deal with existing usernames like this. -* To check whether you have any usernames like this that need cleaning up, run the case insensitive duplicate queries from our[Useful Queries doc](https://docs.google.com/document/d/1-Y_iUduSxdDNeK1yiGUxe7t-Md7Fy965jp4o4m1XEoE/edit?usp=sharing "Useful Queries doc"). +* To check whether you have any usernames like this that need cleaning up, run the case insensitive duplicate queries from our [Useful Queries doc](https://docs.google.com/document/d/1-Y_iUduSxdDNeK1yiGUxe7t-Md7Fy965jp4o4m1XEoE/edit?usp=sharing "Useful Queries doc"). * Once you identify the usernames that need cleaning up, you should use either merge endpoint (if it’s the same person) or rename endpoint (if they are different people). * After the cleanup you can safely upgrade without issue. From 49486edf874c82d3088477f55297d28f129cc8e0 Mon Sep 17 00:00:00 2001 From: Derek Murphy Date: Wed, 1 May 2019 15:49:02 -0400 Subject: [PATCH 12/12] Update API commands for 3575 release notes Should be all set now. --- doc/release-notes/3575-usernames.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/3575-usernames.md b/doc/release-notes/3575-usernames.md index 62734934b20..896e9910817 100644 --- a/doc/release-notes/3575-usernames.md +++ b/doc/release-notes/3575-usernames.md @@ -1,4 +1,4 @@ * In an effort to prevent accidental duplicate accounts, user spoofing, or other username-based confusion, this release introduces a database constraint that no longer allows usernames that are exactly the same but use different capitalization, e.g. Bob11 vs. bob11. You may need to do some cleanup before upgrading to deal with existing usernames like this. * To check whether you have any usernames like this that need cleaning up, run the case insensitive duplicate queries from our [Useful Queries doc](https://docs.google.com/document/d/1-Y_iUduSxdDNeK1yiGUxe7t-Md7Fy965jp4o4m1XEoE/edit?usp=sharing "Useful Queries doc"). -* Once you identify the usernames that need cleaning up, you should use either merge endpoint (if it’s the same person) or rename endpoint (if they are different people). +* Once you identify the usernames that need cleaning up, you should use either [Merge User Accounts](http://guides.dataverse.org/en/latest/api/native-api.html#merge-user-accounts) (if it’s the same person) or [Change User Identifier](http://guides.dataverse.org/en/latest/api/native-api.html#change-user-identifier) (if they are different people). * After the cleanup you can safely upgrade without issue.