1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-19 21:29:42 +02:00
documize/domain/backup/endpoint.go

187 lines
4.7 KiB
Go
Raw Normal View History

// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
package backup
import (
"archive/zip"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/documize/community/core/env"
"github.com/documize/community/core/response"
"github.com/documize/community/core/streamutil"
"github.com/documize/community/core/uniqueid"
"github.com/documize/community/domain"
indexer "github.com/documize/community/domain/search"
"github.com/documize/community/domain/store"
)
// Handler contains the runtime information such as logging and database.
type Handler struct {
Runtime *env.Runtime
Store *store.Store
Indexer indexer.Indexer
}
// Backup generates binary file of all instance settings and contents.
// The content is pulled directly from the database and marshalled to JSON.
// A zip file is then sent to the caller.
func (h *Handler) Backup(w http.ResponseWriter, r *http.Request) {
method := "system.backup"
ctx := domain.GetRequestContext(r)
if !ctx.Administrator {
response.WriteForbiddenError(w)
h.Runtime.Log.Info(fmt.Sprintf("Non-admin attempted system backup operation (user ID: %s)", ctx.UserID))
return
}
defer streamutil.Close(r.Body)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
response.WriteBadRequestError(w, method, err.Error())
h.Runtime.Log.Error(method, err)
return
}
spec := backupSpec{}
err = json.Unmarshal(body, &spec)
if err != nil {
response.WriteBadRequestError(w, method, err.Error())
h.Runtime.Log.Error(method, err)
return
}
// data, err := backup(ctx, *h.Store, spec)
// if err != nil {
// response.WriteServerError(w, method, err)
// h.Runtime.Log.Error(method, err)
// return
// }
// Filename is current timestamp
fn := fmt.Sprintf("dmz-backup-%s.zip", uniqueid.Generate())
ziptest(fn)
bb, err := ioutil.ReadFile(fn)
if err != nil {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", `attachment; filename="`+fn+`" ; `+`filename*="`+fn+`"`)
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bb)))
w.Header().Set("x-documize-filename", fn)
x, err := w.Write(bb)
if err != nil {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
w.WriteHeader(http.StatusOK)
h.Runtime.Log.Info(fmt.Sprintf("Backup completed for %s by %s, size %d", ctx.OrgID, ctx.UserID, x))
}
type backupSpec struct {
}
func backup(ctx domain.RequestContext, s store.Store, spec backupSpec) (file []byte, err error) {
buf := new(bytes.Buffer)
zw := zip.NewWriter(buf)
// Add some files to the archive.
var files = []struct {
Name, Body string
}{
{"readme.txt", "This archive contains some text files."},
{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
{"todo.txt", "Get animal handling licence.\nWrite more examples."},
}
for _, file := range files {
f, err := zw.Create(file.Name)
if err != nil {
return nil, err
}
_, err = f.Write([]byte(file.Body))
if err != nil {
return nil, err
}
}
// Make sure to check the error on Close.
err = zw.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func ziptest(filename string) {
// Create a file to write the archive buffer to
// Could also use an in memory buffer.
outFile, err := os.Create(filename)
if err != nil {
fmt.Println(err)
}
defer outFile.Close()
// Create a zip writer on top of the file writer
zipWriter := zip.NewWriter(outFile)
// Add files to archive
// We use some hard coded data to demonstrate,
// but you could iterate through all the files
// in a directory and pass the name and contents
// of each file, or you can take data from your
// program and write it write in to the archive
// without
var filesToArchive = []struct {
Name, Body string
}{
{"test.txt", "String contents of file"},
{"test2.txt", "\x61\x62\x63\n"},
}
// Create and write files to the archive, which in turn
// are getting written to the underlying writer to the
// .zip file we created at the beginning
for _, file := range filesToArchive {
fileWriter, err := zipWriter.Create(file.Name)
if err != nil {
fmt.Println(err)
}
_, err = fileWriter.Write([]byte(file.Body))
if err != nil {
fmt.Println(err)
}
}
// Clean up
err = zipWriter.Close()
if err != nil {
fmt.Println(err)
}
}