From 8f5f6da990cc5a41dc85baf7c57f454b9fd7c59b Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 18 Oct 2023 14:04:21 +0000 Subject: [PATCH 1/5] Extract loading template ACL --- site/src/api/queries/templates.ts | 7 +++++++ .../TemplatePermissionsPage.tsx | 12 ++++++++++-- site/src/xServices/template/templateACLXService.ts | 12 +++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index e5a39a015b661..a548a8d47233a 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -36,6 +36,13 @@ export const templates = (orgId: string) => { }; }; +export const templateACL = (templateId: string) => { + return { + queryKey: ["templateAcl", templateId], + queryFn: () => API.getTemplateACL(templateId), + }; +}; + export const templateExamples = (orgId: string) => { return { queryKey: [...getTemplatesQueryKey(orgId), "examples"], diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index 898202bd51b7c..0244762bb43d5 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -13,6 +13,8 @@ import { templateACLMachine } from "xServices/template/templateACLXService"; import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"; import { docs } from "utils/docs"; +import { useQuery } from "react-query"; +import { templateACL } from "api/queries/templates"; export const TemplatePermissionsPage: FC< React.PropsWithChildren @@ -23,7 +25,13 @@ export const TemplatePermissionsPage: FC< const [state, send] = useMachine(templateACLMachine, { context: { templateId: template.id }, }); - const { templateACL, userToBeUpdated, groupToBeUpdated } = state.context; + const { userToBeUpdated, groupToBeUpdated } = state.context; + const templateACLQuery = useQuery({ + ...templateACL(template.id), + onSuccess: (data) => { + send({ type: "LOAD", data }); + }, + }); return ( <> @@ -58,7 +66,7 @@ export const TemplatePermissionsPage: FC< { send("ADD_USER", { user, role, onDone: reset }); diff --git a/site/src/xServices/template/templateACLXService.ts b/site/src/xServices/template/templateACLXService.ts index 9b0b1e7462d1d..7748d416c86e4 100644 --- a/site/src/xServices/template/templateACLXService.ts +++ b/site/src/xServices/template/templateACLXService.ts @@ -1,4 +1,4 @@ -import { getTemplateACL, updateTemplateACL } from "api/api"; +import { updateTemplateACL } from "api/api"; import { TemplateACL, TemplateGroup, @@ -43,6 +43,10 @@ export const templateACLMachine = createMachine( }; }, events: {} as // User + | { + type: "LOAD"; + data: TemplateACL; + } | { type: "ADD_USER"; user: TemplateUser; @@ -80,9 +84,8 @@ export const templateACLMachine = createMachine( initial: "loading", states: { loading: { - invoke: { - src: "loadTemplateACL", - onDone: { + on: { + LOAD: { actions: ["assignTemplateACL"], target: "idle", }, @@ -183,7 +186,6 @@ export const templateACLMachine = createMachine( }, { services: { - loadTemplateACL: ({ templateId }) => getTemplateACL(templateId), // User addUser: ({ templateId }, { user, role }) => updateTemplateACL(templateId, { From f424a70de78d72b0aab4dc9dfb39c981c07fefa8 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 18 Oct 2023 14:41:10 +0000 Subject: [PATCH 2/5] Extract adding user --- site/src/api/api.ts | 2 +- site/src/api/queries/templates.ts | 27 +++++++++- .../TemplatePermissionsPage.tsx | 17 +++++-- .../xServices/template/templateACLXService.ts | 49 ------------------- 4 files changed, 39 insertions(+), 56 deletions(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index dccdc383ccbf9..c602a727e389e 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -947,7 +947,7 @@ export const getTemplateACL = async ( export const updateTemplateACL = async ( templateId: string, data: TypesGen.UpdateTemplateACL, -): Promise => { +): Promise<{ message: string }> => { const response = await axios.patch( `/api/v2/templates/${templateId}/acl`, data, diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index a548a8d47233a..ba7dcd3111bb1 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -6,8 +6,13 @@ import { type TemplateVersion, CreateTemplateRequest, ProvisionerJob, + TemplateRole, } from "api/typesGenerated"; -import { type QueryClient, type QueryOptions } from "react-query"; +import { + MutationOptions, + type QueryClient, + type QueryOptions, +} from "react-query"; import { delay } from "utils/delay"; export const templateByNameKey = (orgId: string, name: string) => [ @@ -43,6 +48,26 @@ export const templateACL = (templateId: string) => { }; }; +export const addUserToTemplateACL = ( + queryClient: QueryClient, +): MutationOptions< + Awaited>, + unknown, + { templateId: string; userId: string; role: TemplateRole } +> => { + return { + mutationFn: ({ templateId, userId, role }) => + API.updateTemplateACL(templateId, { + user_perms: { + [userId]: role, + }, + }), + onSuccess: async (templateAcl, { templateId }) => { + await queryClient.invalidateQueries(["templateAcl", templateId]); + }, + }; +}; + export const templateExamples = (orgId: string) => { return { queryKey: [...getTemplatesQueryKey(orgId), "examples"], diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index 0244762bb43d5..e057d9c9d77e1 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -13,8 +13,8 @@ import { templateACLMachine } from "xServices/template/templateACLXService"; import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"; import { docs } from "utils/docs"; -import { useQuery } from "react-query"; -import { templateACL } from "api/queries/templates"; +import { useMutation, useQuery, useQueryClient } from "react-query"; +import { addUserToTemplateACL, templateACL } from "api/queries/templates"; export const TemplatePermissionsPage: FC< React.PropsWithChildren @@ -32,6 +32,8 @@ export const TemplatePermissionsPage: FC< send({ type: "LOAD", data }); }, }); + const queryClient = useQueryClient(); + const addUserMutation = useMutation(addUserToTemplateACL(queryClient)); return ( <> @@ -68,10 +70,15 @@ export const TemplatePermissionsPage: FC< templateID={template.id} templateACL={templateACLQuery.data} canUpdatePermissions={Boolean(permissions?.canUpdateTemplate)} - onAddUser={(user, role, reset) => { - send("ADD_USER", { user, role, onDone: reset }); + onAddUser={async (user, role, reset) => { + await addUserMutation.mutateAsync({ + templateId: template.id, + userId: user.id, + role, + }); + reset(); }} - isAddingUser={state.matches("addingUser")} + isAddingUser={addUserMutation.isLoading} onUpdateUser={(user, role) => { send("UPDATE_USER_ROLE", { user, role }); }} diff --git a/site/src/xServices/template/templateACLXService.ts b/site/src/xServices/template/templateACLXService.ts index 7748d416c86e4..45e93976e9a77 100644 --- a/site/src/xServices/template/templateACLXService.ts +++ b/site/src/xServices/template/templateACLXService.ts @@ -15,7 +15,6 @@ export const templateACLMachine = createMachine( templateId: string; templateACL?: TemplateACL; // User - userToBeAdded?: TemplateUser; userToBeUpdated?: TemplateUser; addUserCallback?: () => void; // Group @@ -28,9 +27,6 @@ export const templateACLMachine = createMachine( data: TemplateACL; }; // User - addUser: { - data: unknown; - }; updateUser: { data: unknown; }; @@ -47,12 +43,6 @@ export const templateACLMachine = createMachine( type: "LOAD"; data: TemplateACL; } - | { - type: "ADD_USER"; - user: TemplateUser; - role: TemplateRole; - onDone: () => void; - } | { type: "UPDATE_USER_ROLE"; user: TemplateUser; @@ -94,7 +84,6 @@ export const templateACLMachine = createMachine( idle: { on: { // User - ADD_USER: { target: "addingUser", actions: ["assignUserToBeAdded"] }, UPDATE_USER_ROLE: { target: "updatingUser", actions: ["assignUserToBeUpdated"], @@ -119,15 +108,6 @@ export const templateACLMachine = createMachine( }, }, // User - addingUser: { - invoke: { - src: "addUser", - onDone: { - target: "idle", - actions: ["addUserToTemplateACL", "runAddUserCallback"], - }, - }, - }, updatingUser: { invoke: { src: "updateUser", @@ -187,12 +167,6 @@ export const templateACLMachine = createMachine( { services: { // User - addUser: ({ templateId }, { user, role }) => - updateTemplateACL(templateId, { - user_perms: { - [user.id]: role, - }, - }), updateUser: ({ templateId }, { user, role }) => updateTemplateACL(templateId, { user_perms: { @@ -230,29 +204,6 @@ export const templateACLMachine = createMachine( templateACL: (_, { data }) => data, }), // User - assignUserToBeAdded: assign({ - userToBeAdded: (_, { user, role }) => ({ ...user, role }), - addUserCallback: (_, { onDone }) => onDone, - }), - addUserToTemplateACL: assign({ - templateACL: ({ templateACL, userToBeAdded }) => { - if (!userToBeAdded) { - throw new Error("No user to be added"); - } - if (!templateACL) { - throw new Error("Template ACL is not loaded yet"); - } - return { - ...templateACL, - users: [...templateACL.users, userToBeAdded], - }; - }, - }), - runAddUserCallback: ({ addUserCallback }) => { - if (addUserCallback) { - addUserCallback(); - } - }, assignUserToBeUpdated: assign({ userToBeUpdated: (_, { user, role }) => ({ ...user, role }), }), From 82fba2fc90f20e8a4c765194f6a7f707879c0da1 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 18 Oct 2023 16:45:55 +0000 Subject: [PATCH 3/5] Extract update user role --- site/src/api/queries/templates.ts | 2 +- .../TemplatePermissionsPage.tsx | 23 +++++-- .../TemplatePermissionsPageView.tsx | 8 +-- .../xServices/template/templateACLXService.ts | 61 ------------------- 4 files changed, 21 insertions(+), 73 deletions(-) diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index ba7dcd3111bb1..dba9aad0ed31b 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -48,7 +48,7 @@ export const templateACL = (templateId: string) => { }; }; -export const addUserToTemplateACL = ( +export const setUserRole = ( queryClient: QueryClient, ): MutationOptions< Awaited>, diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index e057d9c9d77e1..83e4acee838fc 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -14,7 +14,8 @@ import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"; import { docs } from "utils/docs"; import { useMutation, useQuery, useQueryClient } from "react-query"; -import { addUserToTemplateACL, templateACL } from "api/queries/templates"; +import { setUserRole, templateACL } from "api/queries/templates"; +import { displaySuccess } from "components/GlobalSnackbar/utils"; export const TemplatePermissionsPage: FC< React.PropsWithChildren @@ -25,7 +26,7 @@ export const TemplatePermissionsPage: FC< const [state, send] = useMachine(templateACLMachine, { context: { templateId: template.id }, }); - const { userToBeUpdated, groupToBeUpdated } = state.context; + const { groupToBeUpdated } = state.context; const templateACLQuery = useQuery({ ...templateACL(template.id), onSuccess: (data) => { @@ -33,7 +34,8 @@ export const TemplatePermissionsPage: FC< }, }); const queryClient = useQueryClient(); - const addUserMutation = useMutation(addUserToTemplateACL(queryClient)); + const addUserMutation = useMutation(setUserRole(queryClient)); + const updateUserMutation = useMutation(setUserRole(queryClient)); return ( <> @@ -79,10 +81,19 @@ export const TemplatePermissionsPage: FC< reset(); }} isAddingUser={addUserMutation.isLoading} - onUpdateUser={(user, role) => { - send("UPDATE_USER_ROLE", { user, role }); + onUpdateUser={async (user, role) => { + await updateUserMutation.mutateAsync({ + templateId: template.id, + userId: user.id, + role, + }); + displaySuccess("User role updated successfully!"); }} - updatingUser={userToBeUpdated} + updatingUserId={ + updateUserMutation.isLoading + ? updateUserMutation.variables?.userId + : undefined + } onRemoveUser={(user) => { send("REMOVE_USER", { user }); }} diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx index e106242ccc443..6502d78402ffb 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx @@ -161,7 +161,7 @@ export interface TemplatePermissionsPageViewProps { ) => void; isAddingUser: boolean; onUpdateUser: (user: TemplateUser, role: TemplateRole) => void; - updatingUser: TemplateUser | undefined; + updatingUserId: TemplateUser["id"] | undefined; onRemoveUser: (user: TemplateUser) => void; // Group onAddGroup: ( @@ -185,7 +185,7 @@ export const TemplatePermissionsPageView: FC< // User onAddUser, isAddingUser, - updatingUser, + updatingUserId, onUpdateUser, onRemoveUser, // Group @@ -313,9 +313,7 @@ export const TemplatePermissionsPageView: FC< { onUpdateUser( user, diff --git a/site/src/xServices/template/templateACLXService.ts b/site/src/xServices/template/templateACLXService.ts index 45e93976e9a77..ee43872a36cd5 100644 --- a/site/src/xServices/template/templateACLXService.ts +++ b/site/src/xServices/template/templateACLXService.ts @@ -14,9 +14,6 @@ export const templateACLMachine = createMachine( context: {} as { templateId: string; templateACL?: TemplateACL; - // User - userToBeUpdated?: TemplateUser; - addUserCallback?: () => void; // Group groupToBeAdded?: TemplateGroup; groupToBeUpdated?: TemplateGroup; @@ -27,9 +24,6 @@ export const templateACLMachine = createMachine( data: TemplateACL; }; // User - updateUser: { - data: unknown; - }; // Group addGroup: { data: unknown; @@ -43,11 +37,6 @@ export const templateACLMachine = createMachine( type: "LOAD"; data: TemplateACL; } - | { - type: "UPDATE_USER_ROLE"; - user: TemplateUser; - role: TemplateRole; - } | { type: "REMOVE_USER"; user: TemplateUser; @@ -84,10 +73,6 @@ export const templateACLMachine = createMachine( idle: { on: { // User - UPDATE_USER_ROLE: { - target: "updatingUser", - actions: ["assignUserToBeUpdated"], - }, REMOVE_USER: { target: "removingUser", actions: ["removeUserFromTemplateACL"], @@ -108,19 +93,6 @@ export const templateACLMachine = createMachine( }, }, // User - updatingUser: { - invoke: { - src: "updateUser", - onDone: { - target: "idle", - actions: [ - "updateUserOnTemplateACL", - "clearUserToBeUpdated", - "displayUpdateUserSuccessMessage", - ], - }, - }, - }, removingUser: { invoke: { src: "removeUser", @@ -167,12 +139,6 @@ export const templateACLMachine = createMachine( { services: { // User - updateUser: ({ templateId }, { user, role }) => - updateTemplateACL(templateId, { - user_perms: { - [user.id]: role, - }, - }), removeUser: ({ templateId }, { user }) => updateTemplateACL(templateId, { user_perms: { @@ -204,33 +170,6 @@ export const templateACLMachine = createMachine( templateACL: (_, { data }) => data, }), // User - assignUserToBeUpdated: assign({ - userToBeUpdated: (_, { user, role }) => ({ ...user, role }), - }), - updateUserOnTemplateACL: assign({ - templateACL: ({ templateACL, userToBeUpdated }) => { - if (!userToBeUpdated) { - throw new Error("No user to be added"); - } - if (!templateACL) { - throw new Error("Template ACL is not loaded yet"); - } - return { - ...templateACL, - users: templateACL.users.map((oldTemplateUser) => { - return oldTemplateUser.id === userToBeUpdated.id - ? userToBeUpdated - : oldTemplateUser; - }), - }; - }, - }), - clearUserToBeUpdated: assign({ - userToBeUpdated: (_) => undefined, - }), - displayUpdateUserSuccessMessage: () => { - displaySuccess("User role update successfully!"); - }, removeUserFromTemplateACL: assign({ templateACL: ({ templateACL }, { user }) => { if (!templateACL) { From f972b82a1512394a8b0fbcf97e796eedfcffd5c5 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 18 Oct 2023 16:49:37 +0000 Subject: [PATCH 4/5] Extract user remove --- .../TemplatePermissionsPage.tsx | 10 +++- .../xServices/template/templateACLXService.ts | 51 +------------------ 2 files changed, 9 insertions(+), 52 deletions(-) diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index 83e4acee838fc..27210425d2621 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -36,6 +36,7 @@ export const TemplatePermissionsPage: FC< const queryClient = useQueryClient(); const addUserMutation = useMutation(setUserRole(queryClient)); const updateUserMutation = useMutation(setUserRole(queryClient)); + const removeUserMutation = useMutation(setUserRole(queryClient)); return ( <> @@ -94,8 +95,13 @@ export const TemplatePermissionsPage: FC< ? updateUserMutation.variables?.userId : undefined } - onRemoveUser={(user) => { - send("REMOVE_USER", { user }); + onRemoveUser={async (user) => { + await removeUserMutation.mutateAsync({ + templateId: template.id, + userId: user.id, + role: "", + }); + displaySuccess("User removed successfully!"); }} onAddGroup={(group, role, reset) => { send("ADD_GROUP", { group, role, onDone: reset }); diff --git a/site/src/xServices/template/templateACLXService.ts b/site/src/xServices/template/templateACLXService.ts index ee43872a36cd5..453d4fdc1630e 100644 --- a/site/src/xServices/template/templateACLXService.ts +++ b/site/src/xServices/template/templateACLXService.ts @@ -1,10 +1,5 @@ import { updateTemplateACL } from "api/api"; -import { - TemplateACL, - TemplateGroup, - TemplateRole, - TemplateUser, -} from "api/typesGenerated"; +import { TemplateACL, TemplateGroup, TemplateRole } from "api/typesGenerated"; import { displaySuccess } from "components/GlobalSnackbar/utils"; import { assign, createMachine } from "xstate"; @@ -23,7 +18,6 @@ export const templateACLMachine = createMachine( loadTemplateACL: { data: TemplateACL; }; - // User // Group addGroup: { data: unknown; @@ -37,10 +31,6 @@ export const templateACLMachine = createMachine( type: "LOAD"; data: TemplateACL; } - | { - type: "REMOVE_USER"; - user: TemplateUser; - } // Group | { type: "ADD_GROUP"; @@ -72,11 +62,6 @@ export const templateACLMachine = createMachine( }, idle: { on: { - // User - REMOVE_USER: { - target: "removingUser", - actions: ["removeUserFromTemplateACL"], - }, // Group ADD_GROUP: { target: "addingGroup", @@ -92,16 +77,6 @@ export const templateACLMachine = createMachine( }, }, }, - // User - removingUser: { - invoke: { - src: "removeUser", - onDone: { - target: "idle", - actions: ["displayRemoveUserSuccessMessage"], - }, - }, - }, // Group addingGroup: { invoke: { @@ -138,13 +113,6 @@ export const templateACLMachine = createMachine( }, { services: { - // User - removeUser: ({ templateId }, { user }) => - updateTemplateACL(templateId, { - user_perms: { - [user.id]: "", - }, - }), // Group addGroup: ({ templateId }, { group, role }) => updateTemplateACL(templateId, { @@ -169,23 +137,6 @@ export const templateACLMachine = createMachine( assignTemplateACL: assign({ templateACL: (_, { data }) => data, }), - // User - removeUserFromTemplateACL: assign({ - templateACL: ({ templateACL }, { user }) => { - if (!templateACL) { - throw new Error("Template ACL is not loaded yet"); - } - return { - ...templateACL, - users: templateACL.users.filter((oldTemplateUser) => { - return oldTemplateUser.id !== user.id; - }), - }; - }, - }), - displayRemoveUserSuccessMessage: () => { - displaySuccess("User removed successfully!"); - }, // Group assignGroupToBeAdded: assign({ groupToBeAdded: (_, { group, role }) => ({ ...group, role }), From 1bf584e95f9a616c77d7582cf8f444baf6f6a5f9 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 18 Oct 2023 17:49:34 +0000 Subject: [PATCH 5/5] Extract all the groups actions from machine and remove it --- site/src/api/queries/templates.ts | 22 +- .../TemplatePermissionsPage.tsx | 55 +++-- .../TemplatePermissionsPageView.tsx | 8 +- .../xServices/template/templateACLXService.ts | 209 ------------------ 4 files changed, 58 insertions(+), 236 deletions(-) delete mode 100644 site/src/xServices/template/templateACLXService.ts diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index dba9aad0ed31b..a295832fca00e 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -62,7 +62,27 @@ export const setUserRole = ( [userId]: role, }, }), - onSuccess: async (templateAcl, { templateId }) => { + onSuccess: async (_res, { templateId }) => { + await queryClient.invalidateQueries(["templateAcl", templateId]); + }, + }; +}; + +export const setGroupRole = ( + queryClient: QueryClient, +): MutationOptions< + Awaited>, + unknown, + { templateId: string; groupId: string; role: TemplateRole } +> => { + return { + mutationFn: ({ templateId, groupId, role }) => + API.updateTemplateACL(templateId, { + group_perms: { + [groupId]: role, + }, + }), + onSuccess: async (_res, { templateId }) => { await queryClient.invalidateQueries(["templateAcl", templateId]); }, }; diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index 27210425d2621..6cf11ec1faf62 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -1,7 +1,6 @@ import Button from "@mui/material/Button"; import Link from "@mui/material/Link"; import ArrowRightAltOutlined from "@mui/icons-material/ArrowRightAltOutlined"; -import { useMachine } from "@xstate/react"; import { Paywall } from "components/Paywall/Paywall"; import { Stack } from "components/Stack/Stack"; import { useFeatureVisibility } from "hooks/useFeatureVisibility"; @@ -9,12 +8,11 @@ import { useOrganizationId } from "hooks/useOrganizationId"; import { FC } from "react"; import { Helmet } from "react-helmet-async"; import { pageTitle } from "utils/page"; -import { templateACLMachine } from "xServices/template/templateACLXService"; import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"; import { docs } from "utils/docs"; import { useMutation, useQuery, useQueryClient } from "react-query"; -import { setUserRole, templateACL } from "api/queries/templates"; +import { setGroupRole, setUserRole, templateACL } from "api/queries/templates"; import { displaySuccess } from "components/GlobalSnackbar/utils"; export const TemplatePermissionsPage: FC< @@ -23,21 +21,17 @@ export const TemplatePermissionsPage: FC< const organizationId = useOrganizationId(); const { template, permissions } = useTemplateSettings(); const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility(); - const [state, send] = useMachine(templateACLMachine, { - context: { templateId: template.id }, - }); - const { groupToBeUpdated } = state.context; - const templateACLQuery = useQuery({ - ...templateACL(template.id), - onSuccess: (data) => { - send({ type: "LOAD", data }); - }, - }); + const templateACLQuery = useQuery(templateACL(template.id)); const queryClient = useQueryClient(); + const addUserMutation = useMutation(setUserRole(queryClient)); const updateUserMutation = useMutation(setUserRole(queryClient)); const removeUserMutation = useMutation(setUserRole(queryClient)); + const addGroupMutation = useMutation(setGroupRole(queryClient)); + const updateGroupMutation = useMutation(setGroupRole(queryClient)); + const removeGroupMutation = useMutation(setGroupRole(queryClient)); + return ( <> @@ -103,16 +97,35 @@ export const TemplatePermissionsPage: FC< }); displaySuccess("User removed successfully!"); }} - onAddGroup={(group, role, reset) => { - send("ADD_GROUP", { group, role, onDone: reset }); + onAddGroup={async (group, role, reset) => { + await addGroupMutation.mutateAsync({ + templateId: template.id, + groupId: group.id, + role, + }); + reset(); }} - isAddingGroup={state.matches("addingGroup")} - onUpdateGroup={(group, role) => { - send("UPDATE_GROUP_ROLE", { group, role }); + isAddingGroup={addGroupMutation.isLoading} + onUpdateGroup={async (group, role) => { + await updateGroupMutation.mutateAsync({ + templateId: template.id, + groupId: group.id, + role, + }); + displaySuccess("Group role updated successfully!"); }} - updatingGroup={groupToBeUpdated} - onRemoveGroup={(group) => { - send("REMOVE_GROUP", { group }); + updatingGroupId={ + updateGroupMutation.isLoading + ? updateGroupMutation.variables?.groupId + : undefined + } + onRemoveGroup={async (group) => { + await removeGroupMutation.mutateAsync({ + groupId: group.id, + templateId: template.id, + role: "", + }); + displaySuccess("Group removed successfully!"); }} /> )} diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx index 6502d78402ffb..a4cded2abe1b6 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx @@ -171,7 +171,7 @@ export interface TemplatePermissionsPageViewProps { ) => void; isAddingGroup: boolean; onUpdateGroup: (group: TemplateGroup, role: TemplateRole) => void; - updatingGroup: TemplateGroup | undefined; + updatingGroupId?: TemplateGroup["id"] | undefined; onRemoveGroup: (group: Group) => void; } @@ -191,7 +191,7 @@ export const TemplatePermissionsPageView: FC< // Group onAddGroup, isAddingGroup, - updatingGroup, + updatingGroupId, onUpdateGroup, onRemoveGroup, }) => { @@ -265,9 +265,7 @@ export const TemplatePermissionsPageView: FC< { onUpdateGroup( group, diff --git a/site/src/xServices/template/templateACLXService.ts b/site/src/xServices/template/templateACLXService.ts deleted file mode 100644 index 453d4fdc1630e..0000000000000 --- a/site/src/xServices/template/templateACLXService.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { updateTemplateACL } from "api/api"; -import { TemplateACL, TemplateGroup, TemplateRole } from "api/typesGenerated"; -import { displaySuccess } from "components/GlobalSnackbar/utils"; -import { assign, createMachine } from "xstate"; - -export const templateACLMachine = createMachine( - { - schema: { - context: {} as { - templateId: string; - templateACL?: TemplateACL; - // Group - groupToBeAdded?: TemplateGroup; - groupToBeUpdated?: TemplateGroup; - addGroupCallback?: () => void; - }, - services: {} as { - loadTemplateACL: { - data: TemplateACL; - }; - // Group - addGroup: { - data: unknown; - }; - updateGroup: { - data: unknown; - }; - }, - events: {} as // User - | { - type: "LOAD"; - data: TemplateACL; - } - // Group - | { - type: "ADD_GROUP"; - group: TemplateGroup; - role: TemplateRole; - onDone: () => void; - } - | { - type: "UPDATE_GROUP_ROLE"; - group: TemplateGroup; - role: TemplateRole; - } - | { - type: "REMOVE_GROUP"; - group: TemplateGroup; - }, - }, - tsTypes: {} as import("./templateACLXService.typegen").Typegen0, - id: "templateACL", - initial: "loading", - states: { - loading: { - on: { - LOAD: { - actions: ["assignTemplateACL"], - target: "idle", - }, - }, - }, - idle: { - on: { - // Group - ADD_GROUP: { - target: "addingGroup", - actions: ["assignGroupToBeAdded"], - }, - UPDATE_GROUP_ROLE: { - target: "updatingGroup", - actions: ["assignGroupToBeUpdated"], - }, - REMOVE_GROUP: { - target: "removingGroup", - actions: ["removeGroupFromTemplateACL"], - }, - }, - }, - // Group - addingGroup: { - invoke: { - src: "addGroup", - onDone: { - target: "idle", - actions: ["addGroupToTemplateACL", "runAddGroupCallback"], - }, - }, - }, - updatingGroup: { - invoke: { - src: "updateGroup", - onDone: { - target: "idle", - actions: [ - "updateGroupOnTemplateACL", - "clearGroupToBeUpdated", - "displayUpdateGroupSuccessMessage", - ], - }, - }, - }, - removingGroup: { - invoke: { - src: "removeGroup", - onDone: { - target: "idle", - actions: ["displayRemoveGroupSuccessMessage"], - }, - }, - }, - }, - }, - { - services: { - // Group - addGroup: ({ templateId }, { group, role }) => - updateTemplateACL(templateId, { - group_perms: { - [group.id]: role, - }, - }), - updateGroup: ({ templateId }, { group, role }) => - updateTemplateACL(templateId, { - group_perms: { - [group.id]: role, - }, - }), - removeGroup: ({ templateId }, { group }) => - updateTemplateACL(templateId, { - group_perms: { - [group.id]: "", - }, - }), - }, - actions: { - assignTemplateACL: assign({ - templateACL: (_, { data }) => data, - }), - // Group - assignGroupToBeAdded: assign({ - groupToBeAdded: (_, { group, role }) => ({ ...group, role }), - addGroupCallback: (_, { onDone }) => onDone, - }), - addGroupToTemplateACL: assign({ - templateACL: ({ templateACL, groupToBeAdded }) => { - if (!groupToBeAdded) { - throw new Error("No group to be added"); - } - if (!templateACL) { - throw new Error("Template ACL is not loaded yet"); - } - return { - ...templateACL, - group: [...templateACL.group, groupToBeAdded], - }; - }, - }), - runAddGroupCallback: ({ addGroupCallback }) => { - if (addGroupCallback) { - addGroupCallback(); - } - }, - assignGroupToBeUpdated: assign({ - groupToBeUpdated: (_, { group, role }) => ({ ...group, role }), - }), - updateGroupOnTemplateACL: assign({ - templateACL: ({ templateACL, groupToBeUpdated }) => { - if (!groupToBeUpdated) { - throw new Error("No group to be added"); - } - if (!templateACL) { - throw new Error("Template ACL is not loaded yet"); - } - return { - ...templateACL, - group: templateACL.group.map((oldTemplateGroup) => { - return oldTemplateGroup.id === groupToBeUpdated.id - ? groupToBeUpdated - : oldTemplateGroup; - }), - }; - }, - }), - clearGroupToBeUpdated: assign({ - groupToBeUpdated: (_) => undefined, - }), - displayUpdateGroupSuccessMessage: () => { - displaySuccess("Group role update successfully!"); - }, - removeGroupFromTemplateACL: assign({ - templateACL: ({ templateACL }, { group }) => { - if (!templateACL) { - throw new Error("Template ACL is not loaded yet"); - } - return { - ...templateACL, - group: templateACL.group.filter((oldTemplateGroup) => { - return oldTemplateGroup.id !== group.id; - }), - }; - }, - }), - displayRemoveGroupSuccessMessage: () => { - displaySuccess("Group removed successfully!"); - }, - }, - }, -);