Download db backup from admin page.
This commit is contained in:
parent
d53676a907
commit
bfeddd25d1
@ -6,7 +6,9 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -247,3 +249,17 @@ func (vdb *VspDatabase) GetCookieSecret() ([]byte, error) {
|
|||||||
|
|
||||||
return cookieSecret, err
|
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
|
// ticketSearch is the handler for "POST /admin/ticket". The hash param will be
|
||||||
// be used to retrieve a ticket from the database.
|
// used to retrieve a ticket from the database.
|
||||||
func ticketSearch(c *gin.Context) {
|
func ticketSearch(c *gin.Context) {
|
||||||
hash := c.PostForm("hash")
|
hash := c.PostForm("hash")
|
||||||
|
|
||||||
@ -59,6 +59,16 @@ func adminLogout(c *gin.Context) {
|
|||||||
setAdminStatus(nil, c)
|
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
|
// setAdminStatus stores the authentication status of the current session and
|
||||||
// redirects the client to GET /admin.
|
// redirects the client to GET /admin.
|
||||||
func setAdminStatus(admin interface{}, c *gin.Context) {
|
func setAdminStatus(admin interface{}, c *gin.Context) {
|
||||||
|
|||||||
@ -4,13 +4,16 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>Admin</h3>
|
<h3>Admin</h3>
|
||||||
|
|
||||||
|
<a class="btn btn-primary" href="/admin/backup" download>Backup Database</a>
|
||||||
|
|
||||||
<form class="my-2" action="/admin/logout" method="post">
|
<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>
|
||||||
|
|
||||||
<form class="my-2" action="/admin/ticket" method="post">
|
<form class="my-2" action="/admin/ticket" method="post">
|
||||||
<input type="text" name="hash" size="64" minlength="64" maxlength="64" required placeholder="Ticket hash">
|
<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>
|
</form>
|
||||||
|
|
||||||
{{ with .SearchResult }}
|
{{ with .SearchResult }}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<h3>Login</h3>
|
<h3>Login</h3>
|
||||||
<form action="/admin" method="post">
|
<form action="/admin" method="post">
|
||||||
<input type="password" name="password" required placeholder="Enter password">
|
<input type="password" name="password" required placeholder="Enter password">
|
||||||
<button type="submit">Login</button>
|
<button class="btn btn-primary" type="submit">Login</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{ if .IncorrectPassword }}
|
{{ if .IncorrectPassword }}
|
||||||
|
|||||||
@ -207,6 +207,7 @@ func router(debugMode bool, cookieSecret []byte, dcrd rpc.DcrdConnect, wallets r
|
|||||||
)
|
)
|
||||||
admin.GET("", adminPage)
|
admin.GET("", adminPage)
|
||||||
admin.POST("/ticket", ticketSearch)
|
admin.POST("/ticket", ticketSearch)
|
||||||
|
admin.GET("/backup", downloadDatabaseBackup)
|
||||||
admin.POST("/logout", adminLogout)
|
admin.POST("/logout", adminLogout)
|
||||||
|
|
||||||
// These API routes access dcrd and the voting wallets, and they need
|
// These API routes access dcrd and the voting wallets, and they need
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user