@@ -4,6 +4,10 @@ import {
4
4
VStack ,
5
5
Text ,
6
6
Switch as HopeSwitch ,
7
+ Input ,
8
+ FormControl ,
9
+ FormLabel ,
10
+ Flex ,
7
11
} from "@hope-ui/solid"
8
12
import { r , handleRespWithoutNotify , notify } from "~/utils"
9
13
import { useFetch , useManageTitle , useT } from "~/hooks"
@@ -18,8 +22,10 @@ import {
18
22
PPageResp ,
19
23
} from "~/types"
20
24
import { createSignal , For } from "solid-js"
25
+ import crypto from "crypto-js"
21
26
22
27
interface Data {
28
+ encrypted : string
23
29
settings : SettingItem [ ]
24
30
users : User [ ]
25
31
storages : Storage [ ]
@@ -51,6 +57,7 @@ const Log = (props: { msg: string; type: LogType }) => {
51
57
52
58
const BackupRestore = ( ) => {
53
59
const [ override , setOverride ] = createSignal ( false )
60
+ const [ password , setPassword ] = createSignal ( "" )
54
61
const t = useT ( )
55
62
useManageTitle ( "manage.sidemenu.backup-restore" )
56
63
let logRef : HTMLDivElement
@@ -84,14 +91,36 @@ const BackupRestore = () => {
84
91
getStoragesLoading ( )
85
92
)
86
93
}
94
+ function encrypt ( data : any , key : string ) : string {
95
+ if ( key == "" ) return data
96
+ const encJson = crypto . AES . encrypt ( JSON . stringify ( data ) , key ) . toString ( )
97
+ return crypto . enc . Base64 . stringify ( crypto . enc . Utf8 . parse ( encJson ) )
98
+ }
99
+
100
+ function decrypt (
101
+ data : any ,
102
+ key : string ,
103
+ raw : boolean ,
104
+ encrypted : boolean ,
105
+ ) : string {
106
+ if ( ! encrypted ) return data
107
+ const decData = crypto . enc . Base64 . parse ( data ) . toString ( crypto . enc . Utf8 )
108
+ if ( raw ) return crypto . AES . decrypt ( decData , key ) . toString ( crypto . enc . Utf8 )
109
+ return JSON . parse (
110
+ crypto . AES . decrypt ( decData , key ) . toString ( crypto . enc . Utf8 ) ,
111
+ )
112
+ }
113
+
87
114
const backup = async ( ) => {
88
115
appendLog ( t ( "br.start_backup" ) , "info" )
89
116
const allData : Data = {
117
+ encrypted : "" ,
90
118
settings : [ ] ,
91
119
users : [ ] ,
92
120
storages : [ ] ,
93
121
metas : [ ] ,
94
122
}
123
+ if ( password ( ) != "" ) allData . encrypted = encrypt ( "encrypted" , password ( ) )
95
124
for ( const item of [
96
125
{ name : "settings" , fn : getSettings , page : false } ,
97
126
{ name : "users" , fn : getUsers , page : true } ,
@@ -109,8 +138,20 @@ const BackupRestore = () => {
109
138
"success" ,
110
139
)
111
140
if ( item . page ) {
141
+ for ( let i = 0 ; i < data . content . length ; i ++ ) {
142
+ const obj = data . content [ i ]
143
+ for ( const key in obj ) {
144
+ obj [ key ] = encrypt ( obj [ key ] , password ( ) )
145
+ }
146
+ }
112
147
allData [ item . name ] = data . content
113
148
} else {
149
+ for ( let i = 0 ; i < data . length ; i ++ ) {
150
+ const obj = data [ i ]
151
+ for ( const key in obj ) {
152
+ obj [ key ] = encrypt ( obj [ key ] , password ( ) )
153
+ }
154
+ }
114
155
allData [ item . name ] = data
115
156
}
116
157
} ,
@@ -228,6 +269,25 @@ const BackupRestore = () => {
228
269
const reader = new FileReader ( )
229
270
reader . onload = async ( ) => {
230
271
const data : Data = JSON . parse ( reader . result as string )
272
+ const encrypted = Boolean ( data . encrypted )
273
+ if ( encrypted )
274
+ if (
275
+ decrypt ( data . encrypted , password ( ) , true , true ) !== '"encrypted"'
276
+ ) {
277
+ appendLog ( t ( "br.wrong_encrypt_password" ) , "error" )
278
+ return
279
+ }
280
+ const dataasarray = Object . values ( data )
281
+ for ( let i = dataasarray . length - 4 ; i < dataasarray . length ; i ++ ) {
282
+ const obj = dataasarray [ i ]
283
+ console . log ( obj )
284
+ for ( let a = 0 ; a < obj . length ; a ++ ) {
285
+ const obj1 = obj [ a ]
286
+ for ( const key in obj1 ) {
287
+ obj1 [ key ] = decrypt ( obj1 [ key ] , password ( ) , false , encrypted )
288
+ }
289
+ }
290
+ }
231
291
if ( override ( ) ) {
232
292
await backup ( )
233
293
}
@@ -348,16 +408,27 @@ const BackupRestore = () => {
348
408
>
349
409
{ t ( "br.restore" ) }
350
410
</ Button >
351
- < HopeSwitch
352
- id = "restore-override"
353
- checked = { override ( ) }
354
- onChange = { ( e : { currentTarget : HTMLInputElement } ) =>
355
- setOverride ( e . currentTarget . checked )
356
- }
357
- >
358
- { t ( "br.override" ) }
359
- </ HopeSwitch >
360
411
</ HStack >
412
+ < FormControl w = "$full" display = "flex" flexDirection = "column" >
413
+ < Flex w = "$full" direction = "column" gap = "$1" >
414
+ < FormLabel > { t ( `br.override` ) } </ FormLabel >
415
+ < HopeSwitch
416
+ id = "restore-override"
417
+ checked = { override ( ) }
418
+ onChange = { ( e : { currentTarget : HTMLInputElement } ) =>
419
+ setOverride ( e . currentTarget . checked )
420
+ }
421
+ > </ HopeSwitch >
422
+
423
+ < FormLabel > { t ( `br.encrypt_password` ) } </ FormLabel >
424
+ < Input
425
+ id = "password"
426
+ type = "password"
427
+ placeholder = { t ( `br.encrypt_password_placeholder` ) }
428
+ onInput = { ( e ) => setPassword ( e . currentTarget . value ) }
429
+ />
430
+ </ Flex >
431
+ </ FormControl >
361
432
< VStack
362
433
p = "$2"
363
434
ref = { logRef ! }
0 commit comments