mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
- Add spanish translations - Does not include tests - Add func to get the translations for a user locale
293 lines
8.7 KiB
Go
293 lines
8.7 KiB
Go
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
package api
|
|
|
|
import (
|
|
"archive/zip"
|
|
"encoding/json"
|
|
"github.com/mattermost/platform/model"
|
|
"github.com/mattermost/platform/utils"
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
const (
|
|
EXPORT_PATH = "export/"
|
|
EXPORT_FILENAME = "MattermostExport.zip"
|
|
EXPORT_OPTIONS_FILE = "options.json"
|
|
EXPORT_TEAMS_FOLDER = "teams"
|
|
EXPORT_CHANNELS_FOLDER = "channels"
|
|
EXPORT_CHANNEL_MEMBERS_FOLDER = "members"
|
|
EXPORT_POSTS_FOLDER = "posts"
|
|
EXPORT_USERS_FOLDER = "users"
|
|
EXPORT_LOCAL_STORAGE_FOLDER = "files"
|
|
)
|
|
|
|
type ExportWriter interface {
|
|
Create(name string) (io.Writer, error)
|
|
}
|
|
|
|
type ExportOptions struct {
|
|
TeamsToExport []string `json:"teams"`
|
|
ChannelsToExport []string `json:"channels"`
|
|
UsersToExport []string `json:"users"`
|
|
ExportLocalStorage bool `json:"export_local_storage"`
|
|
}
|
|
|
|
func (options *ExportOptions) ToJson() string {
|
|
b, err := json.Marshal(options)
|
|
if err != nil {
|
|
return ""
|
|
} else {
|
|
return string(b)
|
|
}
|
|
}
|
|
|
|
func ExportOptionsFromJson(data io.Reader) *ExportOptions {
|
|
decoder := json.NewDecoder(data)
|
|
var o ExportOptions
|
|
decoder.Decode(&o)
|
|
return &o
|
|
}
|
|
|
|
func ExportToFile(options *ExportOptions) (link string, err *model.AppError) {
|
|
// Open file for export
|
|
if file, err := openFileWriteStream(EXPORT_PATH + EXPORT_FILENAME); err != nil {
|
|
return "", err
|
|
} else {
|
|
defer closeFileWriteStream(file)
|
|
ExportToWriter(file, options)
|
|
}
|
|
|
|
return "/api/v1/files/get_export", nil
|
|
}
|
|
|
|
func ExportToWriter(w io.Writer, options *ExportOptions) *model.AppError {
|
|
// Open a writer to write to zip file
|
|
zipWriter := zip.NewWriter(w)
|
|
defer zipWriter.Close()
|
|
|
|
// Write our options to file
|
|
if optionsFile, err := zipWriter.Create(EXPORT_OPTIONS_FILE); err != nil {
|
|
return model.NewLocAppError("ExportToWriter", "api.export.options.create.app_error", nil, err.Error())
|
|
} else {
|
|
if _, err := optionsFile.Write([]byte(options.ToJson())); err != nil {
|
|
return model.NewLocAppError("ExportToWriter", "api.export.options.write.app_error", nil, err.Error())
|
|
}
|
|
}
|
|
|
|
// Export Teams
|
|
ExportTeams(zipWriter, options)
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportTeams(writer ExportWriter, options *ExportOptions) *model.AppError {
|
|
// Get the teams
|
|
var teams []*model.Team
|
|
if len(options.TeamsToExport) == 0 {
|
|
if result := <-Srv.Store.Team().GetAll(); result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
teams = result.Data.([]*model.Team)
|
|
}
|
|
} else {
|
|
for _, teamId := range options.TeamsToExport {
|
|
if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
team := result.Data.(*model.Team)
|
|
teams = append(teams, team)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Export the teams
|
|
for i := range teams {
|
|
// Sanitize
|
|
teams[i].PreExport()
|
|
|
|
if teamFile, err := writer.Create(EXPORT_TEAMS_FOLDER + "/" + teams[i].Name + ".json"); err != nil {
|
|
return model.NewLocAppError("ExportTeams", "api.export.open_file.app_error", nil, err.Error())
|
|
} else {
|
|
if _, err := teamFile.Write([]byte(teams[i].ToJson())); err != nil {
|
|
return model.NewLocAppError("ExportTeams", "api.export.write_file.app_error", nil, err.Error())
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Export the channels, local storage and users
|
|
for _, team := range teams {
|
|
if err := ExportChannels(writer, options, team.Id); err != nil {
|
|
return err
|
|
}
|
|
if err := ExportUsers(writer, options, team.Id); err != nil {
|
|
return err
|
|
}
|
|
if err := ExportLocalStorage(writer, options, team.Id); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportChannels(writer ExportWriter, options *ExportOptions, teamId string) *model.AppError {
|
|
// Get the channels
|
|
var channels []*model.Channel
|
|
if len(options.ChannelsToExport) == 0 {
|
|
if result := <-Srv.Store.Channel().GetForExport(teamId); result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
channels = result.Data.([]*model.Channel)
|
|
}
|
|
} else {
|
|
for _, channelId := range options.ChannelsToExport {
|
|
if result := <-Srv.Store.Channel().Get(channelId); result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
channel := result.Data.(*model.Channel)
|
|
channels = append(channels, channel)
|
|
}
|
|
}
|
|
}
|
|
|
|
for i := range channels {
|
|
// Get members
|
|
mchan := Srv.Store.Channel().GetMembers(channels[i].Id)
|
|
|
|
// Sanitize
|
|
channels[i].PreExport()
|
|
|
|
if channelFile, err := writer.Create(EXPORT_CHANNELS_FOLDER + "/" + channels[i].Id + ".json"); err != nil {
|
|
return model.NewLocAppError("ExportChannels", "api.export.open_file.app_error", nil, err.Error())
|
|
} else {
|
|
if _, err := channelFile.Write([]byte(channels[i].ToJson())); err != nil {
|
|
return model.NewLocAppError("ExportChannels", "api.export.write_file.app_error", nil, err.Error())
|
|
}
|
|
}
|
|
|
|
var members []model.ChannelMember
|
|
if result := <-mchan; result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
members = result.Data.([]model.ChannelMember)
|
|
}
|
|
|
|
if membersFile, err := writer.Create(EXPORT_CHANNELS_FOLDER + "/" + channels[i].Id + "_members.json"); err != nil {
|
|
return model.NewLocAppError("ExportChannels", "api.export.open_file.app_error", nil, err.Error())
|
|
} else {
|
|
result, err2 := json.Marshal(members)
|
|
if err2 != nil {
|
|
return model.NewLocAppError("ExportChannels", "api.export.json.app_error", nil, err.Error())
|
|
}
|
|
if _, err3 := membersFile.Write([]byte(result)); err3 != nil {
|
|
return model.NewLocAppError("ExportChannels", "api.export.write_file.app_error", nil, err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, channel := range channels {
|
|
if err := ExportPosts(writer, options, channel.Id); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportPosts(writer ExportWriter, options *ExportOptions, channelId string) *model.AppError {
|
|
// Get the posts
|
|
var posts []*model.Post
|
|
if result := <-Srv.Store.Post().GetForExport(channelId); result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
posts = result.Data.([]*model.Post)
|
|
}
|
|
|
|
// Export the posts
|
|
if postsFile, err := writer.Create(EXPORT_POSTS_FOLDER + "/" + channelId + "_posts.json"); err != nil {
|
|
return model.NewLocAppError("ExportPosts", "api.export.open_file.app_error", nil, err.Error())
|
|
} else {
|
|
result, err2 := json.Marshal(posts)
|
|
if err2 != nil {
|
|
return model.NewLocAppError("ExportPosts", "api.export.json.app_error", nil, err.Error())
|
|
}
|
|
if _, err3 := postsFile.Write([]byte(result)); err3 != nil {
|
|
return model.NewLocAppError("ExportPosts", "api.export.write_file.app_error", nil, err.Error())
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportUsers(writer ExportWriter, options *ExportOptions, teamId string) *model.AppError {
|
|
// Get the users
|
|
var users []*model.User
|
|
if result := <-Srv.Store.User().GetForExport(teamId); result.Err != nil {
|
|
return result.Err
|
|
} else {
|
|
users = result.Data.([]*model.User)
|
|
}
|
|
|
|
// Write the users
|
|
if usersFile, err := writer.Create(EXPORT_USERS_FOLDER + "/" + teamId + "_users.json"); err != nil {
|
|
return model.NewLocAppError("ExportUsers", "api.export.open_file.app_error", nil, err.Error())
|
|
} else {
|
|
result, err2 := json.Marshal(users)
|
|
if err2 != nil {
|
|
return model.NewLocAppError("ExportUsers", "api.export.json.app_error", nil, err.Error())
|
|
}
|
|
if _, err3 := usersFile.Write([]byte(result)); err3 != nil {
|
|
return model.NewLocAppError("ExportUsers", "api.export.write_file.app_error", nil, err.Error())
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func copyDirToExportWriter(writer ExportWriter, inPath string, outPath string) *model.AppError {
|
|
dir, err := os.Open(inPath)
|
|
if err != nil {
|
|
return model.NewLocAppError("copyDirToExportWriter", "api.export.open_dir.app_error", nil, err.Error())
|
|
}
|
|
|
|
fileInfoList, err := dir.Readdir(0)
|
|
if err != nil {
|
|
return model.NewLocAppError("copyDirToExportWriter", "api.export.read_dir.app_error", nil, err.Error())
|
|
}
|
|
|
|
for _, fileInfo := range fileInfoList {
|
|
if fileInfo.IsDir() {
|
|
copyDirToExportWriter(writer, inPath+"/"+fileInfo.Name(), outPath+"/"+fileInfo.Name())
|
|
} else {
|
|
if toFile, err := writer.Create(outPath + "/" + fileInfo.Name()); err != nil {
|
|
return model.NewLocAppError("copyDirToExportWriter", "api.export.open_file.app_error", nil, err.Error())
|
|
} else {
|
|
fromFile, err := os.Open(inPath + "/" + fileInfo.Name())
|
|
if err != nil {
|
|
return model.NewLocAppError("copyDirToExportWriter", "api.export.open.app_error", nil, err.Error())
|
|
}
|
|
io.Copy(toFile, fromFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportLocalStorage(writer ExportWriter, options *ExportOptions, teamId string) *model.AppError {
|
|
teamDir := utils.Cfg.FileSettings.Directory + "teams/" + teamId
|
|
|
|
if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 {
|
|
return model.NewLocAppError("ExportLocalStorage", "api.export.s3.app_error", nil, "")
|
|
} else if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_LOCAL {
|
|
if err := copyDirToExportWriter(writer, teamDir, EXPORT_LOCAL_STORAGE_FOLDER); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|