web ui: allow to create folders from a template

This commit is contained in:
Nicola Murino
2021-02-04 19:09:43 +01:00
parent 17a42a0c11
commit 267d9f1831
13 changed files with 268 additions and 51 deletions

View File

@@ -36,6 +36,7 @@ type folderPageMode int
const (
folderPageModeAdd folderPageMode = iota + 1
folderPageModeUpdate
folderPageModeTemplate
)
const (
@@ -88,6 +89,7 @@ type basePage struct {
ConnectionsURL string
FoldersURL string
FolderURL string
FolderTemplateURL string
LogoutURL string
ChangeAdminPwdURL string
FolderQuotaScanURL string
@@ -277,6 +279,7 @@ func getBasePageData(title, currentURL string, r *http.Request) basePage {
AdminURL: webAdminPath,
FoldersURL: webFoldersPath,
FolderURL: webFolderPath,
FolderTemplateURL: webTemplateFolder,
LogoutURL: webLogoutPath,
ChangeAdminPwdURL: webChangeAdminPwdPath,
QuotaScanURL: webQuotaScanPath,
@@ -409,6 +412,9 @@ func renderFolderPage(w http.ResponseWriter, r *http.Request, folder vfs.BaseVir
case folderPageModeUpdate:
title = "Update folder"
currentURL = fmt.Sprintf("%v/%v", webFolderPath, url.PathEscape(folder.Name))
case folderPageModeTemplate:
title = "Folder template"
currentURL = webTemplateFolder
}
data := folderPage{
basePage: getBasePageData(title, currentURL, r),
@@ -419,6 +425,20 @@ func renderFolderPage(w http.ResponseWriter, r *http.Request, folder vfs.BaseVir
renderTemplate(w, templateFolder, data)
}
func getFoldersForTemplate(r *http.Request) []string {
var res []string
formValue := r.Form.Get("folders")
folders := make(map[string]bool)
for _, name := range getSliceFromDelimitedValues(formValue, "\n") {
if _, ok := folders[name]; ok {
continue
}
folders[name] = true
res = append(res, name)
}
return res
}
func getUsersForTemplate(r *http.Request) []userTemplateFields {
var res []userTemplateFields
formValue := r.Form.Get("users")
@@ -789,6 +809,16 @@ func replacePlaceholders(field string, replacements map[string]string) string {
return field
}
func getFolderFromTemplate(folder vfs.BaseVirtualFolder, name string) vfs.BaseVirtualFolder {
folder.Name = name
replacements := make(map[string]string)
replacements["%name%"] = folder.Name
folder.MappedPath = replacePlaceholders(folder.MappedPath, replacements)
return folder
}
func getCryptFsFromTemplate(fsConfig vfs.CryptFsConfig, replacements map[string]string) vfs.CryptFsConfig {
if fsConfig.Passphrase != nil {
if fsConfig.Passphrase.IsPlain() {
@@ -1185,6 +1215,61 @@ func handleGetWebUsers(w http.ResponseWriter, r *http.Request) {
renderTemplate(w, templateUsers, data)
}
func handleWebTemplateFolderGet(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("from") != "" {
name := r.URL.Query().Get("from")
folder, err := dataprovider.GetFolderByName(name)
if err == nil {
renderFolderPage(w, r, folder, folderPageModeTemplate, "")
} else if _, ok := err.(*dataprovider.RecordNotFoundError); ok {
renderNotFoundPage(w, r, err)
} else {
renderInternalServerErrorPage(w, r, err)
}
} else {
folder := vfs.BaseVirtualFolder{}
renderFolderPage(w, r, folder, folderPageModeTemplate, "")
}
}
func handleWebTemplateFolderPost(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
templateFolder := vfs.BaseVirtualFolder{}
err := r.ParseForm()
if err != nil {
renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
return
}
if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil {
renderForbiddenPage(w, r, err.Error())
return
}
templateFolder.MappedPath = r.Form.Get("mapped_path")
var dump dataprovider.BackupData
dump.Version = dataprovider.DumpVersion
foldersFields := getFoldersForTemplate(r)
for _, tmpl := range foldersFields {
f := getFolderFromTemplate(templateFolder, tmpl)
if err := dataprovider.ValidateFolder(&f); err != nil {
renderMessagePage(w, r, fmt.Sprintf("Error validating folder %#v", f.Name), "", http.StatusBadRequest, err, "")
return
}
dump.Folders = append(dump.Folders, f)
}
if len(dump.Folders) == 0 {
renderMessagePage(w, r, "No folders to export", "No valid folders found, export is not possible", http.StatusBadRequest, nil, "")
return
}
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"", len(dump.Folders)))
render.JSON(w, r, dump)
}
func handleWebTemplateUserGet(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("from") != "" {
username := r.URL.Query().Get("from")