|
1 | | -import{ComponentProps,FC,useState}from"react" |
| 1 | +import{FC}from"react" |
2 | 2 | import{Section}from"../../../components/SettingsLayout/Section" |
3 | 3 | import{AccountForm}from"../../../components/SettingsAccountForm/SettingsAccountForm" |
4 | 4 | import{useAuth}from"components/AuthProvider/AuthProvider" |
5 | 5 | import{useMe}from"hooks/useMe" |
6 | 6 | import{usePermissions}from"hooks/usePermissions" |
7 | | -importTextFieldfrom"@mui/material/TextField" |
8 | | -importBoxfrom"@mui/material/Box" |
9 | | -importGitHubIconfrom"@mui/icons-material/GitHub" |
10 | | -importKeyIconfrom"@mui/icons-material/VpnKey" |
11 | | -importButtonfrom"@mui/material/Button" |
12 | | -import{useLocation}from"react-router-dom" |
13 | | -import{retrieveRedirect}from"utils/redirect" |
14 | | -importTypographyfrom"@mui/material/Typography" |
15 | | -import{convertToOAUTH,getAuthMethods}from"api/api" |
16 | | -import{AuthMethods,LoginType}from"api/typesGenerated" |
17 | | -importSkeletonfrom"@mui/material/Skeleton" |
18 | | -import{Stack}from"components/Stack/Stack" |
19 | | -import{useMutation,useQuery}from"@tanstack/react-query" |
20 | | -import{ConfirmDialog}from"components/Dialogs/ConfirmDialog/ConfirmDialog" |
21 | | -import{getErrorMessage}from"api/errors" |
22 | | - |
23 | | -typeLoginTypeConfirmation= |
24 | | -|{ |
25 | | -open:false |
26 | | -selectedType:undefined |
27 | | -} |
28 | | -|{ |
29 | | -open:true |
30 | | -selectedType:LoginType |
31 | | -} |
32 | 7 |
|
33 | 8 | exportconstAccountPage:FC=()=>{ |
34 | 9 | const[authState,authSend]=useAuth() |
35 | 10 | constme=useMe() |
36 | 11 | constpermissions=usePermissions() |
37 | 12 | const{ updateProfileError}=authState.context |
38 | 13 | constcanEditUsers=permissions&&permissions.updateUsers |
39 | | -constlocation=useLocation() |
40 | | -constredirectTo=retrieveRedirect(location.search) |
41 | | -const[loginTypeConfirmation,setLoginTypeConfirmation]= |
42 | | -useState<LoginTypeConfirmation>({open:false,selectedType:undefined}) |
43 | | -const{data:authMethods}=useQuery({ |
44 | | -queryKey:["authMethods"], |
45 | | -queryFn:getAuthMethods, |
46 | | -}) |
47 | | -constloginTypeMutation=useMutation(convertToOAUTH,{ |
48 | | -onSuccess:(data)=>{ |
49 | | -window.location.href=`/api/v2/users/oidc/callback?oidc_merge_state=${ |
50 | | -data.state_string |
51 | | -}&redirect=${encodeURIComponent(redirectTo)}` |
52 | | -}, |
53 | | -}) |
54 | 14 |
|
55 | 15 | return( |
56 | | -<Stackspacing={8}> |
57 | | -<Sectiontitle="Account"description="Update your account info"> |
58 | | -<AccountForm |
59 | | -editable={Boolean(canEditUsers)} |
60 | | -email={me.email} |
61 | | -updateProfileError={updateProfileError} |
62 | | -isLoading={authState.matches("signedIn.profile.updatingProfile")} |
63 | | -initialValues={{ |
64 | | -username:me.username, |
65 | | -}} |
66 | | -onSubmit={(data)=>{ |
67 | | -authSend({ |
68 | | -type:"UPDATE_PROFILE", |
69 | | - data, |
70 | | -}) |
71 | | -}} |
72 | | -/> |
73 | | -</Section> |
74 | | - |
75 | | -<Section |
76 | | -title="Single Sign On" |
77 | | -description="Authenticate in Coder using one-click" |
78 | | -> |
79 | | -<Boxdisplay="grid"gap="16px"> |
80 | | -{authMethods ?( |
81 | | -authMethods.me_login_type==="password" ?( |
82 | | -<> |
83 | | -{authMethods.github.enabled&&( |
84 | | -<GitHubButton |
85 | | -disabled={loginTypeMutation.isLoading} |
86 | | -onClick={()=> |
87 | | -setLoginTypeConfirmation({ |
88 | | -open:true, |
89 | | -selectedType:"github", |
90 | | -}) |
91 | | -} |
92 | | -> |
93 | | - GitHub |
94 | | -</GitHubButton> |
95 | | -)} |
96 | | -{authMethods.oidc.enabled&&( |
97 | | -<OIDCButton |
98 | | -authMethods={authMethods} |
99 | | -disabled={loginTypeMutation.isLoading} |
100 | | -onClick={()=> |
101 | | -setLoginTypeConfirmation({ |
102 | | -open:true, |
103 | | -selectedType:"oidc", |
104 | | -}) |
105 | | -} |
106 | | -> |
107 | | -{getOIDCLabel(authMethods)} |
108 | | -</OIDCButton> |
109 | | -)} |
110 | | -</> |
111 | | -) :( |
112 | | -<> |
113 | | -{authMethods.me_login_type==="github"&&( |
114 | | -<GitHubButtondisabled> |
115 | | - Authenticated with GitHub |
116 | | -</GitHubButton> |
117 | | -)} |
118 | | - |
119 | | -{authMethods.me_login_type==="oidc"&&( |
120 | | -<OIDCButtonauthMethods={authMethods}disabled> |
121 | | - Authenticated with{getOIDCLabel(authMethods)} |
122 | | -</OIDCButton> |
123 | | -)} |
124 | | -</> |
125 | | -) |
126 | | -) :( |
127 | | -<> |
128 | | -<Skeleton |
129 | | -variant="rectangular" |
130 | | -sx={{height:40,borderRadius:1}} |
131 | | -/> |
132 | | -<Skeleton |
133 | | -variant="rectangular" |
134 | | -sx={{height:40,borderRadius:1}} |
135 | | -/> |
136 | | -</> |
137 | | -)} |
138 | | -</Box> |
139 | | -</Section> |
140 | | - |
141 | | -<ConfirmLoginTypeChangeModal |
142 | | -open={loginTypeConfirmation.open} |
143 | | -error={loginTypeMutation.error} |
144 | | -// We still want to show it loading when it is success so the modal is |
145 | | -// not going to close or change until the oauth redirect |
146 | | -loading={loginTypeMutation.isLoading||loginTypeMutation.isSuccess} |
147 | | -onClose={()=>{ |
148 | | -setLoginTypeConfirmation({open:false,selectedType:undefined}) |
149 | | -loginTypeMutation.reset() |
| 16 | +<Sectiontitle="Account"description="Update your account info"> |
| 17 | +<AccountForm |
| 18 | +editable={Boolean(canEditUsers)} |
| 19 | +email={me.email} |
| 20 | +updateProfileError={updateProfileError} |
| 21 | +isLoading={authState.matches("signedIn.profile.updatingProfile")} |
| 22 | +initialValues={{ |
| 23 | +username:me.username, |
150 | 24 | }} |
151 | | -onConfirm={(password)=>{ |
152 | | -if(!loginTypeConfirmation.selectedType){ |
153 | | -thrownewError("No login type selected") |
154 | | -} |
155 | | -loginTypeMutation.mutate({ |
156 | | -to_login_type:loginTypeConfirmation.selectedType, |
157 | | -email:me.email, |
158 | | - password, |
| 25 | +onSubmit={(data)=>{ |
| 26 | +authSend({ |
| 27 | +type:"UPDATE_PROFILE", |
| 28 | + data, |
159 | 29 | }) |
160 | 30 | }} |
161 | 31 | /> |
162 | | -</Stack> |
163 | | -) |
164 | | -} |
165 | | - |
166 | | -constGitHubButton=(props:ComponentProps<typeofButton>)=>{ |
167 | | -return( |
168 | | -<Button |
169 | | -startIcon={<GitHubIconsx={{width:16,height:16}}/>} |
170 | | -fullWidth |
171 | | -type="submit" |
172 | | -size="large" |
173 | | -{...props} |
174 | | -/> |
175 | | -) |
176 | | -} |
177 | | - |
178 | | -constOIDCButton=({ |
179 | | - authMethods, |
180 | | - ...buttonProps |
181 | | -}:ComponentProps<typeofButton>&{authMethods:AuthMethods})=>{ |
182 | | -return( |
183 | | -<Button |
184 | | -size="large" |
185 | | -startIcon={ |
186 | | -authMethods.oidc.iconUrl ?( |
187 | | -<Box |
188 | | -component="img" |
189 | | -alt="Open ID Connect icon" |
190 | | -src={authMethods.oidc.iconUrl} |
191 | | -sx={{width:16,height:16}} |
192 | | -/> |
193 | | -) :( |
194 | | -<KeyIconsx={{width:16,height:16}}/> |
195 | | -) |
196 | | -} |
197 | | -fullWidth |
198 | | -type="submit" |
199 | | -{...buttonProps} |
200 | | -/> |
201 | | -) |
202 | | -} |
203 | | - |
204 | | -constgetOIDCLabel=(authMethods:AuthMethods)=>{ |
205 | | -returnauthMethods.oidc.signInText||"OpenID Connect" |
206 | | -} |
207 | | - |
208 | | -constConfirmLoginTypeChangeModal=({ |
209 | | - open, |
210 | | - loading, |
211 | | - error, |
212 | | - onClose, |
213 | | - onConfirm, |
214 | | -}:{ |
215 | | -open:boolean |
216 | | -loading:boolean |
217 | | -error:unknown |
218 | | -onClose:()=>void |
219 | | -onConfirm:(password:string)=>void |
220 | | -})=>{ |
221 | | -const[password,setPassword]=useState("") |
222 | | - |
223 | | -consthandleConfirm=()=>{ |
224 | | -onConfirm(password) |
225 | | -} |
226 | | - |
227 | | -return( |
228 | | -<ConfirmDialog |
229 | | -open={open} |
230 | | -onClose={()=>{ |
231 | | -onClose() |
232 | | -}} |
233 | | -onConfirm={handleConfirm} |
234 | | -hideCancel={false} |
235 | | -cancelText="Cancel" |
236 | | -confirmText="Update" |
237 | | -title="Change login type" |
238 | | -confirmLoading={loading} |
239 | | -description={ |
240 | | -<Stack> |
241 | | -<Typography> |
242 | | - After changing your login type, you will not be able to change it |
243 | | - again. Are you sure you want to proceed and change your login type? |
244 | | -</Typography> |
245 | | -<TextField |
246 | | -autoFocus |
247 | | -onKeyDown={(event)=>{ |
248 | | -if(event.key==="Enter"){ |
249 | | -handleConfirm() |
250 | | -} |
251 | | -}} |
252 | | -error={Boolean(error)} |
253 | | -helperText={ |
254 | | -error |
255 | | - ?getErrorMessage(error,"Your password is incorrect") |
256 | | - :undefined |
257 | | -} |
258 | | -name="confirm-password" |
259 | | -id="confirm-password" |
260 | | -value={password} |
261 | | -onChange={(e)=>setPassword(e.currentTarget.value)} |
262 | | -label="Confirm your password" |
263 | | -type="password" |
264 | | -/> |
265 | | -</Stack> |
266 | | -} |
267 | | -/> |
| 32 | +</Section> |
268 | 33 | ) |
269 | 34 | } |
270 | 35 |
|
|