aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorguillaume-peoch-sonarsource <guillaume.peoch@sonarsource.com>2023-07-31 11:27:05 +0200
committersonartech <sonartech@sonarsource.com>2023-07-31 20:03:32 +0000
commit5a71bede94abbaea239c544130876c5f0e535815 (patch)
tree80f5c9e1c2d215066dd1ebabd676fbe55bd4083f /server/sonar-web
parente7d3f62c1c161b76230960bc4301eaf7f20f7f1a (diff)
downloadsonarqube-5a71bede94abbaea239c544130876c5f0e535815.tar.gz
sonarqube-5a71bede94abbaea239c544130876c5f0e535815.zip
SONAR-19967 Use POST api/v2/users on the FE
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/api/mocks/UsersServiceMock.ts18
-rw-r--r--server/sonar-web/src/main/js/api/users.ts20
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/AssigneeSelect.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UserForm.tsx10
-rw-r--r--server/sonar-web/src/main/js/helpers/request.ts14
-rw-r--r--server/sonar-web/src/main/js/queries/users.ts8
6 files changed, 46 insertions, 30 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/UsersServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/UsersServiceMock.ts
index decdb9c4d53..ad4cf06f831 100644
--- a/server/sonar-web/src/main/js/api/mocks/UsersServiceMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/UsersServiceMock.ts
@@ -28,11 +28,11 @@ import { addUserToGroup, removeUserFromGroup } from '../user_groups';
import {
UserGroup,
changePassword,
- createUser,
deleteUser,
getIdentityProviders,
getUserGroups,
getUsers,
+ postUser,
updateUser,
} from '../users';
@@ -125,7 +125,7 @@ export default class UsersServiceMock {
jest.mocked(getSystemInfo).mockImplementation(this.handleGetSystemInfo);
jest.mocked(getIdentityProviders).mockImplementation(this.handleGetIdentityProviders);
jest.mocked(getUsers).mockImplementation((p) => this.handleGetUsers(p));
- jest.mocked(createUser).mockImplementation(this.handleCreateUser);
+ jest.mocked(postUser).mockImplementation(this.handlePostUser);
jest.mocked(updateUser).mockImplementation(this.handleUpdateUser);
jest.mocked(getUserGroups).mockImplementation(this.handleGetUserGroups);
jest.mocked(addUserToGroup).mockImplementation(this.handleAddUserToGroup);
@@ -248,19 +248,19 @@ export default class UsersServiceMock {
});
};
- handleCreateUser = (data: {
+ handlePostUser = (data: {
email?: string;
local?: boolean;
login: string;
name: string;
password?: string;
- scmAccount: string[];
+ scmAccounts: string[];
}) => {
- const { email, local, login, name, scmAccount } = data;
- if (scmAccount.some((a) => isEmpty(a.trim()))) {
+ const { email, local, login, name, scmAccounts } = data;
+ if (scmAccounts.some((a) => isEmpty(a.trim()))) {
return Promise.reject({
status: 400,
- json: () => Promise.resolve({ errors: [{ msg: 'Error: Empty SCM' }] }),
+ json: () => Promise.resolve({ message: 'Error: Empty SCM' }),
});
}
const newUser = mockRestUser({
@@ -268,7 +268,7 @@ export default class UsersServiceMock {
local,
login,
name,
- scmAccounts: scmAccount,
+ scmAccounts,
});
this.users.push(newUser);
return this.reply(undefined);
@@ -373,7 +373,7 @@ export default class UsersServiceMock {
const index = this.users.findIndex((u) => u.login === data.login);
const user = this.users.splice(index, 1)[0];
user.active = false;
- return this.reply({ user });
+ return this.reply(undefined);
};
reset = () => {
diff --git a/server/sonar-web/src/main/js/api/users.ts b/server/sonar-web/src/main/js/api/users.ts
index 68c37e2d869..73812ab046f 100644
--- a/server/sonar-web/src/main/js/api/users.ts
+++ b/server/sonar-web/src/main/js/api/users.ts
@@ -18,7 +18,15 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { throwGlobalError } from '../helpers/error';
-import { deleteJSON, getJSON, HttpStatus, parseJSON, post, postJSON } from '../helpers/request';
+import {
+ deleteJSON,
+ getJSON,
+ HttpStatus,
+ parseJSON,
+ post,
+ postJSON,
+ postJSONBody,
+} from '../helpers/request';
import { IdentityProvider, Paging } from '../types/types';
import {
ChangePasswordResults,
@@ -26,7 +34,6 @@ import {
HomePage,
NoticeType,
RestUserBase,
- RestUserDetailed,
User,
} from '../types/users';
@@ -89,15 +96,14 @@ export function getUsers<T extends RestUserBase>(data: {
return getJSON('/api/v2/users', data).catch(throwGlobalError);
}
-export function createUser(data: {
+export function postUser(data: {
email?: string;
- local?: boolean;
login: string;
name: string;
password?: string;
- scmAccount: string[];
+ scmAccounts: string[];
}): Promise<void | Response> {
- return post('/api/users/create', data);
+ return postJSONBody('/api/v2/users', data);
}
export function updateUser(data: {
@@ -118,7 +124,7 @@ export function deleteUser({
}: {
login: string;
anonymize?: boolean;
-}): Promise<{ user: RestUserDetailed }> {
+}): Promise<void | Response> {
return deleteJSON(`/api/v2/users/${login}`, { anonymize }).catch(throwGlobalError);
}
diff --git a/server/sonar-web/src/main/js/apps/issues/components/AssigneeSelect.tsx b/server/sonar-web/src/main/js/apps/issues/components/AssigneeSelect.tsx
index 664518cad3d..111f4561a85 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/AssigneeSelect.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/AssigneeSelect.tsx
@@ -24,7 +24,7 @@ import { CurrentUserContext } from '../../../app/components/current-user/Current
import Avatar from '../../../components/ui/Avatar';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { Issue } from '../../../types/types';
-import { RestUser, isLoggedIn, isUserActive } from '../../../types/users';
+import { RestUser, UserActive, isLoggedIn, isUserActive } from '../../../types/users';
import { searchAssignees } from '../utils';
// exported for test
@@ -40,7 +40,7 @@ export interface AssigneeSelectProps {
inputId: string;
}
-function userToOption(user: RestUser) {
+function userToOption(user: RestUser | UserActive) {
const userInfo = user.name || user.login;
return {
value: user.login,
@@ -58,7 +58,7 @@ export default function AssigneeSelect(props: AssigneeSelectProps) {
isLoggedIn(currentUser) && issues.some((issue) => currentUser.login !== issue.assignee);
const defaultOptions = allowCurrentUserSelection
- ? [UNASSIGNED, userToOption(currentUser as unknown as RestUser)]
+ ? [UNASSIGNED, userToOption(currentUser)]
: [UNASSIGNED];
const controlLabel = assignee ? (
diff --git a/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx b/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx
index b63ad7288ee..798ec561001 100644
--- a/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx
+++ b/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx
@@ -25,8 +25,8 @@ import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
import { throwGlobalError } from '../../../helpers/error';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { parseError } from '../../../helpers/request';
-import { useCreateUserMutation, useUpdateUserMutation } from '../../../queries/users';
+import { parseMessage } from '../../../helpers/request';
+import { usePostUserMutation, useUpdateUserMutation } from '../../../queries/users';
import { RestUserDetailed } from '../../../types/users';
import UserScmAccountInput from './UserScmAccountInput';
@@ -41,7 +41,7 @@ const INTERNAL_SERVER_ERROR = 500;
export default function UserForm(props: Props) {
const { user } = props;
- const { mutate: createUser } = useCreateUserMutation();
+ const { mutate: createUser } = usePostUserMutation();
const { mutate: updateUser } = useUpdateUserMutation();
const [email, setEmail] = React.useState<string>(user?.email ?? '');
@@ -55,7 +55,7 @@ export default function UserForm(props: Props) {
if (![BAD_REQUEST, INTERNAL_SERVER_ERROR].includes(response.status)) {
throwGlobalError(response);
} else {
- parseError(response).then((errorMsg) => setError(errorMsg), throwGlobalError);
+ parseMessage(response).then((errorMsg) => setError(errorMsg), throwGlobalError);
}
};
@@ -66,7 +66,7 @@ export default function UserForm(props: Props) {
login,
name,
password,
- scmAccount: scmAccounts,
+ scmAccounts,
},
{ onSuccess: props.onClose, onError: handleError }
);
diff --git a/server/sonar-web/src/main/js/helpers/request.ts b/server/sonar-web/src/main/js/helpers/request.ts
index 9b40c1f14ed..5a1537dfb81 100644
--- a/server/sonar-web/src/main/js/helpers/request.ts
+++ b/server/sonar-web/src/main/js/helpers/request.ts
@@ -178,7 +178,7 @@ export function parseText(response: Response): Promise<string> {
}
/**
- * Parse response of failed request
+ * Parse error response of failed request
*/
export function parseError(response: Response): Promise<string> {
const DEFAULT_MESSAGE = translate('default_error_message');
@@ -188,6 +188,16 @@ export function parseError(response: Response): Promise<string> {
}
/**
+ * Parse message response of failed request
+ */
+export function parseMessage(response: Response): Promise<string> {
+ const DEFAULT_MESSAGE = translate('default_error_message');
+ return parseJSON(response)
+ .then(({ message }) => message)
+ .catch(() => DEFAULT_MESSAGE);
+}
+
+/**
* Shortcut to do a GET request and return a Response
*/
export function get(url: string, data?: RequestData, bypassRedirect?: boolean): Promise<Response> {
@@ -275,7 +285,7 @@ export function post(url: string, data?: RequestData, bypassRedirect?: boolean):
/**
* Shortcut to do a DELETE request
*/
-export function deleteJSON(url: string, data?: RequestData): Promise<any> {
+export function deleteJSON(url: string, data?: RequestData): Promise<Response> {
return request(url)
.setMethod('DELETE')
.setData(data)
diff --git a/server/sonar-web/src/main/js/queries/users.ts b/server/sonar-web/src/main/js/queries/users.ts
index 51e3ce0acb9..f74f5730f33 100644
--- a/server/sonar-web/src/main/js/queries/users.ts
+++ b/server/sonar-web/src/main/js/queries/users.ts
@@ -25,7 +25,7 @@ import {
useQueryClient,
} from '@tanstack/react-query';
import { range } from 'lodash';
-import { createUser, deleteUser, getUsers, updateUser } from '../api/users';
+import { deleteUser, getUsers, postUser, updateUser } from '../api/users';
import { RestUserBase } from '../types/users';
const STALE_TIME = 4 * 60 * 1000;
@@ -65,12 +65,12 @@ export function useInvalidateUsersList() {
return () => queryClient.invalidateQueries({ queryKey: ['user', 'list'] });
}
-export function useCreateUserMutation() {
+export function usePostUserMutation() {
const queryClient = useQueryClient();
return useMutation({
- mutationFn: async (data: Parameters<typeof createUser>[0]) => {
- await createUser(data);
+ mutationFn: async (data: Parameters<typeof postUser>[0]) => {
+ await postUser(data);
},
onSuccess() {
queryClient.invalidateQueries({ queryKey: ['user', 'list'] });