Skip to content

Commit 44d8de6

Browse files
committed
Move reset password to react-query
1 parent 04fb5d3 commit 44d8de6

File tree

3 files changed

+42
-132
lines changed

3 files changed

+42
-132
lines changed

site/src/pages/UsersPage/UsersPage.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ describe("UsersPage", () => {
338338
});
339339

340340
// Check if the success message is displayed
341-
await screen.findByText(usersXServiceLanguage.resetUserPasswordSuccess);
341+
await screen.findByText("Password reset");
342342

343343
// Check if the API was called correctly
344344
expect(API.updateUserPassword).toBeCalledTimes(1);
@@ -357,7 +357,7 @@ describe("UsersPage", () => {
357357
});
358358

359359
// Check if the error message is displayed
360-
await screen.findByText(usersXServiceLanguage.resetUserPasswordError);
360+
await screen.findByText("Error resetting password");
361361

362362
// Check if the API was called correctly
363363
expect(API.updateUserPassword).toBeCalledTimes(1);

site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ import {
2626
suspendUser,
2727
activateUser,
2828
deleteUser,
29+
updatePassword,
2930
} from "api/queries/users";
3031
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
3132
import { getErrorMessage } from "api/errors";
33+
import { generateRandomString } from "utils/random";
3234

3335
export const Language = {
3436
suspendDialogTitle: "Suspend user",
@@ -39,9 +41,6 @@ export const Language = {
3941
activateDialogMessagePrefix: "Do you want to activate the user",
4042
};
4143

42-
const getSelectedUser = (id: string, users?: User[]) =>
43-
users?.find((u) => u.id === id);
44-
4544
export const UsersPage: FC<{ children?: ReactNode }> = () => {
4645
const queryClient = useQueryClient();
4746
const navigate = useNavigate();
@@ -60,7 +59,6 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
6059
offset: pagination.offset,
6160
}),
6261
);
63-
const { userIdToResetPassword, newUserPassword } = usersState.context;
6462
const { updateUsers: canEditUsers, viewDeploymentValues } = usePermissions();
6563
const rolesQuery = useQuery({ ...roles(), enabled: canEditUsers });
6664
const { data: deploymentValues } = useQuery({
@@ -104,6 +102,12 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
104102
// Delete
105103
const [confirmDeleteUser, setConfirmDeleteUser] = useState<User>();
106104
const deleteUserMutation = useMutation(deleteUser(queryClient));
105+
// Reset password
106+
const [confirmResetPassword, setConfirmResetPassword] = useState<{
107+
user: User;
108+
newPassword: string;
109+
}>();
110+
const updatePasswordMutation = useMutation(updatePassword());
107111

108112
return (
109113
<>
@@ -130,7 +134,10 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
130134
onSuspendUser={setConfirmSuspendUser}
131135
onActivateUser={setConfirmActivateUser}
132136
onResetUserPassword={(user) => {
133-
usersSend({ type: "RESET_USER_PASSWORD", userId: user.id });
137+
setConfirmResetPassword({
138+
user,
139+
newPassword: generateRandomString(12),
140+
});
134141
}}
135142
onUpdateUserRoles={(user, roles) => {
136143
usersSend({
@@ -232,23 +239,29 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
232239
}
233240
/>
234241

235-
{userIdToResetPassword && (
236-
<ResetPasswordDialog
237-
open={
238-
usersState.matches("confirmUserPasswordReset") ||
239-
usersState.matches("resettingUserPassword")
242+
<ResetPasswordDialog
243+
key={confirmResetPassword?.user.username}
244+
open={confirmResetPassword !== undefined}
245+
loading={updatePasswordMutation.isLoading}
246+
user={confirmResetPassword?.user}
247+
newPassword={confirmResetPassword?.newPassword}
248+
onClose={() => {
249+
setConfirmResetPassword(undefined);
250+
}}
251+
onConfirm={async () => {
252+
try {
253+
await updatePasswordMutation.mutateAsync({
254+
userId: confirmResetPassword!.user.id,
255+
password: confirmResetPassword!.newPassword,
256+
old_password: "",
257+
});
258+
setConfirmResetPassword(undefined);
259+
displaySuccess("Password reset");
260+
} catch (e) {
261+
displayError(getErrorMessage(e, "Error resetting password"));
240262
}
241-
loading={usersState.matches("resettingUserPassword")}
242-
user={getSelectedUser(userIdToResetPassword, usersQuery.data?.users)}
243-
newPassword={newUserPassword}
244-
onClose={() => {
245-
usersSend("CANCEL_USER_PASSWORD_RESET");
246-
}}
247-
onConfirm={() => {
248-
usersSend("CONFIRM_USER_PASSWORD_RESET");
249-
}}
250-
/>
251-
)}
263+
}}
264+
/>
252265
</>
253266
);
254267
};

site/src/xServices/users/usersXService.ts

Lines changed: 6 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,26 @@ import { assign, createMachine } from "xstate";
22
import * as API from "api/api";
33
import { getErrorMessage } from "api/errors";
44
import * as TypesGen from "api/typesGenerated";
5-
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
6-
import { generateRandomString } from "utils/random";
5+
import { displayError } from "components/GlobalSnackbar/utils";
76

87
export const Language = {
9-
resetUserPasswordSuccess: "Successfully updated the user password.",
10-
resetUserPasswordError: "Error on resetting the user password.",
118
updateUserRolesSuccess: "Successfully updated the user roles.",
129
updateUserRolesError: "Error on updating the user roles.",
1310
};
1411

1512
export interface UsersContext {
16-
// Reset user password
17-
userIdToResetPassword?: TypesGen.User["id"];
18-
resetUserPasswordError?: unknown;
19-
newUserPassword?: string;
2013
// Update user roles
2114
userIdToUpdateRoles?: TypesGen.User["id"];
2215
updateUserRolesError?: unknown;
2316
}
2417

2518
export type UsersEvent =
26-
// Reset password events
27-
| { type: "RESET_USER_PASSWORD"; userId: TypesGen.User["id"] }
28-
| { type: "CONFIRM_USER_PASSWORD_RESET" }
29-
| { type: "CANCEL_USER_PASSWORD_RESET" }
3019
// Update roles events
31-
| {
32-
type: "UPDATE_USER_ROLES";
33-
userId: TypesGen.User["id"];
34-
roles: TypesGen.Role["name"][];
35-
};
20+
{
21+
type: "UPDATE_USER_ROLES";
22+
userId: TypesGen.User["id"];
23+
roles: TypesGen.Role["name"][];
24+
};
3625

3726
export const usersMachine =
3827
/** @xstate-layout N4IgpgJg5mDOIC5QFdZgE6wMoBcCGOYAdLPujgJYB2UACnlNQRQPZUDEA2gAwC6ioAA4tYFSmwEgAHogC0ARgBMigBxEAnCoCsAdhWrdK9QBYdAGhABPRPO7ruRAMzdj3HYuNbFANm5b1AL4BFqgY2PiERDA4lDQAqmiY7BBsxNQAbiwA1sTRCWE8-EggwqLiVJIyCArc8upOxt6K-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-j-ITHPcS7DXhWc1XMTT-qATGa4jxDoK5kxWjeL0mqIJ5NczwUEIAA */
@@ -43,21 +32,6 @@ export const usersMachine =
4332
context: {} as UsersContext,
4433
events: {} as UsersEvent,
4534
services: {} as {
46-
createUser: {
47-
data: TypesGen.User;
48-
};
49-
suspendUser: {
50-
data: TypesGen.User;
51-
};
52-
deleteUser: {
53-
data: undefined;
54-
};
55-
activateUser: {
56-
data: TypesGen.User;
57-
};
58-
updateUserPassword: {
59-
data: undefined;
60-
};
6135
updateUserRoles: {
6236
data: TypesGen.User;
6337
};
@@ -70,51 +44,12 @@ export const usersMachine =
7044
idle: {
7145
entry: "clearSelectedUser",
7246
on: {
73-
RESET_USER_PASSWORD: {
74-
target: "confirmUserPasswordReset",
75-
actions: [
76-
"assignUserIdToResetPassword",
77-
"generateRandomPassword",
78-
],
79-
},
8047
UPDATE_USER_ROLES: {
8148
target: "updatingUserRoles",
8249
actions: "assignUserIdToUpdateRoles",
8350
},
8451
},
8552
},
86-
confirmUserPasswordReset: {
87-
on: {
88-
CONFIRM_USER_PASSWORD_RESET: {
89-
target: "resettingUserPassword",
90-
},
91-
CANCEL_USER_PASSWORD_RESET: {
92-
target: "idle",
93-
},
94-
},
95-
},
96-
resettingUserPassword: {
97-
entry: "clearResetUserPasswordError",
98-
invoke: {
99-
src: "resetUserPassword",
100-
id: "resetUserPassword",
101-
onDone: [
102-
{
103-
target: "idle",
104-
actions: "displayResetPasswordSuccess",
105-
},
106-
],
107-
onError: [
108-
{
109-
target: "idle",
110-
actions: [
111-
"assignResetUserPasswordError",
112-
"displayResetPasswordErrorMessage",
113-
],
114-
},
115-
],
116-
},
117-
},
11853
updatingUserRoles: {
11954
entry: "clearUpdateUserRolesError",
12055
invoke: {
@@ -141,20 +76,6 @@ export const usersMachine =
14176
},
14277
{
14378
services: {
144-
resetUserPassword: (context) => {
145-
if (!context.userIdToResetPassword) {
146-
throw new Error("userIdToResetPassword is undefined");
147-
}
148-
149-
if (!context.newUserPassword) {
150-
throw new Error("newUserPassword not generated");
151-
}
152-
153-
return API.updateUserPassword(context.userIdToResetPassword, {
154-
password: context.newUserPassword,
155-
old_password: "",
156-
});
157-
},
15879
updateUserRoles: (context, event) => {
15980
if (!context.userIdToUpdateRoles) {
16081
throw new Error("userIdToUpdateRoles is undefined");
@@ -166,51 +87,27 @@ export const usersMachine =
16687

16788
actions: {
16889
clearSelectedUser: assign({
169-
userIdToResetPassword: (_) => undefined,
17090
userIdToUpdateRoles: (_) => undefined,
17191
}),
17292

173-
assignUserIdToResetPassword: assign({
174-
userIdToResetPassword: (_, event) => event.userId,
175-
}),
17693
assignUserIdToUpdateRoles: assign({
17794
userIdToUpdateRoles: (_, event) => event.userId,
17895
}),
17996

180-
assignResetUserPasswordError: assign({
181-
resetUserPasswordError: (_, event) => event.data,
182-
}),
18397
assignUpdateRolesError: assign({
18498
updateUserRolesError: (_, event) => event.data,
18599
}),
186100

187-
clearResetUserPasswordError: assign({
188-
resetUserPasswordError: (_) => undefined,
189-
}),
190101
clearUpdateUserRolesError: assign({
191102
updateUserRolesError: (_) => undefined,
192103
}),
193-
194-
displayResetPasswordSuccess: () => {
195-
displaySuccess(Language.resetUserPasswordSuccess);
196-
},
197-
displayResetPasswordErrorMessage: (context) => {
198-
const message = getErrorMessage(
199-
context.resetUserPasswordError,
200-
Language.resetUserPasswordError,
201-
);
202-
displayError(message);
203-
},
204104
displayUpdateRolesErrorMessage: (context) => {
205105
const message = getErrorMessage(
206106
context.updateUserRolesError,
207107
Language.updateUserRolesError,
208108
);
209109
displayError(message);
210110
},
211-
generateRandomPassword: assign({
212-
newUserPassword: (_) => generateRandomString(12),
213-
}),
214111
updateUserRolesInTheList: assign({
215112
// users: ({ users }, event) => {
216113
// if (!users) {

0 commit comments

Comments
 (0)