Add REST endpoint to set username

This REST endpoint only allows to set the initial username. Once set
the username cannot be changed or deleted.

Use the new REST endpoint from the UI instead of the old
AccountSecurity.changeUserName(...) RPC.

The AccountSecurity.changeUserName(...) RPC is removed since it is no
longer used.

Change-Id: I48f4d7642b551e17ceef7772563a229aa83fc1ad
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2015-07-24 11:47:57 +02:00
parent 7c87d0f929
commit f07e98ba5c
10 changed files with 253 additions and 68 deletions

View File

@@ -28,7 +28,6 @@ import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
@@ -39,28 +38,12 @@ import java.util.regex.Pattern;
/** Operation to change the username of an account. */
public class ChangeUserName implements Callable<VoidResult> {
public static final String USERNAME_CANNOT_BE_CHANGED =
"Username cannot be changed.";
private static final Pattern USER_NAME_PATTERN =
Pattern.compile(Account.USER_NAME_PATTERN);
/** Factory to change the username for the current user. */
public static class CurrentUser {
private final Factory factory;
private final Provider<ReviewDb> db;
private final Provider<IdentifiedUser> user;
@Inject
CurrentUser(Factory factory, Provider<ReviewDb> db,
Provider<IdentifiedUser> user) {
this.factory = factory;
this.db = db;
this.user = user;
}
public ChangeUserName create(String newUsername) {
return factory.create(db.get(), user.get(), newUsername);
}
}
/** Generic factory to change any user's username. */
public interface Factory {
ChangeUserName create(ReviewDb db, IdentifiedUser user, String newUsername);
@@ -92,7 +75,7 @@ public class ChangeUserName implements Callable<VoidResult> {
InvalidUserNameException {
final Collection<AccountExternalId> old = old();
if (!old.isEmpty()) {
throw new IllegalStateException("Username cannot be changed.");
throw new IllegalStateException(USERNAME_CANNOT_BE_CHANGED);
}
if (newUsername != null && !newUsername.isEmpty()) {

View File

@@ -43,6 +43,7 @@ public class Module extends RestApiModule {
put(ACCOUNT_KIND, "name").to(PutName.class);
delete(ACCOUNT_KIND, "name").to(PutName.class);
get(ACCOUNT_KIND, "username").to(GetUsername.class);
put(ACCOUNT_KIND, "username").to(PutUsername.class);
get(ACCOUNT_KIND, "active").to(GetActive.class);
put(ACCOUNT_KIND, "active").to(PutActive.class);
delete(ACCOUNT_KIND, "active").to(DeleteActive.class);

View File

@@ -0,0 +1,90 @@
// Copyright (C) 2015 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.InvalidUserNameException;
import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.PutUsername.Input;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@Singleton
public class PutUsername implements RestModifyView<AccountResource, Input> {
public static class Input {
@DefaultInput
public String username;
}
private final Provider<CurrentUser> self;
private final ChangeUserName.Factory changeUserNameFactory;
private final Realm realm;
private final Provider<ReviewDb> db;
@Inject
PutUsername(Provider<CurrentUser> self,
ChangeUserName.Factory changeUserNameFactory,
Realm realm,
Provider<ReviewDb> db) {
this.self = self;
this.changeUserNameFactory = changeUserNameFactory;
this.realm = realm;
this.db = db;
}
@Override
public String apply(AccountResource rsrc, Input input) throws AuthException,
MethodNotAllowedException, UnprocessableEntityException,
ResourceConflictException, OrmException {
if (self.get() != rsrc.getUser()
&& !self.get().getCapabilities().canAdministrateServer()) {
throw new AuthException("not allowed to set username");
}
if (!realm.allowsEdit(Account.FieldName.USER_NAME)) {
throw new MethodNotAllowedException("realm does not allow editing username");
}
if (input == null) {
input = new Input();
}
try {
changeUserNameFactory.create(db.get(), rsrc.getUser(), input.username).call();
} catch (IllegalStateException e) {
if (ChangeUserName.USERNAME_CANNOT_BE_CHANGED.equals(e.getMessage())) {
throw new MethodNotAllowedException(e.getMessage());
} else {
throw e;
}
} catch (InvalidUserNameException e) {
throw new UnprocessableEntityException("invalid username");
} catch (NameAlreadyUsedException e) {
throw new ResourceConflictException("username already used");
}
return input.username;
}
}

View File

@@ -302,7 +302,6 @@ public class GerritGlobalModule extends FactoryModule {
factory(SubmoduleSectionParser.Factory.class);
bind(AccountManager.class);
bind(ChangeUserName.CurrentUser.class);
factory(ChangeUserName.Factory.class);
bind(new TypeLiteral<List<CommentLinkInfo>>() {})