blob: 2ec20d0f5cbd277dc96f313a3d332ee3ab86777e [file] [log] [blame]
// 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();
}
}
}
}
}