New function to delete account. Create deletion functions for blockchain and warehouse. Add function /account/delete to webapi. Close #42

This commit is contained in:
Kleissner
2021-10-20 08:46:53 +02:00
parent 285bed59e3
commit e45d6fe888
6 changed files with 148 additions and 11 deletions

View File

@@ -267,3 +267,16 @@ func unregisterPeerMonitor(channel chan<- *PeerInfo) {
}
}
}
// DeleteAccount deletes the account
func DeleteAccount() {
// delete the blockchain
UserBlockchain.DeleteBlockchain()
// delete the warehouse
UserWarehouse.DeleteWarehouse()
// delete the private key
config.PrivateKey = ""
saveConfig()
}

View File

@@ -328,3 +328,18 @@ func (blockchain *Blockchain) Read(number uint64) (decoded *BlockDecoded, status
return decoded, StatusOK, nil
}
// DeleteBlockchain deletes the entire blockchain
func (blockchain *Blockchain) DeleteBlockchain() (status int, err error) {
blockchain.Lock()
defer blockchain.Unlock()
for n := uint64(0); n < blockchain.height; n++ {
blockchain.database.Delete(blockNumberToKey(n))
}
// update the blockchain header in the database, reset height, increase version
blockchain.headerWrite(0, blockchain.version+1)
return StatusOK, nil
}

View File

@@ -68,6 +68,15 @@ func (wh *Warehouse) FileExists(hash string) (path string, fileInfo os.FileInfo,
return "", nil, false
}
// DeleteWarehouse deletes all files in the warehouse
func (wh *Warehouse) DeleteWarehouse() (err error) {
return wh.IterateFiles(func(Hash []byte, Size int64) (Continue bool) {
wh.DeleteFile(Hash)
return true
})
}
// ---- hash functions ----
func ValidateHash(hash []byte) (hashA string, err error) {
@@ -96,3 +105,68 @@ func buildPath(storagePath, hash string) (directory string, filename string) {
return newPath, filename
}
// IterateFiles iterates through all the files and calls the callback
func (wh *Warehouse) IterateFiles(Callback func(Hash []byte, Size int64) (Continue bool)) (err error) {
// list all directories in the local Storage folder. We have to walk 2 levels down to see the actual files.
files, err := ioutil.ReadDir(wh.Directory)
if err != nil {
return err
}
for _, file := range files {
name1 := file.Name()
_, err = hex.DecodeString(name1)
// we are only looking for directories. Name has to be "XXXX" hex chars only.
if !file.IsDir() || len(name1) != 4 || err != nil {
continue
}
// iterate through the next level
files1, err := ioutil.ReadDir(filepath.Join(wh.Directory, name1))
if err != nil {
return err
}
for _, file2 := range files1 {
name2 := file2.Name()
_, err = hex.DecodeString(name2)
// we are only looking for directories. Name has to be "XXXX" hex chars only.
if !file2.IsDir() || len(name2) != 4 || err != nil {
continue
}
// iterate through the next level
files2, err := ioutil.ReadDir(filepath.Join(wh.Directory, name1, name2))
if err != nil {
return err
}
for _, file3 := range files2 {
name3 := file3.Name()
_, err = hex.DecodeString(name3)
// finally we are only looking for files
if file3.IsDir() || len(name3) != hashSize*2-8 || err != nil {
continue
}
size := file3.Size()
hash, err := hex.DecodeString(name1 + name2 + name3)
if err != nil {
return err
}
// found the hash! forward
if !Callback(hash, size) {
return nil
}
}
}
}
return nil
}

View File

@@ -41,7 +41,8 @@ func Start(ListenAddresses []string, UseSSL bool, CertificateFile, CertificateKe
Router.HandleFunc("/test", apiTest).Methods("GET")
Router.HandleFunc("/status", apiStatus).Methods("GET")
Router.HandleFunc("/peer/self", apiPeerSelf).Methods("GET")
Router.HandleFunc("/account/info", apiAccountInfo).Methods("GET")
Router.HandleFunc("/account/delete", apiAccountDelete).Methods("GET")
Router.HandleFunc("/blockchain/header", apiBlockchainHeaderFunc).Methods("GET")
Router.HandleFunc("/blockchain/append", apiBlockchainAppend).Methods("POST")
Router.HandleFunc("/blockchain/read", apiBlockchainRead).Methods("GET")

View File

@@ -9,6 +9,7 @@ package webapi
import (
"encoding/hex"
"net/http"
"strconv"
"github.com/PeernetOfficial/core"
)
@@ -50,11 +51,11 @@ type apiResponsePeerSelf struct {
}
/*
apiPeerSelf provides information about the self peer details
Request: GET /peer/self
apiAccountInfo provides information about the current account.
Request: GET /account/info
Result: 200 with JSON structure apiResponsePeerSelf
*/
func apiPeerSelf(w http.ResponseWriter, r *http.Request) {
func apiAccountInfo(w http.ResponseWriter, r *http.Request) {
response := apiResponsePeerSelf{}
response.NodeID = hex.EncodeToString(core.SelfNodeID())
@@ -63,3 +64,21 @@ func apiPeerSelf(w http.ResponseWriter, r *http.Request) {
EncodeJSON(w, r, response)
}
/*
apiAccountDelete deletes the current account. The confirm parameter must include the user's choice.
Request: GET /account/delete?confirm=[0 or 1]
Result: 204 if the user choses not to delete the account
200 if successfully deleted
*/
func apiAccountDelete(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if confirm, _ := strconv.ParseBool(r.Form.Get("confirm")); !confirm {
w.WriteHeader(http.StatusNoContent)
return
}
core.DeleteAccount()
w.WriteHeader(http.StatusOK)
}

View File

@@ -6,10 +6,9 @@ It can be used by local client software to connect to the Peernet network and us
## Use Considerations (when not to use it)
Do not expose this API to the internet. The web API uses the core library which uses the user's public and private key to connect to the network.
It shall only run on a loopback IP such as `127.0.0.1` or `::1`. Special HTTP headers (including the Access-Control headers) are intentionally not set.
Do not expose this API to the internet or local network. The API is unauthenticated and provides direct access to the users blockchain. It also provide sensitive actions such as deleting the account (including the private key). An attacker could abuse the API to add any local file to the user's blockchain and then read it.
The API is unauthenticated and provides direct access to the users blockchain.
The API shall only run on a loopback IP such as `127.0.0.1` or `::1`. Special HTTP headers (including the Access-Control headers) are intentionally not set.
## Deployment
@@ -27,8 +26,10 @@ webapi.Router.HandleFunc("/newfunction", newFunction).Methods("GET")
These are the functions provided by the API:
```
/status Provides current connectivity status to the network
/peer/self Provides information about the self peer details
/status Provide current connectivity status to the network
/account/info Information about the current account
/account/delete Delete account
/blockchain/header Header of the blockchain
/blockchain/append Append a block to the blockchain
@@ -89,12 +90,14 @@ type apiResponseStatus struct {
}
```
### Self Information
## Account API
### Information
This function returns information about the current peer.
```
Request: GET /peer/self
Request: GET /account/info
Response: 200 with JSON structure apiResponsePeerSelf
```
@@ -107,6 +110,18 @@ type apiResponsePeerSelf struct {
}
```
### Delete
This deletes the account. This action is irreversible. After deleting the account, the backend shall no longer be used.
Note that it currently does not send a termination message to other peers. As a result, other peers may retain data or metadata.
```
Request: GET /account/delete?confirm=[0 or 1]
Result: 204 if the user choses not to delete the account
200 if successfully deleted
```
## Blockchain Functions
Common status codes returned by various endpoints in the `blockchain` package: