Skip to content

Commit 6dacf70

Browse files
johnstcnjsjoeio
andauthored
fix: disable AccountForm when user is not allowed edit users (#3649)
* RED: add unit tests for AccountForm username field * GREEN: disable username field and button on account form when user edits are not allowed Co-authored-by: Joe Previte <jjprevite@gmail.com>
1 parent b9dd566 commit 6dacf70

File tree

4 files changed

+93
-4
lines changed

4 files changed

+93
-4
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { screen } from "@testing-library/react"
2+
import { MockUser2 } from "../../testHelpers/entities"
3+
import { render } from "../../testHelpers/renderHelpers"
4+
import { AccountForm, AccountFormValues } from "./SettingsAccountForm"
5+
6+
// NOTE: it does not matter what the role props of MockUser are set to,
7+
// only that editable is set to true or false. This is passed from
8+
// the call to /authorization done by authXService
9+
describe("AccountForm", () => {
10+
describe("when editable is set to true", () => {
11+
it("allows updating username", async () => {
12+
// Given
13+
const mockInitialValues: AccountFormValues = {
14+
username: MockUser2.username,
15+
}
16+
17+
// When
18+
render(
19+
<AccountForm
20+
editable
21+
email={MockUser2.email}
22+
initialValues={mockInitialValues}
23+
isLoading={false}
24+
onSubmit={() => {
25+
return
26+
}}
27+
/>,
28+
)
29+
30+
// Then
31+
const el = await screen.findByLabelText("Username")
32+
expect(el).toBeEnabled()
33+
const btn = await screen.findByRole("button", { name: /Update settings/i })
34+
expect(btn).toBeEnabled()
35+
})
36+
})
37+
38+
describe("when editable is set to false", () => {
39+
it("does not allow updating username", async () => {
40+
// Given
41+
const mockInitialValues: AccountFormValues = {
42+
username: MockUser2.username,
43+
}
44+
45+
// When
46+
render(
47+
<AccountForm
48+
editable={false}
49+
email={MockUser2.email}
50+
initialValues={mockInitialValues}
51+
isLoading={false}
52+
onSubmit={() => {
53+
return
54+
}}
55+
/>,
56+
)
57+
58+
// Then
59+
const el = await screen.findByLabelText("Username")
60+
expect(el).toBeDisabled()
61+
const btn = await screen.findByRole("button", { name: /Update settings/i })
62+
expect(btn).toBeDisabled()
63+
})
64+
})
65+
})

site/src/components/SettingsAccountForm/SettingsAccountForm.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getFormHelpersWithError, nameValidator, onChangeTrimmed } from "../../u
77
import { LoadingButton } from "../LoadingButton/LoadingButton"
88
import { Stack } from "../Stack/Stack"
99

10-
interface AccountFormValues {
10+
export interface AccountFormValues {
1111
username: string
1212
}
1313

@@ -22,6 +22,7 @@ const validationSchema = Yup.object({
2222
})
2323

2424
export interface AccountFormProps {
25+
editable: boolean
2526
email: string
2627
isLoading: boolean
2728
initialValues: AccountFormValues
@@ -32,6 +33,7 @@ export interface AccountFormProps {
3233
}
3334

3435
export const AccountForm: FC<React.PropsWithChildren<AccountFormProps>> = ({
36+
editable,
3537
email,
3638
isLoading,
3739
onSubmit,
@@ -62,14 +64,22 @@ export const AccountForm: FC<React.PropsWithChildren<AccountFormProps>> = ({
6264
<TextField
6365
{...getFieldHelpers("username")}
6466
onChange={onChangeTrimmed(form)}
67+
aria-disabled={!editable}
6568
autoComplete="username"
69+
disabled={!editable}
6670
fullWidth
6771
label={Language.usernameLabel}
6872
variant="outlined"
6973
/>
7074

7175
<div>
72-
<LoadingButton loading={isLoading} type="submit" variant="contained">
76+
<LoadingButton
77+
loading={isLoading}
78+
aria-disabled={!editable}
79+
disabled={!editable}
80+
type="submit"
81+
variant="contained"
82+
>
7383
{isLoading ? "" : Language.updateSettings}
7484
</LoadingButton>
7585
</div>

site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export const Language = {
1111
export const AccountPage: React.FC = () => {
1212
const xServices = useContext(XServiceContext)
1313
const [authState, authSend] = useActor(xServices.authXService)
14-
const { me, updateProfileError } = authState.context
14+
const { me, permissions, updateProfileError } = authState.context
15+
const canEditUsers = permissions && permissions.updateUsers
1516

1617
if (!me) {
1718
throw new Error("No current user found")
@@ -20,10 +21,13 @@ export const AccountPage: React.FC = () => {
2021
return (
2122
<Section title={Language.title}>
2223
<AccountForm
24+
editable={Boolean(canEditUsers)}
2325
email={me.email}
2426
updateProfileError={updateProfileError}
2527
isLoading={authState.matches("signedIn.profile.updatingProfile")}
26-
initialValues={{ username: me.username }}
28+
initialValues={{
29+
username: me.username,
30+
}}
2731
onSubmit={(data) => {
2832
authSend({
2933
type: "UPDATE_PROFILE",

site/src/testHelpers/entities.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ export const MockUser: TypesGen.User = {
6161
roles: [MockOwnerRole],
6262
}
6363

64+
export const MockUserAdmin: TypesGen.User = {
65+
id: "test-user",
66+
username: "TestUser",
67+
email: "test@coder.com",
68+
created_at: "",
69+
status: "active",
70+
organization_ids: ["fc0774ce-cc9e-48d4-80ae-88f7a4d4a8b0"],
71+
roles: [MockUserAdminRole],
72+
}
73+
6474
export const MockUser2: TypesGen.User = {
6575
id: "test-user-2",
6676
username: "TestUser2",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy