@@ -30,6 +30,9 @@ import { useTranslation } from "react-i18next";
3030import { Card , Container } from "react-bootstrap" ;
3131import { signal } from "@preact/signals" ;
3232import { PasswordComponent } from "../components/password_component" ;
33+ import i18n from "../i18n" ;
34+ import { showAlert } from "../components/Alert" ;
35+ import { Base64 } from "js-base64" ;
3336
3437
3538interface UserState {
@@ -116,15 +119,18 @@ class UserComponent extends Component<{}, State> {
116119}
117120
118121export 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 } ) ;
120124 const [ currentPassword , setCurrentPassword ] = useState ( "" ) ;
121125 const [ currentPasswordIsValid , setCurrentPasswordIsValid ] = useState ( true ) ;
122126 const [ newPassword , setNewPassword ] = useState ( "" ) ;
123127 const [ newPasswordIsValid , setNewPasswordIsValid ] = useState ( true ) ;
124128 const validated = signal ( false ) ;
125129
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 } ) ;
128134
129135 const checkPasswords = ( ) => {
130136 let ret = true ;
@@ -147,7 +153,7 @@ export function User() {
147153 return ret ;
148154 }
149155
150- const submit = async ( e : SubmitEvent ) => {
156+ const submitUpdatePassword = async ( e : SubmitEvent ) => {
151157 e . preventDefault ( ) ;
152158
153159 if ( ! checkPasswords ( ) ) {
@@ -202,24 +208,81 @@ export function User() {
202208 } ) ;
203209 if ( resp . status === 200 ) {
204210 logout ( true ) ;
205- handleClose ( ) ;
211+ handleUpdatePasswordClose ( ) ;
206212 }
207213 } ;
208214
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+
209243 const { t} = useTranslation ( "" , { useSuspense : false , keyPrefix : "user" } ) ;
210244
211245 return ( < >
212246 < Container fluid >
213247 < Card className = "p-3 my-3" >
214248 < 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 } >
216250 { t ( "change_password" ) }
217251 </ 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 >
218255 </ Card >
219256 </ Container >
220257
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 >
223286 < Modal . Header >
224287 < Modal . Title >
225288 { t ( "change_password" ) }
@@ -238,7 +301,7 @@ export function User() {
238301 </ Form . Group >
239302 </ Modal . Body >
240303 < Modal . Footer >
241- < Button variant = "secondary" onClick = { handleClose } >
304+ < Button variant = "secondary" onClick = { handleUpdatePasswordClose } >
242305 { t ( "close" ) }
243306 </ Button >
244307 < Button variant = "primary" type = "submit" >
0 commit comments