@@ -0,0 +1,24 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.common; | |||
public enum SortOrder { | |||
ASCENDING, DESCENDING | |||
} |
@@ -33,7 +33,7 @@ public record RestPage( | |||
Integer pageSize, | |||
@Positive | |||
@Schema(defaultValue = DEFAULT_PAGE_INDEX, description = "Number of results per page") | |||
@Schema(defaultValue = DEFAULT_PAGE_INDEX, description = "1-based page index") | |||
Integer pageIndex | |||
) { | |||
@@ -0,0 +1,37 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.v2.api.model; | |||
import com.fasterxml.jackson.annotation.JsonValue; | |||
import io.swagger.v3.oas.annotations.media.Schema; | |||
@Schema(defaultValue = "desc", description = "Sort order") | |||
public enum RestSortOrder { | |||
ASC("asc"), | |||
DESC("desc"); | |||
@JsonValue | |||
private final String serializedOrder; | |||
RestSortOrder(String serializedOrder) { | |||
this.serializedOrder = serializedOrder; | |||
} | |||
} |
@@ -30,6 +30,7 @@ import org.sonar.server.common.user.service.UsersSearchRequest; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonar.server.v2.api.model.RestPage; | |||
import org.sonar.server.v2.api.model.RestSortOrder; | |||
import org.sonar.server.v2.api.user.converter.UsersSearchRestResponseGenerator; | |||
import org.sonar.server.v2.api.user.model.RestUser; | |||
import org.sonar.server.v2.api.user.request.UserCreateRestRequest; | |||
@@ -54,8 +55,9 @@ public class DefaultUserController implements UserController { | |||
} | |||
@Override | |||
public UsersSearchRestResponse search(UsersSearchRestRequest usersSearchRestRequest, RestPage page) { | |||
public UsersSearchRestResponse search(UsersSearchRestRequest usersSearchRestRequest, RestPage page, @Nullable RestSortOrder order) { | |||
throwIfAdminOnlyParametersAreUsed(usersSearchRestRequest); | |||
checkRequest(!RestSortOrder.DESC.equals(order), "order parameter is present for doc-demo purpose, it will be removed."); | |||
SearchResults<UserSearchResult> userSearchResults = userService.findUsers(toUserSearchRequest(usersSearchRestRequest, page)); | |||
Paging paging = forPageIndex(page.pageIndex()).withPageSize(page.pageSize()).andTotal(userSearchResults.total()); |
@@ -23,7 +23,9 @@ import io.swagger.v3.oas.annotations.Operation; | |||
import io.swagger.v3.oas.annotations.Parameter; | |||
import io.swagger.v3.oas.annotations.enums.ParameterIn; | |||
import javax.validation.Valid; | |||
import org.jetbrains.annotations.Nullable; | |||
import org.sonar.server.v2.api.model.RestPage; | |||
import org.sonar.server.v2.api.model.RestSortOrder; | |||
import org.sonar.server.v2.api.user.model.RestUser; | |||
import org.sonar.server.v2.api.user.request.UserCreateRestRequest; | |||
import org.sonar.server.v2.api.user.request.UsersSearchRestRequest; | |||
@@ -50,7 +52,7 @@ public interface UserController { | |||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) | |||
@ResponseStatus(HttpStatus.OK) | |||
@Operation(summary = "Users search", description = """ | |||
Get a list of users. By default, only active users are returned. | |||
Get a list of users. By default, only active users are returned.<br> | |||
The following fields are only returned when user has Administer System permission or for logged-in in user : | |||
'email' | |||
'externalIdentity' | |||
@@ -58,10 +60,13 @@ public interface UserController { | |||
'groups' | |||
'lastConnectionDate' | |||
'sonarLintLastConnectionDate' | |||
'tokensCount' | |||
'tokensCount'<br> | |||
Field 'sonarqubeLastConnectionDate' is only updated every hour, so it may not be accurate, for instance when a user authenticates many times in less than one hour. | |||
""") | |||
UsersSearchRestResponse search(@ParameterObject UsersSearchRestRequest usersSearchRestRequest, @Valid @ParameterObject RestPage restPage); | |||
UsersSearchRestResponse search( | |||
@Valid @ParameterObject UsersSearchRestRequest usersSearchRestRequest, | |||
@Valid @ParameterObject RestPage restPage, | |||
@RequestParam(name = "order", required = false) @Nullable RestSortOrder order); | |||
@DeleteMapping(path = "/{login}") | |||
@ResponseStatus(HttpStatus.NO_CONTENT) | |||
@@ -95,7 +100,7 @@ public interface UserController { | |||
@Operation(summary = "User creation", description = """ | |||
Create a user. | |||
If a deactivated user account exists with the given login, it will be reactivated. | |||
Requires Administer System permission | |||
Requires Administer System permission. | |||
""") | |||
RestUser create(@Valid @RequestBody UserCreateRestRequest userCreateRestRequest); | |||
@@ -62,35 +62,23 @@ public class UsersSearchRestResponseGenerator implements UsersSearchResponseGene | |||
String login = userDto.getLogin(); | |||
String name = userDto.getName(); | |||
String avatar = null; | |||
Boolean active = null; | |||
Boolean local = null; | |||
String email = null; | |||
String externalIdentityProvider = null; | |||
String externalLogin = null; | |||
Boolean managed = null; | |||
String sqLastConnectionDate = null; | |||
String slLastConnectionDate = null; | |||
Integer groupSize = null; | |||
Integer tokensCount = null; | |||
List<String> scmAccounts = null; | |||
if (!userSession.isLoggedIn()) { | |||
return new RestUserForAnonymousUsers(login, login, name); | |||
} | |||
avatar = userSearchResult.avatar().orElse(null); | |||
active = userDto.isActive(); | |||
local = userDto.isLocal(); | |||
email = userDto.getEmail(); | |||
externalIdentityProvider = userDto.getExternalIdentityProvider(); | |||
String avatar = userSearchResult.avatar().orElse(null); | |||
Boolean active = userDto.isActive(); | |||
Boolean local = userDto.isLocal(); | |||
String email = userDto.getEmail(); | |||
String externalIdentityProvider = userDto.getExternalIdentityProvider(); | |||
if (userSession.isSystemAdministrator() || Objects.equals(userSession.getUuid(), userDto.getUuid())) { | |||
externalLogin = userDto.getExternalLogin(); | |||
managed = userSearchResult.managed(); | |||
sqLastConnectionDate = toDateTime(userDto.getLastConnectionDate()); | |||
slLastConnectionDate = toDateTime(userDto.getLastSonarlintConnectionDate()); | |||
groupSize = userSearchResult.groups().size(); | |||
tokensCount = userSearchResult.tokensCount(); | |||
scmAccounts = userSearchResult.userDto().getSortedScmAccounts(); | |||
String externalLogin = userDto.getExternalLogin(); | |||
Boolean managed = userSearchResult.managed(); | |||
String sqLastConnectionDate = toDateTime(userDto.getLastConnectionDate()); | |||
String slLastConnectionDate = toDateTime(userDto.getLastSonarlintConnectionDate()); | |||
int groupSize = userSearchResult.groups().size(); | |||
int tokensCount = userSearchResult.tokensCount(); | |||
List<String> scmAccounts = userSearchResult.userDto().getSortedScmAccounts(); | |||
return new RestUserForAdmins( | |||
login, | |||
login, |