WebAdmin: refactor template permissions
Some checks failed
Code scanning - action / CodeQL-Build (push) Has been cancelled
CI / Test and deploy (push) Has been cancelled
CI / Test and deploy Windows (push) Has been cancelled
CI / Test build flags (push) Has been cancelled
CI / Test with PgSQL/MySQL/Cockroach (push) Has been cancelled
CI / Build Linux packages (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Docker / Build (push) Has been cancelled

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2024-11-26 20:39:36 +01:00
parent 0f9314f900
commit d3e76898cd
No known key found for this signature in database
GPG key ID: 935D2952DEC4EECF
12 changed files with 372 additions and 465 deletions

View file

@ -547,6 +547,16 @@ func (a *Admin) HasPermission(perm string) bool {
return slices.Contains(a.Permissions, perm)
}
// HasPermissions returns true if the admin has all the specified permissions
func (a *Admin) HasPermissions(perms ...string) bool {
for _, perm := range perms {
if !a.HasPermission(perm) {
return false
}
}
return len(perms) > 0
}
// GetAllowedIPAsString returns the allowed IP as comma separated string
func (a *Admin) GetAllowedIPAsString() string {
return strings.Join(a.Filters.AllowList, ",")

View file

@ -13555,7 +13555,9 @@ func TestMaxTransfers(t *testing.T) {
assert.NoError(t, err)
err = os.RemoveAll(user.GetHomeDir())
assert.NoError(t, err)
assert.Len(t, common.Connections.GetStats(""), 0)
assert.Eventually(t, func() bool {
return len(common.Connections.GetStats("")) == 0
}, 1000*time.Millisecond, 50*time.Millisecond)
assert.Eventually(t, func() bool {
return common.Connections.GetTotalTransfers() == 0
}, 1000*time.Millisecond, 50*time.Millisecond)
@ -22158,108 +22160,6 @@ func TestRenderUserTemplateMock(t *testing.T) {
assert.NoError(t, err)
}
func TestUserTemplateWithFoldersMock(t *testing.T) {
folder := vfs.BaseVirtualFolder{
Name: "vfolder",
MappedPath: filepath.Join(os.TempDir(), "mapped"),
Description: "vfolder desc with spéciàl ch@rs",
}
token, err := getJWTWebTokenFromTestServer(defaultTokenAuthUser, defaultTokenAuthPass)
assert.NoError(t, err)
csrfToken, err := getCSRFTokenFromInternalPageMock(webTemplateFolder, token)
assert.NoError(t, err)
user := getTestUser()
form := make(url.Values)
form.Set("username", user.Username)
form.Set("home_dir", filepath.Join(os.TempDir(), "%username%"))
form.Set("uid", strconv.FormatInt(int64(user.UID), 10))
form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
form.Set("upload_bandwidth", "0")
form.Set("download_bandwidth", "0")
form.Set("upload_data_transfer", "0")
form.Set("download_data_transfer", "0")
form.Set("total_data_transfer", "0")
form.Set("permissions", "*")
form.Set("status", strconv.Itoa(user.Status))
form.Set("expiration_date", "2020-01-01 00:00:00")
form.Set("fs_provider", "0")
form.Set("max_upload_file_size", "0")
form.Set("default_shares_expiration", "0")
form.Set("max_shares_expiration", "0")
form.Set("password_expiration", "0")
form.Set("password_strength", "0")
form.Set("ftp_security", "1")
form.Set("external_auth_cache_time", "0")
form.Set("description", "desc %username% %password%")
form.Set("start_directory", "/base/%username%")
form.Set("vfolder_path", "/vdir%username%")
form.Set("vfolder_name", folder.Name)
form.Set("vfolder_quota_size", "-1")
form.Set("vfolder_quota_files", "-1")
form.Add("tpl_username", "auser1")
form.Add("tpl_password", "password1")
form.Add("tpl_public_keys", " ")
form.Add("tpl_username", "auser2")
form.Add("tpl_password", "password2")
form.Add("tpl_public_keys", testPubKey)
form.Add("tpl_username", "auser1")
form.Add("tpl_password", "password")
form.Add("tpl_public_keys", "")
form.Set("form_action", "export_from_template")
b, contentType, _ := getMultipartFormData(form, "", "")
req, _ := http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr := executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
require.Contains(t, rr.Body.String(), util.I18nErrorInvalidCSRF)
folder, resp, err := httpdtest.AddFolder(folder, http.StatusCreated)
assert.NoError(t, err, string(resp))
form.Set(csrfFormToken, csrfToken)
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
var dump dataprovider.BackupData
err = json.Unmarshal(rr.Body.Bytes(), &dump)
assert.NoError(t, err)
assert.Len(t, dump.Users, 2)
assert.Len(t, dump.Folders, 1)
user1 := dump.Users[0]
user2 := dump.Users[1]
folder1 := dump.Folders[0]
assert.Equal(t, "auser1", user1.Username)
assert.Equal(t, "auser2", user2.Username)
assert.Equal(t, "desc auser1 password1", user1.Description)
assert.Equal(t, "desc auser2 password2", user2.Description)
assert.Equal(t, filepath.Join(os.TempDir(), user1.Username), user1.HomeDir)
assert.Equal(t, filepath.Join(os.TempDir(), user2.Username), user2.HomeDir)
assert.Equal(t, path.Join("/base", user1.Username), user1.Filters.StartDirectory)
assert.Equal(t, path.Join("/base", user2.Username), user2.Filters.StartDirectory)
assert.Equal(t, 0, user2.Filters.DefaultSharesExpiration)
assert.Equal(t, folder.Name, folder1.Name)
assert.Len(t, user1.PublicKeys, 0)
assert.Len(t, user2.PublicKeys, 1)
assert.Len(t, user1.VirtualFolders, 1)
assert.Len(t, user2.VirtualFolders, 1)
assert.Equal(t, "/vdirauser1", user1.VirtualFolders[0].VirtualPath)
assert.Equal(t, "/vdirauser2", user2.VirtualFolders[0].VirtualPath)
assert.Equal(t, 1, user1.Filters.FTPSecurity)
assert.Equal(t, 1, user2.Filters.FTPSecurity)
_, err = httpdtest.RemoveFolder(folder, http.StatusOK)
assert.NoError(t, err)
}
func TestUserSaveFromTemplateMock(t *testing.T) {
token, err := getJWTWebTokenFromTestServer(defaultTokenAuthUser, defaultTokenAuthPass)
assert.NoError(t, err)
@ -22295,12 +22195,20 @@ func TestUserSaveFromTemplateMock(t *testing.T) {
form.Add("template_users[0][tpl_public_keys]", " ")
form.Add("template_users[1][tpl_username]", user2)
form.Add("template_users[1][tpl_public_keys]", testPubKey)
form.Set(csrfFormToken, csrfToken)
b, contentType, _ := getMultipartFormData(form, "", "")
req, _ := http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr := executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
assert.Contains(t, rr.Body.String(), util.I18nErrorInvalidCSRF)
form.Set(csrfFormToken, csrfToken)
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusSeeOther, rr)
u1, _, err := httpdtest.GetUserByUsername(user1, http.StatusOK)
@ -22333,7 +22241,7 @@ func TestUserSaveFromTemplateMock(t *testing.T) {
assert.NoError(t, err)
}
func TestUserTemplateMock(t *testing.T) {
func TestUserTemplateErrors(t *testing.T) {
token, err := getJWTWebTokenFromTestServer(defaultTokenAuthUser, defaultTokenAuthPass)
assert.NoError(t, err)
csrfToken, err := getCSRFTokenFromInternalPageMock(webTemplateFolder, token)
@ -22398,13 +22306,14 @@ func TestUserTemplateMock(t *testing.T) {
form.Set("s3_upload_concurrency", strconv.Itoa(user.FsConfig.S3Config.UploadConcurrency))
form.Set("s3_download_part_size", strconv.FormatInt(user.FsConfig.S3Config.DownloadPartSize, 10))
form.Set("s3_download_concurrency", strconv.Itoa(user.FsConfig.S3Config.DownloadConcurrency))
// no user defined
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusBadRequest, rr)
assert.Contains(t, rr.Body.String(), util.I18nErrorUserTemplate)
form.Set("template_users[0][tpl_username]", "user1")
form.Set("template_users[0][tpl_password]", "password1")
@ -22427,75 +22336,135 @@ func TestUserTemplateMock(t *testing.T) {
rr = executeRequest(req)
checkResponseCode(t, http.StatusBadRequest, rr)
require.Contains(t, rr.Body.String(), util.I18nErrorUserTemplate)
}
func TestUserTemplateRoleAndPermissions(t *testing.T) {
r1 := getTestRole()
r2 := getTestRole()
r2.Name += "_mod"
role1, resp, err := httpdtest.AddRole(r1, http.StatusCreated)
assert.NoError(t, err, string(resp))
role2, resp, err := httpdtest.AddRole(r2, http.StatusCreated)
assert.NoError(t, err, string(resp))
admin := getTestAdmin()
admin.Username = altAdminUsername
admin.Password = altAdminPassword
admin.Role = role1.Name
admin.Permissions = []string{dataprovider.PermAdminManageFolders, dataprovider.PermAdminChangeUsers,
dataprovider.PermAdminViewUsers}
admin, _, err = httpdtest.AddAdmin(admin, http.StatusCreated)
assert.NoError(t, err)
token, err := getJWTWebTokenFromTestServer(altAdminUsername, altAdminPassword)
assert.NoError(t, err)
req, _ := http.NewRequest(http.MethodGet, webTemplateUser, nil)
setJWTCookieForReq(req, token)
rr := executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
csrfToken, err := getCSRFTokenFromInternalPageMock(webTemplateFolder, token)
assert.NoError(t, err)
user1 := "u1"
user2 := "u2"
form := make(url.Values)
form.Set("username", "")
form.Set("role", role2.Name)
form.Set("home_dir", filepath.Join(os.TempDir(), "%username%"))
form.Set("upload_bandwidth", "0")
form.Set("download_bandwidth", "0")
form.Set("upload_data_transfer", "0")
form.Set("download_data_transfer", "0")
form.Set("total_data_transfer", "0")
form.Set("uid", "0")
form.Set("gid", "0")
form.Set("max_sessions", "0")
form.Set("quota_size", "0")
form.Set("quota_files", "0")
form.Set("permissions", "*")
form.Set("status", "1")
form.Set("expiration_date", "")
form.Set("fs_provider", "0")
form.Set("max_upload_file_size", "0")
form.Set("default_shares_expiration", "0")
form.Set("max_shares_expiration", "0")
form.Set("password_expiration", "0")
form.Set("password_strength", "0")
form.Set("external_auth_cache_time", "0")
form.Add("template_users[0][tpl_username]", user1)
form.Add("template_users[0][tpl_password]", "password1")
form.Add("template_users[0][tpl_public_keys]", " ")
form.Add("template_users[1][tpl_username]", user2)
form.Add("template_users[1][tpl_public_keys]", testPubKey)
form.Set(csrfFormToken, csrfToken)
b, contentType, _ := getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
// Add the required permissions
admin.Permissions = append(admin.Permissions, dataprovider.PermAdminAddUsers)
_, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK)
assert.NoError(t, err)
token, err = getJWTWebTokenFromTestServer(altAdminUsername, altAdminPassword)
assert.NoError(t, err)
req, _ = http.NewRequest(http.MethodGet, webTemplateUser, nil)
setJWTCookieForReq(req, token)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
csrfToken, err = getCSRFTokenFromInternalPageMock(webTemplateUser, token)
assert.NoError(t, err)
form.Set(csrfFormToken, csrfToken)
form.Set("template_users[0][tpl_username]", "user1")
form.Set("template_users[0][tpl_password]", "password1")
form.Set("template_users[0][tpl_public_keys]", " ")
form.Set("template_users[1][tpl_username]", "user2")
form.Set("template_users[1][tpl_password]", "password2")
form.Set("template_users[1][tpl_public_keys]", testPubKey)
form.Set("template_users[2][tpl_username]", "")
form.Set("template_users[2][tpl_password]", "password3")
form.Set("template_users[2][tpl_public_keys]", testPubKey)
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
checkResponseCode(t, http.StatusSeeOther, rr)
var dump dataprovider.BackupData
err = json.Unmarshal(rr.Body.Bytes(), &dump)
require.NoError(t, err)
require.Len(t, dump.Users, 2)
require.Len(t, dump.Admins, 0)
require.Len(t, dump.Folders, 0)
u1, _, err := httpdtest.GetUserByUsername(user1, http.StatusOK)
assert.NoError(t, err)
assert.Equal(t, admin.Role, u1.Role)
u2, _, err := httpdtest.GetUserByUsername(user2, http.StatusOK)
assert.NoError(t, err)
assert.Equal(t, admin.Role, u2.Role)
var user1, user2 dataprovider.User
for _, u := range dump.Users {
switch u.Username {
case "user1":
user1 = u
default:
user2 = u
}
}
require.Equal(t, "user1", user1.Username)
require.Equal(t, sdk.S3FilesystemProvider, user1.FsConfig.Provider)
require.Equal(t, "user2", user2.Username)
require.Equal(t, sdk.S3FilesystemProvider, user2.FsConfig.Provider)
require.Len(t, user1.PublicKeys, 0)
require.Len(t, user2.PublicKeys, 1)
require.Equal(t, filepath.Join(os.TempDir(), user1.Username), user1.HomeDir)
require.Equal(t, filepath.Join(os.TempDir(), user2.Username), user2.HomeDir)
require.Equal(t, user1.Username, user1.FsConfig.S3Config.AccessKey)
require.Equal(t, user2.Username, user2.FsConfig.S3Config.AccessKey)
require.Equal(t, path.Join("base", user1.Username)+"/", user1.FsConfig.S3Config.KeyPrefix)
require.Equal(t, path.Join("base", user2.Username)+"/", user2.FsConfig.S3Config.KeyPrefix)
require.True(t, user1.FsConfig.S3Config.AccessSecret.IsEncrypted())
require.True(t, user1.FsConfig.S3Config.SSECustomerKey.IsEncrypted())
err = user1.FsConfig.S3Config.AccessSecret.Decrypt()
require.NoError(t, err)
err = user1.FsConfig.S3Config.SSECustomerKey.Decrypt()
require.NoError(t, err)
require.Equal(t, "password1", user1.FsConfig.S3Config.AccessSecret.GetPayload())
require.Equal(t, "password1", user1.FsConfig.S3Config.SSECustomerKey.GetPayload())
require.True(t, user2.FsConfig.S3Config.AccessSecret.IsEncrypted())
require.True(t, user2.FsConfig.S3Config.SSECustomerKey.IsEncrypted())
err = user2.FsConfig.S3Config.AccessSecret.Decrypt()
require.NoError(t, err)
err = user2.FsConfig.S3Config.SSECustomerKey.Decrypt()
require.NoError(t, err)
require.Equal(t, "password2", user2.FsConfig.S3Config.AccessSecret.GetPayload())
require.Equal(t, "password2", user2.FsConfig.S3Config.SSECustomerKey.GetPayload())
require.True(t, user1.Filters.Hooks.ExternalAuthDisabled)
require.True(t, user1.Filters.Hooks.CheckPasswordDisabled)
require.False(t, user1.Filters.Hooks.PreLoginDisabled)
require.True(t, user2.Filters.Hooks.ExternalAuthDisabled)
require.True(t, user2.Filters.Hooks.CheckPasswordDisabled)
require.False(t, user2.Filters.Hooks.PreLoginDisabled)
require.True(t, user1.Filters.DisableFsChecks)
require.True(t, user2.Filters.DisableFsChecks)
_, err = httpdtest.RemoveUser(u1, http.StatusOK)
assert.NoError(t, err)
_, err = httpdtest.RemoveUser(u2, http.StatusOK)
assert.NoError(t, err)
// Set an empty role
form.Set("role", "")
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateUser, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusSeeOther, rr)
u1, _, err = httpdtest.GetUserByUsername(user1, http.StatusOK)
assert.NoError(t, err)
assert.Equal(t, admin.Role, u1.Role)
u2, _, err = httpdtest.GetUserByUsername(user2, http.StatusOK)
assert.NoError(t, err)
assert.Equal(t, admin.Role, u2.Role)
_, err = httpdtest.RemoveUser(u1, http.StatusOK)
assert.NoError(t, err)
_, err = httpdtest.RemoveUser(u2, http.StatusOK)
assert.NoError(t, err)
_, err = httpdtest.RemoveAdmin(admin, http.StatusOK)
assert.NoError(t, err)
_, err = httpdtest.RemoveRole(role1, http.StatusOK)
assert.NoError(t, err)
_, err = httpdtest.RemoveRole(role2, http.StatusOK)
assert.NoError(t, err)
}
func TestUserPlaceholders(t *testing.T) {
@ -22664,7 +22633,7 @@ func TestFolderSaveFromTemplateMock(t *testing.T) {
assert.NoError(t, err)
}
func TestFolderTemplateMock(t *testing.T) {
func TestFolderTemplateErrors(t *testing.T) {
folderName := "vfolder-template"
mappedPath := filepath.Join(os.TempDir(), "%name%mapped%name%path")
token, err := getJWTWebTokenFromTestServer(defaultTokenAuthUser, defaultTokenAuthPass)
@ -22680,7 +22649,6 @@ func TestFolderTemplateMock(t *testing.T) {
form.Set("template_folders[2][tpl_foldername]", "folder3")
form.Set("template_folders[3][tpl_foldername]", "folder1 ")
form.Add("template_folders[3][tpl_foldername]", " ")
form.Set("form_action", "export_from_template")
b, contentType, _ := getMultipartFormData(form, "", "")
req, _ := http.NewRequest(http.MethodPost, webTemplateFolder, &b)
setJWTCookieForReq(req, token)
@ -22698,36 +22666,6 @@ func TestFolderTemplateMock(t *testing.T) {
checkResponseCode(t, http.StatusBadRequest, rr)
assert.Contains(t, rr.Body.String(), util.I18nErrorInvalidForm)
folder1 := "folder1"
folder2 := "folder2"
folder3 := "folder3"
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateFolder, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
var dump dataprovider.BackupData
err = json.Unmarshal(rr.Body.Bytes(), &dump)
require.NoError(t, err)
require.Len(t, dump.Users, 0)
require.Len(t, dump.Admins, 0)
require.Len(t, dump.Folders, 3)
for _, folder := range dump.Folders {
switch folder.Name {
case folder1:
require.Equal(t, "desc folder folder1", folder.Description)
require.True(t, strings.HasSuffix(folder.MappedPath, "folder1mappedfolder1path"))
case folder2:
require.Equal(t, "desc folder folder2", folder.Description)
require.True(t, strings.HasSuffix(folder.MappedPath, "folder2mappedfolder2path"))
default:
require.Equal(t, "desc folder folder3", folder.Description)
require.True(t, strings.HasSuffix(folder.MappedPath, "folder3mappedfolder3path"))
}
}
form.Set("fs_provider", "1")
form.Set("s3_bucket", "bucket")
form.Set("s3_region", "us-east-1")
@ -22750,52 +22688,6 @@ func TestFolderTemplateMock(t *testing.T) {
form.Set("s3_upload_part_max_time", "0")
form.Set("s3_download_part_size", "6")
form.Set("s3_download_concurrency", "2")
b, contentType, _ = getMultipartFormData(form, "", "")
req, _ = http.NewRequest(http.MethodPost, webTemplateFolder, &b)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
dump = dataprovider.BackupData{
Version: dataprovider.DumpVersion,
}
err = json.Unmarshal(rr.Body.Bytes(), &dump)
require.NoError(t, err)
require.Len(t, dump.Users, 0)
require.Len(t, dump.Admins, 0)
require.Len(t, dump.Folders, 3)
for _, folder := range dump.Folders {
switch folder.Name {
case folder1:
require.Equal(t, folder1, folder.FsConfig.S3Config.AccessKey)
err = folder.FsConfig.S3Config.AccessSecret.Decrypt()
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("pwd%s", folder1), folder.FsConfig.S3Config.AccessSecret.GetPayload())
require.Equal(t, path.Join("base", folder1)+"/", folder.FsConfig.S3Config.KeyPrefix)
err = folder.FsConfig.S3Config.SSECustomerKey.Decrypt()
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("key%s", folder1), folder.FsConfig.S3Config.SSECustomerKey.GetPayload())
case folder2:
require.Equal(t, folder2, folder.FsConfig.S3Config.AccessKey)
err = folder.FsConfig.S3Config.AccessSecret.Decrypt()
require.NoError(t, err)
require.Equal(t, "pwd"+folder2, folder.FsConfig.S3Config.AccessSecret.GetPayload())
require.Equal(t, "base/"+folder2+"/", folder.FsConfig.S3Config.KeyPrefix)
err = folder.FsConfig.S3Config.SSECustomerKey.Decrypt()
require.NoError(t, err)
require.Equal(t, "key"+folder2, folder.FsConfig.S3Config.SSECustomerKey.GetPayload())
default:
require.Equal(t, folder3, folder.FsConfig.S3Config.AccessKey)
err = folder.FsConfig.S3Config.AccessSecret.Decrypt()
require.NoError(t, err)
require.Equal(t, "pwd"+folder3, folder.FsConfig.S3Config.AccessSecret.GetPayload())
require.Equal(t, "base/"+folder3+"/", folder.FsConfig.S3Config.KeyPrefix)
err = folder.FsConfig.S3Config.SSECustomerKey.Decrypt()
require.NoError(t, err)
require.Equal(t, "key"+folder3, folder.FsConfig.S3Config.SSECustomerKey.GetPayload())
}
}
form.Set("template_folders[0][tpl_foldername]", " ")
form.Set("template_folders[1][tpl_foldername]", "")
@ -22820,6 +22712,61 @@ func TestFolderTemplateMock(t *testing.T) {
assert.Contains(t, rr.Body.String(), util.I18nErrorInvalidHomeDir)
}
func TestFolderTemplatePermission(t *testing.T) {
admin := getTestAdmin()
admin.Username = altAdminUsername
admin.Password = altAdminPassword
admin.Permissions = []string{dataprovider.PermAdminChangeUsers, dataprovider.PermAdminAddUsers, dataprovider.PermAdminViewUsers}
admin, _, err := httpdtest.AddAdmin(admin, http.StatusCreated)
assert.NoError(t, err)
// no permission to view or add folders from templates
token, err := getJWTWebTokenFromTestServer(altAdminUsername, altAdminPassword)
assert.NoError(t, err)
csrfToken, err := getCSRFTokenFromInternalPageMock(webTemplateUser, token)
assert.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, webTemplateFolder, nil)
assert.NoError(t, err)
req.RequestURI = webTemplateFolder
setJWTCookieForReq(req, token)
rr := executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
form := make(url.Values)
form.Set("name", "name")
form.Set("mapped_path", filepath.Join(os.TempDir(), "%name%"))
form.Set("description", "desc folder %name%")
form.Set("template_folders[0][tpl_foldername]", "folder1")
form.Set("template_folders[1][tpl_foldername]", "folder2")
form.Set(csrfFormToken, csrfToken)
b, contentType, _ := getMultipartFormData(form, "", "")
req, err = http.NewRequest(http.MethodPost, webTemplateFolder, &b)
assert.NoError(t, err)
setJWTCookieForReq(req, token)
req.Header.Set("Content-Type", contentType)
rr = executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
admin.Permissions = append(admin.Permissions, dataprovider.PermAdminManageFolders)
_, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK)
assert.NoError(t, err)
token, err = getJWTWebTokenFromTestServer(altAdminUsername, altAdminPassword)
assert.NoError(t, err)
_, err = getCSRFTokenFromInternalPageMock(webTemplateUser, token)
assert.NoError(t, err)
req, err = http.NewRequest(http.MethodGet, webTemplateFolder, nil)
assert.NoError(t, err)
req.RequestURI = webTemplateFolder
setJWTCookieForReq(req, token)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
_, err = httpdtest.RemoveAdmin(admin, http.StatusOK)
assert.NoError(t, err)
}
func TestWebUserS3Mock(t *testing.T) {
webToken, err := getJWTWebTokenFromTestServer(defaultTokenAuthUser, defaultTokenAuthPass)
assert.NoError(t, err)

View file

@ -1794,7 +1794,7 @@ func TestJWTTokenValidation(t *testing.T) {
assert.Equal(t, webClientLoginPath, rr.Header().Get("Location"))
errTest := errors.New("test error")
permFn := server.checkPerm(dataprovider.PermAdminAny)
permFn := server.checkPerms(dataprovider.PermAdminAny)
fn = permFn(r)
rr = httptest.NewRecorder()
req, _ = http.NewRequest(http.MethodGet, userPath, nil)
@ -1802,7 +1802,7 @@ func TestJWTTokenValidation(t *testing.T) {
fn.ServeHTTP(rr, req.WithContext(ctx))
assert.Equal(t, http.StatusBadRequest, rr.Code)
permFn = server.checkPerm(dataprovider.PermAdminAny)
permFn = server.checkPerms(dataprovider.PermAdminAny)
fn = permFn(r)
rr = httptest.NewRecorder()
req, _ = http.NewRequest(http.MethodGet, webUserPath, nil)

View file

@ -297,7 +297,7 @@ func (s *httpdServer) requireBuiltinLogin(next http.Handler) http.Handler {
})
}
func (s *httpdServer) checkPerm(perm string) func(next http.Handler) http.Handler {
func (s *httpdServer) checkPerms(perms ...string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, claims, err := jwtauth.FromContext(r.Context())
@ -312,13 +312,15 @@ func (s *httpdServer) checkPerm(perm string) func(next http.Handler) http.Handle
tokenClaims := jwtTokenClaims{}
tokenClaims.Decode(claims)
if !tokenClaims.hasPerm(perm) {
if isWebRequest(r) {
s.renderForbiddenPage(w, r, util.NewI18nError(fs.ErrPermission, util.I18nError403Message))
} else {
sendAPIResponse(w, r, nil, http.StatusText(http.StatusForbidden), http.StatusForbidden)
for _, perm := range perms {
if !tokenClaims.hasPerm(perm) {
if isWebRequest(r) {
s.renderForbiddenPage(w, r, util.NewI18nError(fs.ErrPermission, util.I18nError403Message))
} else {
sendAPIResponse(w, r, nil, http.StatusText(http.StatusForbidden), http.StatusForbidden)
}
return
}
return
}
next.ServeHTTP(w, r)

View file

@ -1325,97 +1325,97 @@ func (s *httpdServer) initializeRouter() {
router.With(forbidAPIKeyAuthentication).Get(admin2FARecoveryCodesPath, getRecoveryCodes)
router.With(forbidAPIKeyAuthentication).Post(admin2FARecoveryCodesPath, generateRecoveryCodes)
router.With(forbidAPIKeyAuthentication, s.checkPerm(dataprovider.PermAdminAny)).
router.With(forbidAPIKeyAuthentication, s.checkPerms(dataprovider.PermAdminAny)).
Get(apiKeysPath, getAPIKeys)
router.With(forbidAPIKeyAuthentication, s.checkPerm(dataprovider.PermAdminAny)).
router.With(forbidAPIKeyAuthentication, s.checkPerms(dataprovider.PermAdminAny)).
Post(apiKeysPath, addAPIKey)
router.With(forbidAPIKeyAuthentication, s.checkPerm(dataprovider.PermAdminAny)).
router.With(forbidAPIKeyAuthentication, s.checkPerms(dataprovider.PermAdminAny)).
Get(apiKeysPath+"/{id}", getAPIKeyByID)
router.With(forbidAPIKeyAuthentication, s.checkPerm(dataprovider.PermAdminAny)).
router.With(forbidAPIKeyAuthentication, s.checkPerms(dataprovider.PermAdminAny)).
Put(apiKeysPath+"/{id}", updateAPIKey)
router.With(forbidAPIKeyAuthentication, s.checkPerm(dataprovider.PermAdminAny)).
router.With(forbidAPIKeyAuthentication, s.checkPerms(dataprovider.PermAdminAny)).
Delete(apiKeysPath+"/{id}", deleteAPIKey)
router.Group(func(router chi.Router) {
router.Use(s.checkAuthRequirements)
router.With(s.checkPerm(dataprovider.PermAdminViewServerStatus)).
router.With(s.checkPerms(dataprovider.PermAdminViewServerStatus)).
Get(serverStatusPath, func(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
render.JSON(w, r, getServicesStatus())
})
router.With(s.checkPerm(dataprovider.PermAdminViewConnections)).Get(activeConnectionsPath, getActiveConnections)
router.With(s.checkPerm(dataprovider.PermAdminCloseConnections)).
router.With(s.checkPerms(dataprovider.PermAdminViewConnections)).Get(activeConnectionsPath, getActiveConnections)
router.With(s.checkPerms(dataprovider.PermAdminCloseConnections)).
Delete(activeConnectionsPath+"/{connectionID}", handleCloseConnection)
router.With(s.checkPerm(dataprovider.PermAdminQuotaScans)).Get(quotasBasePath+"/users/scans", getUsersQuotaScans)
router.With(s.checkPerm(dataprovider.PermAdminQuotaScans)).Post(quotasBasePath+"/users/{username}/scan", startUserQuotaScan)
router.With(s.checkPerm(dataprovider.PermAdminQuotaScans)).Get(quotasBasePath+"/folders/scans", getFoldersQuotaScans)
router.With(s.checkPerm(dataprovider.PermAdminQuotaScans)).Post(quotasBasePath+"/folders/{name}/scan", startFolderQuotaScan)
router.With(s.checkPerm(dataprovider.PermAdminViewUsers)).Get(userPath, getUsers)
router.With(s.checkPerm(dataprovider.PermAdminAddUsers)).Post(userPath, addUser)
router.With(s.checkPerm(dataprovider.PermAdminViewUsers)).Get(userPath+"/{username}", getUserByUsername) //nolint:goconst
router.With(s.checkPerm(dataprovider.PermAdminChangeUsers)).Put(userPath+"/{username}", updateUser)
router.With(s.checkPerm(dataprovider.PermAdminDeleteUsers)).Delete(userPath+"/{username}", deleteUser)
router.With(s.checkPerm(dataprovider.PermAdminDisableMFA)).Put(userPath+"/{username}/2fa/disable", disableUser2FA) //nolint:goconst
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Get(folderPath, getFolders)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Get(folderPath+"/{name}", getFolderByName) //nolint:goconst
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Post(folderPath, addFolder)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Put(folderPath+"/{name}", updateFolder)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Delete(folderPath+"/{name}", deleteFolder)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Get(groupPath, getGroups)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Get(groupPath+"/{name}", getGroupByName)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Post(groupPath, addGroup)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Put(groupPath+"/{name}", updateGroup)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Delete(groupPath+"/{name}", deleteGroup)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(dumpDataPath, dumpData)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(loadDataPath, loadData)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(loadDataPath, loadDataFromRequest)
router.With(s.checkPerm(dataprovider.PermAdminChangeUsers)).Put(quotasBasePath+"/users/{username}/usage",
router.With(s.checkPerms(dataprovider.PermAdminQuotaScans)).Get(quotasBasePath+"/users/scans", getUsersQuotaScans)
router.With(s.checkPerms(dataprovider.PermAdminQuotaScans)).Post(quotasBasePath+"/users/{username}/scan", startUserQuotaScan)
router.With(s.checkPerms(dataprovider.PermAdminQuotaScans)).Get(quotasBasePath+"/folders/scans", getFoldersQuotaScans)
router.With(s.checkPerms(dataprovider.PermAdminQuotaScans)).Post(quotasBasePath+"/folders/{name}/scan", startFolderQuotaScan)
router.With(s.checkPerms(dataprovider.PermAdminViewUsers)).Get(userPath, getUsers)
router.With(s.checkPerms(dataprovider.PermAdminAddUsers)).Post(userPath, addUser)
router.With(s.checkPerms(dataprovider.PermAdminViewUsers)).Get(userPath+"/{username}", getUserByUsername) //nolint:goconst
router.With(s.checkPerms(dataprovider.PermAdminChangeUsers)).Put(userPath+"/{username}", updateUser)
router.With(s.checkPerms(dataprovider.PermAdminDeleteUsers)).Delete(userPath+"/{username}", deleteUser)
router.With(s.checkPerms(dataprovider.PermAdminDisableMFA)).Put(userPath+"/{username}/2fa/disable", disableUser2FA) //nolint:goconst
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Get(folderPath, getFolders)
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Get(folderPath+"/{name}", getFolderByName) //nolint:goconst
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Post(folderPath, addFolder)
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Put(folderPath+"/{name}", updateFolder)
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Delete(folderPath+"/{name}", deleteFolder)
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Get(groupPath, getGroups)
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Get(groupPath+"/{name}", getGroupByName)
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Post(groupPath, addGroup)
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Put(groupPath+"/{name}", updateGroup)
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Delete(groupPath+"/{name}", deleteGroup)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(dumpDataPath, dumpData)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(loadDataPath, loadData)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(loadDataPath, loadDataFromRequest)
router.With(s.checkPerms(dataprovider.PermAdminChangeUsers)).Put(quotasBasePath+"/users/{username}/usage",
updateUserQuotaUsage)
router.With(s.checkPerm(dataprovider.PermAdminChangeUsers)).Put(quotasBasePath+"/users/{username}/transfer-usage",
router.With(s.checkPerms(dataprovider.PermAdminChangeUsers)).Put(quotasBasePath+"/users/{username}/transfer-usage",
updateUserTransferQuotaUsage)
router.With(s.checkPerm(dataprovider.PermAdminChangeUsers)).Put(quotasBasePath+"/folders/{name}/usage",
router.With(s.checkPerms(dataprovider.PermAdminChangeUsers)).Put(quotasBasePath+"/folders/{name}/usage",
updateFolderQuotaUsage)
router.With(s.checkPerm(dataprovider.PermAdminViewDefender)).Get(defenderHosts, getDefenderHosts)
router.With(s.checkPerm(dataprovider.PermAdminViewDefender)).Get(defenderHosts+"/{id}", getDefenderHostByID)
router.With(s.checkPerm(dataprovider.PermAdminManageDefender)).Delete(defenderHosts+"/{id}", deleteDefenderHostByID)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(adminPath, getAdmins)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(adminPath, addAdmin)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(adminPath+"/{username}", getAdminByUsername)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Put(adminPath+"/{username}", updateAdmin)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Delete(adminPath+"/{username}", deleteAdmin)
router.With(s.checkPerm(dataprovider.PermAdminDisableMFA)).Put(adminPath+"/{username}/2fa/disable", disableAdmin2FA)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(retentionChecksPath, getRetentionChecks)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(retentionBasePath+"/{username}/check",
router.With(s.checkPerms(dataprovider.PermAdminViewDefender)).Get(defenderHosts, getDefenderHosts)
router.With(s.checkPerms(dataprovider.PermAdminViewDefender)).Get(defenderHosts+"/{id}", getDefenderHostByID)
router.With(s.checkPerms(dataprovider.PermAdminManageDefender)).Delete(defenderHosts+"/{id}", deleteDefenderHostByID)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(adminPath, getAdmins)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(adminPath, addAdmin)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(adminPath+"/{username}", getAdminByUsername)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Put(adminPath+"/{username}", updateAdmin)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Delete(adminPath+"/{username}", deleteAdmin)
router.With(s.checkPerms(dataprovider.PermAdminDisableMFA)).Put(adminPath+"/{username}/2fa/disable", disableAdmin2FA)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(retentionChecksPath, getRetentionChecks)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(retentionBasePath+"/{username}/check",
startRetentionCheck)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), compressor.Handler).
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), compressor.Handler).
Get(fsEventsPath, searchFsEvents)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), compressor.Handler).
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), compressor.Handler).
Get(providerEventsPath, searchProviderEvents)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), compressor.Handler).
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), compressor.Handler).
Get(logEventsPath, searchLogEvents)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(eventActionsPath, getEventActions)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(eventActionsPath+"/{name}", getEventActionByName)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(eventActionsPath, addEventAction)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Put(eventActionsPath+"/{name}", updateEventAction)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Delete(eventActionsPath+"/{name}", deleteEventAction)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(eventRulesPath, getEventRules)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(eventRulesPath+"/{name}", getEventRuleByName)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(eventRulesPath, addEventRule)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Put(eventRulesPath+"/{name}", updateEventRule)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Delete(eventRulesPath+"/{name}", deleteEventRule)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(eventRulesPath+"/run/{name}", runOnDemandRule)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(rolesPath, getRoles)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(rolesPath, addRole)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(rolesPath+"/{name}", getRoleByName)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Put(rolesPath+"/{name}", updateRole)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Delete(rolesPath+"/{name}", deleteRole)
router.With(s.checkPerm(dataprovider.PermAdminAny), compressor.Handler).Get(ipListsPath+"/{type}", getIPListEntries) //nolint:goconst
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(ipListsPath+"/{type}", addIPListEntry)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(ipListsPath+"/{type}/{ipornet}", getIPListEntry) //nolint:goconst
router.With(s.checkPerm(dataprovider.PermAdminAny)).Put(ipListsPath+"/{type}/{ipornet}", updateIPListEntry)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Delete(ipListsPath+"/{type}/{ipornet}", deleteIPListEntry)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(eventActionsPath, getEventActions)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(eventActionsPath+"/{name}", getEventActionByName)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(eventActionsPath, addEventAction)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Put(eventActionsPath+"/{name}", updateEventAction)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Delete(eventActionsPath+"/{name}", deleteEventAction)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(eventRulesPath, getEventRules)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(eventRulesPath+"/{name}", getEventRuleByName)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(eventRulesPath, addEventRule)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Put(eventRulesPath+"/{name}", updateEventRule)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Delete(eventRulesPath+"/{name}", deleteEventRule)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(eventRulesPath+"/run/{name}", runOnDemandRule)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(rolesPath, getRoles)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(rolesPath, addRole)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(rolesPath+"/{name}", getRoleByName)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Put(rolesPath+"/{name}", updateRole)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Delete(rolesPath+"/{name}", deleteRole)
router.With(s.checkPerms(dataprovider.PermAdminAny), compressor.Handler).Get(ipListsPath+"/{type}", getIPListEntries) //nolint:goconst
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(ipListsPath+"/{type}", addIPListEntry)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(ipListsPath+"/{type}/{ipornet}", getIPListEntry) //nolint:goconst
router.With(s.checkPerms(dataprovider.PermAdminAny)).Put(ipListsPath+"/{type}/{ipornet}", updateIPListEntry)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Delete(ipListsPath+"/{type}/{ipornet}", deleteIPListEntry)
})
})
@ -1730,156 +1730,157 @@ func (s *httpdServer) setupWebAdminRoutes() {
router.Group(func(router chi.Router) {
router.Use(s.checkAuthRequirements)
router.With(s.checkPerm(dataprovider.PermAdminViewUsers), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewUsers), s.refreshCookie).
Get(webUsersPath, s.handleGetWebUsers)
router.With(s.checkPerm(dataprovider.PermAdminViewUsers), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewUsers), compressor.Handler, s.refreshCookie).
Get(webUsersPath+jsonAPISuffix, getAllUsers)
router.With(s.checkPerm(dataprovider.PermAdminAddUsers), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAddUsers), s.refreshCookie).
Get(webUserPath, s.handleWebAddUserGet)
router.With(s.checkPerm(dataprovider.PermAdminChangeUsers), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminChangeUsers), s.refreshCookie).
Get(webUserPath+"/{username}", s.handleWebUpdateUserGet)
router.With(s.checkPerm(dataprovider.PermAdminAddUsers)).Post(webUserPath, s.handleWebAddUserPost)
router.With(s.checkPerm(dataprovider.PermAdminChangeUsers)).Post(webUserPath+"/{username}",
router.With(s.checkPerms(dataprovider.PermAdminAddUsers)).Post(webUserPath, s.handleWebAddUserPost)
router.With(s.checkPerms(dataprovider.PermAdminChangeUsers)).Post(webUserPath+"/{username}",
s.handleWebUpdateUserPost)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageGroups), s.refreshCookie).
Get(webGroupsPath, s.handleWebGetGroups)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageGroups), compressor.Handler, s.refreshCookie).
Get(webGroupsPath+jsonAPISuffix, getAllGroups)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageGroups), s.refreshCookie).
Get(webGroupPath, s.handleWebAddGroupGet)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Post(webGroupPath, s.handleWebAddGroupPost)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Post(webGroupPath, s.handleWebAddGroupPost)
router.With(s.checkPerms(dataprovider.PermAdminManageGroups), s.refreshCookie).
Get(webGroupPath+"/{name}", s.handleWebUpdateGroupGet)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups)).Post(webGroupPath+"/{name}",
router.With(s.checkPerms(dataprovider.PermAdminManageGroups)).Post(webGroupPath+"/{name}",
s.handleWebUpdateGroupPost)
router.With(s.checkPerm(dataprovider.PermAdminManageGroups), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminManageGroups), s.verifyCSRFHeader).
Delete(webGroupPath+"/{name}", deleteGroup)
router.With(s.checkPerm(dataprovider.PermAdminViewConnections), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewConnections), s.refreshCookie).
Get(webConnectionsPath, s.handleWebGetConnections)
router.With(s.checkPerm(dataprovider.PermAdminViewConnections), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewConnections), s.refreshCookie).
Get(webConnectionsPath+jsonAPISuffix, getActiveConnections)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders), s.refreshCookie).
Get(webFoldersPath, s.handleWebGetFolders)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders), compressor.Handler, s.refreshCookie).
Get(webFoldersPath+jsonAPISuffix, getAllFolders)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders), s.refreshCookie).
Get(webFolderPath, s.handleWebAddFolderGet)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Post(webFolderPath, s.handleWebAddFolderPost)
router.With(s.checkPerm(dataprovider.PermAdminViewServerStatus), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Post(webFolderPath, s.handleWebAddFolderPost)
router.With(s.checkPerms(dataprovider.PermAdminViewServerStatus), s.refreshCookie).
Get(webStatusPath, s.handleWebGetStatus)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminsPath, s.handleGetWebAdmins)
router.With(s.checkPerm(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
Get(webAdminsPath+jsonAPISuffix, getAllAdmins)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminPath, s.handleWebAddAdminGet)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminPath+"/{username}", s.handleWebUpdateAdminGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminPath, s.handleWebAddAdminPost)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminPath+"/{username}",
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminPath, s.handleWebAddAdminPost)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminPath+"/{username}",
s.handleWebUpdateAdminPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader).
Delete(webAdminPath+"/{username}", deleteAdmin)
router.With(s.checkPerm(dataprovider.PermAdminDisableMFA), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminDisableMFA), s.verifyCSRFHeader).
Put(webAdminPath+"/{username}/2fa/disable", disableAdmin2FA)
router.With(s.checkPerm(dataprovider.PermAdminCloseConnections), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminCloseConnections), s.verifyCSRFHeader).
Delete(webConnectionsPath+"/{connectionID}", handleCloseConnection)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders), s.refreshCookie).
Get(webFolderPath+"/{name}", s.handleWebUpdateFolderGet)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders)).Post(webFolderPath+"/{name}",
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Post(webFolderPath+"/{name}",
s.handleWebUpdateFolderPost)
router.With(s.checkPerm(dataprovider.PermAdminManageFolders), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders), s.verifyCSRFHeader).
Delete(webFolderPath+"/{name}", deleteFolder)
router.With(s.checkPerm(dataprovider.PermAdminQuotaScans), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminQuotaScans), s.verifyCSRFHeader).
Post(webScanVFolderPath+"/{name}", startFolderQuotaScan)
router.With(s.checkPerm(dataprovider.PermAdminDeleteUsers), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminDeleteUsers), s.verifyCSRFHeader).
Delete(webUserPath+"/{username}", deleteUser)
router.With(s.checkPerm(dataprovider.PermAdminDisableMFA), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminDisableMFA), s.verifyCSRFHeader).
Put(webUserPath+"/{username}/2fa/disable", disableUser2FA)
router.With(s.checkPerm(dataprovider.PermAdminQuotaScans), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminQuotaScans), s.verifyCSRFHeader).
Post(webQuotaScanPath+"/{username}", startUserQuotaScan)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(webMaintenancePath, s.handleWebMaintenance)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(webBackupPath, dumpData)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webRestorePath, s.handleWebRestore)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(webMaintenancePath, s.handleWebMaintenance)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(webBackupPath, dumpData)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webRestorePath, s.handleWebRestore)
router.With(s.checkPerms(dataprovider.PermAdminAddUsers, dataprovider.PermAdminChangeUsers), s.refreshCookie).
Get(webTemplateUser, s.handleWebTemplateUserGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webTemplateUser, s.handleWebTemplateUserPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAddUsers, dataprovider.PermAdminChangeUsers)).
Post(webTemplateUser, s.handleWebTemplateUserPost)
router.With(s.checkPerms(dataprovider.PermAdminManageFolders), s.refreshCookie).
Get(webTemplateFolder, s.handleWebTemplateFolderGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webTemplateFolder, s.handleWebTemplateFolderPost)
router.With(s.checkPerm(dataprovider.PermAdminViewDefender)).Get(webDefenderPath, s.handleWebDefenderPage)
router.With(s.checkPerm(dataprovider.PermAdminViewDefender)).Get(webDefenderHostsPath, getDefenderHosts)
router.With(s.checkPerm(dataprovider.PermAdminManageDefender), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminManageFolders)).Post(webTemplateFolder, s.handleWebTemplateFolderPost)
router.With(s.checkPerms(dataprovider.PermAdminViewDefender)).Get(webDefenderPath, s.handleWebDefenderPage)
router.With(s.checkPerms(dataprovider.PermAdminViewDefender)).Get(webDefenderHostsPath, getDefenderHosts)
router.With(s.checkPerms(dataprovider.PermAdminManageDefender), s.verifyCSRFHeader).
Delete(webDefenderHostsPath+"/{id}", deleteDefenderHostByID)
router.With(s.checkPerm(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
Get(webAdminEventActionsPath+jsonAPISuffix, getAllActions)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminEventActionsPath, s.handleWebGetEventActions)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminEventActionPath, s.handleWebAddEventActionGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminEventActionPath,
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminEventActionPath,
s.handleWebAddEventActionPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminEventActionPath+"/{name}", s.handleWebUpdateEventActionGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminEventActionPath+"/{name}",
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminEventActionPath+"/{name}",
s.handleWebUpdateEventActionPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader).
Delete(webAdminEventActionPath+"/{name}", deleteEventAction)
router.With(s.checkPerm(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
Get(webAdminEventRulesPath+jsonAPISuffix, getAllRules)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminEventRulesPath, s.handleWebGetEventRules)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminEventRulePath, s.handleWebAddEventRuleGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminEventRulePath,
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminEventRulePath,
s.handleWebAddEventRulePost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminEventRulePath+"/{name}", s.handleWebUpdateEventRuleGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminEventRulePath+"/{name}",
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminEventRulePath+"/{name}",
s.handleWebUpdateEventRulePost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader).
Delete(webAdminEventRulePath+"/{name}", deleteEventRule)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader).
Post(webAdminEventRulePath+"/run/{name}", runOnDemandRule)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminRolesPath, s.handleWebGetRoles)
router.With(s.checkPerm(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
Get(webAdminRolesPath+jsonAPISuffix, getAllRoles)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminRolePath, s.handleWebAddRoleGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminRolePath, s.handleWebAddRolePost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminRolePath, s.handleWebAddRolePost)
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).
Get(webAdminRolePath+"/{name}", s.handleWebUpdateRoleGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webAdminRolePath+"/{name}",
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webAdminRolePath+"/{name}",
s.handleWebUpdateRolePost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader).
Delete(webAdminRolePath+"/{name}", deleteRole)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), s.refreshCookie).Get(webEventsPath,
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), s.refreshCookie).Get(webEventsPath,
s.handleWebGetEvents)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), compressor.Handler, s.refreshCookie).
Get(webEventsFsSearchPath, searchFsEvents)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), compressor.Handler, s.refreshCookie).
Get(webEventsProviderSearchPath, searchProviderEvents)
router.With(s.checkPerm(dataprovider.PermAdminViewEvents), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminViewEvents), compressor.Handler, s.refreshCookie).
Get(webEventsLogSearchPath, searchLogEvents)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Get(webIPListsPath, s.handleWebIPListsPage)
router.With(s.checkPerm(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny)).Get(webIPListsPath, s.handleWebIPListsPage)
router.With(s.checkPerms(dataprovider.PermAdminAny), compressor.Handler, s.refreshCookie).
Get(webIPListsPath+"/{type}", getIPListEntries)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).Get(webIPListPath+"/{type}",
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).Get(webIPListPath+"/{type}",
s.handleWebAddIPListEntryGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webIPListPath+"/{type}",
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webIPListPath+"/{type}",
s.handleWebAddIPListEntryPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).Get(webIPListPath+"/{type}/{ipornet}",
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).Get(webIPListPath+"/{type}/{ipornet}",
s.handleWebUpdateIPListEntryGet)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webIPListPath+"/{type}/{ipornet}",
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webIPListPath+"/{type}/{ipornet}",
s.handleWebUpdateIPListEntryPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader).
Delete(webIPListPath+"/{type}/{ipornet}", deleteIPListEntry)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.refreshCookie).Get(webConfigsPath, s.handleWebConfigs)
router.With(s.checkPerm(dataprovider.PermAdminAny)).Post(webConfigsPath, s.handleWebConfigsPost)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.refreshCookie).Get(webConfigsPath, s.handleWebConfigs)
router.With(s.checkPerms(dataprovider.PermAdminAny)).Post(webConfigsPath, s.handleWebConfigsPost)
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader, s.refreshCookie).
Post(webConfigsPath+"/smtp/test", testSMTPConfig)
router.With(s.checkPerm(dataprovider.PermAdminAny), s.verifyCSRFHeader, s.refreshCookie).
router.With(s.checkPerms(dataprovider.PermAdminAny), s.verifyCSRFHeader, s.refreshCookie).
Post(webOAuth2TokenPath, s.handleSMTPOAuth2TokenRequestPost)
})
})

View file

@ -31,7 +31,6 @@ import (
"strings"
"time"
"github.com/go-chi/render"
"github.com/rs/xid"
"github.com/sftpgo/sdk"
sdkkms "github.com/sftpgo/sdk/kms"
@ -3280,7 +3279,6 @@ func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http
templateFolder.FsConfig = fsConfig
var dump dataprovider.BackupData
dump.Version = dataprovider.DumpVersion
foldersFields := getFoldersForTemplate(r)
for _, tmpl := range foldersFields {
@ -3300,12 +3298,6 @@ func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http
), "")
return
}
if r.Form.Get("form_action") == "export_from_template" {
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"",
len(dump.Folders)))
render.JSON(w, r, dump)
return
}
if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
s.renderMessagePage(w, r, util.I18nTemplateFolderTitle, getRespStatus(err), err, "")
return
@ -3372,7 +3364,6 @@ func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.R
}
var dump dataprovider.BackupData
dump.Version = dataprovider.DumpVersion
userTmplFields := getUsersForTemplate(r)
for _, tmpl := range userTmplFields {
@ -3381,14 +3372,10 @@ func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.R
s.renderMessagePage(w, r, util.I18nTemplateUserTitle, http.StatusBadRequest, err, "")
return
}
// to create a template the "*" permission is required, so role admins cannot use
// this method, we don't need to force the role
dump.Users = append(dump.Users, u)
for _, folder := range u.VirtualFolders {
if !dump.HasFolder(folder.Name) {
dump.Folders = append(dump.Folders, folder.BaseVirtualFolder)
}
if claims.Role != "" {
u.Role = claims.Role
}
dump.Users = append(dump.Users, u)
}
if len(dump.Users) == 0 {
@ -3399,12 +3386,6 @@ func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.R
), "")
return
}
if r.Form.Get("form_action") == "export_from_template" {
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-users-from-template.json\"",
len(dump.Users)))
render.JSON(w, r, dump)
return
}
if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
s.renderMessagePage(w, r, util.I18nTemplateUserTitle, getRespStatus(err), err, "")
return

View file

@ -535,8 +535,6 @@
"virtual_folders_help": "Quota size/files -1 means included within user quota, 0 unlimited. Don't set -1 for shared folders. You can use MB/GB/TB suffix. Without suffix we assume bytes",
"disconnect": "Disconnect the user after the update",
"disconnect_help": "This way you force the user to login again, if connected, and so to use the new configuration",
"submit_generate": "Generate and save users",
"submit_export": "Generate and export users",
"invalid_quota_size": "Invalid quota size",
"expires_in": "Expires in",
"expires_in_help": "Account expiration as number of days from the creation. 0 means no expiration",
@ -570,8 +568,6 @@
"template_name_placeholder": "replaced with the name of the specified virtual folder",
"template_help": "The generated virtual folders can be saved or exported. Exported folders can be imported from the \"Maintenance\" section of this SFTPGo instance or another.",
"name": "Virtual folder name",
"submit_generate": "Generate and save folders",
"submit_export": "Generate and export folder",
"template_no_folder": "No valid virtual folder defined, unable to complete the requested action"
},
"storage": {

View file

@ -535,8 +535,6 @@
"virtual_folders_help": "Dimensione quota/numero file -1 significa incluso nella quota utente, 0 illimitato. Non impostare -1 per le cartelle condivise. È possibile utilizzare il suffisso MB/GB/TB. Senza suffisso assumiamo byte",
"disconnect": "Disconnettere l'utente dopo l'aggiornamento",
"disconnect_help": "In questo modo si obbliga l'utente a effettuare nuovamente il login, se connesso, e quindi ad utilizzare la nuova configurazione",
"submit_generate": "Genera e salva utenti",
"submit_export": "Genera ed esporta utenti",
"invalid_quota_size": "Quota (dimensione) non valida",
"expires_in": "Scadenza",
"expires_in_help": "Scadenza dell'account espressa in numero di giorni dalla creazione. 0 significa nessuna scadenza",
@ -570,8 +568,6 @@
"template_name_placeholder": "sostituito con il nome della cartella virtuale specificata",
"template_help": "Le cartelle virtuali generate possono essere salvate o esportate. Le cartelle esportate possono essere importate dalla sezione \"Manutenzione\" di questa istanza SFTPGo o di un'altra.",
"name": "Nome cartella virtuale",
"submit_generate": "Genera e salva cartelle",
"submit_export": "Genera e esporta cartelle",
"template_no_folder": "Nessuna cartella virtuale valida definita. Impossibile completare l'azione richiesta"
},
"storage": {

View file

@ -108,19 +108,8 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
<div class="d-flex justify-content-end mt-12">
<input type="hidden" name="_form_token" value="{{.CSRFToken}}">
{{- if eq .Mode 3}}
<button type="submit" id="form_generate_submit" class="btn btn-secondary px-10 me-10" name="form_action" value="export_from_template">
<span data-i18n="virtual_folders.submit_export" class="indicator-label">
Generate and export folders
</span>
<span data-i18n="general.wait" class="indicator-progress">
Please wait...
<span class="spinner-border spinner-border-sm align-middle ms-2"></span>
</span>
</button>
{{- end}}
<button type="submit" id="form_submit" class="btn btn-primary px-10" name="form_action" value="submit">
<span {{if eq .Mode 3}}data-i18n="virtual_folders.submit_generate"{{else}}data-i18n="general.submit"{{end}} class="indicator-label">
<span data-i18n="general.submit" class="indicator-label">
Submit
</span>
<span data-i18n="general.wait" class="indicator-progress">

View file

@ -300,14 +300,10 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
actions+=`<div class="menu-item px-3">
<a data-i18n="general.edit" href="#" class="menu-link px-3" data-table-action="edit_row">Edit</a>
</div>`;
//{{- end}}
//{{- if .LoggedUser.HasPermission "*"}}
numActions++;
actions+=`<div class="menu-item px-3">
<a data-i18n="general.template" href="#" class="menu-link px-3" data-table-action="template_row">Template</a>
</div>`;
//{{- end}}
//{{- if .LoggedUser.HasPermission "manage_folders"}}
numActions++;
actions+=`<div class="menu-item px-3">
<a data-i18n="general.delete" href="#" class="menu-link text-danger px-3" data-table-action="delete_row">Delete</a>

View file

@ -801,19 +801,8 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
<div class="d-flex justify-content-end mt-12">
<input type="hidden" name="expiration_date" id="hidden_start_datetime" value="">
<input type="hidden" name="_form_token" value="{{.CSRFToken}}">
{{- if eq .Mode 3}}
<button type="submit" id="form_generate_submit" class="btn btn-secondary px-10 me-10" name="form_action" value="export_from_template">
<span data-i18n="user.submit_export" class="indicator-label">
Generate and export users
</span>
<span data-i18n="general.wait" class="indicator-progress">
Please wait...
<span class="spinner-border spinner-border-sm align-middle ms-2"></span>
</span>
</button>
{{- end}}
<button type="submit" id="form_submit" class="btn btn-primary px-10" name="form_action" value="submit">
<span {{if eq .Mode 3}}data-i18n="user.submit_generate"{{else}}data-i18n="general.submit"{{end}} class="indicator-label">
<span data-i18n="general.submit" class="indicator-label">
Submit
</span>
<span data-i18n="general.wait" class="indicator-progress">

View file

@ -547,7 +547,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
<a data-i18n="general.edit" href="#" class="menu-link px-3" data-table-action="edit_row">Edit</a>
</div>`;
//{{- end}}
//{{- if .LoggedUser.HasPermission "*"}}
//{{- if .LoggedUser.HasPermissions "add_users" "edit_users"}}
numActions++;
actions+=`<div class="menu-item px-3">
<a data-i18n="general.template" href="#" class="menu-link px-3" data-table-action="template_row">Template</a>