]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20532 Add API call for GitHub custom role mapping
authorMathieu Suen <mathieu.suen@sonarsource.com>
Tue, 26 Sep 2023 12:54:21 +0000 (14:54 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 28 Sep 2023 20:03:11 +0000 (20:03 +0000)
server/sonar-web/src/main/js/api/provisioning.ts
server/sonar-web/src/main/js/queries/identity-provider.ts

index b33172edd22ed664f40c29867b83f8d00970093f..b65ded5c9a27da5e4f1f91153605c2886ed03ab8 100644 (file)
@@ -68,3 +68,11 @@ export function updateGithubRolesMapping(
 ) {
   return axios.patch<GitHubMapping>(`/api/v2/github-permission-mappings/${role}`, data);
 }
+
+export function addGithubRolesMapping(data: Omit<GitHubMapping, 'id'>) {
+  return axios.post<GitHubMapping>(`/api/v2/github-permission-mappings/`, data);
+}
+
+export function deleteGithubRolesMapping(role: string) {
+  return axios.delete(`/api/v2/github-permission-mappings/${role}`);
+}
index 7d6702739a7400f993640e3af513a2eb3c190fff..8a20c11108d04381133bb5b4a64c412521820d70 100644 (file)
  */
 
 import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
-import { isEqual, omit } from 'lodash';
+import { isEqual, keyBy, omit, partition } from 'lodash';
 import { useContext } from 'react';
 import {
   activateGithubProvisioning,
   activateScim,
+  addGithubRolesMapping,
   checkConfigurationValidity,
   deactivateGithubProvisioning,
   deactivateScim,
+  deleteGithubRolesMapping,
   fetchGithubProvisioningStatus,
   fetchGithubRolesMapping,
   fetchIsScimEnabled,
@@ -122,13 +124,14 @@ export function useSyncWithGitHubNow() {
   };
 }
 
+const defaultRoleOrder = ['admin', 'maintain', 'write', 'triage', 'read'];
+
 export function useGithubRolesMappingQuery() {
   return useQuery(['identity_provider', 'github_mapping'], fetchGithubRolesMapping, {
     staleTime: MAPPING_STALE_TIME,
     select: (data) =>
       [...data].sort((a, b) => {
         // Order is reversed to put non-existing roles at the end (their index is -1)
-        const defaultRoleOrder = ['admin', 'maintain', 'write', 'triage', 'read'];
         if (defaultRoleOrder.includes(a.id) || defaultRoleOrder.includes(b.id)) {
           return defaultRoleOrder.indexOf(b.id) - defaultRoleOrder.indexOf(a.id);
         }
@@ -141,32 +144,37 @@ export function useGithubRolesMappingMutation() {
   const client = useQueryClient();
   const queryKey = ['identity_provider', 'github_mapping'];
   return useMutation({
-    mutationFn: (mapping: GitHubMapping[]) => {
-      const state = client.getQueryData<GitHubMapping[]>(queryKey);
-      const changedRoles = state
-        ? mapping.filter(
-            (item) =>
-              !isEqual(
-                item,
-                state.find((el) => el.id === item.id),
-              ),
-          )
-        : mapping;
-      return Promise.all(
-        changedRoles.map((data) => updateGithubRolesMapping(data.id, omit(data, 'id', 'roleName'))),
+    mutationFn: async (mapping: GitHubMapping[]) => {
+      const [defaultMapping, customMapping] = partition(mapping, (m) =>
+        defaultRoleOrder.includes(m.roleName),
+      );
+      const state = keyBy(client.getQueryData<GitHubMapping[]>(queryKey), (m) => m.id);
+
+      const [customMaybeChangedmRoles, customNewRoles] = partition(
+        customMapping,
+        (m) => state[m.id],
+      );
+
+      const changeRole = [...defaultMapping, ...customMaybeChangedmRoles].filter(
+        (item) => !isEqual(item, state[item.id]),
+      );
+
+      const customDeleteRole = Object.values(state).filter(
+        (m) => !defaultRoleOrder.includes(m.roleName) && !changeRole.some((cm) => m.id === cm.id),
       );
+
+      return {
+        addedOrChange: await Promise.all([
+          ...changeRole.map((data) =>
+            updateGithubRolesMapping(data.id, omit(data, 'id', 'roleName')),
+          ),
+          ...customNewRoles.map((m) => addGithubRolesMapping(m)),
+        ]),
+        delete: await Promise.all([customDeleteRole.map((dm) => deleteGithubRolesMapping(dm.id))]),
+      };
     },
-    onSuccess: (data) => {
-      const state = client.getQueryData<GitHubMapping[]>(queryKey);
-      if (state) {
-        client.setQueryData(
-          queryKey,
-          state.map((item) => {
-            const changed = data.find((el) => el.id === item.id);
-            return changed ?? item;
-          }),
-        );
-      }
+    onSuccess: ({ addedOrChange }) => {
+      client.setQueryData(queryKey, addedOrChange);
     },
   });
 }