Download db backup from admin page.
This commit is contained in:
parent
d53676a907
commit
bfeddd25d1
@ -6,7 +6,9 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -247,3 +249,17 @@ func (vdb *VspDatabase) GetCookieSecret() ([]byte, error) {
|
||||
|
||||
return cookieSecret, err
|
||||
}
|
||||
|
||||
// BackupDB streams a backup of the database over an http response writer.
|
||||
func (vdb *VspDatabase) BackupDB(w http.ResponseWriter) error {
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", `attachment; filename="vspd.db"`)
|
||||
|
||||
err := vdb.db.View(func(tx *bolt.Tx) error {
|
||||
w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size())))
|
||||
_, err := tx.WriteTo(w)
|
||||
return err
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ func adminPage(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// ticketSearch is the handler for "POST /admin/ticket". The "hash" param will
|
||||
// be used to retrieve a ticket from the database.
|
||||
// ticketSearch is the handler for "POST /admin/ticket". The hash param will be
|
||||
// used to retrieve a ticket from the database.
|
||||
func ticketSearch(c *gin.Context) {
|
||||
hash := c.PostForm("hash")
|
||||
|
||||
@ -59,6 +59,16 @@ func adminLogout(c *gin.Context) {
|
||||
setAdminStatus(nil, c)
|
||||
}
|
||||
|
||||
// downloadDatabaseBackup is the handler for "GET /backup". A binary
|
||||
// representation of the whole database is generated and returned to the client.
|
||||
func downloadDatabaseBackup(c *gin.Context) {
|
||||
err := db.BackupDB(c.Writer)
|
||||
if err != nil {
|
||||
log.Errorf("Error backing up database: %v", err)
|
||||
c.String(http.StatusInternalServerError, "Error backing up database")
|
||||
}
|
||||
}
|
||||
|
||||
// setAdminStatus stores the authentication status of the current session and
|
||||
// redirects the client to GET /admin.
|
||||
func setAdminStatus(admin interface{}, c *gin.Context) {
|
||||
|
||||
@ -4,13 +4,16 @@
|
||||
|
||||
<section>
|
||||
<h3>Admin</h3>
|
||||
|
||||
<a class="btn btn-primary" href="/admin/backup" download>Backup Database</a>
|
||||
|
||||
<form class="my-2" action="/admin/logout" method="post">
|
||||
<button type="submit">Logout</button>
|
||||
<button class="btn btn-primary" type="submit">Logout</button>
|
||||
</form>
|
||||
|
||||
<form class="my-2" action="/admin/ticket" method="post">
|
||||
<input type="text" name="hash" size="64" minlength="64" maxlength="64" required placeholder="Ticket hash">
|
||||
<button type="submit">Search</button>
|
||||
<button class="btn btn-primary" type="submit">Search</button>
|
||||
</form>
|
||||
|
||||
{{ with .SearchResult }}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<h3>Login</h3>
|
||||
<form action="/admin" method="post">
|
||||
<input type="password" name="password" required placeholder="Enter password">
|
||||
<button type="submit">Login</button>
|
||||
<button class="btn btn-primary" type="submit">Login</button>
|
||||
</form>
|
||||
|
||||
{{ if .IncorrectPassword }}
|
||||
|
||||
@ -207,6 +207,7 @@ func router(debugMode bool, cookieSecret []byte, dcrd rpc.DcrdConnect, wallets r
|
||||
)
|
||||
admin.GET("", adminPage)
|
||||
admin.POST("/ticket", ticketSearch)
|
||||
admin.GET("/backup", downloadDatabaseBackup)
|
||||
admin.POST("/logout", adminLogout)
|
||||
|
||||
// These API routes access dcrd and the voting wallets, and they need
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user