]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19967 Use GET api/v2/users on the FE for Assignees
authorguillaume-peoch-sonarsource <guillaume.peoch@sonarsource.com>
Mon, 31 Jul 2023 08:29:58 +0000 (10:29 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 31 Jul 2023 20:03:32 +0000 (20:03 +0000)
server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
server/sonar-web/src/main/js/api/mocks/SecurityHotspotServiceMock.ts
server/sonar-web/src/main/js/api/users.ts
server/sonar-web/src/main/js/apps/issues/components/AssigneeSelect.tsx
server/sonar-web/src/main/js/apps/issues/utils.ts
server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-it.tsx
server/sonar-web/src/main/js/apps/security-hotspots/components/Assignee.tsx
server/sonar-web/src/main/js/components/issue/components/IssueAssign.tsx

index efaf2bd2c709c40ac5fc7981d3f8c9d725e810f2..3ee95b5ef5c584e5dc728d801abc9feb068a677c 100644 (file)
@@ -42,7 +42,7 @@ import { MetricKey } from '../../types/metrics';
 import { SearchRulesQuery } from '../../types/rules';
 import { Standards } from '../../types/security';
 import { Dict, Rule, RuleActivation, RuleDetails, SnippetsByComponent } from '../../types/types';
-import { LoggedInUser, NoticeType, User } from '../../types/users';
+import { LoggedInUser, NoticeType, RestUser } from '../../types/users';
 import {
   addIssueComment,
   bulkChangeIssues,
@@ -61,7 +61,7 @@ import {
   setIssueType,
 } from '../issues';
 import { getRuleDetails, searchRules } from '../rules';
-import { dismissNotice, getCurrentUser, searchUsers } from '../users';
+import { dismissNotice, getCurrentUser, getUsers } from '../users';
 import { IssueData, mockIssuesList } from './data/issues';
 import { mockRuleList } from './data/rules';
 
@@ -123,7 +123,7 @@ export default class IssuesServiceMock {
     jest.mocked(searchIssues).mockImplementation(this.handleSearchIssues);
     jest.mocked(searchIssueTags).mockImplementation(this.handleSearchIssueTags);
     jest.mocked(searchRules).mockImplementation(this.handleSearchRules);
-    jest.mocked(searchUsers).mockImplementation(this.handleSearchUsers);
+    jest.mocked(getUsers).mockImplementation(this.handleGetUsers);
     jest.mocked(setIssueAssignee).mockImplementation(this.handleSetIssueAssignee);
     jest.mocked(setIssueSeverity).mockImplementation(this.handleSetIssueSeverity);
     jest.mocked(setIssueTags).mockImplementation(this.handleSetIssueTags);
@@ -625,8 +625,11 @@ export default class IssuesServiceMock {
     );
   };
 
-  handleSearchUsers = () => {
-    return this.reply({ paging: mockPaging(), users: [mockLoggedInUser() as unknown as User] });
+  handleGetUsers = () => {
+    return this.reply({
+      pageRestResponse: mockPaging(),
+      users: [mockLoggedInUser() as unknown as RestUser],
+    });
   };
 
   handleSearchIssueAuthors = () => {
index a2086d31ab73dfcfa393af4dd4136344fe958cda..6124747de14c51220dd96d84745f898a8d02f509 100644 (file)
@@ -27,7 +27,7 @@ import {
 } from '../../helpers/mocks/security-hotspots';
 import { mockSourceLine } from '../../helpers/mocks/sources';
 import { getStandards } from '../../helpers/security-standard';
-import { mockPaging, mockUser } from '../../helpers/testMocks';
+import { mockPaging, mockRestUser } from '../../helpers/testMocks';
 import {
   Hotspot,
   HotspotAssignRequest,
@@ -35,6 +35,7 @@ import {
   HotspotResolution,
   HotspotStatus,
 } from '../../types/security-hotspots';
+import { RestUser } from '../../types/users';
 import { getSources } from '../components';
 import { getMeasures } from '../measures';
 import {
@@ -47,7 +48,7 @@ import {
   getSecurityHotspots,
   setSecurityHotspotStatus,
 } from '../security-hotspots';
-import { searchUsers } from '../users';
+import { getUsers } from '../users';
 
 const NUMBER_OF_LINES = 20;
 
@@ -66,7 +67,7 @@ export default class SecurityHotspotServiceMock {
     jest.mocked(getSecurityHotspotList).mockImplementation(this.handleGetSecurityHotspotList);
     jest.mocked(assignSecurityHotspot).mockImplementation(this.handleAssignSecurityHotspot);
     jest.mocked(setSecurityHotspotStatus).mockImplementation(this.handleSetSecurityHotspotStatus);
-    jest.mocked(searchUsers).mockImplementation(this.handleSearchUsers);
+    jest.mocked(getUsers).mockImplementation((p) => this.handleGetUsers(p));
     jest.mocked(getSources).mockResolvedValue(
       times(NUMBER_OF_LINES, (n) =>
         mockSourceLine({
@@ -119,14 +120,14 @@ export default class SecurityHotspotServiceMock {
     return Promise.resolve();
   };
 
-  handleSearchUsers = () => {
+  handleGetUsers: typeof getUsers<RestUser> = () => {
     return this.reply({
       users: [
-        mockUser({ name: 'User John', login: 'user.john' }),
-        mockUser({ name: 'User Doe', login: 'user.doe' }),
-        mockUser({ name: 'User Foo', login: 'user.foo' }),
+        mockRestUser({ name: 'User John', login: 'user.john' }),
+        mockRestUser({ name: 'User Doe', login: 'user.doe' }),
+        mockRestUser({ name: 'User Foo', login: 'user.foo' }),
       ],
-      paging: mockPaging(),
+      pageRestResponse: mockPaging(),
     });
   };
 
index d75c811ff95a281e65702e67bd83d27e67f8db09..68c37e2d869d2b552ed34349f3155a8003672e17 100644 (file)
@@ -75,20 +75,6 @@ export function getIdentityProviders(): Promise<{ identityProviders: IdentityPro
   return getJSON('/api/users/identity_providers').catch(throwGlobalError);
 }
 
-export function searchUsers(data: {
-  p?: number;
-  ps?: number;
-  q?: string;
-  managed?: boolean;
-  lastConnectedAfter?: string;
-  lastConnectedBefore?: string;
-  slLastConnectedAfter?: string;
-  slLastConnectedBefore?: string;
-}): Promise<{ paging: Paging; users: User[] }> {
-  data.q = data.q || undefined;
-  return getJSON('/api/users/search', data).catch(throwGlobalError);
-}
-
 export function getUsers<T extends RestUserBase>(data: {
   q: string;
   active?: boolean;
index 5bca99c6339c2279e484655e1f5656dbd9ed7c61..664518cad3dd92196c1f51bb8931802f7aea4e99 100644 (file)
@@ -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 { UserActive, isLoggedIn, isUserActive } from '../../../types/users';
+import { RestUser, isLoggedIn, isUserActive } from '../../../types/users';
 import { searchAssignees } from '../utils';
 
 // exported for test
@@ -40,7 +40,7 @@ export interface AssigneeSelectProps {
   inputId: string;
 }
 
-function userToOption(user: UserActive) {
+function userToOption(user: RestUser) {
   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)]
+    ? [UNASSIGNED, userToOption(currentUser as unknown as RestUser)]
     : [UNASSIGNED];
 
   const controlLabel = assignee ? (
index 9638728d3abffd1a088ddcde682b7479a44459f5..dd499df95d574337bca3a1e94be6a27d3f9fd222 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import { isArray } from 'lodash';
-import { searchUsers } from '../../api/users';
+import { getUsers } from '../../api/users';
 import { formatMeasure } from '../../helpers/measures';
 import {
   cleanQuery,
@@ -37,7 +37,7 @@ import { Facet, RawFacet } from '../../types/issues';
 import { MetricType } from '../../types/metrics';
 import { SecurityStandard } from '../../types/security';
 import { Dict, Issue, Paging, RawQuery } from '../../types/types';
-import { UserBase } from '../../types/users';
+import { RestUser } from '../../types/users';
 
 const OWASP_ASVS_4_0 = 'owaspAsvs-4.0';
 
@@ -192,9 +192,9 @@ export function formatFacetStat(stat: number | undefined) {
 export const searchAssignees = (
   query: string,
   page = 1
-): Promise<{ paging: Paging; results: UserBase[] }> => {
-  return searchUsers({ p: page, q: query }).then(({ paging, users }) => ({
-    paging,
+): Promise<{ paging: Paging; results: RestUser[] }> => {
+  return getUsers<RestUser>({ pageIndex: page, q: query }).then(({ pageRestResponse, users }) => ({
+    paging: pageRestResponse,
     results: users,
   }));
 };
index 07d5ffe584b5e56731c54e723f00390d96206ffb..68ad9c44b9c36ebfd320a7341120d8eda4595d54 100644 (file)
@@ -26,7 +26,7 @@ import BranchesServiceMock from '../../../api/mocks/BranchesServiceMock';
 import CodingRulesServiceMock from '../../../api/mocks/CodingRulesServiceMock';
 import SecurityHotspotServiceMock from '../../../api/mocks/SecurityHotspotServiceMock';
 import { getSecurityHotspots, setSecurityHotspotStatus } from '../../../api/security-hotspots';
-import { searchUsers } from '../../../api/users';
+import { getUsers } from '../../../api/users';
 import { mockComponent } from '../../../helpers/mocks/component';
 import { openHotspot, probeSonarLintServers } from '../../../helpers/sonarlint';
 import { get, save } from '../../../helpers/storage';
@@ -224,7 +224,7 @@ describe('CRUD', () => {
       await user.keyboard('User');
     });
 
-    expect(searchUsers).toHaveBeenLastCalledWith({ q: 'User' });
+    expect(getUsers).toHaveBeenLastCalledWith({ q: 'User' });
     await user.keyboard('{Enter}');
     expect(ui.successGlobalMessage.get()).toHaveTextContent(`hotspots.assign.success.User John`);
   });
index 8631310d85d5c0e2b01778dd0a4da4a653ee8a10..c732c7b7e2d04c94db221e882ebc7380e6404d37 100644 (file)
@@ -22,13 +22,13 @@ import { noop } from 'lodash';
 import * as React from 'react';
 import { Options, SingleValue } from 'react-select';
 import { assignSecurityHotspot } from '../../../api/security-hotspots';
-import { searchUsers } from '../../../api/users';
+import { getUsers } from '../../../api/users';
 import { CurrentUserContext } from '../../../app/components/current-user/CurrentUserContext';
 import Avatar from '../../../components/ui/Avatar';
 import { addGlobalSuccessMessage } from '../../../helpers/globalMessages';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { Hotspot, HotspotResolution, HotspotStatus } from '../../../types/security-hotspots';
-import { isLoggedIn, isUserActive } from '../../../types/users';
+import { RestUser, isLoggedIn, isUserActive } from '../../../types/users';
 
 interface Props {
   hotspot: Hotspot;
@@ -78,7 +78,7 @@ export default function Assignee(props: Props) {
     query: string,
     cb: (options: Options<LabelValueSelectOption<string>>) => void
   ) => {
-    searchUsers({ q: query })
+    getUsers<RestUser>({ q: query })
       .then((result) => {
         const options: Array<LabelValueSelectOption<string>> = result.users
           .filter(isUserActive)
index 4ca851e5a3901243518253cacc50fe79fe4cb9f7..fa0e959ff83eaed280a0749343926ade3400d9be 100644 (file)
 import { LabelValueSelectOption, PopupZLevel, SearchSelectDropdown } from 'design-system';
 import * as React from 'react';
 import { Options, SingleValue } from 'react-select';
-import { searchUsers } from '../../../api/users';
+import { getUsers } from '../../../api/users';
 import { CurrentUserContext } from '../../../app/components/current-user/CurrentUserContext';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { Issue } from '../../../types/types';
-import { isLoggedIn, isUserActive } from '../../../types/users';
+import { RestUser, isLoggedIn, isUserActive } from '../../../types/users';
 import Avatar from '../../ui/Avatar';
 
 interface Props {
@@ -85,7 +85,7 @@ export default function IssueAssignee(props: Props) {
     query: string,
     cb: (options: Options<LabelValueSelectOption<string>>) => void
   ) => {
-    searchUsers({ q: query })
+    getUsers<RestUser>({ q: query })
       .then((result) => {
         const options: Array<LabelValueSelectOption<string>> = result.users
           .filter(isUserActive)