1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773 |
- package common_test
- import (
- "bytes"
- "crypto/rand"
- "fmt"
- "io"
- "math"
- "net"
- "net/http"
- "os"
- "path"
- "path/filepath"
- "runtime"
- "strings"
- "testing"
- "time"
- _ "github.com/go-sql-driver/mysql"
- _ "github.com/lib/pq"
- _ "github.com/mattn/go-sqlite3"
- "github.com/pkg/sftp"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "golang.org/x/crypto/ssh"
- "github.com/rs/zerolog"
- "github.com/drakkan/sftpgo/v2/common"
- "github.com/drakkan/sftpgo/v2/config"
- "github.com/drakkan/sftpgo/v2/dataprovider"
- "github.com/drakkan/sftpgo/v2/httpclient"
- "github.com/drakkan/sftpgo/v2/httpdtest"
- "github.com/drakkan/sftpgo/v2/kms"
- "github.com/drakkan/sftpgo/v2/logger"
- "github.com/drakkan/sftpgo/v2/vfs"
- )
- const (
- configDir = ".."
- httpAddr = "127.0.0.1:9999"
- httpProxyAddr = "127.0.0.1:7777"
- sftpServerAddr = "127.0.0.1:4022"
- defaultUsername = "test_common_sftp"
- defaultPassword = "test_password"
- defaultSFTPUsername = "test_common_sftpfs_user"
- osWindows = "windows"
- testFileName = "test_file_common_sftp.dat"
- testDir = "test_dir_common"
- )
- var (
- allPerms = []string{dataprovider.PermAny}
- homeBasePath string
- testFileContent = []byte("test data")
- )
- func TestMain(m *testing.M) {
- homeBasePath = os.TempDir()
- logFilePath := filepath.Join(configDir, "common_test.log")
- logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
- os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
- err := config.LoadConfig(configDir, "")
- if err != nil {
- logger.ErrorToConsole("error loading configuration: %v", err)
- os.Exit(1)
- }
- providerConf := config.GetProviderConf()
- logger.InfoToConsole("Starting COMMON tests, provider: %v", providerConf.Driver)
- err = common.Initialize(config.GetCommonConfig())
- if err != nil {
- logger.WarnToConsole("error initializing common: %v", err)
- os.Exit(1)
- }
- err = dataprovider.Initialize(providerConf, configDir, true)
- if err != nil {
- logger.ErrorToConsole("error initializing data provider: %v", err)
- os.Exit(1)
- }
- httpConfig := config.GetHTTPConfig()
- httpConfig.Timeout = 5
- httpConfig.RetryMax = 0
- httpConfig.Initialize(configDir) //nolint:errcheck
- kmsConfig := config.GetKMSConfig()
- err = kmsConfig.Initialize()
- if err != nil {
- logger.ErrorToConsole("error initializing kms: %v", err)
- os.Exit(1)
- }
- sftpdConf := config.GetSFTPDConfig()
- sftpdConf.Bindings[0].Port = 4022
- httpdConf := config.GetHTTPDConfig()
- httpdConf.Bindings[0].Port = 4080
- httpdtest.SetBaseURL("http://127.0.0.1:4080")
- go func() {
- if err := sftpdConf.Initialize(configDir); err != nil {
- logger.ErrorToConsole("could not start SFTP server: %v", err)
- os.Exit(1)
- }
- }()
- go func() {
- if err := httpdConf.Initialize(configDir); err != nil {
- logger.ErrorToConsole("could not start HTTP server: %v", err)
- os.Exit(1)
- }
- }()
- go func() {
- // start a test HTTP server to receive action notifications
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "OK\n")
- })
- http.HandleFunc("/404", func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusNotFound)
- fmt.Fprintf(w, "Not found\n")
- })
- if err := http.ListenAndServe(httpAddr, nil); err != nil {
- logger.ErrorToConsole("could not start HTTP notification server: %v", err)
- os.Exit(1)
- }
- }()
- go func() {
- common.Config.ProxyProtocol = 2
- listener, err := net.Listen("tcp", httpProxyAddr)
- if err != nil {
- logger.ErrorToConsole("error creating listener for proxy protocol server: %v", err)
- os.Exit(1)
- }
- proxyListener, err := common.Config.GetProxyListener(listener)
- if err != nil {
- logger.ErrorToConsole("error creating proxy protocol listener: %v", err)
- os.Exit(1)
- }
- common.Config.ProxyProtocol = 0
- s := &http.Server{}
- if err := s.Serve(proxyListener); err != nil {
- logger.ErrorToConsole("could not start HTTP proxy protocol server: %v", err)
- os.Exit(1)
- }
- }()
- waitTCPListening(httpAddr)
- waitTCPListening(httpProxyAddr)
- waitTCPListening(sftpdConf.Bindings[0].GetAddress())
- waitTCPListening(httpdConf.Bindings[0].GetAddress())
- exitCode := m.Run()
- os.Remove(logFilePath)
- os.Exit(exitCode)
- }
- func TestBaseConnection(t *testing.T) {
- u := getTestUser()
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- assert.NoError(t, checkBasicSFTP(client))
- _, err = client.ReadDir(testDir)
- assert.ErrorIs(t, err, os.ErrNotExist)
- err = client.RemoveDirectory(testDir)
- assert.ErrorIs(t, err, os.ErrNotExist)
- err = client.Mkdir(testDir)
- assert.NoError(t, err)
- err = client.Mkdir(testDir)
- assert.Error(t, err)
- info, err := client.Stat(testDir)
- if assert.NoError(t, err) {
- assert.True(t, info.IsDir())
- }
- err = client.RemoveDirectory(testDir)
- assert.NoError(t, err)
- err = client.Remove(testFileName)
- assert.ErrorIs(t, err, os.ErrNotExist)
- f, err := client.Create(testFileName)
- assert.NoError(t, err)
- _, err = f.Write(testFileContent)
- assert.NoError(t, err)
- err = f.Close()
- assert.NoError(t, err)
- linkName := testFileName + ".link"
- err = client.Symlink(testFileName, linkName)
- assert.NoError(t, err)
- err = client.Symlink(testFileName, testFileName)
- assert.Error(t, err)
- info, err = client.Stat(testFileName)
- if assert.NoError(t, err) {
- assert.Equal(t, int64(len(testFileContent)), info.Size())
- assert.False(t, info.IsDir())
- }
- info, err = client.Lstat(linkName)
- if assert.NoError(t, err) {
- assert.NotEqual(t, int64(7), info.Size())
- assert.True(t, info.Mode()&os.ModeSymlink != 0)
- assert.False(t, info.IsDir())
- }
- err = client.RemoveDirectory(linkName)
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_FAILURE")
- }
- err = client.Remove(testFileName)
- assert.NoError(t, err)
- err = client.Remove(linkName)
- assert.NoError(t, err)
- err = client.Rename(testFileName, "test")
- assert.ErrorIs(t, err, os.ErrNotExist)
- f, err = client.Create(testFileName)
- assert.NoError(t, err)
- err = f.Close()
- assert.NoError(t, err)
- err = client.Rename(testFileName, testFileName+"1")
- assert.NoError(t, err)
- err = client.Remove(testFileName + "1")
- assert.NoError(t, err)
- err = client.RemoveDirectory("missing")
- assert.Error(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestSetStat(t *testing.T) {
- u := getTestUser()
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- f, err := client.Create(testFileName)
- assert.NoError(t, err)
- _, err = f.Write(testFileContent)
- assert.NoError(t, err)
- err = f.Close()
- assert.NoError(t, err)
- acmodTime := time.Now().Add(36 * time.Hour)
- err = client.Chtimes(testFileName, acmodTime, acmodTime)
- assert.NoError(t, err)
- newFi, err := client.Lstat(testFileName)
- assert.NoError(t, err)
- diff := math.Abs(newFi.ModTime().Sub(acmodTime).Seconds())
- assert.LessOrEqual(t, diff, float64(1))
- if runtime.GOOS != osWindows {
- err = client.Chown(testFileName, os.Getuid(), os.Getgid())
- assert.NoError(t, err)
- }
- newPerm := os.FileMode(0666)
- err = client.Chmod(testFileName, newPerm)
- assert.NoError(t, err)
- newFi, err = client.Lstat(testFileName)
- if assert.NoError(t, err) {
- assert.Equal(t, newPerm, newFi.Mode().Perm())
- }
- err = client.Truncate(testFileName, 2)
- assert.NoError(t, err)
- info, err := client.Stat(testFileName)
- if assert.NoError(t, err) {
- assert.Equal(t, int64(2), info.Size())
- }
- err = client.Remove(testFileName)
- assert.NoError(t, err)
- err = client.Truncate(testFileName, 0)
- assert.ErrorIs(t, err, os.ErrNotExist)
- err = client.Chtimes(testFileName, acmodTime, acmodTime)
- assert.ErrorIs(t, err, os.ErrNotExist)
- if runtime.GOOS != osWindows {
- err = client.Chown(testFileName, os.Getuid(), os.Getgid())
- assert.ErrorIs(t, err, os.ErrNotExist)
- }
- err = client.Chmod(testFileName, newPerm)
- assert.ErrorIs(t, err, os.ErrNotExist)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestPermissionErrors(t *testing.T) {
- user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
- assert.NoError(t, err)
- u := getTestSFTPUser()
- subDir := "/sub"
- u.Permissions[subDir] = nil
- sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = client.MkdirAll(path.Join(subDir, subDir))
- assert.NoError(t, err)
- f, err := client.Create(path.Join(subDir, subDir, testFileName))
- if assert.NoError(t, err) {
- _, err = f.Write(testFileContent)
- assert.NoError(t, err)
- err = f.Close()
- assert.NoError(t, err)
- }
- }
- conn, client, err = getSftpClient(sftpUser)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- assert.NoError(t, checkBasicSFTP(client))
- _, err = client.ReadDir(subDir)
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Mkdir(path.Join(subDir, subDir))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.RemoveDirectory(path.Join(subDir, subDir))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Symlink("test", path.Join(subDir, subDir))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Chmod(path.Join(subDir, subDir), os.ModePerm)
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Chown(path.Join(subDir, subDir), os.Getuid(), os.Getgid())
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Chtimes(path.Join(subDir, subDir), time.Now(), time.Now())
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Truncate(path.Join(subDir, subDir), 0)
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Remove(path.Join(subDir, subDir, testFileName))
- assert.ErrorIs(t, err, os.ErrPermission)
- }
- _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestFileNotAllowedErrors(t *testing.T) {
- deniedDir := "/denied"
- u := getTestUser()
- u.Filters.FilePatterns = []dataprovider.PatternsFilter{
- {
- Path: deniedDir,
- DeniedPatterns: []string{"*.txt"},
- },
- }
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFile := filepath.Join(u.GetHomeDir(), deniedDir, "file.txt")
- err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir), os.ModePerm)
- assert.NoError(t, err)
- err = os.WriteFile(testFile, testFileContent, os.ModePerm)
- assert.NoError(t, err)
- err = client.Remove(path.Join(deniedDir, "file.txt"))
- // the sftp client will try to remove the path as directory after receiving
- // a permission denied error, so we get a generic failure here
- assert.Error(t, err)
- err = client.Rename(path.Join(deniedDir, "file.txt"), path.Join(deniedDir, "file1.txt"))
- assert.ErrorIs(t, err, os.ErrPermission)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestTruncateQuotaLimits(t *testing.T) {
- u := getTestUser()
- u.QuotaSize = 20
- mappedPath1 := filepath.Join(os.TempDir(), "mapped1")
- folderName1 := filepath.Base(mappedPath1)
- vdirPath1 := "/vmapped1"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- QuotaFiles: 10,
- })
- mappedPath2 := filepath.Join(os.TempDir(), "mapped2")
- folderName2 := filepath.Base(mappedPath2)
- vdirPath2 := "/vmapped2"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- u = getTestSFTPUser()
- u.QuotaSize = 20
- sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- for _, user := range []dataprovider.User{localUser, sftpUser} {
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- f, err := client.OpenFile(testFileName, os.O_WRONLY)
- if assert.NoError(t, err) {
- n, err := f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(2)
- assert.NoError(t, err)
- expectedQuotaFiles := 0
- expectedQuotaSize := int64(2)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
- assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
- _, err = f.Seek(expectedQuotaSize, io.SeekStart)
- assert.NoError(t, err)
- n, err = f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(5)
- assert.NoError(t, err)
- expectedQuotaSize = int64(5)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
- assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
- _, err = f.Seek(expectedQuotaSize, io.SeekStart)
- assert.NoError(t, err)
- n, err = f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Close()
- assert.NoError(t, err)
- expectedQuotaFiles = 1
- expectedQuotaSize = int64(5) + int64(len(testFileContent))
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
- assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
- }
- // now truncate by path
- err = client.Truncate(testFileName, 5)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, int64(5), user.UsedQuotaSize)
- // now open an existing file without truncate it, quota should not change
- f, err = client.OpenFile(testFileName, os.O_WRONLY)
- if assert.NoError(t, err) {
- err = f.Close()
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, int64(5), user.UsedQuotaSize)
- }
- // open the file truncating it
- f, err = client.OpenFile(testFileName, os.O_WRONLY|os.O_TRUNC)
- if assert.NoError(t, err) {
- err = f.Close()
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, int64(0), user.UsedQuotaSize)
- }
- // now test max write size
- f, err = client.OpenFile(testFileName, os.O_WRONLY)
- if assert.NoError(t, err) {
- n, err := f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(11)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, int64(11), user.UsedQuotaSize)
- _, err = f.Seek(int64(11), io.SeekStart)
- assert.NoError(t, err)
- n, err = f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(5)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, int64(5), user.UsedQuotaSize)
- _, err = f.Seek(int64(5), io.SeekStart)
- assert.NoError(t, err)
- n, err = f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(12)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, int64(12), user.UsedQuotaSize)
- _, err = f.Seek(int64(12), io.SeekStart)
- assert.NoError(t, err)
- _, err = f.Write(testFileContent)
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), common.ErrQuotaExceeded.Error())
- }
- err = f.Close()
- assert.Error(t, err)
- // the file is deleted
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 0, user.UsedQuotaFiles)
- assert.Equal(t, int64(0), user.UsedQuotaSize)
- }
- if user.Username == defaultUsername {
- // basic test inside a virtual folder
- vfileName1 := path.Join(vdirPath1, testFileName)
- f, err = client.OpenFile(vfileName1, os.O_WRONLY)
- if assert.NoError(t, err) {
- n, err := f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(2)
- assert.NoError(t, err)
- expectedQuotaFiles := 0
- expectedQuotaSize := int64(2)
- fold, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
- assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
- err = f.Close()
- assert.NoError(t, err)
- expectedQuotaFiles = 1
- fold, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
- assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
- }
- err = client.Truncate(vfileName1, 1)
- assert.NoError(t, err)
- fold, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(1), fold.UsedQuotaSize)
- assert.Equal(t, 1, fold.UsedQuotaFiles)
- // now test on vdirPath2, the folder quota is included in the user's quota
- vfileName2 := path.Join(vdirPath2, testFileName)
- f, err = client.OpenFile(vfileName2, os.O_WRONLY)
- if assert.NoError(t, err) {
- n, err := f.Write(testFileContent)
- assert.NoError(t, err)
- assert.Equal(t, len(testFileContent), n)
- err = f.Truncate(3)
- assert.NoError(t, err)
- expectedQuotaFiles := 0
- expectedQuotaSize := int64(3)
- fold, _, err := httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
- assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
- err = f.Close()
- assert.NoError(t, err)
- expectedQuotaFiles = 1
- fold, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
- assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
- assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
- }
- // cleanup
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- user.UsedQuotaFiles = 0
- user.UsedQuotaSize = 0
- _, err = httpdtest.UpdateQuotaUsage(user, "reset", http.StatusOK)
- assert.NoError(t, err)
- user.QuotaSize = 0
- _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
- assert.NoError(t, err)
- }
- }
- }
- _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(localUser.GetHomeDir())
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestVirtualFoldersQuotaRenameOverwrite(t *testing.T) {
- testFileSize := int64(131072)
- testFileSize1 := int64(65537)
- testFileName1 := "test_file1.dat" //nolint:goconst
- u := getTestUser()
- u.QuotaFiles = 0
- u.QuotaSize = 0
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- folderName1 := filepath.Base(mappedPath1)
- vdirPath1 := "/vdir1" //nolint:goconst
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- folderName2 := filepath.Base(mappedPath2)
- vdirPath2 := "/vdir2" //nolint:goconst
- mappedPath3 := filepath.Join(os.TempDir(), "vdir3")
- folderName3 := filepath.Base(mappedPath3)
- vdirPath3 := "/vdir3"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- QuotaFiles: 2,
- QuotaSize: 0,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- MappedPath: mappedPath2,
- Name: folderName2,
- },
- VirtualPath: vdirPath2,
- QuotaFiles: 0,
- QuotaSize: testFileSize + testFileSize1 + 1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName3,
- MappedPath: mappedPath3,
- },
- VirtualPath: vdirPath3,
- QuotaFiles: 2,
- QuotaSize: testFileSize * 2,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName1, testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath3, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath3, testFileName+"1"), testFileSize, client)
- assert.NoError(t, err)
- err = client.Rename(testFileName, path.Join(vdirPath1, testFileName+".rename"))
- assert.Error(t, err)
- // we overwrite an existing file and we have unlimited size
- err = client.Rename(testFileName, path.Join(vdirPath1, testFileName))
- assert.NoError(t, err)
- // we have no space and we try to overwrite a bigger file with a smaller one, this should succeed
- err = client.Rename(testFileName1, path.Join(vdirPath2, testFileName))
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- // we have no space and we try to overwrite a smaller file with a bigger one, this should fail
- err = client.Rename(testFileName, path.Join(vdirPath2, testFileName1))
- assert.Error(t, err)
- fi, err := client.Stat(path.Join(vdirPath1, testFileName1))
- if assert.NoError(t, err) {
- assert.Equal(t, testFileSize1, fi.Size())
- }
- // we are overquota inside vdir3 size 2/2 and size 262144/262144
- err = client.Rename(path.Join(vdirPath1, testFileName1), path.Join(vdirPath3, testFileName1+".rename"))
- assert.Error(t, err)
- // we overwrite an existing file and we have enough size
- err = client.Rename(path.Join(vdirPath1, testFileName1), path.Join(vdirPath3, testFileName))
- assert.NoError(t, err)
- testFileName2 := "test_file2.dat"
- err = writeSFTPFile(testFileName2, testFileSize+testFileSize1, client)
- assert.NoError(t, err)
- // we overwrite an existing file and we haven't enough size
- err = client.Rename(testFileName2, path.Join(vdirPath3, testFileName))
- assert.Error(t, err)
- // now remove a file from vdir3, create a dir with 2 files and try to rename it in vdir3
- // this will fail since the rename will result in 3 files inside vdir3 and quota limits only
- // allow 2 total files there
- err = client.Remove(path.Join(vdirPath3, testFileName+"1"))
- assert.NoError(t, err)
- aDir := "a dir"
- err = client.Mkdir(aDir)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(aDir, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(aDir, testFileName1+"1"), testFileSize1, client)
- assert.NoError(t, err)
- err = client.Rename(aDir, path.Join(vdirPath3, aDir))
- assert.Error(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName3}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath3)
- assert.NoError(t, err)
- }
- func TestQuotaRenameOverwrite(t *testing.T) {
- u := getTestUser()
- u.QuotaFiles = 100
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileSize := int64(131072)
- testFileSize1 := int64(65537)
- testFileName1 := "test_file1.dat"
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName1, testFileSize1, client)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- err = client.Rename(testFileName, testFileName1)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize, user.UsedQuotaSize)
- err = client.Remove(testFileName1)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName1, testFileSize1, client)
- assert.NoError(t, err)
- err = client.Rename(testFileName1, testFileName)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1, user.UsedQuotaSize)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestVirtualFoldersQuotaValues(t *testing.T) {
- u := getTestUser()
- u.QuotaFiles = 100
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- vdirPath1 := "/vdir1"
- folderName1 := filepath.Base(mappedPath1)
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- vdirPath2 := "/vdir2"
- folderName2 := filepath.Base(mappedPath2)
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- // quota is included in the user's one
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- // quota is unlimited and excluded from user's one
- QuotaFiles: 0,
- QuotaSize: 0,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileSize := int64(131072)
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- // we copy the same file two times to test quota update on file overwrite
- err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
- assert.NoError(t, err)
- expectedQuotaFiles := 2
- expectedQuotaSize := testFileSize * 2
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
- assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
- f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- err = client.Remove(path.Join(vdirPath1, testFileName))
- assert.NoError(t, err)
- err = client.Remove(path.Join(vdirPath2, testFileName))
- assert.NoError(t, err)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestQuotaRenameInsideSameVirtualFolder(t *testing.T) {
- u := getTestUser()
- u.QuotaFiles = 100
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- vdirPath1 := "/vdir1"
- folderName1 := filepath.Base(mappedPath1)
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- vdirPath2 := "/vdir2"
- folderName2 := filepath.Base(mappedPath2)
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- // quota is included in the user's one
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- // quota is unlimited and excluded from user's one
- QuotaFiles: 0,
- QuotaSize: 0,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileName1 := "test_file1.dat"
- testFileSize := int64(131072)
- testFileSize1 := int64(65535)
- dir1 := "dir1" //nolint:goconst
- dir2 := "dir2" //nolint:goconst
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath1, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath1, dir2))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir2))
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // initial files:
- // - vdir1/dir1/testFileName
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName
- // - vdir2/dir2/testFileName1
- //
- // rename a file inside vdir1 it is included inside user quota, so we have:
- // - vdir1/dir1/testFileName.rename
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName
- // - vdir2/dir2/testFileName1
- err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(vdirPath1, dir1, testFileName+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // rename a file inside vdir2, it isn't included inside user quota, so we have:
- // - vdir1/dir1/testFileName.rename
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName.rename
- // - vdir2/dir2/testFileName1
- err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(vdirPath2, dir1, testFileName+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // rename a file inside vdir2 overwriting an existing, we now have:
- // - vdir1/dir1/testFileName.rename
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName.rename (initial testFileName1)
- err = client.Rename(path.Join(vdirPath2, dir2, testFileName1), path.Join(vdirPath2, dir1, testFileName+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // rename a file inside vdir1 overwriting an existing, we now have:
- // - vdir1/dir1/testFileName.rename (initial testFileName1)
- // - vdir2/dir1/testFileName.rename (initial testFileName1)
- err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(vdirPath1, dir1, testFileName+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // rename a directory inside the same virtual folder, quota should not change
- err = client.RemoveDirectory(path.Join(vdirPath1, dir2))
- assert.NoError(t, err)
- err = client.RemoveDirectory(path.Join(vdirPath2, dir2))
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirPath1, dir1), path.Join(vdirPath1, dir2))
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirPath2, dir1), path.Join(vdirPath2, dir2))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestQuotaRenameBetweenVirtualFolder(t *testing.T) {
- u := getTestUser()
- u.QuotaFiles = 100
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- folderName1 := filepath.Base(mappedPath1)
- vdirPath1 := "/vdir1"
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- folderName2 := filepath.Base(mappedPath2)
- vdirPath2 := "/vdir2"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- // quota is included in the user's one
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- // quota is unlimited and excluded from user's one
- QuotaFiles: 0,
- QuotaSize: 0,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileName1 := "test_file1.dat"
- testFileSize := int64(131072)
- testFileSize1 := int64(65535)
- dir1 := "dir1"
- dir2 := "dir2"
- err = client.Mkdir(path.Join(vdirPath1, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath1, dir2))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir2))
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- // initial files:
- // - vdir1/dir1/testFileName
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName
- // - vdir2/dir2/testFileName1
- //
- // rename a file from vdir1 to vdir2, vdir1 is included inside user quota, so we have:
- // - vdir1/dir1/testFileName
- // - vdir2/dir1/testFileName
- // - vdir2/dir2/testFileName1
- // - vdir2/dir1/testFileName1.rename
- err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(vdirPath2, dir1, testFileName1+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize, user.UsedQuotaSize)
- f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 3, f.UsedQuotaFiles)
- // rename a file from vdir2 to vdir1, vdir2 is not included inside user quota, so we have:
- // - vdir1/dir1/testFileName
- // - vdir1/dir2/testFileName.rename
- // - vdir2/dir2/testFileName1
- // - vdir2/dir1/testFileName1.rename
- err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(vdirPath1, dir2, testFileName+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize*2, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize*2, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1*2, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // rename a file from vdir1 to vdir2 overwriting an existing file, vdir1 is included inside user quota, so we have:
- // - vdir1/dir2/testFileName.rename
- // - vdir2/dir2/testFileName1 (is the initial testFileName)
- // - vdir2/dir1/testFileName1.rename
- err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(vdirPath2, dir2, testFileName1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1+testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // rename a file from vdir2 to vdir1 overwriting an existing file, vdir2 is not included inside user quota, so we have:
- // - vdir1/dir2/testFileName.rename (is the initial testFileName1)
- // - vdir2/dir2/testFileName1 (is the initial testFileName)
- err = client.Rename(path.Join(vdirPath2, dir1, testFileName1+".rename"), path.Join(vdirPath1, dir2, testFileName+".rename"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName+"1.dupl"), testFileSize1, client)
- assert.NoError(t, err)
- err = client.RemoveDirectory(path.Join(vdirPath1, dir1))
- assert.NoError(t, err)
- err = client.RemoveDirectory(path.Join(vdirPath2, dir1))
- assert.NoError(t, err)
- // - vdir1/dir2/testFileName.rename (initial testFileName1)
- // - vdir1/dir2/testFileName
- // - vdir2/dir2/testFileName1 (initial testFileName)
- // - vdir2/dir2/testFileName (initial testFileName1)
- // - vdir2/dir2/testFileName1.dupl
- // rename directories between the two virtual folders
- err = client.Rename(path.Join(vdirPath2, dir2), path.Join(vdirPath1, dir1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 5, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1*3+testFileSize*2, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1*3+testFileSize*2, f.UsedQuotaSize)
- assert.Equal(t, 5, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- // now move on vpath2
- err = client.Rename(path.Join(vdirPath1, dir2), path.Join(vdirPath2, dir1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 3, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1*2+testFileSize, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1*2+testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 3, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestQuotaRenameFromVirtualFolder(t *testing.T) {
- u := getTestUser()
- u.QuotaFiles = 100
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- folderName1 := filepath.Base(mappedPath1)
- vdirPath1 := "/vdir1"
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- folderName2 := filepath.Base(mappedPath2)
- vdirPath2 := "/vdir2"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- // quota is included in the user's one
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- // quota is unlimited and excluded from user's one
- QuotaFiles: 0,
- QuotaSize: 0,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileName1 := "test_file1.dat"
- testFileSize := int64(131072)
- testFileSize1 := int64(65535)
- dir1 := "dir1"
- dir2 := "dir2"
- err = client.Mkdir(path.Join(vdirPath1, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath1, dir2))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir2))
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- // initial files:
- // - vdir1/dir1/testFileName
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName
- // - vdir2/dir2/testFileName1
- //
- // rename a file from vdir1 to the user home dir, vdir1 is included in user quota so we have:
- // - testFileName
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName
- // - vdir2/dir2/testFileName1
- err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(testFileName))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- // rename a file from vdir2 to the user home dir, vdir2 is not included in user quota so we have:
- // - testFileName
- // - testFileName1
- // - vdir1/dir2/testFileName1
- // - vdir2/dir1/testFileName
- err = client.Rename(path.Join(vdirPath2, dir2, testFileName1), path.Join(testFileName1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 3, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // rename a file from vdir1 to the user home dir overwriting an existing file, vdir1 is included in user quota so we have:
- // - testFileName (initial testFileName1)
- // - testFileName1
- // - vdir2/dir1/testFileName
- err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(testFileName))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // rename a file from vdir2 to the user home dir overwriting an existing file, vdir2 is not included in user quota so we have:
- // - testFileName (initial testFileName1)
- // - testFileName1 (initial testFileName)
- err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(testFileName1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- // dir rename
- err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- // - testFileName (initial testFileName1)
- // - testFileName1 (initial testFileName)
- // - vdir1/dir1/testFileName
- // - vdir1/dir1/testFileName1
- // - dir1/testFileName
- // - dir1/testFileName1
- err = client.Rename(path.Join(vdirPath2, dir1), dir1)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 6, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize*3+testFileSize1*3, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 2, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- // - testFileName (initial testFileName1)
- // - testFileName1 (initial testFileName)
- // - dir2/testFileName
- // - dir2/testFileName1
- // - dir1/testFileName
- // - dir1/testFileName1
- err = client.Rename(path.Join(vdirPath1, dir1), dir2)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 6, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize*3+testFileSize1*3, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, int64(0), f.UsedQuotaSize)
- assert.Equal(t, 0, f.UsedQuotaFiles)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestQuotaRenameToVirtualFolder(t *testing.T) {
- u := getTestUser()
- u.QuotaFiles = 100
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- folderName1 := filepath.Base(mappedPath1)
- vdirPath1 := "/vdir1"
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- folderName2 := filepath.Base(mappedPath2)
- vdirPath2 := "/vdir2"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- // quota is included in the user's one
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- // quota is unlimited and excluded from user's one
- QuotaFiles: 0,
- QuotaSize: 0,
- })
- u.Permissions[vdirPath1] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload,
- dataprovider.PermOverwrite, dataprovider.PermDelete, dataprovider.PermCreateSymlinks, dataprovider.PermCreateDirs}
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileName1 := "test_file1.dat"
- testFileSize := int64(131072)
- testFileSize1 := int64(65535)
- dir1 := "dir1"
- dir2 := "dir2"
- err = client.Mkdir(path.Join(vdirPath1, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath1, dir2))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir1))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, dir2))
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName1, testFileSize1, client)
- assert.NoError(t, err)
- // initial files:
- // - testFileName
- // - testFileName1
- //
- // rename a file from user home dir to vdir1, vdir1 is included in user quota so we have:
- // - testFileName
- // - /vdir1/dir1/testFileName1
- err = client.Rename(testFileName1, path.Join(vdirPath1, dir1, testFileName1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // rename a file from user home dir to vdir2, vdir2 is not included in user quota so we have:
- // - /vdir2/dir1/testFileName
- // - /vdir1/dir1/testFileName1
- err = client.Rename(testFileName, path.Join(vdirPath2, dir1, testFileName))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // upload two new files to the user home dir so we have:
- // - testFileName
- // - testFileName1
- // - /vdir1/dir1/testFileName1
- // - /vdir2/dir1/testFileName
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(testFileName1, testFileSize1, client)
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 3, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1+testFileSize1, user.UsedQuotaSize)
- // rename a file from user home dir to vdir1 overwriting an existing file, vdir1 is included in user quota so we have:
- // - testFileName1
- // - /vdir1/dir1/testFileName1 (initial testFileName)
- // - /vdir2/dir1/testFileName
- err = client.Rename(testFileName, path.Join(vdirPath1, dir1, testFileName1))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 2, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // rename a file from user home dir to vdir2 overwriting an existing file, vdir2 is not included in user quota so we have:
- // - /vdir1/dir1/testFileName1 (initial testFileName)
- // - /vdir2/dir1/testFileName (initial testFileName1)
- err = client.Rename(testFileName1, path.Join(vdirPath2, dir1, testFileName))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 1, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- err = client.Mkdir(dir1)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(dir1, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- // - /dir1/testFileName
- // - /dir1/testFileName1
- // - /vdir1/dir1/testFileName1 (initial testFileName)
- // - /vdir2/dir1/testFileName (initial testFileName1)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 3, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- // - /vdir1/adir/testFileName
- // - /vdir1/adir/testFileName1
- // - /vdir1/dir1/testFileName1 (initial testFileName)
- // - /vdir2/dir1/testFileName (initial testFileName1)
- err = client.Rename(dir1, path.Join(vdirPath1, "adir"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 3, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize*2+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 3, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 1, f.UsedQuotaFiles)
- err = client.Mkdir(dir1)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(dir1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(dir1, testFileName1), testFileSize1, client)
- assert.NoError(t, err)
- // - /vdir1/adir/testFileName
- // - /vdir1/adir/testFileName1
- // - /vdir1/dir1/testFileName1 (initial testFileName)
- // - /vdir2/dir1/testFileName (initial testFileName1)
- // - /vdir2/adir/testFileName
- // - /vdir2/adir/testFileName1
- err = client.Rename(dir1, path.Join(vdirPath2, "adir"))
- assert.NoError(t, err)
- user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, 3, user.UsedQuotaFiles)
- assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
- f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize*2+testFileSize1, f.UsedQuotaSize)
- assert.Equal(t, 3, f.UsedQuotaFiles)
- f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
- assert.NoError(t, err)
- assert.Equal(t, testFileSize1*2+testFileSize, f.UsedQuotaSize)
- assert.Equal(t, 3, f.UsedQuotaFiles)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestVirtualFoldersLink(t *testing.T) {
- u := getTestUser()
- mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
- folderName1 := filepath.Base(mappedPath1)
- vdirPath1 := "/vdir1"
- mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
- folderName2 := filepath.Base(mappedPath2)
- vdirPath2 := "/vdir2"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName1,
- MappedPath: mappedPath1,
- },
- VirtualPath: vdirPath1,
- // quota is included in the user's one
- QuotaFiles: -1,
- QuotaSize: -1,
- })
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName2,
- MappedPath: mappedPath2,
- },
- VirtualPath: vdirPath2,
- // quota is unlimited and excluded from user's one
- QuotaFiles: 0,
- QuotaSize: 0,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileSize := int64(131072)
- testDir := "adir"
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath1, testDir))
- assert.NoError(t, err)
- err = client.Mkdir(path.Join(vdirPath2, testDir))
- assert.NoError(t, err)
- err = client.Symlink(testFileName, testFileName+".link")
- assert.NoError(t, err)
- err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testFileName+".link"))
- assert.NoError(t, err)
- err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testDir, testFileName+".link"))
- assert.NoError(t, err)
- err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testFileName+".link"))
- assert.NoError(t, err)
- err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testDir, testFileName+".link"))
- assert.NoError(t, err)
- err = client.Symlink(testFileName, path.Join(vdirPath1, testFileName+".link1"))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(testFileName, path.Join(vdirPath1, testDir, testFileName+".link1"))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(testFileName, path.Join(vdirPath2, testFileName+".link1"))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(testFileName, path.Join(vdirPath2, testDir, testFileName+".link1"))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(path.Join(vdirPath1, testFileName), testFileName+".link1")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(path.Join(vdirPath2, testFileName), testFileName+".link1")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath2, testDir, testFileName+".link1"))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath1, testFileName+".link1"))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink("/", "/roolink")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Symlink(testFileName, "/")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Symlink(testFileName, vdirPath1)
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Symlink(vdirPath1, testFileName+".link2")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath1)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath2)
- assert.NoError(t, err)
- }
- func TestDirs(t *testing.T) {
- u := getTestUser()
- mappedPath := filepath.Join(os.TempDir(), "vdir")
- folderName := filepath.Base(mappedPath)
- vdirPath := "/path/vdir"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName,
- MappedPath: mappedPath,
- },
- VirtualPath: vdirPath,
- })
- u.Permissions["/subdir"] = []string{dataprovider.PermDownload, dataprovider.PermUpload,
- dataprovider.PermDelete, dataprovider.PermCreateDirs, dataprovider.PermRename, dataprovider.PermListItems}
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- info, err := client.ReadDir("/")
- if assert.NoError(t, err) {
- assert.Len(t, info, 1)
- assert.Equal(t, "path", info[0].Name())
- }
- fi, err := client.Stat(path.Dir(vdirPath))
- if assert.NoError(t, err) {
- assert.True(t, fi.IsDir())
- }
- err = client.RemoveDirectory("/")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.RemoveDirectory(vdirPath)
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.RemoveDirectory(path.Dir(vdirPath))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.Mkdir(vdirPath)
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Mkdir("adir")
- assert.NoError(t, err)
- err = client.Rename("/adir", path.Dir(vdirPath))
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = client.MkdirAll("/subdir/adir")
- assert.NoError(t, err)
- err = client.Rename("adir", "subdir/adir")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- err = writeSFTPFile("/subdir/afile.bin", 64, client)
- assert.NoError(t, err)
- err = writeSFTPFile("/afile.bin", 32, client)
- assert.NoError(t, err)
- err = client.Rename("afile.bin", "subdir/afile.bin")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename("afile.bin", "subdir/afile1.bin")
- assert.NoError(t, err)
- err = client.Rename(path.Dir(vdirPath), "renamed_vdir")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath)
- assert.NoError(t, err)
- }
- func TestCryptFsStat(t *testing.T) {
- user, _, err := httpdtest.AddUser(getCryptFsUser(), http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testFileSize := int64(4096)
- err = writeSFTPFile(testFileName, testFileSize, client)
- assert.NoError(t, err)
- info, err := client.Stat(testFileName)
- if assert.NoError(t, err) {
- assert.Equal(t, testFileSize, info.Size())
- }
- info, err = os.Stat(filepath.Join(user.HomeDir, testFileName))
- if assert.NoError(t, err) {
- assert.Greater(t, info.Size(), testFileSize)
- }
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestFsPermissionErrors(t *testing.T) {
- if runtime.GOOS == osWindows {
- t.Skip("this test is not available on Windows")
- }
- user, _, err := httpdtest.AddUser(getCryptFsUser(), http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- testDir := "tDir"
- err = client.Mkdir(testDir)
- assert.NoError(t, err)
- err = os.Chmod(user.GetHomeDir(), 0111)
- assert.NoError(t, err)
- err = client.RemoveDirectory(testDir)
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(testDir, testDir+"1")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = os.Chmod(user.GetHomeDir(), os.ModePerm)
- assert.NoError(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestResolvePathError(t *testing.T) {
- u := getTestUser()
- u.HomeDir = "relative_path"
- conn := common.NewBaseConnection("", common.ProtocolFTP, "", u)
- testPath := "apath"
- _, err := conn.ListDir(testPath)
- assert.Error(t, err)
- err = conn.CreateDir(testPath)
- assert.Error(t, err)
- err = conn.RemoveDir(testPath)
- assert.Error(t, err)
- err = conn.Rename(testPath, testPath+"1")
- assert.Error(t, err)
- err = conn.CreateSymlink(testPath, testPath+".sym")
- assert.Error(t, err)
- _, err = conn.DoStat(testPath, 0)
- assert.Error(t, err)
- err = conn.SetStat(testPath, &common.StatAttributes{
- Atime: time.Now(),
- Mtime: time.Now(),
- })
- assert.Error(t, err)
- u = getTestUser()
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- MappedPath: "relative_mapped_path",
- },
- VirtualPath: "/vpath",
- })
- err = os.MkdirAll(u.HomeDir, os.ModePerm)
- assert.NoError(t, err)
- conn.User = u
- err = conn.Rename(testPath, "/vpath/subpath")
- assert.Error(t, err)
- outHomePath := filepath.Join(os.TempDir(), testFileName)
- err = os.WriteFile(outHomePath, testFileContent, os.ModePerm)
- assert.NoError(t, err)
- err = os.Symlink(outHomePath, filepath.Join(u.HomeDir, testFileName+".link"))
- assert.NoError(t, err)
- err = os.WriteFile(filepath.Join(u.HomeDir, testFileName), testFileContent, os.ModePerm)
- assert.NoError(t, err)
- err = conn.CreateSymlink(testFileName, testFileName+".link")
- assert.Error(t, err)
- err = os.RemoveAll(u.GetHomeDir())
- assert.NoError(t, err)
- err = os.Remove(outHomePath)
- assert.NoError(t, err)
- }
- func TestUserPasswordHashing(t *testing.T) {
- if config.GetProviderConf().Driver == dataprovider.MemoryDataProviderName {
- t.Skip("this test is not supported with the memory provider")
- }
- u := getTestUser()
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- err = dataprovider.Close()
- assert.NoError(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf := config.GetProviderConf()
- providerConf.PasswordHashing.Algo = dataprovider.HashingAlgoArgon2ID
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- currentUser, err := dataprovider.UserExists(user.Username)
- assert.NoError(t, err)
- assert.True(t, strings.HasPrefix(currentUser.Password, "$2a$"))
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = checkBasicSFTP(client)
- assert.NoError(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- u = getTestUser()
- user, _, err = httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- currentUser, err = dataprovider.UserExists(user.Username)
- assert.NoError(t, err)
- assert.True(t, strings.HasPrefix(currentUser.Password, "$argon2id$"))
- conn, client, err = getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = checkBasicSFTP(client)
- assert.NoError(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = dataprovider.Close()
- assert.NoError(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf = config.GetProviderConf()
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- }
- func TestDelayedQuotaUpdater(t *testing.T) {
- err := dataprovider.Close()
- assert.NoError(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf := config.GetProviderConf()
- providerConf.DelayedQuotaUpdate = 120
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- u := getTestUser()
- u.QuotaFiles = 100
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- err = dataprovider.UpdateUserQuota(&user, 10, 6000, false)
- assert.NoError(t, err)
- files, size, err := dataprovider.GetUsedQuota(user.Username)
- assert.NoError(t, err)
- assert.Equal(t, 10, files)
- assert.Equal(t, int64(6000), size)
- userGet, err := dataprovider.UserExists(user.Username)
- assert.NoError(t, err)
- assert.Equal(t, 0, userGet.UsedQuotaFiles)
- assert.Equal(t, int64(0), userGet.UsedQuotaSize)
- err = dataprovider.UpdateUserQuota(&user, 10, 6000, true)
- assert.NoError(t, err)
- files, size, err = dataprovider.GetUsedQuota(user.Username)
- assert.NoError(t, err)
- assert.Equal(t, 10, files)
- assert.Equal(t, int64(6000), size)
- userGet, err = dataprovider.UserExists(user.Username)
- assert.NoError(t, err)
- assert.Equal(t, 10, userGet.UsedQuotaFiles)
- assert.Equal(t, int64(6000), userGet.UsedQuotaSize)
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- folder := vfs.BaseVirtualFolder{
- Name: "folder",
- MappedPath: filepath.Join(os.TempDir(), "p"),
- }
- err = dataprovider.AddFolder(&folder)
- assert.NoError(t, err)
- err = dataprovider.UpdateVirtualFolderQuota(&folder, 10, 6000, false)
- assert.NoError(t, err)
- files, size, err = dataprovider.GetUsedVirtualFolderQuota(folder.Name)
- assert.NoError(t, err)
- assert.Equal(t, 10, files)
- assert.Equal(t, int64(6000), size)
- folderGet, err := dataprovider.GetFolderByName(folder.Name)
- assert.NoError(t, err)
- assert.Equal(t, 0, folderGet.UsedQuotaFiles)
- assert.Equal(t, int64(0), folderGet.UsedQuotaSize)
- err = dataprovider.UpdateVirtualFolderQuota(&folder, 10, 6000, true)
- assert.NoError(t, err)
- files, size, err = dataprovider.GetUsedVirtualFolderQuota(folder.Name)
- assert.NoError(t, err)
- assert.Equal(t, 10, files)
- assert.Equal(t, int64(6000), size)
- folderGet, err = dataprovider.GetFolderByName(folder.Name)
- assert.NoError(t, err)
- assert.Equal(t, 10, folderGet.UsedQuotaFiles)
- assert.Equal(t, int64(6000), folderGet.UsedQuotaSize)
- err = dataprovider.DeleteFolder(folder.Name)
- assert.NoError(t, err)
- err = dataprovider.Close()
- assert.NoError(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf = config.GetProviderConf()
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- }
- func TestPasswordCaching(t *testing.T) {
- user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
- assert.NoError(t, err)
- found, match := dataprovider.CheckCachedPassword(user.Username, defaultPassword)
- assert.False(t, found)
- assert.False(t, match)
- user.Password = "wrong"
- _, _, err = getSftpClient(user)
- assert.Error(t, err)
- found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
- assert.False(t, found)
- assert.False(t, match)
- user.Password = ""
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = checkBasicSFTP(client)
- assert.NoError(t, err)
- }
- found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
- assert.True(t, found)
- assert.True(t, match)
- found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword+"_")
- assert.True(t, found)
- assert.False(t, match)
- found, match = dataprovider.CheckCachedPassword(user.Username+"_", defaultPassword)
- assert.False(t, found)
- assert.False(t, match)
- user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
- assert.NoError(t, err)
- found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
- assert.False(t, found)
- assert.False(t, match)
- conn, client, err = getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = checkBasicSFTP(client)
- assert.NoError(t, err)
- }
- found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
- assert.True(t, found)
- assert.True(t, match)
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
- assert.False(t, found)
- assert.False(t, match)
- }
- func TestSyncUploadAction(t *testing.T) {
- if runtime.GOOS == osWindows {
- t.Skip("this test is not available on Windows")
- }
- uploadScriptPath := filepath.Join(os.TempDir(), "upload.sh")
- common.Config.Actions.ExecuteOn = []string{"upload"}
- common.Config.Actions.ExecuteSync = []string{"upload"}
- common.Config.Actions.Hook = uploadScriptPath
- user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
- assert.NoError(t, err)
- movedPath := filepath.Join(user.HomeDir, "moved.dat")
- err = os.WriteFile(uploadScriptPath, getUploadScriptContent(movedPath), 0755)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- size := int64(32768)
- err = writeSFTPFileNoCheck(testFileName, size, client)
- assert.NoError(t, err)
- _, err = client.Stat(testFileName)
- assert.Error(t, err)
- info, err := client.Stat(filepath.Base(movedPath))
- if assert.NoError(t, err) {
- assert.Equal(t, size, info.Size())
- }
- }
- err = os.Remove(uploadScriptPath)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- common.Config.Actions.ExecuteOn = nil
- common.Config.Actions.ExecuteSync = nil
- common.Config.Actions.Hook = uploadScriptPath
- }
- func TestQuotaTrackDisabled(t *testing.T) {
- err := dataprovider.Close()
- assert.NoError(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf := config.GetProviderConf()
- providerConf.TrackQuota = 0
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = writeSFTPFile(testFileName, 32, client)
- assert.NoError(t, err)
- err = client.Rename(testFileName, testFileName+"1")
- assert.NoError(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = dataprovider.Close()
- assert.NoError(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf = config.GetProviderConf()
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- }
- func TestGetQuotaError(t *testing.T) {
- if dataprovider.GetProviderStatus().Driver == "memory" {
- t.Skip("this test is not available with the memory provider")
- }
- u := getTestUser()
- mappedPath := filepath.Join(os.TempDir(), "vdir")
- folderName := filepath.Base(mappedPath)
- vdirPath := "/vpath"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderName,
- MappedPath: mappedPath,
- },
- VirtualPath: vdirPath,
- QuotaSize: 0,
- QuotaFiles: 10,
- })
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = writeSFTPFile(testFileName, 32, client)
- assert.NoError(t, err)
- err = dataprovider.Close()
- assert.NoError(t, err)
- err = client.Rename(testFileName, path.Join(vdirPath, testFileName))
- assert.Error(t, err)
- err = config.LoadConfig(configDir, "")
- assert.NoError(t, err)
- providerConf := config.GetProviderConf()
- err = dataprovider.Initialize(providerConf, configDir, true)
- assert.NoError(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPath)
- assert.NoError(t, err)
- }
- func TestRenameDir(t *testing.T) {
- u := getTestUser()
- testDir := "/dir-to-rename"
- u.Permissions[testDir] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = client.Mkdir(testDir)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(testDir, testFileName), 32, client)
- assert.NoError(t, err)
- err = client.Rename(testDir, testDir+"_rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestRenameSymlink(t *testing.T) {
- u := getTestUser()
- testDir := "/dir-no-create-links"
- otherDir := "otherdir"
- u.Permissions[testDir] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermDelete,
- dataprovider.PermCreateDirs}
- user, _, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err)
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- err = client.Mkdir(otherDir)
- assert.NoError(t, err)
- err = client.Symlink(otherDir, otherDir+".link")
- assert.NoError(t, err)
- err = client.Rename(otherDir+".link", path.Join(testDir, "symlink"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(otherDir+".link", "allowed_link")
- assert.NoError(t, err)
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- }
- func TestSFTPLoopError(t *testing.T) {
- user1 := getTestUser()
- user2 := getTestUser()
- user1.Username += "1"
- user2.Username += "2"
- // user1 is a local account with a virtual SFTP folder to user2
- // user2 has user1 as SFTP fs
- user1.VirtualFolders = append(user1.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: "sftp",
- FsConfig: vfs.Filesystem{
- Provider: vfs.SFTPFilesystemProvider,
- SFTPConfig: vfs.SFTPFsConfig{
- Endpoint: sftpServerAddr,
- Username: user2.Username,
- Password: kms.NewPlainSecret(defaultPassword),
- },
- },
- },
- VirtualPath: "/vdir",
- })
- user2.FsConfig.Provider = vfs.SFTPFilesystemProvider
- user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
- Endpoint: sftpServerAddr,
- Username: user1.Username,
- Password: kms.NewPlainSecret(defaultPassword),
- }
- user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
- assert.NoError(t, err, string(resp))
- user2, resp, err = httpdtest.AddUser(user2, http.StatusCreated)
- assert.NoError(t, err, string(resp))
- user1.VirtualFolders[0].FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
- user2.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
- conn := common.NewBaseConnection("", common.ProtocolWebDAV, "", user1)
- _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
- assert.ErrorIs(t, err, os.ErrPermission)
- conn = common.NewBaseConnection("", common.ProtocolSFTP, "", user1)
- _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SFTP loop")
- }
- conn = common.NewBaseConnection("", common.ProtocolFTP, "", user1)
- _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SFTP loop")
- }
- _, err = httpdtest.RemoveUser(user1, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user1.GetHomeDir())
- assert.NoError(t, err)
- _, err = httpdtest.RemoveUser(user2, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user2.GetHomeDir())
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: "sftp"}, http.StatusOK)
- assert.NoError(t, err)
- }
- func TestNonLocalCrossRename(t *testing.T) {
- baseUser, resp, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
- assert.NoError(t, err, string(resp))
- u := getTestUser()
- u.HomeDir += "_folders"
- u.Username += "_folders"
- mappedPathSFTP := filepath.Join(os.TempDir(), "sftp")
- folderNameSFTP := filepath.Base(mappedPathSFTP)
- vdirSFTPPath := "/vdir/sftp"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderNameSFTP,
- FsConfig: vfs.Filesystem{
- Provider: vfs.SFTPFilesystemProvider,
- SFTPConfig: vfs.SFTPFsConfig{
- Endpoint: sftpServerAddr,
- Username: baseUser.Username,
- Password: kms.NewPlainSecret(defaultPassword),
- },
- },
- },
- VirtualPath: vdirSFTPPath,
- })
- mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
- folderNameCrypt := filepath.Base(mappedPathCrypt)
- vdirCryptPath := "/vdir/crypt"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderNameCrypt,
- FsConfig: vfs.Filesystem{
- Provider: vfs.CryptedFilesystemProvider,
- CryptConfig: vfs.CryptFsConfig{
- Passphrase: kms.NewPlainSecret(defaultPassword),
- },
- },
- MappedPath: mappedPathCrypt,
- },
- VirtualPath: vdirCryptPath,
- })
- user, resp, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err, string(resp))
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- assert.NoError(t, checkBasicSFTP(client))
- err = writeSFTPFile(testFileName, 4096, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirSFTPPath, testFileName), 8192, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirCryptPath, testFileName), 16384, client)
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirSFTPPath, testFileName), path.Join(vdirCryptPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirSFTPPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(testFileName, path.Join(vdirCryptPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(testFileName, path.Join(vdirSFTPPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(path.Join(vdirSFTPPath, testFileName), testFileName+".rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(path.Join(vdirCryptPath, testFileName), testFileName+".rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- // rename on local fs or on the same folder must work
- err = client.Rename(testFileName, testFileName+".rename")
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirSFTPPath, testFileName), path.Join(vdirSFTPPath, testFileName+"_rename"))
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirCryptPath, testFileName+"_rename"))
- assert.NoError(t, err)
- // renaming a virtual folder is not allowed
- err = client.Rename(vdirSFTPPath, vdirSFTPPath+"_rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(vdirCryptPath, vdirCryptPath+"_rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(vdirCryptPath, path.Join(vdirCryptPath, "rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Mkdir(path.Join(vdirCryptPath, "subcryptdir"))
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirCryptPath, "subcryptdir"), vdirCryptPath)
- assert.ErrorIs(t, err, os.ErrPermission)
- // renaming root folder is not allowed
- err = client.Rename("/", "new_name")
- assert.ErrorIs(t, err, os.ErrPermission)
- // renaming a path to a virtual folder is not allowed
- err = client.Rename("/vdir", "new_vdir")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameSFTP}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveUser(baseUser, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(baseUser.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPathCrypt)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPathSFTP)
- assert.NoError(t, err)
- }
- func TestNonLocalCrossRenameNonLocalBaseUser(t *testing.T) {
- baseUser, resp, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
- assert.NoError(t, err, string(resp))
- u := getTestSFTPUser()
- mappedPathLocal := filepath.Join(os.TempDir(), "local")
- folderNameLocal := filepath.Base(mappedPathLocal)
- vdirLocalPath := "/vdir/local"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderNameLocal,
- MappedPath: mappedPathLocal,
- },
- VirtualPath: vdirLocalPath,
- })
- mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
- folderNameCrypt := filepath.Base(mappedPathCrypt)
- vdirCryptPath := "/vdir/crypt"
- u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
- BaseVirtualFolder: vfs.BaseVirtualFolder{
- Name: folderNameCrypt,
- FsConfig: vfs.Filesystem{
- Provider: vfs.CryptedFilesystemProvider,
- CryptConfig: vfs.CryptFsConfig{
- Passphrase: kms.NewPlainSecret(defaultPassword),
- },
- },
- MappedPath: mappedPathCrypt,
- },
- VirtualPath: vdirCryptPath,
- })
- user, resp, err := httpdtest.AddUser(u, http.StatusCreated)
- assert.NoError(t, err, string(resp))
- conn, client, err := getSftpClient(user)
- if assert.NoError(t, err) {
- defer conn.Close()
- defer client.Close()
- assert.NoError(t, checkBasicSFTP(client))
- err = writeSFTPFile(testFileName, 4096, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirLocalPath, testFileName), 8192, client)
- assert.NoError(t, err)
- err = writeSFTPFile(path.Join(vdirCryptPath, testFileName), 16384, client)
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirLocalPath, testFileName), path.Join(vdirCryptPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirLocalPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(testFileName, path.Join(vdirCryptPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(testFileName, path.Join(vdirLocalPath, testFileName+".rename"))
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(path.Join(vdirLocalPath, testFileName), testFileName+".rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(path.Join(vdirCryptPath, testFileName), testFileName+".rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- // rename on local fs or on the same folder must work
- err = client.Rename(testFileName, testFileName+".rename")
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirLocalPath, testFileName), path.Join(vdirLocalPath, testFileName+"_rename"))
- assert.NoError(t, err)
- err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirCryptPath, testFileName+"_rename"))
- assert.NoError(t, err)
- // renaming a virtual folder is not allowed
- err = client.Rename(vdirLocalPath, vdirLocalPath+"_rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- err = client.Rename(vdirCryptPath, vdirCryptPath+"_rename")
- assert.ErrorIs(t, err, os.ErrPermission)
- // renaming root folder is not allowed
- err = client.Rename("/", "new_name")
- assert.ErrorIs(t, err, os.ErrPermission)
- // renaming a path to a virtual folder is not allowed
- err = client.Rename("/vdir", "new_vdir")
- if assert.Error(t, err) {
- assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
- }
- }
- _, err = httpdtest.RemoveUser(user, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameLocal}, http.StatusOK)
- assert.NoError(t, err)
- _, err = httpdtest.RemoveUser(baseUser, http.StatusOK)
- assert.NoError(t, err)
- err = os.RemoveAll(user.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(baseUser.GetHomeDir())
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPathCrypt)
- assert.NoError(t, err)
- err = os.RemoveAll(mappedPathLocal)
- assert.NoError(t, err)
- }
- func TestProxyProtocol(t *testing.T) {
- resp, err := httpclient.Get(fmt.Sprintf("http://%v", httpProxyAddr))
- if assert.NoError(t, err) {
- defer resp.Body.Close()
- assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
- }
- }
- func TestSetProtocol(t *testing.T) {
- conn := common.NewBaseConnection("id", "sshd_exec", "", dataprovider.User{HomeDir: os.TempDir()})
- conn.SetProtocol(common.ProtocolSCP)
- require.Equal(t, "SCP_id", conn.GetID())
- }
- func TestGetFsError(t *testing.T) {
- u := getTestUser()
- u.FsConfig.Provider = vfs.GCSFilesystemProvider
- u.FsConfig.GCSConfig.Bucket = "test"
- u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
- conn := common.NewBaseConnection("", common.ProtocolFTP, "", u)
- _, _, err := conn.GetFsAndResolvedPath("/vpath")
- assert.Error(t, err)
- }
- func waitTCPListening(address string) {
- for {
- conn, err := net.Dial("tcp", address)
- if err != nil {
- logger.WarnToConsole("tcp server %v not listening: %v", address, err)
- time.Sleep(100 * time.Millisecond)
- continue
- }
- logger.InfoToConsole("tcp server %v now listening", address)
- conn.Close()
- break
- }
- }
- func checkBasicSFTP(client *sftp.Client) error {
- _, err := client.Getwd()
- if err != nil {
- return err
- }
- _, err = client.ReadDir(".")
- return err
- }
- func getSftpClient(user dataprovider.User) (*ssh.Client, *sftp.Client, error) {
- var sftpClient *sftp.Client
- config := &ssh.ClientConfig{
- User: user.Username,
- HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
- return nil
- },
- }
- if user.Password != "" {
- config.Auth = []ssh.AuthMethod{ssh.Password(user.Password)}
- } else {
- config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
- }
- conn, err := ssh.Dial("tcp", sftpServerAddr, config)
- if err != nil {
- return conn, sftpClient, err
- }
- sftpClient, err = sftp.NewClient(conn)
- if err != nil {
- conn.Close()
- }
- return conn, sftpClient, err
- }
- func getTestUser() dataprovider.User {
- user := dataprovider.User{
- Username: defaultUsername,
- Password: defaultPassword,
- HomeDir: filepath.Join(homeBasePath, defaultUsername),
- Status: 1,
- ExpirationDate: 0,
- }
- user.Permissions = make(map[string][]string)
- user.Permissions["/"] = allPerms
- return user
- }
- func getTestSFTPUser() dataprovider.User {
- u := getTestUser()
- u.Username = defaultSFTPUsername
- u.FsConfig.Provider = vfs.SFTPFilesystemProvider
- u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
- u.FsConfig.SFTPConfig.Username = defaultUsername
- u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
- return u
- }
- func getCryptFsUser() dataprovider.User {
- u := getTestUser()
- u.FsConfig.Provider = vfs.CryptedFilesystemProvider
- u.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret(defaultPassword)
- return u
- }
- func writeSFTPFile(name string, size int64, client *sftp.Client) error {
- err := writeSFTPFileNoCheck(name, size, client)
- if err != nil {
- return err
- }
- info, err := client.Stat(name)
- if err != nil {
- return err
- }
- if info.Size() != size {
- return fmt.Errorf("file size mismatch, wanted %v, actual %v", size, info.Size())
- }
- return nil
- }
- func writeSFTPFileNoCheck(name string, size int64, client *sftp.Client) error {
- content := make([]byte, size)
- _, err := rand.Read(content)
- if err != nil {
- return err
- }
- f, err := client.Create(name)
- if err != nil {
- return err
- }
- _, err = io.Copy(f, bytes.NewBuffer(content))
- if err != nil {
- f.Close()
- return err
- }
- return f.Close()
- }
- func getUploadScriptContent(movedPath string) []byte {
- content := []byte("#!/bin/sh\n\n")
- content = append(content, []byte("sleep 1\n")...)
- content = append(content, []byte(fmt.Sprintf("mv ${SFTPGO_ACTION_PATH} %v\n", movedPath))...)
- return content
- }
|