diff options
author | Luca Milanesio <luca.milanesio@gmail.com> | 2021-06-08 23:06:20 +0100 |
---|---|---|
committer | Luca Milanesio <luca.milanesio@gmail.com> | 2021-06-11 09:01:15 +0000 |
commit | 2794dd53c0346bf102b5146c5446e8201e5879a5 (patch) | |
tree | 294a0b178343fff55358e6352d9daaf436e4c1b9 | |
parent | 8c741b0c81d2f8e80d4e874390e87b6d69ede802 (diff) |
LocalUsernamesToLowerCase: manage duplication automatically
When having two external-ids that are different just in their
case, the LocalUsernamesToLowerCase should automatically remove
one of them and only keep the lowercase version.
Example for the same account id:
gerrit:MyUsername
gerrit:MyUSERNAME
The above two external-ids would have caused
a DuplicateExternalIdKeyException which is not helpful as
both identities are the same and associated with the same account id
and have the same associated property values:
- email
- password
Automatically remove one of the two (or more) identities in
conflict and display a warning message explaining what has just
happened and how the situation has been managed transparently.
NOTE: The duplicates that are getting removed are identical
once they are converted to lowercase. The ones that are getting deleted
are not relevant: the only thing that is important is that only one of
them is kept, as all the others are identical.
To test this change:
Positive use-case:
--
Before the LocalUsernamesToLowerCase execution:
[externalId "gerrit:johndoe"]
accountId = 1000000
email = john@doe.org
[externalId "gerrit:JohnDoe"]
accountId = 1000000
email = JOHN@doe.org
After the LocalUsernamesToLowerCase execution, there is a single entry:
[externalId "gerrit:johndoe"]
accountId = 1000000
email = john@doe.org
OR
[externalId "gerrit:johndoe"]
accountId = 1000000
email = JOHN@doe.org
Negative use-cases:
[externalId "gerrit:johndoe"]
accountId = 1000000
[externalId "gerrit:JohnDoe"]
accountId = 1000000
email = JOHN@doe.org
The LocalUsernamesToLowerCase execution fails with a
duplicated ids exception and no changes are made on the
external ids.
[externalId "gerrit:johndoe"]
accountId = 1000000
[externalId "gerrit:JohnDoe"]
accountId = 1000001
The LocalUsernamesToLowerCase execution fails with a
duplicated ids exception and no changes are made on the
external ids.
Bug: Issue 14645
Change-Id: I9832fbf0c8df947aab5494325169b9c726e40019
-rw-r--r-- | Documentation/pgm-LocalUsernamesToLowerCase.txt | 6 | ||||
-rw-r--r-- | java/com/google/gerrit/pgm/BUILD | 1 | ||||
-rw-r--r-- | java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java | 33 |
3 files changed, 39 insertions, 1 deletions
diff --git a/Documentation/pgm-LocalUsernamesToLowerCase.txt b/Documentation/pgm-LocalUsernamesToLowerCase.txt index 53081a18ba..a526647624 100644 --- a/Documentation/pgm-LocalUsernamesToLowerCase.txt +++ b/Documentation/pgm-LocalUsernamesToLowerCase.txt @@ -28,10 +28,14 @@ Web UI. Please be aware that the conversion of the local usernames to lower case can't be undone. -The program will produce errors if there are accounts that have the +The program will produce errors if there are accounts with a different +account-id or other properties (e.g. email, password) that have the same local username, but with different case. In this case the local username for these accounts is not converted to lower case. +The program will automatically remove duplicates where the username +differs only in case but all other attributes are identical. + After all usernames have been migrated, the link:pgm-reindex.html[ reindex] program is automatically invoked to reindex all accounts. diff --git a/java/com/google/gerrit/pgm/BUILD b/java/com/google/gerrit/pgm/BUILD index a57b37a505..2b1b83d643 100644 --- a/java/com/google/gerrit/pgm/BUILD +++ b/java/com/google/gerrit/pgm/BUILD @@ -46,6 +46,7 @@ java_library( "//lib:servlet-api-without-neverlink", "//lib/auto:auto-value", "//lib/auto:auto-value-annotations", + "//lib/commons:lang", "//lib/flogger:api", "//lib/guice", "//lib/guice:guice-assistedinject", diff --git a/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java b/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java index e6e091c360..8e2f70f5f0 100644 --- a/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java +++ b/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java @@ -36,6 +36,9 @@ import com.google.inject.Provider; import java.io.IOException; import java.util.Collection; import java.util.Locale; +import java.util.Optional; +import org.apache.commons.lang.StringUtils; +import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.TextProgressMonitor; @@ -108,8 +111,38 @@ public class LocalUsernamesToLowerCase extends SiteProgram { extId.accountId(), extId.email(), extId.password()); + replaceIfNotExists(extIdNotes, extId, extIdLowerCase); + } + } + } + + private void replaceIfNotExists( + ExternalIdNotes extIdNotes, ExternalId extId, ExternalId extIdLowerCase) throws IOException { + try { + Optional<ExternalId> existingExternalId = + extIdNotes + .get(extIdLowerCase.key()) + .filter(eid -> eid.accountId().equals(extIdLowerCase.accountId())) + .filter(eid -> StringUtils.equalsIgnoreCase(eid.email(), extId.email())) + .filter(eid -> StringUtils.equalsIgnoreCase(eid.password(), extId.password())); + if (existingExternalId.isPresent()) { + System.err.println( + "WARNING: external-id " + + extIdLowerCase + + " already exists with the same account-id " + + extId.accountId() + + " :" + + "removing the duplicate external-id " + + extId.key()); + extIdNotes.delete(extId); + } else { extIdNotes.replace(extId, extIdLowerCase); } + } catch (ConfigInvalidException e) { + throw new IOException( + "Unable to parse external id definition when looking for current external-id " + + extIdLowerCase, + e); } } |