diff options
author | Antoine Vigneau <antoine.vigneau@sonarsource.com> | 2023-07-25 21:07:09 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-07-28 20:03:15 +0000 |
commit | c43733d1db5a9aa18b9b8985ad2a19972421987d (patch) | |
tree | 512938ea09fc2bc2d7453d6c9abbf969ee8fc112 /server/sonar-webserver-webapi | |
parent | 3994545c5d4313228716935ec752c0eb1253a077 (diff) | |
download | sonarqube-c43733d1db5a9aa18b9b8985ad2a19972421987d.tar.gz sonarqube-c43733d1db5a9aa18b9b8985ad2a19972421987d.zip |
SONAR-19969 Support apiv2 POST /users to create a user
Diffstat (limited to 'server/sonar-webserver-webapi')
5 files changed, 40 insertions, 67 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CreateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CreateActionIT.java index 5071be725cd..430dc0e30c7 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CreateActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CreateActionIT.java @@ -33,10 +33,14 @@ import org.sonar.db.audit.NoOpAuditPersister; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; import org.sonar.server.authentication.CredentialsLocalAuthentication; +import org.sonar.server.common.avatar.AvatarResolverImpl; +import org.sonar.server.common.management.ManagedInstanceChecker; +import org.sonar.server.common.user.UserDeactivator; +import org.sonar.server.common.user.service.UserService; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; -import org.sonar.server.common.management.ManagedInstanceChecker; +import org.sonar.server.management.ManagedInstanceService; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.NewUserNotifier; import org.sonar.server.user.UserUpdater; @@ -72,8 +76,10 @@ public class CreateActionIT { private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final ManagedInstanceChecker managedInstanceChecker = mock(ManagedInstanceChecker.class); - private final WsActionTester tester = new WsActionTester(new CreateAction(db.getDbClient(), new UserUpdater(mock(NewUserNotifier.class), - db.getDbClient(), new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), new NoOpAuditPersister(), localAuthentication), userSessionRule, managedInstanceChecker)); + private final ManagedInstanceService managedInstanceService = mock(ManagedInstanceService.class); + private final UserService userService = new UserService(db.getDbClient(), new AvatarResolverImpl(), managedInstanceService, managedInstanceChecker, mock(UserDeactivator.class), + new UserUpdater(mock(NewUserNotifier.class), db.getDbClient(), new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), new NoOpAuditPersister(), localAuthentication)); + private final WsActionTester tester = new WsActionTester(new CreateAction(userSessionRule, managedInstanceChecker, userService)); @Before public void setUp() { diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DeactivateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DeactivateActionIT.java index 129f5561d38..87eebebcc4e 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DeactivateActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DeactivateActionIT.java @@ -56,6 +56,7 @@ import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.management.ManagedInstanceService; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.ExternalIdentity; +import org.sonar.server.user.UserUpdater; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; import org.sonar.server.ws.WsActionTester; @@ -85,7 +86,8 @@ public class DeactivateActionIT { private final UserDeactivator userDeactivator = new UserDeactivator(dbClient, userAnonymizer); private final ManagedInstanceChecker managedInstanceChecker = mock(ManagedInstanceChecker.class); - private final UserService userService = new UserService(dbClient, mock(AvatarResolver.class), mock(ManagedInstanceService.class), managedInstanceChecker, userDeactivator); + private final UserService userService = new UserService(dbClient, mock(AvatarResolver.class), mock(ManagedInstanceService.class), managedInstanceChecker, userDeactivator, + mock(UserUpdater.class)); private final WsActionTester ws = new WsActionTester(new DeactivateAction(dbClient, userSession, new UserJsonWriter(userSession), userService)); @Test diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/SearchActionIT.java index 732d219d5a0..091a47fd5ac 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/SearchActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/SearchActionIT.java @@ -44,6 +44,7 @@ import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ServerException; import org.sonar.server.management.ManagedInstanceService; import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.user.UserUpdater; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Common.Paging; @@ -81,7 +82,8 @@ public class SearchActionIT { new AvatarResolverImpl(), managedInstanceService, mock(ManagedInstanceChecker.class), - mock(UserDeactivator.class)); + mock(UserDeactivator.class), + mock(UserUpdater.class)); private final SearchWsReponseGenerator searchWsReponseGenerator = new SearchWsReponseGenerator(userSession); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CreateAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CreateAction.java index 839e2697918..e6c65a5fa59 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CreateAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CreateAction.java @@ -19,23 +19,19 @@ */ package org.sonar.server.user.ws; -import java.util.HashSet; import java.util.List; -import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.user.UserDto; import org.sonar.server.common.management.ManagedInstanceChecker; -import org.sonar.server.user.ExternalIdentity; -import org.sonar.server.user.NewUser; +import org.sonar.server.common.user.service.UserCreateRequest; +import org.sonar.server.common.user.service.UserSearchResult; +import org.sonar.server.common.user.service.UserService; import org.sonar.server.user.UserSession; -import org.sonar.server.user.UserUpdater; import org.sonarqube.ws.Users.CreateWsResponse; import static com.google.common.base.Preconditions.checkArgument; @@ -43,7 +39,6 @@ import static com.google.common.base.Strings.emptyToNull; import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.Collections.emptyList; import static java.util.Optional.ofNullable; -import static org.sonar.server.user.ExternalIdentity.SQ_AUTHORITY; import static org.sonar.server.user.UserUpdater.EMAIL_MAX_LENGTH; import static org.sonar.server.user.UserUpdater.LOGIN_MAX_LENGTH; import static org.sonar.server.user.UserUpdater.LOGIN_MIN_LENGTH; @@ -60,16 +55,14 @@ import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_SCM_ACCOUNT; public class CreateAction implements UsersWsAction { - private final DbClient dbClient; - private final UserUpdater userUpdater; private final UserSession userSession; private final ManagedInstanceChecker managedInstanceChecker; + private final UserService userService; - public CreateAction(DbClient dbClient, UserUpdater userUpdater, UserSession userSession, ManagedInstanceChecker managedInstanceService) { - this.dbClient = dbClient; - this.userUpdater = userUpdater; + public CreateAction(UserSession userSession, ManagedInstanceChecker managedInstanceService, UserService userService) { this.userSession = userSession; this.managedInstanceChecker = managedInstanceService; + this.userService = userService; } @Override @@ -124,32 +117,17 @@ public class CreateAction implements UsersWsAction { public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkIsSystemAdministrator(); managedInstanceChecker.throwIfInstanceIsManaged(); - CreateRequest createRequest = toWsRequest(request); - checkArgument(isValidIfPresent(createRequest.getEmail()), "Email '%s' is not valid", createRequest.getEmail()); - writeProtobuf(doHandle(createRequest), request, response); + + UserCreateRequest userCreateRequest = toUserCreateRequest(request); + String email = userCreateRequest.getEmail().orElse(null); + checkArgument(isValidIfPresent(email), "Email '%s' is not valid", email); + + writeProtobuf(doHandle(userCreateRequest), request, response); } - private CreateWsResponse doHandle(CreateRequest request) { - try (DbSession dbSession = dbClient.openSession(false)) { - String login = request.getLogin(); - NewUser.Builder newUser = NewUser.builder() - .setLogin(login) - .setName(request.getName()) - .setEmail(request.getEmail()) - .setScmAccounts(request.getScmAccounts()) - .setPassword(request.getPassword()); - if (!request.isLocal()) { - newUser.setExternalIdentity(new ExternalIdentity(SQ_AUTHORITY, login, login)); - } - UserDto existingUser = dbClient.userDao().selectByLogin(dbSession, login); - if (existingUser == null) { - return buildResponse(userUpdater.createAndCommit(dbSession, newUser.build(), u -> { - })); - } - checkArgument(!existingUser.isActive(), "An active user with login '%s' already exists", login); - return buildResponse(userUpdater.reactivateAndCommit(dbSession, existingUser, newUser.build(), u -> { - })); - } + private CreateWsResponse doHandle(UserCreateRequest userCreateRequest) { + UserSearchResult userSearchResult = userService.createUser(userCreateRequest); + return buildResponse(userSearchResult.userDto()); } private static CreateWsResponse buildResponse(UserDto userDto) { @@ -163,42 +141,24 @@ public class CreateAction implements UsersWsAction { return CreateWsResponse.newBuilder().setUser(userBuilder).build(); } - private static CreateRequest toWsRequest(Request request) { - return CreateRequest.builder() + private static UserCreateRequest toUserCreateRequest(Request request) { + return UserCreateRequest.builder() + .setEmail(request.param(PARAM_EMAIL)) + .setLocal(request.mandatoryParamAsBoolean(PARAM_LOCAL)) .setLogin(request.mandatoryParam(PARAM_LOGIN)) .setName(request.mandatoryParam(PARAM_NAME)) .setPassword(request.param(PARAM_PASSWORD)) - .setEmail(request.param(PARAM_EMAIL)) .setScmAccounts(parseScmAccounts(request)) - .setLocal(request.mandatoryParamAsBoolean(PARAM_LOCAL)) .build(); } public static List<String> parseScmAccounts(Request request) { if (request.hasParam(PARAM_SCM_ACCOUNT)) { - List<String> scmAccounts = request.multiParam(PARAM_SCM_ACCOUNT); - validateScmAccounts(scmAccounts); - return scmAccounts; + return request.multiParam(PARAM_SCM_ACCOUNT); } return emptyList(); } - private static void validateScmAccounts(List<String> scmAccounts) { - scmAccounts.forEach(CreateAction::validateScmAccountFormat); - validateNoDuplicates(scmAccounts); - } - - private static void validateScmAccountFormat(String scmAccount) { - checkArgument(scmAccount.equals(scmAccount.strip()), "SCM account cannot start or end with whitespace: '%s'", scmAccount); - } - - private static void validateNoDuplicates(List<String> scmAccounts) { - Set<String> duplicateCheck = new HashSet<>(); - for (String account : scmAccounts) { - checkArgument(duplicateCheck.add(account), "Duplicate SCM account: '%s'", account); - } - } - static class CreateRequest { private final String login; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/UpdateAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/UpdateAction.java index 08cba756840..4603ecae29e 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/UpdateAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/UpdateAction.java @@ -33,8 +33,9 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.user.UserDto; -import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.common.management.ManagedInstanceChecker; +import org.sonar.server.common.user.service.UserService; +import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.user.UpdateUser; import org.sonar.server.user.UserSession; import org.sonar.server.user.UserUpdater; @@ -160,11 +161,13 @@ public class UpdateAction implements UsersWsAction { } private static UpdateRequest toWsRequest(Request request) { + List<String> scmAccounts = parseScmAccounts(request); + UserService.validateScmAccounts(scmAccounts); return UpdateRequest.builder() .setLogin(request.mandatoryParam(PARAM_LOGIN)) .setName(request.param(PARAM_NAME)) .setEmail(request.param(PARAM_EMAIL)) - .setScmAccounts(parseScmAccounts(request)) + .setScmAccounts(scmAccounts) .build(); } |