vikunja/pkg/models/export.go

241 lines
5.0 KiB
Go
Raw Normal View History

2021-08-25 16:09:56 +00:00
// Copyright 2021 Vikunja and contriubtors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Vikunja is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
package models
import (
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
2021-08-29 17:31:53 +00:00
"code.vikunja.io/api/pkg/files"
2021-08-25 16:09:56 +00:00
"code.vikunja.io/api/pkg/modules/dump"
2021-08-29 17:42:37 +00:00
"code.vikunja.io/api/pkg/notifications"
2021-08-25 16:09:56 +00:00
"code.vikunja.io/api/pkg/user"
2021-08-29 17:32:55 +00:00
"code.vikunja.io/api/pkg/version"
2021-08-29 17:42:37 +00:00
"archive/zip"
2021-08-25 16:09:56 +00:00
"encoding/json"
"fmt"
2021-08-27 15:41:24 +00:00
"io"
2021-08-25 16:09:56 +00:00
"os"
"strconv"
"time"
"xorm.io/xorm"
)
func ExportUserData(u *user.User) (err error) {
exportDir := config.ServiceRootpath.GetString() + "/files/user-export-tmp/"
err = os.MkdirAll(exportDir, 0700)
if err != nil {
return err
}
// Open zip
dumpFile, err := os.Create(exportDir + strconv.FormatInt(u.ID, 64) + "_" + time.Now().Format("2006-01-02_15-03-05") + ".zip")
if err != nil {
return fmt.Errorf("error opening dump file: %s", err)
}
defer dumpFile.Close()
dumpWriter := zip.NewWriter(dumpFile)
defer dumpWriter.Close()
// Get the data
s := db.NewSession()
defer s.Close()
err = exportListsAndTasks(s, u, dumpWriter)
if err != nil {
return err
}
// Task attachment files
2021-08-25 16:49:29 +00:00
err = exportTaskAttachments(s, u, dumpWriter)
if err != nil {
return err
}
2021-08-25 16:09:56 +00:00
// Saved filters
2021-08-27 15:57:36 +00:00
err = exportSavedFilters(s, u, dumpWriter)
if err != nil {
return err
}
2021-08-25 16:09:56 +00:00
// Background files
2021-08-29 17:31:53 +00:00
err = exportListBackgrounds(s, u, dumpWriter)
if err != nil {
return err
}
2021-08-29 17:32:55 +00:00
// Vikunja Version
err = dump.WriteBytesToZip("VERSION", []byte(version.Version), dumpWriter)
if err != nil {
return err
}
2021-08-25 16:09:56 +00:00
// Send a notification
2021-08-29 17:42:37 +00:00
return notifications.Notify(u, &DataExportReadyNotification{
User: u,
})
2021-08-25 16:09:56 +00:00
}
func exportListsAndTasks(s *xorm.Session, u *user.User, wr *zip.Writer) (err error) {
namspaces, _, _, err := (&Namespace{}).ReadAll(s, u, "", -1, 0)
2021-08-25 16:09:56 +00:00
if err != nil {
return err
}
namespaceIDs := []int64{}
namespaces := []*NamespaceWithLists{}
for _, n := range namspaces.([]*NamespaceWithLists) {
if n.ID < 1 {
// Don't include filters
continue
}
namespaceIDs = append(namespaceIDs, n.ID)
namespaces = append(namespaces, n)
}
2021-08-25 16:09:56 +00:00
if len(namespaceIDs) == 0 {
return nil
}
// Get all lists
lists, err := getListsForNamespaces(s, namespaceIDs, true)
if err != nil {
return err
}
tasks, _, _, err := getTasksForLists(s, lists, u, &taskOptions{
page: 0,
perPage: -1,
})
if err != nil {
return err
}
listMap := make(map[int64]*List)
listIDs := []int64{}
for _, n := range namespaces {
for _, l := range n.Lists {
listMap[l.ID] = l
listIDs = append(listIDs, l.ID)
}
}
for _, t := range tasks {
listMap[t.ListID].Tasks = append(listMap[t.ListID].Tasks, t)
}
2021-08-25 16:30:21 +00:00
buckets := []*Bucket{}
err = s.In("list_id", listIDs).Find(&buckets)
if err != nil {
return
}
for _, b := range buckets {
listMap[b.ListID].Buckets = append(listMap[b.ListID].Buckets, b)
}
2021-08-25 16:09:56 +00:00
data, err := json.Marshal(namespaces)
if err != nil {
return err
}
return dump.WriteBytesToZip("data.json", data, wr)
}
2021-08-25 16:49:29 +00:00
func exportTaskAttachments(s *xorm.Session, u *user.User, wr *zip.Writer) (err error) {
2021-08-27 15:41:24 +00:00
lists, _, _, err := getRawListsForUser(
s,
&listOptions{
user: u,
page: -1,
},
)
if err != nil {
return err
}
tasks, _, _, err := getRawTasksForLists(s, lists, u, &taskOptions{page: -1})
if err != nil {
return err
}
taskIDs := []int64{}
for _, t := range tasks {
taskIDs = append(taskIDs, t.ID)
}
tas, err := getTaskAttachmentsByTaskIDs(s, taskIDs)
if err != nil {
return err
}
2021-08-29 17:31:53 +00:00
fs := make(map[int64]io.ReadCloser)
2021-08-27 15:41:24 +00:00
for _, ta := range tas {
if err := ta.File.LoadFileByID(); err != nil {
return err
}
2021-08-29 17:31:53 +00:00
fs[ta.FileID] = ta.File.File
2021-08-27 15:41:24 +00:00
}
2021-08-29 17:31:53 +00:00
return dump.WriteFilesToZip(fs, wr)
2021-08-25 16:49:29 +00:00
}
2021-08-27 15:57:36 +00:00
func exportSavedFilters(s *xorm.Session, u *user.User, wr *zip.Writer) (err error) {
filters, err := getSavedFilters(s, u)
if err != nil {
return err
}
data, err := json.Marshal(filters)
if err != nil {
return err
}
return dump.WriteBytesToZip("filters.json", data, wr)
}
2021-08-29 17:31:53 +00:00
func exportListBackgrounds(s *xorm.Session, u *user.User, wr *zip.Writer) (err error) {
lists, _, _, err := getRawListsForUser(
s,
&listOptions{
user: u,
page: -1,
},
)
if err != nil {
return err
}
fs := make(map[int64]io.ReadCloser)
for _, l := range lists {
if l.BackgroundFileID == 0 {
continue
}
bgFile := &files.File{
ID: l.BackgroundFileID,
}
err = bgFile.LoadFileByID()
if err != nil {
return
}
fs[l.BackgroundFileID] = bgFile.File
}
return dump.WriteFilesToZip(fs, wr)
}