Forráskód Böngészése

Fixed permission issue on shares across acc

Toby Chui 3 éve
szülő
commit
e9ea330fdd

+ 16 - 1
file_system.go

@@ -26,6 +26,7 @@ import (
 
 	"imuslab.com/arozos/mod/compatibility"
 	"imuslab.com/arozos/mod/disk/hybridBackup"
+	"imuslab.com/arozos/mod/filesystem"
 	fs "imuslab.com/arozos/mod/filesystem"
 	fsp "imuslab.com/arozos/mod/filesystem/fspermission"
 	hidden "imuslab.com/arozos/mod/filesystem/hidden"
@@ -2094,8 +2095,22 @@ func system_fs_getFileProperties(w http.ResponseWriter, r *http.Request) {
 
 	//Get file owner
 	owner := userinfo.GetFileOwner(rpath)
+
 	if owner == "" {
-		owner = "Unknown"
+		//Handle special virtual roots
+		vrootID, subpath, _ := filesystem.GetIDFromVirtualPath(vpath)
+		if vrootID == "share" {
+			//Share objects
+			shareOption, _ := shareEntryTable.ResolveShareOptionFromShareSubpath(subpath)
+			if shareOption != nil {
+				owner = shareOption.Owner
+			} else {
+				owner = "Unknown"
+			}
+		} else {
+			owner = "Unknown"
+		}
+
 	}
 
 	result := fileProperties{

+ 23 - 45
mod/share/share.go

@@ -22,7 +22,6 @@ import (
 
 	"github.com/valyala/fasttemplate"
 
-	uuid "github.com/satori/go.uuid"
 	"imuslab.com/arozos/mod/auth"
 	"imuslab.com/arozos/mod/common"
 	filesystem "imuslab.com/arozos/mod/filesystem"
@@ -44,7 +43,6 @@ type Manager struct {
 
 //Create a new Share Manager
 func NewShareManager(options Options) *Manager {
-
 	//Return a new manager object
 	return &Manager{
 		options: options,
@@ -513,7 +511,7 @@ func (s *Manager) HandleShareAccess(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
-		if directDownload == true {
+		if directDownload {
 			//Send 404 header
 			http.NotFound(w, r)
 			return
@@ -605,6 +603,26 @@ func (s *Manager) HandleCreateNewShare(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	//Check if this is in the share folder
+	vrootID, subpath, err := filesystem.GetIDFromVirtualPath(vpath)
+	if err != nil {
+		sendErrorResponse(w, "Unable to resolve virtual path")
+		return
+	}
+	if vrootID == "share" {
+		shareObject, err := s.options.ShareEntryTable.ResolveShareOptionFromShareSubpath(subpath)
+		if err != nil {
+			sendErrorResponse(w, err.Error())
+			return
+		}
+
+		//Check if this share is own by or accessible by the current user. Reject share modification if not
+		if !shareObject.IsOwnedBy(userinfo.Username) && !userinfo.CanWrite(vpath) {
+			sendErrorResponse(w, "Permission Denied: You are not the file owner nor can write to this file")
+			return
+		}
+	}
+
 	share, err := s.CreateNewShare(userinfo, vpath)
 	if err != nil {
 		sendErrorResponse(w, err.Error())
@@ -651,7 +669,7 @@ func (s *Manager) HandleEditShare(w http.ResponseWriter, r *http.Request) {
 	}
 
 	//Check if the user has permission to edit this share
-	if so.Owner != userinfo.Username && userinfo.IsAdmin() == false {
+	if so.Owner != userinfo.Username && !userinfo.IsAdmin() {
 		//This file is not shared by this user and this user is not admin. Block this request
 		sendErrorResponse(w, "Permission denied")
 		return
@@ -727,48 +745,8 @@ func (s *Manager) CreateNewShare(userinfo *user.User, vpath string) (*shareEntry
 		return nil, errors.New("Unable to find the file on disk")
 	}
 
-	rpath = filepath.ToSlash(filepath.Clean(rpath))
-	//Check if source file exists
-	if !fileExists(rpath) {
-		return nil, errors.New("Unable to find the file on disk")
-	}
-
-	//Check if the share already exists. If yes, use the previous link
-	val, ok := s.options.ShareEntryTable.FileToUrlMap.Load(rpath)
-	if ok {
-		//Exists. Send back the old share url
-		ShareOption := val.(*shareEntry.ShareOption)
-		return ShareOption, nil
+	return s.options.ShareEntryTable.CreateNewShare(rpath, userinfo.Username, userinfo.GetUserPermissionGroupNames())
 
-	} else {
-		//Create new link for this file
-		shareUUID := uuid.NewV4().String()
-
-		//user groups when share
-		groups := []string{}
-		for _, pg := range userinfo.GetUserPermissionGroup() {
-			groups = append(groups, pg.Name)
-		}
-
-		//Create a share object
-		shareOption := shareEntry.ShareOption{
-			UUID:             shareUUID,
-			FileRealPath:     rpath,
-			Owner:            userinfo.Username,
-			Accessibles:      groups,
-			Permission:       "anyone",
-			AllowLivePreview: true,
-		}
-
-		//Store results on two map to make sure O(1) Lookup time
-		s.options.ShareEntryTable.FileToUrlMap.Store(rpath, &shareOption)
-		s.options.ShareEntryTable.UrlToFileMap.Store(shareUUID, &shareOption)
-
-		//Write object to database
-		s.options.ShareEntryTable.Database.Write("share", shareUUID, shareOption)
-
-		return &shareOption, nil
-	}
 }
 
 func ServePermissionDeniedPage(w http.ResponseWriter) {

+ 0 - 29
mod/share/shareEmulationFs.go

@@ -1,29 +0,0 @@
-package share
-
-/*
-	Share Emulation File System
-
-	This script emulate the shares that a user can access as a
-	virtual file system mountable by the ArozOS File Manager
-
-*/
-
-type ShareVFS struct {
-	Browse  func(string) ([]string, error)
-	Resolve func(string) (string, error)
-}
-
-func NewShareVFSHierarchySpecificConfig() *ShareVFS {
-	return &ShareVFS{
-		Browse:  GenerateVirtualFileView,
-		Resolve: ResolveVirtualPathToShareObjectPath,
-	}
-}
-
-func ResolveVirtualPathToShareObjectPath(subpath string) (string, error) {
-	return "", nil
-}
-
-func GenerateVirtualFileView(requestedPath string) ([]string, error) {
-	return []string{}, nil
-}

+ 75 - 17
mod/share/shareEntry/shareEntry.go

@@ -8,7 +8,9 @@ import (
 	"strings"
 	"sync"
 
+	uuid "github.com/satori/go.uuid"
 	"imuslab.com/arozos/mod/database"
+	"imuslab.com/arozos/mod/filesystem"
 	fs "imuslab.com/arozos/mod/filesystem"
 )
 
@@ -62,8 +64,49 @@ func NewShareEntryTable(db *database.Database) *ShareEntryTable {
 	}
 }
 
+func (s *ShareEntryTable) CreateNewShare(rpath string, username string, usergroups []string) (*ShareOption, error) {
+	rpath = filepath.ToSlash(filepath.Clean(rpath))
+	//Check if source file exists
+	if !fs.FileExists(rpath) {
+		return nil, errors.New("Unable to find the file on disk")
+	}
+
+	//Check if the share already exists. If yes, use the previous link
+	val, ok := s.FileToUrlMap.Load(rpath)
+	if ok {
+		//Exists. Send back the old share url
+		ShareOption := val.(*ShareOption)
+		return ShareOption, nil
+
+	} else {
+		//Create new link for this file
+		shareUUID := uuid.NewV4().String()
+
+		//Create a share object
+		shareOption := ShareOption{
+			UUID:             shareUUID,
+			FileRealPath:     rpath,
+			Owner:            username,
+			Accessibles:      usergroups,
+			Permission:       "anyone",
+			AllowLivePreview: true,
+		}
+
+		//Store results on two map to make sure O(1) Lookup time
+		s.FileToUrlMap.Store(rpath, &shareOption)
+		s.UrlToFileMap.Store(shareUUID, &shareOption)
+
+		//Write object to database
+		s.Database.Write("share", shareUUID, shareOption)
+
+		return s, nil
+	}
+}
+
 //Delete the share on this vpath
 func (s *ShareEntryTable) DeleteShare(rpath string) error {
+	rpath = filepath.ToSlash(filepath.Clean(rpath))
+
 	//Check if the share already exists. If yes, use the previous link
 	val, ok := s.FileToUrlMap.Load(rpath)
 	if ok {
@@ -160,6 +203,33 @@ func (s *ShareEntryTable) RemoveShareByUUID(uuid string) error {
 	return nil
 }
 
+func (s *ShareEntryTable) ResolveShareOptionFromVpath(vpath string) (*ShareOption, error) {
+	vrootID, subpath, err := filesystem.GetIDFromVirtualPath(vpath)
+	if err != nil {
+		return nil, errors.New("Unable to resolve virtual path")
+	}
+
+	if vrootID != "share" {
+		return nil, errors.New("Given path is not share vroot path")
+	}
+
+	return s.ResolveShareOptionFromShareSubpath(subpath)
+}
+
+func (s *ShareEntryTable) ResolveShareOptionFromShareSubpath(subpath string) (*ShareOption, error) {
+	subpathElements := strings.Split(filepath.ToSlash(filepath.Clean(subpath))[1:], "/")
+	if len(subpathElements) >= 1 {
+		shareObject := s.GetShareObjectFromUUID(subpathElements[0])
+		if shareObject == nil {
+			return nil, errors.New("Invalid subpath")
+		} else {
+			return shareObject, nil
+		}
+	} else {
+		return nil, errors.New("Invalid subpath")
+	}
+}
+
 func (s *ShareEntryTable) ResolveShareVrootPath(subpath string, username string, usergroup []string) (string, error) {
 	//Get a list of accessible files from this user
 	subpathElements := strings.Split(filepath.ToSlash(filepath.Clean(subpath))[1:], "/")
@@ -185,7 +255,6 @@ func (s *ShareEntryTable) ResolveShareVrootPath(subpath string, username string,
 		shareObject := s.GetShareObjectFromUUID(subpathElements[0])
 		folderSubpaths := append([]string{shareObject.FileRealPath}, subpathElements[2:]...)
 		targetFolder := filepath.Join(folderSubpaths...)
-		log.Println("Loading folder:", targetFolder)
 		return targetFolder, nil
 	}
 
@@ -208,22 +277,8 @@ func (s *ShareEntryTable) listRootForUser(username string, usergroup []string) [
 		fileRealpath := fp.(string)
 		thisShareOption := so.(*ShareOption)
 		if fs.FileExists(fileRealpath) {
-			//File exists. Check if the share options allow this user access (Only signed in user has username)
-			if thisShareOption.Permission == "anyone" || thisShareOption.Permission == "signedin" {
+			if thisShareOption.IsAccessibleBy(username, usergroup) {
 				userAccessiableShare = append(userAccessiableShare, thisShareOption)
-			} else if thisShareOption.Permission == "samegroup" || thisShareOption.Permission == "groups" {
-				for _, thisUserGroup := range usergroup {
-					if stringInSlice(thisUserGroup, thisShareOption.Accessibles) {
-						//User's group is in the allowed group
-						userAccessiableShare = append(userAccessiableShare, thisShareOption)
-						break
-					}
-				}
-			} else if thisShareOption.Permission == "users" {
-				if stringInSlice(username, thisShareOption.Accessibles) {
-					//User's group is in the allowed group
-					userAccessiableShare = append(userAccessiableShare, thisShareOption)
-				}
 			}
 		}
 		return true
@@ -233,7 +288,10 @@ func (s *ShareEntryTable) listRootForUser(username string, usergroup []string) [
 	for _, thisShareObject := range userAccessiableShare {
 		rpath := thisShareObject.FileRealPath
 		thisFile := fs.GetFileDataFromPath("share:/"+thisShareObject.UUID+"/"+filepath.Base(rpath), rpath, 2)
-		thisFile.IsShared = true
+		if thisShareObject.Owner == username {
+			thisFile.IsShared = true
+		}
+
 		results = append(results, thisFile)
 	}
 

+ 24 - 0
mod/share/shareEntry/shareOptions.go

@@ -0,0 +1,24 @@
+package shareEntry
+
+func (s *ShareOption) IsOwnedBy(username string) bool {
+	return s.Owner == username
+}
+
+func (s *ShareOption) IsAccessibleBy(username string, usergroup []string) bool {
+	if s.Permission == "anyone" || s.Permission == "signedin" {
+		return true
+	} else if s.Permission == "samegroup" || s.Permission == "groups" {
+		for _, thisUserGroup := range usergroup {
+			if stringInSlice(thisUserGroup, s.Accessibles) {
+				//User's group is in the allowed group
+				return true
+			}
+		}
+	} else if s.Permission == "users" {
+		if stringInSlice(username, s.Accessibles) {
+			//User's name is in the allowed group
+			return true
+		}
+	}
+	return false
+}