From 0967ca53dcce2843c62d7e3a4cb3e632a7f5869e Mon Sep 17 00:00:00 2001 From: hexxa Date: Thu, 24 Feb 2022 22:28:28 +0800 Subject: [PATCH] test(authz): refine authz tests --- src/db/userstore/user_store.go | 8 +- src/handlers/fileshdr/handlers.go | 9 +- src/handlers/multiusers/handlers.go | 47 +-- src/handlers/multiusers/middlewares.go | 1 + src/handlers/settings/handlers.go | 13 - src/server/server_permission_test.go | 392 ++++++++++++++----------- 6 files changed, 241 insertions(+), 229 deletions(-) diff --git a/src/db/userstore/user_store.go b/src/db/userstore/user_store.go index 0c657db..8a347f1 100644 --- a/src/db/userstore/user_store.go +++ b/src/db/userstore/user_store.go @@ -31,7 +31,9 @@ const ( ) var ( - ErrReachedLimit = errors.New("reached space limit") + ErrReachedLimit = errors.New("reached space limit") + ErrNotFound = errors.New("not found") + DefaultPreferences = Preferences{ Bg: &sitestore.BgConfig{ Url: "", @@ -262,11 +264,11 @@ func (us *KVUserStore) GetUserByName(name string) (*User, error) { userID, ok := us.store.GetStringIn(IDsNs, name) if !ok { - return nil, fmt.Errorf("user id (%s) not found", name) + return nil, ErrNotFound } infoStr, ok := us.store.GetStringIn(UsersNs, userID) if !ok { - return nil, fmt.Errorf("user name (%s) not found", userID) + return nil, ErrNotFound } user := &User{} diff --git a/src/handlers/fileshdr/handlers.go b/src/handlers/fileshdr/handlers.go index d45df80..75eaf07 100644 --- a/src/handlers/fileshdr/handlers.go +++ b/src/handlers/fileshdr/handlers.go @@ -829,13 +829,20 @@ func (h *FileHandlers) DelUploading(c *gin.Context) { } userID := c.MustGet(q.UserIDParam).(string) + role := c.MustGet(q.RoleParam).(string) + userName := c.MustGet(q.UserParam).(string) + // op is empty, because users must be admin, or the path belongs to this user + if !h.canAccess(userName, role, "", filePath) { + c.JSON(q.ErrResp(c, 403, errors.New("forbidden"))) + return + } + userIDInt, err := strconv.ParseUint(userID, 10, 64) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return } - userName := c.MustGet(q.UserParam).(string) tmpFilePath := q.UploadPath(userName, filePath) locker := h.NewAutoLocker(c, lockName(tmpFilePath)) locker.Exec(func() { diff --git a/src/handlers/multiusers/handlers.go b/src/handlers/multiusers/handlers.go index 541ffab..9bab2f9 100644 --- a/src/handlers/multiusers/handlers.go +++ b/src/handlers/multiusers/handlers.go @@ -82,7 +82,6 @@ func NewMultiUsersSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*MultiUsersSvc, error) apiRuleCname(userstore.UserRole, "POST", "/v1/users/logout"): true, apiRuleCname(userstore.UserRole, "GET", "/v1/users/isauthed"): true, apiRuleCname(userstore.UserRole, "PATCH", "/v1/users/pwd"): true, - apiRuleCname(userstore.UserRole, "PATCH", "/v1/users/"): true, apiRuleCname(userstore.UserRole, "GET", "/v1/users/self"): true, apiRuleCname(userstore.UserRole, "PATCH", "/v1/users/preferences"): true, apiRuleCname(userstore.UserRole, "POST", "/v1/fs/files"): true, @@ -114,13 +113,11 @@ func NewMultiUsersSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*MultiUsersSvc, error) apiRuleCname(userstore.VisitorRole, "GET", "/"): true, apiRuleCname(userstore.VisitorRole, "GET", publicPath): true, apiRuleCname(userstore.VisitorRole, "POST", "/v1/users/login"): true, - apiRuleCname(userstore.VisitorRole, "GET", "/v1/users/isauthed"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/users/self"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/fs/files"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/fs/dirs"): true, apiRuleCname(userstore.VisitorRole, "OPTIONS", "/v1/settings/health"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/settings/client"): true, - apiRuleCname(userstore.VisitorRole, "POST", "/v1/settings/errors"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/captchas/"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/captchas/imgs"): true, apiRuleCname(userstore.VisitorRole, "GET", "/v1/fs/sharings/exist"): true, @@ -220,7 +217,7 @@ type LoginReq struct { func (h *MultiUsersSvc) Login(c *gin.Context) { req := &LoginReq{} if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(q.ErrResp(c, 500, err)) + c.JSON(q.ErrResp(c, 400, err)) return } @@ -235,13 +232,17 @@ func (h *MultiUsersSvc) Login(c *gin.Context) { user, err := h.deps.Users().GetUserByName(req.User) if err != nil { + if errors.Is(err, userstore.ErrNotFound) { + c.JSON(q.ErrResp(c, 403, err)) + return + } c.JSON(q.ErrResp(c, 500, err)) return } err = bcrypt.CompareHashAndPassword([]byte(user.Pwd), []byte(req.Pwd)) if err != nil { - c.JSON(q.ErrResp(c, 500, err)) + c.JSON(q.ErrResp(c, 403, err)) return } @@ -276,11 +277,6 @@ func (h *MultiUsersSvc) Logout(c *gin.Context) { func (h *MultiUsersSvc) IsAuthed(c *gin.Context) { // token alreay verified in the authn middleware - role := c.MustGet(q.RoleParam).(string) - if role == userstore.VisitorRole { - c.JSON(q.ErrResp(c, 403, q.ErrUnauthorized)) - return - } c.JSON(q.Resp(200)) } @@ -350,15 +346,6 @@ func (h *MultiUsersSvc) ForceSetPwd(c *gin.Context) { return } - claims, err := h.getUserInfo(c) - if err != nil { - c.JSON(q.ErrResp(c, 403, err)) - return - } - if claims[q.RoleParam] != userstore.AdminRole { - c.JSON(q.ErrResp(c, 403, errors.New("operation denied"))) - return - } targetUID, err := strconv.ParseUint(req.ID, 10, 64) if err != nil { c.JSON(q.ErrResp(c, 500, err)) @@ -681,12 +668,6 @@ func (h *MultiUsersSvc) SetUser(c *gin.Context) { return } - role := c.MustGet(q.RoleParam).(string) - if role != userstore.AdminRole { - c.JSON(q.ErrResp(c, 403, errors.New("Forbidden"))) - return - } - err := h.deps.Users().SetInfo(req.ID, &userstore.User{ Role: req.Role, Quota: req.Quota, @@ -710,21 +691,7 @@ func (h *MultiUsersSvc) SetPreferences(c *gin.Context) { return } - claims, err := h.getUserInfo(c) - if err != nil { - c.JSON(q.ErrResp(c, 401, err)) - return - } - if claims[q.RoleParam] == userstore.VisitorRole { - c.JSON(q.ErrResp(c, 403, errors.New("operation denied"))) - return - } - - uidStr, ok := claims[q.UserIDParam] - if !ok { - c.JSON(q.ErrResp(c, 500, errors.New("user id not found"))) - return - } + uidStr := c.MustGet(q.UserIDParam).(string) uid, err := strconv.ParseUint(uidStr, 10, 64) if err != nil { c.JSON(q.ErrResp(c, 500, err)) diff --git a/src/handlers/multiusers/middlewares.go b/src/handlers/multiusers/middlewares.go index 2d78016..cf833e6 100644 --- a/src/handlers/multiusers/middlewares.go +++ b/src/handlers/multiusers/middlewares.go @@ -9,6 +9,7 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/ihexxa/quickshare/src/db/userstore" q "github.com/ihexxa/quickshare/src/handlers" ) diff --git a/src/handlers/settings/handlers.go b/src/handlers/settings/handlers.go index d77ed98..01fd122 100644 --- a/src/handlers/settings/handlers.go +++ b/src/handlers/settings/handlers.go @@ -7,7 +7,6 @@ import ( "github.com/ihexxa/gocfg" "github.com/ihexxa/quickshare/src/db/sitestore" - "github.com/ihexxa/quickshare/src/db/userstore" "github.com/ihexxa/quickshare/src/depidx" q "github.com/ihexxa/quickshare/src/handlers" ) @@ -71,12 +70,6 @@ func (h *SettingsSvc) SetClientCfg(c *gin.Context) { return } - role := c.MustGet(q.RoleParam).(string) - if role != userstore.AdminRole { - c.JSON(q.ErrResp(c, 403, q.ErrUnauthorized)) - return - } - err = h.deps.SiteStore().SetClientCfg(clientCfg) if err != nil { c.JSON(q.ErrResp(c, 500, err)) @@ -102,12 +95,6 @@ type ClientErrorReports struct { } func (h *SettingsSvc) ReportErrors(c *gin.Context) { - role := c.MustGet(q.RoleParam).(string) - if role == userstore.VisitorRole { - c.JSON(q.ErrResp(c, 403, q.ErrUnauthorized)) - return - } - var err error req := &ClientErrorReports{} if err = c.ShouldBindJSON(&req); err != nil { diff --git a/src/server/server_permission_test.go b/src/server/server_permission_test.go index 8b5e68c..65669f9 100644 --- a/src/server/server_permission_test.go +++ b/src/server/server_permission_test.go @@ -81,18 +81,28 @@ func TestPermissions(t *testing.T) { } // tests only check the status code for checking permission - t.Run("Users API Permissions", func(t *testing.T) { - testUsersAPIs := func(user string, pwd string, requireAuth bool, expectedCodes map[string]int) { - desc := user - - cl := client.NewSingleUserClient(addr) - token := &http.Cookie{} - if requireAuth { - resp, _, errs := cl.Login(user, pwd) - assertResp(t, resp, errs, 200, desc) - token = client.GetCookie(resp.Cookies(), q.TokenCookie) - } + t.Run("users API authz tests", func(t *testing.T) { + // Login + // SetPwd + // Self + // SetPreferences + // IsAuthed + // AddUser + // AddUser + // ListUsers + // ForceSetPwd + // ForceSetPwdOther + // ForceSetPwdOtherAdmin + // SetUserSelf + // SetUserOthers + // SetUserOthers + // DelUser + // AddRole + // ListRoles + // DelRole + // Logout + testUsersAPIs := func(desc, user string, pwd string, requireAuth bool, expectedCodes map[string]int) { newPwd := "12345" newRole := userstore.AdminRole newQuota := &userstore.Quota{ @@ -104,9 +114,19 @@ func TestPermissions(t *testing.T) { tmpAdmin, tmpAdminPwd := "tmpAdmin", "1234" tmpNewRole := "tmpNewRole" + cl := client.NewSingleUserClient(addr) + token := &http.Cookie{} + if requireAuth { + resp, _, errs := cl.Login(user, pwd) + assertResp(t, resp, errs, 200, desc) + token = client.GetCookie(resp.Cookies(), q.TokenCookie) + } else { + resp, _, errs := cl.Login(user, pwd) + assertResp(t, resp, errs, 403, desc) + } + resp, _, errs := cl.SetPwd(pwd, newPwd, token) assertResp(t, resp, errs, expectedCodes["SetPwd"], fmt.Sprintf("%s-%s", desc, "SetPwd")) - // set back the password resp, _, errs = cl.SetPwd(newPwd, pwd, token) assertResp(t, resp, errs, expectedCodes["SetPwd"], fmt.Sprintf("%s-%s", desc, "SetPwd")) @@ -122,6 +142,7 @@ func TestPermissions(t *testing.T) { resp, _, errs = cl.IsAuthed(token) assertResp(t, resp, errs, expectedCodes["IsAuthed"], fmt.Sprintf("%s-%s", desc, "IsAuthed")) + // user management resp, addUserResp, errs := cl.AddUser(tmpUser, tmpPwd, tmpRole, token) assertResp(t, resp, errs, expectedCodes["AddUser"], fmt.Sprintf("%s-%s", desc, "AddUser")) resp, addAdminResp, errs := cl.AddUser(tmpAdmin, tmpAdminPwd, userstore.AdminRole, token) @@ -150,10 +171,12 @@ func TestPermissions(t *testing.T) { resp, _, errs = cl.ForceSetPwd(selfResp.ID, newPwd, token) assertResp(t, resp, errs, expectedCodes["ForceSetPwd"], fmt.Sprintf("%s-%s", desc, "ForceSetPwd")) resp, _, errs = cl.ForceSetPwd(selfResp.ID, pwd, token) + assertResp(t, resp, errs, expectedCodes["ForceSetPwd"], fmt.Sprintf("%s-%s", desc, "ForceSetPwdBack")) resp, _, errs = cl.ForceSetPwd(addUserResp.ID, newPwd, token) assertResp(t, resp, errs, expectedCodes["ForceSetPwdOther"], fmt.Sprintf("%s-%s", desc, "ForceSetPwdOther")) resp, _, errs = cl.ForceSetPwd(addUserResp.ID, pwd, token) + assertResp(t, resp, errs, expectedCodes["ForceSetPwdOther"], fmt.Sprintf("%s-%s", desc, "ForceSetPwdOtherBack")) resp, _, errs = cl.ForceSetPwd(addAdminResp.ID, newPwd, token) assertResp(t, resp, errs, expectedCodes["ForceSetPwdOtherAdmin"], fmt.Sprintf("%s-%s", desc, "ForceSetPwdOtherAdmin")) @@ -165,12 +188,14 @@ func TestPermissions(t *testing.T) { resp, _, errs = cl.SetUser(tmpUserID, userstore.AdminRole, newQuota, token) assertResp(t, resp, errs, expectedCodes["SetUserOthers"], fmt.Sprintf("%s-%s", desc, "SetUserOthers")) resp, _, errs = cl.SetUser(0, userstore.UserRole, newQuota, token) - assertResp(t, resp, errs, expectedCodes["SetUserOthers"], fmt.Sprintf("%s-%s", desc, "SetUserOthers")) + assertResp(t, resp, errs, expectedCodes["SetUserOthersAdmin"], fmt.Sprintf("%s-%s", desc, "SetUserOthersAdmin")) resp, _, errs = cl.DelUser(addUserResp.ID, token) assertResp(t, resp, errs, expectedCodes["DelUser"], fmt.Sprintf("%s-%s", desc, "DelUser")) + resp, _, errs = cl.DelUser(addAdminResp.ID, token) + assertResp(t, resp, errs, expectedCodes["DelUserAdmin"], fmt.Sprintf("%s-%s", desc, "DelUserAdmin")) - // test role operations + // role management resp, _, errs = cl.AddRole(tmpNewRole, token) assertResp(t, resp, errs, expectedCodes["AddRole"], fmt.Sprintf("%s-%s", desc, "AddRole")) @@ -183,29 +208,33 @@ func TestPermissions(t *testing.T) { if requireAuth { resp, _, errs := cl.Logout(token) assertResp(t, resp, errs, 200, fmt.Sprintf("%s-%s", desc, "logout")) + } else { + resp, _, errs := cl.Logout(token) + assertResp(t, resp, errs, 403, fmt.Sprintf("%s-%s", desc, "logout")) } } - testUsersAPIs("admin", "1234", true, map[string]int{ + testUsersAPIs("admin user operations", "admin", "1234", true, map[string]int{ "SetPwd": 200, "Self": 200, "SetPreferences": 200, "IsAuthed": 200, "AddUser": 200, "ListUsers": 200, - "ForceSetPwd": 403, // can not set admin's password + "ForceSetPwd": 403, // force setting admin's password is not allowed "ForceSetPwdOther": 200, "ForceSetPwdOtherAdmin": 403, "SetUserSelf": 200, "SetUserOthers": 200, - "SetOtherUser": 200, + "SetUserOthersAdmin": 200, "DelUser": 200, + "DelUserAdmin": 200, "AddRole": 200, "ListRoles": 200, "DelRole": 200, }) - testUsersAPIs("user", "1234", true, map[string]int{ + testUsersAPIs("user user operations", "user", "1234", true, map[string]int{ "SetPwd": 200, "Self": 200, "SetPreferences": 200, @@ -217,13 +246,15 @@ func TestPermissions(t *testing.T) { "ForceSetPwdOtherAdmin": 403, "SetUserSelf": 403, "SetUserOthers": 403, + "SetUserOthersAdmin": 403, "DelUser": 403, + "DelUserAdmin": 403, "AddRole": 403, "ListRoles": 403, "DelRole": 403, }) - testUsersAPIs("visitor", "", false, map[string]int{ + testUsersAPIs("visitor user operations", "visitor", "", false, map[string]int{ "SetPwd": 403, "Self": 403, "SetPreferences": 403, @@ -235,30 +266,25 @@ func TestPermissions(t *testing.T) { "ForceSetPwdOtherAdmin": 403, "SetUserSelf": 403, "SetUserOthers": 403, + "SetUserOthersAdmin": 403, "DelUser": 403, + "DelUserAdmin": 403, "AddRole": 403, "ListRoles": 403, "DelRole": 403, }) }) - t.Run("Files operation API Permissions", func(t *testing.T) { - testFolderOpPermission := func(user string, pwd string, requireAuth bool, expectedCodes map[string]int) { - // List + t.Run("files operation API authz tests", func(t *testing.T) { + testFolderOpPermission := func(desc, user string, pwd string, requireAuth bool, targetPaths []string, expectedCodes map[string]int) { // ListHome + // List + // ListTarget // Mkdir // Move - // Create - // UploadChunk - // UploadStatus - // Metadata - // Move - // Download - // Delete cl := client.NewSingleUserClient(addr) token := &http.Cookie{} - desc := user if requireAuth { resp, _, errs := cl.Login(user, pwd) @@ -269,36 +295,41 @@ func TestPermissions(t *testing.T) { filesCl := client.NewFilesClient(addr, token) resp, lhResp, errs := filesCl.ListHome() - assertResp(t, resp, errs, expectedCodes["ListHome"], desc) + assertResp(t, resp, errs, expectedCodes["ListHome"], fmt.Sprintf("%s-%s", desc, "ListHome")) homePath := lhResp.Cwd if !requireAuth { homePath = "/" } - - resp, _, errs = filesCl.List(homePath) - assertResp(t, resp, errs, expectedCodes["List"], desc) - - for _, itemPath := range []string{ - "/", - "admin/", - "admin/files", - "user2/", - "user2/files", - } { - resp, _, errs = filesCl.List(itemPath) - assertResp(t, resp, errs, expectedCodes["ListPaths"], desc) - } - testPath := filepath.Join(lhResp.Cwd, "test") - - resp, _, errs = filesCl.Mkdir(testPath) - assertResp(t, resp, errs, expectedCodes["Mkdir"], desc) - newPath := filepath.Join(lhResp.Cwd, "test2") + resp, _, errs = filesCl.List(homePath) + assertResp(t, resp, errs, expectedCodes["List"], fmt.Sprintf("%s-%s", desc, "List")) + + for _, itemPath := range targetPaths { + resp, _, errs = filesCl.List(itemPath) + assertResp(t, resp, errs, expectedCodes["ListTarget"], fmt.Sprintf("%s-%s", desc, "ListTarget")) + } + + resp, _, errs = filesCl.Mkdir(testPath) + assertResp(t, resp, errs, expectedCodes["Mkdir"], fmt.Sprintf("%s-%s", desc, "Mkdir")) + + for _, itemPath := range targetPaths { + resp, _, errs = filesCl.Mkdir(filepath.Join(itemPath, "test")) + assertResp(t, resp, errs, expectedCodes["MkdirTarget"], fmt.Sprintf("%s-%s", desc, "MkdirTarget")) + } + resp, _, errs = filesCl.Move(testPath, newPath) - assertResp(t, resp, errs, expectedCodes["Move"], desc) + assertResp(t, resp, errs, expectedCodes["Move"], fmt.Sprintf("%s-%s", desc, "Move")) + + for i, srcDir := range targetPaths { + srcPath := filepath.Join(srcDir, "test") + dstPath := filepath.Join(homePath, fmt.Sprintf("folder_%d", i)) + + resp, _, errs = filesCl.Move(srcPath, dstPath) + assertResp(t, resp, errs, expectedCodes["MoveFrom"], fmt.Sprintf("%s-%s", desc, "MoveFrom")) + } if requireAuth { resp, _, errs := cl.Logout(token) @@ -306,29 +337,59 @@ func TestPermissions(t *testing.T) { } } - testFolderOpPermission("admin", "1234", true, map[string]int{ - "ListHome": 200, - "List": 200, - "ListPaths": 200, - "Mkdir": 200, - "Move": 200, + targetPaths := []string{ + "/", + "admin2/", + "admin2/files", + "user2/", + "user2/files", + } + + testFolderOpPermission("admin folder operations", "admin", "1234", true, targetPaths, map[string]int{ + "ListHome": 200, + "List": 200, + "ListTarget": 200, + "Mkdir": 200, + "MkdirTarget": 200, + "Move": 200, + "MoveFrom": 200, }) - testFolderOpPermission("user", "1234", true, map[string]int{ - "ListHome": 200, - "List": 200, - "ListPaths": 403, - "Mkdir": 200, - "Move": 200, + testFolderOpPermission("user folder operations", "user", "1234", true, targetPaths, map[string]int{ + "ListHome": 200, + "List": 200, + "ListTarget": 403, + "Mkdir": 200, + "MkdirTarget": 403, + "Move": 200, + "MoveFrom": 403, }) - testFolderOpPermission("visitor", "", false, map[string]int{ - "ListHome": 403, - "List": 403, - "ListPaths": 403, - "Mkdir": 403, - "Move": 403, + testFolderOpPermission("visitor folder operations", "visitor", "", false, targetPaths, map[string]int{ + "ListHome": 403, + "List": 403, + "ListTarget": 403, + "Mkdir": 403, + "MkdirTarget": 403, + "Move": 403, + "MoveFrom": 403, }) - testFileOpPermission := func(user string, pwd string, requireAuth bool, targetPath, targetFile string, expectedCodes map[string]int) { + uploadSample := func() { + cl := client.NewSingleUserClient(addr) + token := &http.Cookie{} + + resp, _, errs := cl.Login("user2", "1234") + if len(errs) > 0 { + t.Fatal(errs) + } else if resp.StatusCode != 200 { + t.Fatal(resp.StatusCode) + } + token = client.GetCookie(resp.Cookies(), q.TokenCookie) + assertUploadOK(t, "user2/files/upload", "101", addr, token) + } + uploadSample() + + // test file operations in targetPath with targetFile + testFileOpPermission := func(desc, user string, pwd string, requireAuth bool, targetPath, targetFile string, expectedCodes map[string]int) { // Create // UploadChunk // UploadStatus @@ -354,64 +415,77 @@ func TestPermissions(t *testing.T) { token = client.GetCookie(resp.Cookies(), q.TokenCookie) } - desc := user - fileContent := []byte("01010") - filePath := filepath.Join(targetPath, "old") - fileSize := int64(len(fileContent)) filesCl := client.NewFilesClient(addr, token) - base64Content := base64.StdEncoding.EncodeToString([]byte(fileContent)) - newPath := filepath.Join(targetPath, "new") - resp, _, errs := filesCl.ListHome() + resp, lhResp, errs := filesCl.ListHome() assertResp(t, resp, errs, expectedCodes["ListHome"], fmt.Sprintf("%s-%s", desc, "ListHome")) - resp, _, errs = filesCl.List(targetPath) assertResp(t, resp, errs, expectedCodes["ListTarget"], fmt.Sprintf("%s-%s", desc, "ListTarget")) + fileContent := []byte("01010") + fileSize := int64(len(fileContent)) + base64Content := base64.StdEncoding.EncodeToString([]byte(fileContent)) + filePath := filepath.Join(lhResp.Cwd, "old") + homeNewPath := filepath.Join(lhResp.Cwd, "new") + targetPathFile := filepath.Join(targetPath, user) + resp, _, errs = filesCl.Create(filePath, fileSize) - assertResp(t, resp, errs, expectedCodes["Create"], fmt.Sprintf("%s-%s", desc, "Create")) + assertResp(t, resp, errs, expectedCodes["Create"], fmt.Sprintf("%s-%s", desc, "Create1")) + resp, _, errs = filesCl.Create(targetPathFile, fileSize) + assertResp(t, resp, errs, expectedCodes["CreateTarget"], fmt.Sprintf("%s-%s", desc, "CreateTarget")) + + resp, _, errs = filesCl.UploadStatus(filePath) + assertResp(t, resp, errs, expectedCodes["UploadStatus"], fmt.Sprintf("%s-%s", desc, "UploadStatus")) + resp, _, errs = filesCl.UploadStatus(targetPathFile) + assertResp(t, resp, errs, expectedCodes["UploadStatusTarget"], fmt.Sprintf("%s-%s", desc, "UploadStatusTarget")) resp, _, errs = filesCl.ListUploadings() assertResp(t, resp, errs, expectedCodes["ListUploadings"], fmt.Sprintf("%s-%s", desc, "ListUploadings")) resp, _, errs = filesCl.DelUploading(filePath) assertResp(t, resp, errs, expectedCodes["DelUploading"], fmt.Sprintf("%s-%s", desc, "DelUploading")) + resp, _, errs = filesCl.DelUploading(targetPathFile) + assertResp(t, resp, errs, expectedCodes["DelUploadingTarget"], fmt.Sprintf("%s-%s", desc, "DelUploadingTarget")) // create again resp, _, errs = filesCl.Create(filePath, fileSize) - assertResp(t, resp, errs, expectedCodes["Create"], fmt.Sprintf("%s-%s", desc, "Create")) - - resp, _, errs = filesCl.UploadStatus(filePath) - assertResp(t, resp, errs, expectedCodes["UploadStatus"], fmt.Sprintf("%s-%s", desc, "UploadStatus")) + assertResp(t, resp, errs, expectedCodes["Create"], fmt.Sprintf("%s-%s", desc, "Create2")) + resp, _, errs = filesCl.Create(targetPathFile, fileSize) + assertResp(t, resp, errs, expectedCodes["CreateTarget"], fmt.Sprintf("%s-%s", desc, "CreateTarget")) resp, _, errs = filesCl.UploadChunk(filePath, base64Content, 0) assertResp(t, resp, errs, expectedCodes["UploadChunk"], fmt.Sprintf("%s-%s", desc, "UploadChunk")) + resp, _, errs = filesCl.UploadChunk(targetPathFile, base64Content, 0) + assertResp(t, resp, errs, expectedCodes["UploadChunkTarget"], fmt.Sprintf("%s-%s", desc, "UploadChunkTarget")) resp, _, errs = filesCl.Metadata(filePath) assertResp(t, resp, errs, expectedCodes["Metadata"], fmt.Sprintf("%s-%s", desc, "Metadata")) - resp, _, errs = filesCl.Metadata(targetPath) assertResp(t, resp, errs, expectedCodes["MetadataTarget"], fmt.Sprintf("%s-%s", desc, "MetadataTarget")) resp, _, errs = filesCl.GenerateHash(filePath) assertResp(t, resp, errs, expectedCodes["GenerateHash"], fmt.Sprintf("%s-%s", desc, "GenerateHash")) - - resp, _, errs = filesCl.GenerateHash(targetFile) + resp, _, errs = filesCl.GenerateHash(targetPathFile) assertResp(t, resp, errs, expectedCodes["GenerateHashTarget"], fmt.Sprintf("%s-%s", desc, "GenerateHashTarget")) resp, _, errs = filesCl.Download(filePath, map[string]string{}) assertResp(t, resp, errs, expectedCodes["Download"], fmt.Sprintf("%s-%s", desc, "Download")) + resp, _, errs = filesCl.Download(targetPathFile, map[string]string{}) + assertResp(t, resp, errs, expectedCodes["DownloadTarget"], fmt.Sprintf("%s-%s", desc, "DownloadTarget")) if targetFile != "" { resp, _, errs = filesCl.Download(targetFile, map[string]string{}) - assertResp(t, resp, errs, expectedCodes["DownloadTarget"], fmt.Sprintf("%s-%s", desc, "DownloadTarget")) + assertResp(t, resp, errs, expectedCodes["DownloadTargetFile"], fmt.Sprintf("%s-%s", desc, "DownloadTarget")) } - resp, _, errs = filesCl.Move(filePath, newPath) + resp, _, errs = filesCl.Move(filePath, homeNewPath) assertResp(t, resp, errs, expectedCodes["Move"], fmt.Sprintf("%s-%s", desc, "Move")) + // move target is already tested - resp, _, errs = filesCl.Delete(newPath) + resp, _, errs = filesCl.Delete(homeNewPath) assertResp(t, resp, errs, expectedCodes["Delete"], fmt.Sprintf("%s-%s", desc, "Delete")) + resp, _, errs = filesCl.Delete(targetPathFile) + assertResp(t, resp, errs, expectedCodes["DeleteTarget"], fmt.Sprintf("%s-%s", desc, "DeleteTarget")) if requireAuth { resp, _, errs := cl.Logout(token) @@ -419,78 +493,18 @@ func TestPermissions(t *testing.T) { } } - testFileOpPermission("admin", "1234", true, "admin/files", "", map[string]int{ - "ListHome": 200, - "ListTarget": 200, - "Create": 200, - "ListUploadings": 200, - "DelUploading": 200, - "UploadChunk": 200, - "UploadStatus": 200, - "Metadata": 200, - "MetadataTarget": 200, - "GenerateHash": 200, - "GenerateHashTarget": 400, - "Move": 200, - "Download": 200, - "Delete": 200, - }) - testFileOpPermission("user", "1234", true, "user/files", "", map[string]int{ - "ListHome": 200, - "ListTarget": 200, - "Create": 200, - "ListUploadings": 200, - "DelUploading": 200, - "UploadChunk": 200, - "UploadStatus": 200, - "Metadata": 200, - "MetadataTarget": 200, - "GenerateHash": 200, - "GenerateHashTarget": 400, - "Move": 200, - "Download": 200, - "Delete": 200, - }) - testFileOpPermission("visitor", "", false, "user/files", "", map[string]int{ - "ListHome": 403, - "ListTarget": 403, - "Create": 403, - "ListUploadings": 403, - "DelUploading": 403, - "UploadChunk": 403, - "UploadStatus": 403, - "Metadata": 403, - "MetadataTarget": 403, - "GenerateHash": 403, - "GenerateHashTarget": 403, - "Move": 403, - "Download": 403, - "Delete": 403, - }) - - uploadSample := func() { - cl := client.NewSingleUserClient(addr) - token := &http.Cookie{} - - resp, _, errs := cl.Login("user2", "1234") - if len(errs) > 0 { - t.Fatal(errs) - } else if resp.StatusCode != 200 { - t.Fatal(resp.StatusCode) - } - token = client.GetCookie(resp.Cookies(), q.TokenCookie) - assertUploadOK(t, "user2/files/upload", "101", addr, token) - } - uploadSample() - - testFileOpPermission("admin", "1234", true, "user2/files", "user2/files/upload", map[string]int{ + testFileOpPermission("admin file operations", "admin", "1234", true, "user2/files", "", map[string]int{ "ListHome": 200, "ListTarget": 200, "Create": 200, + "CreateTarget": 200, "ListUploadings": 200, "DelUploading": 200, + "DelUploadingTarget": 200, "UploadChunk": 200, + "UploadChunkTarget": 200, "UploadStatus": 200, + "UploadStatusTarget": 200, "Metadata": 200, "MetadataTarget": 200, "GenerateHash": 200, @@ -499,26 +513,54 @@ func TestPermissions(t *testing.T) { "Download": 200, "DownloadTarget": 200, "Delete": 200, + "DeleteTarget": 200, }) - testFileOpPermission("user", "1234", true, "user2/files", "user2/files/upload", map[string]int{ + testFileOpPermission("user file operations", "user", "1234", true, "user2/files", "", map[string]int{ "ListHome": 200, "ListTarget": 403, - "Create": 403, + "Create": 200, + "CreateTarget": 403, "ListUploadings": 200, - "DelUploading": 500, + "DelUploading": 200, + "DelUploadingTarget": 403, + "UploadChunk": 200, + "UploadChunkTarget": 403, + "UploadStatus": 200, + "UploadStatusTarget": 403, + "Metadata": 200, + "MetadataTarget": 403, + "GenerateHash": 200, + "GenerateHashTarget": 403, + "Move": 200, + "Download": 200, + "DownloadTarget": 403, + "Delete": 200, + "DeleteTarget": 403, + }) + testFileOpPermission("visitor file operations", "visitor", "", false, "user2/files", "", map[string]int{ + "ListHome": 403, + "ListTarget": 403, + "Create": 403, + "CreateTarget": 403, + "ListUploadings": 403, + "DelUploading": 403, + "DelUploadingTarget": 403, "UploadChunk": 403, + "UploadChunkTarget": 403, "UploadStatus": 403, + "UploadStatusTarget": 403, "Metadata": 403, "MetadataTarget": 403, - "GenerateHash": 403, // target path is not user's home + "GenerateHash": 403, "GenerateHashTarget": 403, "Move": 403, "Download": 403, "DownloadTarget": 403, "Delete": 403, + "DeleteTarget": 403, }) - // test sharing permission + // sharing permission tests enableSharing := func() { cl := client.NewSingleUserClient(addr) token := &http.Cookie{} @@ -543,22 +585,28 @@ func TestPermissions(t *testing.T) { } enableSharing() - testFileOpPermission("user", "1234", true, "share/files", "share/files/share", map[string]int{ + testFileOpPermission("user file operations in sharing", "user", "1234", true, "share/files", "share/files/share", map[string]int{ "ListHome": 200, "ListTarget": 200, - "Create": 403, + "Create": 200, + "CreateTarget": 403, "ListUploadings": 200, - "DelUploading": 500, - "UploadChunk": 403, - "UploadStatus": 403, - "Metadata": 403, + "DelUploading": 200, + "DelUploadingTarget": 403, + "UploadChunk": 200, + "UploadChunkTarget": 403, + "UploadStatus": 200, + "UploadStatusTarget": 403, + "Metadata": 200, "MetadataTarget": 403, - "GenerateHash": 403, // target path is not user's home + "GenerateHash": 200, "GenerateHashTarget": 403, - "Move": 403, - "Download": 404, - "DownloadTarget": 200, - "Delete": 403, + "Move": 200, + "Download": 200, + "DownloadTarget": 404, // uploading file to sharing folder is not allowd + "DownloadTargetFile": 200, + "Delete": 200, + "DeleteTarget": 403, }) testShareOpPermission := func(user string, pwd string, requireAuth bool, targetPath string, expectedCodes map[string]int) { @@ -639,7 +687,7 @@ func TestPermissions(t *testing.T) { "AddSharing": 200, "AddSharingTarget": 403, "IsSharing": 200, - "IsSharingTarget": 404, // sharing is deleted by admin + "IsSharingTarget": 404, // sharing is deleted in previous test... "ListSharingIDs": 200, "GetSharingDir": 200, "DelSharing": 200, @@ -650,7 +698,7 @@ func TestPermissions(t *testing.T) { "AddSharing": 403, "AddSharingTarget": 403, "IsSharing": 404, - "IsSharingTarget": 404, + "IsSharingTarget": 404, // sharing is deleted in previous test... "ListSharingIDs": 403, "GetSharingDir": 400, "DelSharing": 403,