Shift around username/password editing
The username is now made more visible on the register screen, encouraging the user to create a new username before they set an SSH public key on their account. Username and password were removed from most tabs and put into their own HTTP Password tab, just below the SSH Public Keys. We also now have a clear password button, to permit erasing a password that was assigned and isn't actually needed by the user. The username can only be set once per account now, and once set is not permitted to be changed. This change simplifies our UI, but it also sets the stage for supporting ${user} variables in access rules for references, and renaming an account once it has branches owned by it would complicate the account rename process. Change-Id: I2c0f26bb4501b88faa451105dd3d74e3830e632c Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
parent
270c5941d4
commit
c25b07b89c
@ -26,6 +26,7 @@ public class PageLinks {
|
||||
public static final String SETTINGS = "settings";
|
||||
public static final String SETTINGS_PREFERENCES = "settings,preferences";
|
||||
public static final String SETTINGS_SSHKEYS = "settings,ssh-keys";
|
||||
public static final String SETTINGS_HTTP_PASSWORD = "settings,http-password";
|
||||
public static final String SETTINGS_WEBIDENT = "settings,web-identities";
|
||||
public static final String SETTINGS_MYGROUPS = "settings,group-memberships";
|
||||
public static final String SETTINGS_AGREEMENTS = "settings,agreements";
|
||||
|
@ -49,6 +49,10 @@ public interface AccountSecurity extends RemoteJsonService {
|
||||
void generatePassword(AccountExternalId.Key key,
|
||||
AsyncCallback<AccountExternalId> callback);
|
||||
|
||||
@SignInRequired
|
||||
void clearPassword(AccountExternalId.Key key,
|
||||
AsyncCallback<AccountExternalId> gerritCallback);
|
||||
|
||||
@SignInRequired
|
||||
void myExternalIds(AsyncCallback<List<AccountExternalId>> callback);
|
||||
|
||||
|
@ -23,6 +23,7 @@ import static com.google.gerrit.common.PageLinks.REGISTER;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_AGREEMENTS;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_CONTACT;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_HTTP_PASSWORD;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_MYGROUPS;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_NEW_AGREEMENT;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES;
|
||||
@ -35,6 +36,7 @@ import com.google.gerrit.client.account.MyAgreementsScreen;
|
||||
import com.google.gerrit.client.account.MyContactInformationScreen;
|
||||
import com.google.gerrit.client.account.MyGroupsScreen;
|
||||
import com.google.gerrit.client.account.MyIdentitiesScreen;
|
||||
import com.google.gerrit.client.account.MyPasswordScreen;
|
||||
import com.google.gerrit.client.account.MyPreferencesScreen;
|
||||
import com.google.gerrit.client.account.MyProfileScreen;
|
||||
import com.google.gerrit.client.account.MySshKeysScreen;
|
||||
@ -331,6 +333,10 @@ public class Dispatcher {
|
||||
return new MyIdentitiesScreen();
|
||||
}
|
||||
|
||||
if (token.equals(SETTINGS_HTTP_PASSWORD)) {
|
||||
return new MyPasswordScreen();
|
||||
}
|
||||
|
||||
if (token.equals(SETTINGS_MYGROUPS)) {
|
||||
return new MyGroupsScreen();
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ public interface GerritCss extends CssResource {
|
||||
String accountDashboard();
|
||||
String accountInfoBlock();
|
||||
String accountName();
|
||||
String accountUsername();
|
||||
String accountPassword();
|
||||
String activeRow();
|
||||
String addReviewer();
|
||||
String removeReviewer();
|
||||
@ -169,8 +171,6 @@ public interface GerritCss extends CssResource {
|
||||
String sshHostKeyPanelKnownHostEntry();
|
||||
String sshKeyPanelEncodedKey();
|
||||
String sshKeyPanelInvalid();
|
||||
String sshPanelUsername();
|
||||
String sshPanelPassword();
|
||||
String topmenu();
|
||||
String topmenuMenuLeft();
|
||||
String topmenuMenuRight();
|
||||
@ -178,5 +178,6 @@ public interface GerritCss extends CssResource {
|
||||
String topmenuTDmenu();
|
||||
String topmost();
|
||||
String useridentity();
|
||||
String usernameField();
|
||||
String version();
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public interface AccountConstants extends Constants {
|
||||
String tabWatchedProjects();
|
||||
String tabContactInformation();
|
||||
String tabSshKeys();
|
||||
String tabHttpAccess();
|
||||
String tabWebIdentities();
|
||||
String tabMyGroups();
|
||||
String tabAgreements();
|
||||
@ -49,7 +50,9 @@ public interface AccountConstants extends Constants {
|
||||
|
||||
String userName();
|
||||
String password();
|
||||
String buttonSetUserName();
|
||||
String buttonChangeUserName();
|
||||
String buttonClearPassword();
|
||||
String buttonGeneratePassword();
|
||||
String invalidUserName();
|
||||
|
||||
@ -117,6 +120,7 @@ public interface AccountConstants extends Constants {
|
||||
String welcomeToGerritCodeReview();
|
||||
String welcomeReviewContact();
|
||||
String welcomeContactFrom();
|
||||
String welcomeUsernameHeading();
|
||||
String welcomeSshKeyHeading();
|
||||
String welcomeSshKeyText();
|
||||
String welcomeAgreementHeading();
|
||||
|
@ -17,6 +17,7 @@ tabPreferences = Preferences
|
||||
tabWatchedProjects = Watched Projects
|
||||
tabContactInformation = Contact Information
|
||||
tabSshKeys = SSH Public Keys
|
||||
tabHttpAccess = HTTP Password
|
||||
tabWebIdentities = Identities
|
||||
tabMyGroups = Groups
|
||||
tabAgreements = Agreements
|
||||
@ -30,8 +31,10 @@ buttonAddSshKey = Add
|
||||
|
||||
userName = Username
|
||||
password = Password
|
||||
buttonSetUserName = Select Username
|
||||
buttonChangeUserName = Change Username
|
||||
buttonGeneratePassword = Regenerate
|
||||
buttonClearPassword = Clear Password
|
||||
buttonGeneratePassword = Generate Password
|
||||
invalidUserName = Username must contain only letters, numbers, _, - or .
|
||||
|
||||
sshKeyInvalid = Invalid Key
|
||||
@ -113,6 +116,8 @@ welcomeContactFrom = \
|
||||
you are to others, and to send updates to code reviews you have either \
|
||||
started or subscribed to.</p>
|
||||
|
||||
welcomeUsernameHeading = Select a unique username:
|
||||
|
||||
welcomeSshKeyHeading = Register an SSH public key:
|
||||
welcomeSshKeyText = \
|
||||
<p>Gerrit Code Review uses \
|
||||
|
@ -20,6 +20,7 @@ import com.google.gerrit.client.ui.TextSaveButtonListener;
|
||||
import com.google.gerrit.reviewdb.Account;
|
||||
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||
import com.google.gerrit.reviewdb.ContactInformation;
|
||||
import com.google.gerrit.reviewdb.Account.FieldName;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
@ -98,12 +99,18 @@ class ContactPanelShort extends Composite {
|
||||
emailLine.add(registerNewEmail);
|
||||
}
|
||||
|
||||
row(infoPlainText, 0, Util.C.contactFieldFullName(), nameTxt);
|
||||
row(infoPlainText, 1, Util.C.contactFieldEmail(), emailLine);
|
||||
int row = 0;
|
||||
if (!Gerrit.getConfig().canEdit(FieldName.USER_NAME)) {
|
||||
infoPlainText.resizeRows(infoPlainText.getRowCount() + 1);
|
||||
row(infoPlainText, row++, Util.C.userName(), new UsernameField());
|
||||
}
|
||||
|
||||
row(infoPlainText, row++, Util.C.contactFieldFullName(), nameTxt);
|
||||
row(infoPlainText, row++, Util.C.contactFieldEmail(), emailLine);
|
||||
|
||||
infoPlainText.getCellFormatter().addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
|
||||
infoPlainText.getCellFormatter().addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
|
||||
infoPlainText.getCellFormatter().addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
|
||||
infoPlainText.getCellFormatter().addStyleName(row - 1, 0, Gerrit.RESOURCES.css().bottomheader());
|
||||
|
||||
save = new Button(Util.C.buttonSaveChanges());
|
||||
save.setEnabled(false);
|
||||
|
@ -46,8 +46,6 @@ public class MyIdentitiesScreen extends SettingsScreen {
|
||||
protected void onInitUI() {
|
||||
super.onInitUI();
|
||||
|
||||
add(new UsernamePanel());
|
||||
|
||||
identites = new IdTable();
|
||||
add(identites);
|
||||
|
||||
|
@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2008 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.client.account;
|
||||
|
||||
import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
||||
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MyPasswordScreen extends SettingsScreen {
|
||||
private CopyableLabel password;
|
||||
private Button generatePassword;
|
||||
private Button clearPassword;
|
||||
private AccountExternalId id;
|
||||
|
||||
@Override
|
||||
protected void onInitUI() {
|
||||
super.onInitUI();
|
||||
|
||||
password = new CopyableLabel("");
|
||||
password.addStyleName(Gerrit.RESOURCES.css().accountPassword());
|
||||
|
||||
generatePassword = new Button(Util.C.buttonGeneratePassword());
|
||||
generatePassword.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
doGeneratePassword();
|
||||
}
|
||||
});
|
||||
|
||||
clearPassword = new Button(Util.C.buttonClearPassword());
|
||||
clearPassword.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
doClearPassword();
|
||||
}
|
||||
});
|
||||
|
||||
final Grid userInfo = new Grid(2, 2);
|
||||
final CellFormatter fmt = userInfo.getCellFormatter();
|
||||
userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock());
|
||||
userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
|
||||
add(userInfo);
|
||||
|
||||
row(userInfo, 0, Util.C.userName(), new UsernameField());
|
||||
row(userInfo, 1, Util.C.password(), password);
|
||||
|
||||
fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
|
||||
|
||||
final FlowPanel buttons = new FlowPanel();
|
||||
buttons.add(generatePassword);
|
||||
buttons.add(clearPassword);
|
||||
add(buttons);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad() {
|
||||
super.onLoad();
|
||||
|
||||
enableUI(false);
|
||||
Util.ACCOUNT_SEC
|
||||
.myExternalIds(new ScreenLoadCallback<List<AccountExternalId>>(this) {
|
||||
public void preDisplay(final List<AccountExternalId> result) {
|
||||
AccountExternalId id = null;
|
||||
for (AccountExternalId i : result) {
|
||||
if (i.isScheme(SCHEME_USERNAME)) {
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display(AccountExternalId id) {
|
||||
String user, pass;
|
||||
if (id != null) {
|
||||
user = id.getSchemeRest();
|
||||
pass = id.getPassword();
|
||||
} else {
|
||||
user = null;
|
||||
pass = null;
|
||||
}
|
||||
this.id = id;
|
||||
|
||||
Gerrit.getUserAccount().setUserName(user);
|
||||
|
||||
password.setText(pass != null ? pass : "");
|
||||
password.setVisible(pass != null);
|
||||
|
||||
enableUI(true);
|
||||
}
|
||||
|
||||
private void row(final Grid info, final int row, final String name,
|
||||
final Widget field) {
|
||||
final CellFormatter fmt = info.getCellFormatter();
|
||||
if (LocaleInfo.getCurrentLocale().isRTL()) {
|
||||
info.setText(row, 1, name);
|
||||
info.setWidget(row, 0, field);
|
||||
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().header());
|
||||
} else {
|
||||
info.setText(row, 0, name);
|
||||
info.setWidget(row, 1, field);
|
||||
fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header());
|
||||
}
|
||||
}
|
||||
|
||||
private void doGeneratePassword() {
|
||||
if (id != null) {
|
||||
enableUI(false);
|
||||
Util.ACCOUNT_SEC.generatePassword(id.getKey(),
|
||||
new GerritCallback<AccountExternalId>() {
|
||||
public void onSuccess(final AccountExternalId result) {
|
||||
display(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
enableUI(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void doClearPassword() {
|
||||
if (id != null) {
|
||||
enableUI(false);
|
||||
Util.ACCOUNT_SEC.clearPassword(id.getKey(),
|
||||
new GerritCallback<AccountExternalId>() {
|
||||
public void onSuccess(final AccountExternalId result) {
|
||||
display(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
enableUI(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void enableUI(boolean on) {
|
||||
on &= id != null;
|
||||
|
||||
generatePassword.setEnabled(on);
|
||||
clearPassword.setVisible(on && id.getPassword() != null);
|
||||
}
|
||||
}
|
@ -69,7 +69,7 @@ public class MyProfileScreen extends SettingsScreen {
|
||||
}
|
||||
|
||||
void display(final Account account) {
|
||||
info.setText(0, fieldIdx, account.getUserName());
|
||||
info.setWidget(0, fieldIdx, new UsernameField());
|
||||
info.setText(1, fieldIdx, account.getFullName());
|
||||
info.setText(2, fieldIdx, account.getPreferredEmail());
|
||||
info.setText(3, fieldIdx, mediumFormat(account.getRegisteredOn()));
|
||||
|
@ -20,9 +20,13 @@ import com.google.gerrit.client.ui.InlineHyperlink;
|
||||
import com.google.gerrit.client.ui.SmallHeading;
|
||||
import com.google.gerrit.common.PageLinks;
|
||||
import com.google.gerrit.reviewdb.Account;
|
||||
import com.google.gerrit.reviewdb.Account.FieldName;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.FormPanel;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HTML;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
|
||||
public class RegisterScreen extends AccountScreen {
|
||||
private final String nextToken;
|
||||
@ -65,6 +69,36 @@ public class RegisterScreen extends AccountScreen {
|
||||
});
|
||||
formBody.add(contactGroup);
|
||||
|
||||
if (Gerrit.getUserAccount().getUserName() == null
|
||||
&& Gerrit.getConfig().canEdit(FieldName.USER_NAME)) {
|
||||
final FlowPanel fp = new FlowPanel();
|
||||
fp.setStyleName(Gerrit.RESOURCES.css().registerScreenSection());
|
||||
fp.add(new SmallHeading(Util.C.welcomeUsernameHeading()));
|
||||
|
||||
final Grid userInfo = new Grid(1, 2);
|
||||
final CellFormatter fmt = userInfo.getCellFormatter();
|
||||
userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock());
|
||||
userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
|
||||
fp.add(userInfo);
|
||||
|
||||
fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().bottomheader());
|
||||
|
||||
UsernameField field = new UsernameField();
|
||||
if (LocaleInfo.getCurrentLocale().isRTL()) {
|
||||
userInfo.setText(0, 1, Util.C.userName());
|
||||
userInfo.setWidget(0, 0, field);
|
||||
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().header());
|
||||
} else {
|
||||
userInfo.setText(0, 0, Util.C.userName());
|
||||
userInfo.setWidget(0, 1, field);
|
||||
fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().header());
|
||||
}
|
||||
|
||||
formBody.add(fp);
|
||||
}
|
||||
|
||||
final FlowPanel sshKeyGroup = new FlowPanel();
|
||||
sshKeyGroup.setStyleName(Gerrit.RESOURCES.css().registerScreenSection());
|
||||
sshKeyGroup.add(new SmallHeading(Util.C.welcomeSshKeyHeading()));
|
||||
|
@ -27,6 +27,7 @@ public abstract class SettingsScreen extends MenuScreen {
|
||||
link(Util.C.tabWatchedProjects(), PageLinks.SETTINGS_PROJECTS);
|
||||
link(Util.C.tabContactInformation(), PageLinks.SETTINGS_CONTACT);
|
||||
link(Util.C.tabSshKeys(), PageLinks.SETTINGS_SSHKEYS);
|
||||
link(Util.C.tabHttpAccess(), PageLinks.SETTINGS_HTTP_PASSWORD);
|
||||
link(Util.C.tabWebIdentities(), PageLinks.SETTINGS_WEBIDENT);
|
||||
link(Util.C.tabMyGroups(), PageLinks.SETTINGS_MYGROUPS);
|
||||
if (Gerrit.getConfig().isUseContributorAgreements()) {
|
||||
|
@ -0,0 +1,183 @@
|
||||
// Copyright (C) 2008 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.client.account;
|
||||
|
||||
import com.google.gerrit.client.ErrorDialog;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.TextSaveButtonListener;
|
||||
import com.google.gerrit.common.errors.InvalidUserNameException;
|
||||
import com.google.gerrit.reviewdb.Account;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwt.event.dom.client.KeyPressHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||
import com.google.gwtexpui.globalkey.client.NpTextBox;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
|
||||
class UsernameField extends Composite {
|
||||
private CopyableLabel userNameLbl;
|
||||
private NpTextBox userNameTxt;
|
||||
private Button setUserName;
|
||||
|
||||
UsernameField() {
|
||||
String user = Gerrit.getUserAccount().getUserName();
|
||||
userNameLbl = new CopyableLabel(user != null ? user : "");
|
||||
userNameLbl.setStyleName(Gerrit.RESOURCES.css().accountUsername());
|
||||
|
||||
if (user != null || !canEditUserName()) {
|
||||
initWidget(userNameLbl);
|
||||
|
||||
} else {
|
||||
final FlowPanel body = new FlowPanel();
|
||||
initWidget(body);
|
||||
setStyleName(Gerrit.RESOURCES.css().usernameField());
|
||||
|
||||
userNameTxt = new NpTextBox();
|
||||
userNameTxt.addKeyPressHandler(new UserNameValidator());
|
||||
userNameTxt.addStyleName(Gerrit.RESOURCES.css().accountUsername());
|
||||
userNameTxt.setVisibleLength(16);
|
||||
userNameTxt.addKeyPressHandler(new KeyPressHandler() {
|
||||
@Override
|
||||
public void onKeyPress(KeyPressEvent event) {
|
||||
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
|
||||
doSetUserName();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setUserName = new Button(Util.C.buttonSetUserName());
|
||||
setUserName.setVisible(canEditUserName());
|
||||
setUserName.setEnabled(false);
|
||||
setUserName.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
doSetUserName();
|
||||
}
|
||||
});
|
||||
new TextSaveButtonListener(userNameTxt, setUserName);
|
||||
|
||||
userNameLbl.setVisible(false);
|
||||
body.add(userNameLbl);
|
||||
body.add(userNameTxt);
|
||||
body.add(setUserName);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canEditUserName() {
|
||||
return Gerrit.getConfig().canEdit(Account.FieldName.USER_NAME);
|
||||
}
|
||||
|
||||
private void doSetUserName() {
|
||||
if (!canEditUserName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String newName = userNameTxt.getText();
|
||||
if ("".equals(newName)) {
|
||||
newName = null;
|
||||
}
|
||||
if (newName != null && !newName.matches(Account.USER_NAME_PATTERN)) {
|
||||
invalidUserName();
|
||||
return;
|
||||
}
|
||||
|
||||
enableUI(false);
|
||||
|
||||
final String newUserName = newName;
|
||||
Util.ACCOUNT_SEC.changeUserName(newUserName,
|
||||
new GerritCallback<VoidResult>() {
|
||||
public void onSuccess(final VoidResult result) {
|
||||
Gerrit.getUserAccount().setUserName(newUserName);
|
||||
userNameLbl.setText(newUserName);
|
||||
userNameLbl.setVisible(true);
|
||||
userNameTxt.setVisible(false);
|
||||
setUserName.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
enableUI(true);
|
||||
if (InvalidUserNameException.MESSAGE.equals(caught.getMessage())) {
|
||||
invalidUserName();
|
||||
} else {
|
||||
super.onFailure(caught);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void invalidUserName() {
|
||||
new ErrorDialog(Util.C.invalidUserName()).center();
|
||||
}
|
||||
|
||||
private void enableUI(final boolean on) {
|
||||
userNameTxt.setEnabled(on);
|
||||
setUserName.setEnabled(on);
|
||||
}
|
||||
|
||||
private final class UserNameValidator implements KeyPressHandler {
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
final char code = event.getCharCode();
|
||||
switch (code) {
|
||||
case KeyCodes.KEY_ALT:
|
||||
case KeyCodes.KEY_BACKSPACE:
|
||||
case KeyCodes.KEY_CTRL:
|
||||
case KeyCodes.KEY_DELETE:
|
||||
case KeyCodes.KEY_DOWN:
|
||||
case KeyCodes.KEY_END:
|
||||
case KeyCodes.KEY_ENTER:
|
||||
case KeyCodes.KEY_ESCAPE:
|
||||
case KeyCodes.KEY_HOME:
|
||||
case KeyCodes.KEY_LEFT:
|
||||
case KeyCodes.KEY_PAGEDOWN:
|
||||
case KeyCodes.KEY_PAGEUP:
|
||||
case KeyCodes.KEY_RIGHT:
|
||||
case KeyCodes.KEY_SHIFT:
|
||||
case KeyCodes.KEY_TAB:
|
||||
case KeyCodes.KEY_UP:
|
||||
// Allow these, even if one of their assigned codes is
|
||||
// identical to an ASCII character we do not want to
|
||||
// allow in the box.
|
||||
//
|
||||
// We still want to let the user move around the input box
|
||||
// with their arrow keys, or to move between fields using tab.
|
||||
// Invalid characters introduced will be caught through the
|
||||
// server's own validation of the input data.
|
||||
//
|
||||
break;
|
||||
|
||||
default:
|
||||
final TextBox box = (TextBox) event.getSource();
|
||||
final String re;
|
||||
if (box.getCursorPos() == 0)
|
||||
re = Account.USER_NAME_PATTERN_FIRST;
|
||||
else
|
||||
re = Account.USER_NAME_PATTERN_REST;
|
||||
if (!String.valueOf(code).matches("^" + re + "$")) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
// Copyright (C) 2008 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.client.account;
|
||||
|
||||
import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
|
||||
|
||||
import com.google.gerrit.client.ErrorDialog;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.TextSaveButtonListener;
|
||||
import com.google.gerrit.common.errors.InvalidUserNameException;
|
||||
import com.google.gerrit.reviewdb.Account;
|
||||
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwt.event.dom.client.KeyPressHandler;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||
import com.google.gwtexpui.globalkey.client.NpTextBox;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UsernamePanel extends Composite {
|
||||
private NpTextBox userNameTxt;
|
||||
private Button changeUserName;
|
||||
|
||||
private CopyableLabel password;
|
||||
private Button generatePassword;
|
||||
|
||||
private AccountExternalId.Key idKey;
|
||||
|
||||
UsernamePanel() {
|
||||
final FlowPanel body = new FlowPanel();
|
||||
initWidget(body);
|
||||
|
||||
userNameTxt = new NpTextBox();
|
||||
userNameTxt.addKeyPressHandler(new UserNameValidator());
|
||||
userNameTxt.addStyleName(Gerrit.RESOURCES.css().sshPanelUsername());
|
||||
userNameTxt.setVisibleLength(16);
|
||||
userNameTxt.setReadOnly(!canEditUserName());
|
||||
userNameTxt.addKeyPressHandler(new KeyPressHandler() {
|
||||
@Override
|
||||
public void onKeyPress(KeyPressEvent event) {
|
||||
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
|
||||
doChangeUserName();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
changeUserName = new Button(Util.C.buttonChangeUserName());
|
||||
changeUserName.setVisible(canEditUserName());
|
||||
changeUserName.setEnabled(false);
|
||||
changeUserName.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
doChangeUserName();
|
||||
}
|
||||
});
|
||||
new TextSaveButtonListener(userNameTxt, changeUserName);
|
||||
|
||||
password = new CopyableLabel("");
|
||||
password.addStyleName(Gerrit.RESOURCES.css().sshPanelPassword());
|
||||
password.setVisible(false);
|
||||
|
||||
generatePassword = new Button(Util.C.buttonGeneratePassword());
|
||||
generatePassword.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
doGeneratePassword();
|
||||
}
|
||||
});
|
||||
|
||||
final Grid userInfo = new Grid(2, 3);
|
||||
final CellFormatter fmt = userInfo.getCellFormatter();
|
||||
userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock());
|
||||
userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
|
||||
body.add(userInfo);
|
||||
|
||||
row(userInfo, 0, Util.C.userName(), userNameTxt, changeUserName);
|
||||
row(userInfo, 1, Util.C.password(), password, generatePassword);
|
||||
|
||||
fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().topmost());
|
||||
|
||||
fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad() {
|
||||
super.onLoad();
|
||||
|
||||
enableUI(false);
|
||||
Util.ACCOUNT_SEC
|
||||
.myExternalIds(new GerritCallback<List<AccountExternalId>>() {
|
||||
public void onSuccess(final List<AccountExternalId> result) {
|
||||
AccountExternalId id = null;
|
||||
for (AccountExternalId i : result) {
|
||||
if (i.isScheme(SCHEME_USERNAME)) {
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
display(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display(AccountExternalId id) {
|
||||
String user, pass;
|
||||
if (id != null) {
|
||||
idKey = id.getKey();
|
||||
user = id.getSchemeRest();
|
||||
pass = id.getPassword();
|
||||
} else {
|
||||
idKey = null;
|
||||
user = null;
|
||||
pass = null;
|
||||
}
|
||||
|
||||
Gerrit.getUserAccount().setUserName(user);
|
||||
userNameTxt.setText(user);
|
||||
userNameTxt.setEnabled(true);
|
||||
generatePassword.setEnabled(idKey != null);
|
||||
|
||||
if (pass != null) {
|
||||
password.setText(pass);
|
||||
password.setVisible(true);
|
||||
} else {
|
||||
password.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void row(final Grid info, final int row, final String name,
|
||||
final Widget field1, final Widget field2) {
|
||||
final CellFormatter fmt = info.getCellFormatter();
|
||||
if (LocaleInfo.getCurrentLocale().isRTL()) {
|
||||
info.setText(row, 2, name);
|
||||
info.setWidget(row, 1, field1);
|
||||
info.setWidget(row, 0, field2);
|
||||
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder());
|
||||
fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().header());
|
||||
} else {
|
||||
info.setText(row, 0, name);
|
||||
info.setWidget(row, 1, field1);
|
||||
info.setWidget(row, 2, field2);
|
||||
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder());
|
||||
fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canEditUserName() {
|
||||
return Gerrit.getConfig().canEdit(Account.FieldName.USER_NAME);
|
||||
}
|
||||
|
||||
void doChangeUserName() {
|
||||
if (!canEditUserName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String newName = userNameTxt.getText();
|
||||
if ("".equals(newName)) {
|
||||
newName = null;
|
||||
}
|
||||
if (newName != null && !newName.matches(Account.USER_NAME_PATTERN)) {
|
||||
invalidUserName();
|
||||
return;
|
||||
}
|
||||
|
||||
enableUI(false);
|
||||
|
||||
final String newUserName = newName;
|
||||
Util.ACCOUNT_SEC.changeUserName(newUserName,
|
||||
new GerritCallback<VoidResult>() {
|
||||
public void onSuccess(final VoidResult result) {
|
||||
Gerrit.getUserAccount().setUserName(newUserName);
|
||||
enableUI(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
enableUI(true);
|
||||
if (InvalidUserNameException.MESSAGE.equals(caught.getMessage())) {
|
||||
invalidUserName();
|
||||
} else {
|
||||
super.onFailure(caught);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void invalidUserName() {
|
||||
userNameTxt.setFocus(true);
|
||||
new ErrorDialog(Util.C.invalidUserName()).center();
|
||||
}
|
||||
|
||||
void doGeneratePassword() {
|
||||
if (idKey == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
enableUI(false);
|
||||
|
||||
Util.ACCOUNT_SEC.generatePassword(idKey,
|
||||
new GerritCallback<AccountExternalId>() {
|
||||
public void onSuccess(final AccountExternalId result) {
|
||||
enableUI(true);
|
||||
display(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
enableUI(true);
|
||||
if (InvalidUserNameException.MESSAGE.equals(caught.getMessage())) {
|
||||
invalidUserName();
|
||||
} else {
|
||||
super.onFailure(caught);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void enableUI(final boolean on) {
|
||||
userNameTxt.setEnabled(on);
|
||||
changeUserName.setEnabled(on);
|
||||
generatePassword.setEnabled(on && idKey != null);
|
||||
}
|
||||
|
||||
private final class UserNameValidator implements KeyPressHandler {
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
final char code = event.getCharCode();
|
||||
switch (code) {
|
||||
case KeyCodes.KEY_ALT:
|
||||
case KeyCodes.KEY_BACKSPACE:
|
||||
case KeyCodes.KEY_CTRL:
|
||||
case KeyCodes.KEY_DELETE:
|
||||
case KeyCodes.KEY_DOWN:
|
||||
case KeyCodes.KEY_END:
|
||||
case KeyCodes.KEY_ENTER:
|
||||
case KeyCodes.KEY_ESCAPE:
|
||||
case KeyCodes.KEY_HOME:
|
||||
case KeyCodes.KEY_LEFT:
|
||||
case KeyCodes.KEY_PAGEDOWN:
|
||||
case KeyCodes.KEY_PAGEUP:
|
||||
case KeyCodes.KEY_RIGHT:
|
||||
case KeyCodes.KEY_SHIFT:
|
||||
case KeyCodes.KEY_TAB:
|
||||
case KeyCodes.KEY_UP:
|
||||
// Allow these, even if one of their assigned codes is
|
||||
// identical to an ASCII character we do not want to
|
||||
// allow in the box.
|
||||
//
|
||||
// We still want to let the user move around the input box
|
||||
// with their arrow keys, or to move between fields using tab.
|
||||
// Invalid characters introduced will be caught through the
|
||||
// server's own validation of the input data.
|
||||
//
|
||||
break;
|
||||
|
||||
default:
|
||||
final TextBox box = (TextBox) event.getSource();
|
||||
final String re;
|
||||
if (box.getCursorPos() == 0)
|
||||
re = Account.USER_NAME_PATTERN_FIRST;
|
||||
else
|
||||
re = Account.USER_NAME_PATTERN_REST;
|
||||
if (!String.valueOf(code).matches("^" + re + "$")) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -984,11 +984,14 @@ a:hover.downloadLink {
|
||||
|
||||
|
||||
/** AccountSettings **/
|
||||
.sshPanelUsername {
|
||||
.usernameField {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.accountUsername {
|
||||
font-family: mono-font;
|
||||
font-size: small;
|
||||
}
|
||||
.sshPanelPassword {
|
||||
.accountPassword {
|
||||
font-family: mono-font;
|
||||
font-size: small;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.RemotePeer;
|
||||
import com.google.gerrit.server.account.AccountManager;
|
||||
import com.google.gerrit.server.account.ChangeUserName;
|
||||
import com.google.gerrit.server.account.ClearPassword;
|
||||
import com.google.gerrit.server.account.GeneratePassword;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
@ -139,6 +140,7 @@ public class WebModule extends FactoryModule {
|
||||
bind(AccountManager.class);
|
||||
bind(ChangeUserName.CurrentUser.class);
|
||||
factory(ChangeUserName.Factory.class);
|
||||
factory(ClearPassword.Factory.class);
|
||||
factory(GeneratePassword.Factory.class);
|
||||
|
||||
bind(SocketAddress.class).annotatedWith(RemotePeer.class).toProvider(
|
||||
|
@ -37,6 +37,7 @@ import com.google.gerrit.server.account.AccountException;
|
||||
import com.google.gerrit.server.account.AccountManager;
|
||||
import com.google.gerrit.server.account.AuthRequest;
|
||||
import com.google.gerrit.server.account.ChangeUserName;
|
||||
import com.google.gerrit.server.account.ClearPassword;
|
||||
import com.google.gerrit.server.account.GeneratePassword;
|
||||
import com.google.gerrit.server.account.Realm;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
@ -75,6 +76,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
||||
private final AccountManager accountManager;
|
||||
private final boolean useContactInfo;
|
||||
|
||||
private final ClearPassword.Factory clearPasswordFactory;
|
||||
private final GeneratePassword.Factory generatePasswordFactory;
|
||||
private final ChangeUserName.CurrentUser changeUserNameFactory;
|
||||
private final DeleteExternalIds.Factory deleteExternalIdsFactory;
|
||||
@ -88,6 +90,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
||||
final RegisterNewEmailSender.Factory esf, final SshKeyCache skc,
|
||||
final AccountByEmailCache abec, final AccountCache uac,
|
||||
final AccountManager am,
|
||||
final ClearPassword.Factory clearPasswordFactory,
|
||||
final GeneratePassword.Factory generatePasswordFactory,
|
||||
final ChangeUserName.CurrentUser changeUserNameFactory,
|
||||
final DeleteExternalIds.Factory deleteExternalIdsFactory,
|
||||
@ -106,6 +109,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
||||
|
||||
useContactInfo = contactStore != null && contactStore.isEnabled();
|
||||
|
||||
this.clearPasswordFactory = clearPasswordFactory;
|
||||
this.generatePasswordFactory = generatePasswordFactory;
|
||||
this.changeUserNameFactory = changeUserNameFactory;
|
||||
this.deleteExternalIdsFactory = deleteExternalIdsFactory;
|
||||
@ -183,6 +187,12 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
||||
Handler.wrap(generatePasswordFactory.create(key)).to(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearPassword(AccountExternalId.Key key,
|
||||
AsyncCallback<AccountExternalId> callback) {
|
||||
Handler.wrap(clearPasswordFactory.create(key)).to(callback);
|
||||
}
|
||||
|
||||
public void myExternalIds(AsyncCallback<List<AccountExternalId>> callback) {
|
||||
externalIdDetailFactory.create().to(callback);
|
||||
}
|
||||
|
@ -91,6 +91,9 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||
public VoidResult call() throws OrmException, NameAlreadyUsedException,
|
||||
InvalidUserNameException {
|
||||
final Collection<AccountExternalId> old = old();
|
||||
if (!old.isEmpty()) {
|
||||
throw new IllegalStateException("Username cannot be changed.");
|
||||
}
|
||||
|
||||
if (newUsername != null && !newUsername.isEmpty()) {
|
||||
if (!USER_NAME_PATTERN.matcher(newUsername).matches()) {
|
||||
|
@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2010 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server.account;
|
||||
|
||||
import com.google.gerrit.common.errors.NoSuchEntityException;
|
||||
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||
import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/** Operation to clear a password for an account. */
|
||||
public class ClearPassword implements Callable<AccountExternalId> {
|
||||
public interface Factory {
|
||||
ClearPassword create(AccountExternalId.Key forUser);
|
||||
}
|
||||
|
||||
private final AccountCache accountCache;
|
||||
private final ReviewDb db;
|
||||
private final IdentifiedUser user;
|
||||
|
||||
private final AccountExternalId.Key forUser;
|
||||
|
||||
@Inject
|
||||
ClearPassword(final AccountCache accountCache, final ReviewDb db,
|
||||
final IdentifiedUser user,
|
||||
|
||||
@Assisted AccountExternalId.Key forUser) {
|
||||
this.accountCache = accountCache;
|
||||
this.db = db;
|
||||
this.user = user;
|
||||
|
||||
this.forUser = forUser;
|
||||
}
|
||||
|
||||
public AccountExternalId call() throws OrmException, NoSuchEntityException {
|
||||
AccountExternalId id = db.accountExternalIds().get(forUser);
|
||||
if (id == null || !user.getAccountId().equals(id.getAccountId())) {
|
||||
throw new NoSuchEntityException();
|
||||
}
|
||||
|
||||
id.setPassword(null);
|
||||
db.accountExternalIds().update(Collections.singleton(id));
|
||||
accountCache.evict(user.getAccountId());
|
||||
return id;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user