2023-02-08 15:26:23 +00:00
when ( NimMajor , NimMinor ) < ( 1 , 4 ) :
{. push raises : [ Defect ] . }
else :
{. push raises : [ ] . }
2023-04-04 13:34:53 +00:00
import
2023-02-08 15:26:23 +00:00
json ,
2023-08-29 12:16:21 +00:00
std / [ os , sequtils ]
import
2023-02-08 15:26:23 +00:00
. / keyfile ,
. / protocol_types
# Checks if a JsonNode has all keys contained in "keys"
proc hasKeys * ( data : JsonNode , keys : openArray [ string ] ) : bool =
return all ( keys , proc ( key : string ) : bool = return data . hasKey ( key ) )
2023-04-04 13:34:53 +00:00
# Safely saves a Keystore's JsonNode to disk.
# If exists, the destination file is renamed with extension .bkp; the file is written at its destination and the .bkp file is removed if write is successful, otherwise is restored
2023-02-08 15:26:23 +00:00
proc save * ( json : JsonNode , path : string , separator : string ) : KeystoreResult [ void ] =
# We first backup the current keystore
if fileExists ( path ) :
try :
moveFile ( path , path & " .bkp " )
2023-04-04 13:34:53 +00:00
except : # TODO: Fix "BareExcept" warning
2023-08-29 12:16:21 +00:00
return err ( AppKeystoreError ( kind : KeystoreOsError ,
msg : " could not backup keystore: " & getCurrentExceptionMsg ( ) ) )
2023-04-04 13:34:53 +00:00
2023-02-08 15:26:23 +00:00
# We save the updated json
var f : File
if not f . open ( path , fmAppend ) :
2023-08-29 12:16:21 +00:00
return err ( AppKeystoreError ( kind : KeystoreOsError ,
msg : getCurrentExceptionMsg ( ) ) )
2023-02-08 15:26:23 +00:00
try :
# To avoid other users/attackers to be able to read keyfiles, we make the file readable/writable only by the running user
setFilePermissions ( path , { fpUserWrite , fpUserRead } )
f . write ( $ json )
# We store a keyfile per line
f . write ( separator )
except CatchableError :
# We got some KeystoreOsError writing to disk. We attempt to restore the previous keystore backup
if fileExists ( path & " .bkp " ) :
try :
f . close ( )
removeFile ( path )
moveFile ( path & " .bkp " , path )
2023-04-04 13:34:53 +00:00
except : # TODO: Fix "BareExcept" warning
2023-02-08 15:26:23 +00:00
# Unlucky, we just fail
2023-08-29 12:16:21 +00:00
return err ( AppKeystoreError ( kind : KeystoreOsError ,
msg : " could not restore keystore backup: " & getCurrentExceptionMsg ( ) ) )
return err ( AppKeystoreError ( kind : KeystoreOsError ,
msg : " could not write keystore: " & getCurrentExceptionMsg ( ) ) )
2023-02-08 15:26:23 +00:00
finally :
f . close ( )
# The write went fine, so we can remove the backup keystore
if fileExists ( path & " .bkp " ) :
try :
removeFile ( path & " .bkp " )
2023-04-04 13:34:53 +00:00
except CatchableError :
2023-08-29 12:16:21 +00:00
return err ( AppKeystoreError ( kind : KeystoreOsError ,
msg : " could not remove keystore backup: " & getCurrentExceptionMsg ( ) ) )
2023-02-08 15:26:23 +00:00
return ok ( )