@@ -30,6 +30,9 @@ import { useTranslation } from "react-i18next";
30
30
import { Card , Container } from "react-bootstrap" ;
31
31
import { signal } from "@preact/signals" ;
32
32
import { PasswordComponent } from "../components/password_component" ;
33
+ import i18n from "../i18n" ;
34
+ import { showAlert } from "../components/Alert" ;
35
+ import { Base64 } from "js-base64" ;
33
36
34
37
35
38
interface UserState {
@@ -116,15 +119,18 @@ class UserComponent extends Component<{}, State> {
116
119
}
117
120
118
121
export function User ( ) {
119
- const [ show , setShow ] = useState ( false ) ;
122
+ const [ showPasswordReset , setShowPasswordReset ] = useState ( false ) ;
123
+ const [ deleteUser , setDeleteUser ] = useState ( { show : false , password : "" , password_valid : true } ) ;
120
124
const [ currentPassword , setCurrentPassword ] = useState ( "" ) ;
121
125
const [ currentPasswordIsValid , setCurrentPasswordIsValid ] = useState ( true ) ;
122
126
const [ newPassword , setNewPassword ] = useState ( "" ) ;
123
127
const [ newPasswordIsValid , setNewPasswordIsValid ] = useState ( true ) ;
124
128
const validated = signal ( false ) ;
125
129
126
- const handleClose = ( ) => setShow ( false ) ;
127
- const handleShow = ( ) => setShow ( true ) ;
130
+ const handleUpdatePasswordClose = ( ) => setShowPasswordReset ( false ) ;
131
+ const handleUpdatePasswordShow = ( ) => setShowPasswordReset ( true ) ;
132
+ const handleDelteUserClose = ( ) => setDeleteUser ( { ...deleteUser , show : false } ) ;
133
+ const handleDeleteUserShow = ( ) => setDeleteUser ( { ...deleteUser , show : true } ) ;
128
134
129
135
const checkPasswords = ( ) => {
130
136
let ret = true ;
@@ -147,7 +153,7 @@ export function User() {
147
153
return ret ;
148
154
}
149
155
150
- const submit = async ( e : SubmitEvent ) => {
156
+ const submitUpdatePassword = async ( e : SubmitEvent ) => {
151
157
e . preventDefault ( ) ;
152
158
153
159
if ( ! checkPasswords ( ) ) {
@@ -202,24 +208,81 @@ export function User() {
202
208
} ) ;
203
209
if ( resp . status === 200 ) {
204
210
logout ( true ) ;
205
- handleClose ( ) ;
211
+ handleUpdatePasswordClose ( ) ;
206
212
}
207
213
} ;
208
214
215
+ const submitDeleteUser = async ( e : SubmitEvent ) => {
216
+ e . preventDefault ( ) ;
217
+
218
+ const t = i18n . t ;
219
+
220
+ const loginSaltBs64 = window . localStorage . getItem ( "LoginKey" ) ;
221
+ const loginSalt = Base64 . toUint8Array ( loginSaltBs64 ) ;
222
+ const loginKey = await generate_hash ( deleteUser . password , loginSalt )
223
+
224
+ const resp = await fetch ( BACKEND + "/user/delete" , {
225
+ credentials : "include" ,
226
+ method : "DELETE" ,
227
+ headers : {
228
+ "Content-Type" : "application/json"
229
+ } ,
230
+ body : JSON . stringify ( { login_key : [ ] . slice . call ( loginKey ) } )
231
+ } ) ;
232
+
233
+ if ( resp . status === 200 ) {
234
+ location . reload ( ) ;
235
+ } else if ( resp . status === 400 ) {
236
+ setDeleteUser ( { ...deleteUser , password_valid : false } )
237
+ } else {
238
+ showAlert ( `${ t ( "alert_default_text" ) } : ${ resp . status } ${ await resp . text ( ) } ` , "danger" )
239
+ handleDelteUserClose ( ) ;
240
+ }
241
+ }
242
+
209
243
const { t} = useTranslation ( "" , { useSuspense : false , keyPrefix : "user" } ) ;
210
244
211
245
return ( < >
212
246
< Container fluid >
213
247
< Card className = "p-3 my-3" >
214
248
< UserComponent />
215
- < Button variant = "primary" className = "col col-sm-6 col-md-4 col-lg-3 col-xl-2" onClick = { handleShow } >
249
+ < Button variant = "primary" className = "col col-sm-6 col-md-4 col-lg-3 col-xl-2 mb-3 " onClick = { handleUpdatePasswordShow } >
216
250
{ t ( "change_password" ) }
217
251
</ Button >
252
+ < Button variant = "danger" className = "col col-sm-6 col-md-4 col-lg-3 col-xl-2" onClick = { handleDeleteUserShow } >
253
+ { t ( "delete_user" ) }
254
+ </ Button >
218
255
</ Card >
219
256
</ Container >
220
257
221
- < Modal show = { show } onHide = { handleClose } centered >
222
- < Form onSubmit = { submit } validated = { validated . value } noValidate >
258
+ { /* Delete user modal */ }
259
+ < Modal show = { deleteUser . show } onHide = { handleDelteUserClose } centered >
260
+ < Form onSubmit = { submitDeleteUser } validated = { validated . value } noValidate >
261
+ < Modal . Header >
262
+ < Modal . Title >
263
+ { t ( "delete_user" ) }
264
+ </ Modal . Title >
265
+ </ Modal . Header >
266
+ < Modal . Body >
267
+ < Form . Group className = "pb-3" controlId = "deleteUserPassword" >
268
+ < Form . Label > { t ( "password" ) } </ Form . Label >
269
+ < PasswordComponent onChange = { ( e ) => setDeleteUser ( { ...deleteUser , password : ( e . target as HTMLInputElement ) . value } ) } isInvalid = { ! deleteUser . password_valid } invalidMessage = { t ( "password_invalid" ) } />
270
+ </ Form . Group >
271
+ </ Modal . Body >
272
+ < Modal . Footer >
273
+ < Button variant = "secondary" onClick = { handleDelteUserClose } >
274
+ { t ( "close" ) }
275
+ </ Button >
276
+ < Button variant = "danger" type = "submit" >
277
+ { t ( "delete_user" ) }
278
+ </ Button >
279
+ </ Modal . Footer >
280
+ </ Form >
281
+ </ Modal >
282
+
283
+ { /* Reset password modal */ }
284
+ < Modal show = { showPasswordReset } onHide = { handleUpdatePasswordClose } centered >
285
+ < Form onSubmit = { submitUpdatePassword } validated = { validated . value } noValidate >
223
286
< Modal . Header >
224
287
< Modal . Title >
225
288
{ t ( "change_password" ) }
@@ -238,7 +301,7 @@ export function User() {
238
301
</ Form . Group >
239
302
</ Modal . Body >
240
303
< Modal . Footer >
241
- < Button variant = "secondary" onClick = { handleClose } >
304
+ < Button variant = "secondary" onClick = { handleUpdatePasswordClose } >
242
305
{ t ( "close" ) }
243
306
</ Button >
244
307
< Button variant = "primary" type = "submit" >
0 commit comments